EEVblog Electronics Community Forum

Electronics => FPGA => Topic started by: nockieboy on October 16, 2019, 01:42:20 pm

Title: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 16, 2019, 01:42:20 pm
Hi all,

Don't know if anyone has noticed, but Grant Searle's website (http://searle.hostei.com/grant/z80/ (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.  |O

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.  ;D

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 (https://github.com/nockieboy/gpu)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 16, 2019, 01:54:57 pm
Does this contain what you need? https://github.com/wsoltys/multicomp
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 16, 2019, 02:55:18 pm
Does this contain what you need? https://github.com/wsoltys/multicomp

Ah 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: dferyance on October 16, 2019, 05:43:02 pm
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.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on October 16, 2019, 08:10:33 pm
Why VGA? It would be more natural to go digital.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 16, 2019, 08:27:06 pm
Why VGA? It would be more natural to go digital.
Got a back-of-napkin design for that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: kizmit99 on October 16, 2019, 09:14:56 pm
Why VGA? It would be more natural to go digital.
Got a back-of-napkin design for that?

The 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_HDMI (http://hamsterworks.co.nz/mediawiki/index.php/Minimal_HDMI)
https://www.fpga4fun.com/HDMI.html (https://www.fpga4fun.com/HDMI.html)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Canis Dirus Leidy on October 16, 2019, 11:00:09 pm
Why VGA? It would be more natural to go digital.
Got a back-of-napkin design for that?
There were several examples at marsohod.org (in Russian):
Connecting MAXII (EPM240) to a LCD panel with a parallel RGB interface (https://marsohod.org/projects/plata1/172-phframe1)
Driving LVDS interface with MAXII (https://marsohod.org/projects/plata1/173-phframe2) (dirty hack, due to lack of PLL in EPM240, but works).
DIY framebuffer (from old SDRAM) for DIY photoframe (https://marsohod.org/projects/plata1/174-phframe3)
HDMI interface with MAX10 (https://marsohod.org/projects/proekty-dlya-platy-marsokhod3/307-max10-hdmi)

P.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".
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 16, 2019, 11:35:23 pm
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's that easy, objection withdrawn. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Codex on October 17, 2019, 03:59:37 am
Web Archive has a copy :)
https://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.html (https://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.html)

He has a mirror here.
http://zx80.netai.net/grant/index.html (http://zx80.netai.net/grant/index.html)


http://searle.wales/ (http://searle.wales/)

twitter for updates and links to the mirror :)
https://twitter.com/zx80nut?lang=en (https://twitter.com/zx80nut?lang=en)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: CJay on October 17, 2019, 05:22:24 am
Hi all,

Don't know if anyone has noticed, but Grant Searle's website (http://searle.hostei.com/grant/z80/ (http://searle.hostei.com/grant/z80/)) seems to have blinked out of existence.


Bugger.

Wish I'd archived it all now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 17, 2019, 06:21:39 am
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's that easy, objection withdrawn. :-+

DVI-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.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 17, 2019, 01:03:29 pm
Bugger.

Wish I'd archived it all now.

Don'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.  :-+

Web Archive has a copy :)
https://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.html (https://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.html)

He has a mirror here.
http://zx80.netai.net/grant/index.html (http://zx80.netai.net/grant/index.html)

twitter for updates and links to the mirror :)
https://twitter.com/zx80nut?lang=en (https://twitter.com/zx80nut?lang=en)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 17, 2019, 01:32:29 pm
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.

A 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?)

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.

I'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.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: dferyance on October 17, 2019, 01:40:32 pm
Quote
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...

Yes, 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 17, 2019, 01:52:55 pm
Why VGA? It would be more natural to go digital.

Err, 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!  :o

I guess the concept of VGA is relatively easy for me to grasp, but if I can do HDMI then I most certainly will!


The 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_HDMI (http://hamsterworks.co.nz/mediawiki/index.php/Minimal_HDMI)
https://www.fpga4fun.com/HDMI.html (https://www.fpga4fun.com/HDMI.html)

Thanks kizmit - that second link is certainly intriguing and has piqued my interest.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 17, 2019, 01:59:57 pm
Quote
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...

Yes, 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.

My 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?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 17, 2019, 02:40:49 pm
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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 17, 2019, 02:56:25 pm
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.

Ideally, 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.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 17, 2019, 03:14:03 pm
Ideally, 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.

I 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 17, 2019, 03:37:49 pm
Shared ram chips, in DIP-package, are about 2 Kbyte.
The alternative is to force the Z80 releasing the bus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: CJay on October 17, 2019, 03:39:37 pm
Bugger.

Wish I'd archived it all now.

Don'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.  :-+

Web Archive has a copy :)
https://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.html (https://web.archive.org/web/20181123194029/http://searle.hostei.com/grant/index.html)

He has a mirror here.
http://zx80.netai.net/grant/index.html (http://zx80.netai.net/grant/index.html)

twitter for updates and links to the mirror :)
https://twitter.com/zx80nut?lang=en (https://twitter.com/zx80nut?lang=en)

Yeah, found them and they're safe now :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 17, 2019, 04:24:43 pm
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!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on October 17, 2019, 08:42:20 pm
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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 17, 2019, 11:49:55 pm
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.
Yep, 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% done :D

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.
Any reason you would want to bit bang video, other than to show off for the demoscene (https://www.linusakesson.net/scene/craft/)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 18, 2019, 01:11:58 am
I use VGA (or composite) for this retro stuff because retro machines just look weird on LCD displays generally and I have a lot more monitors with VGA and only a couple things with HDMI. It's also a lot easier to wire VGA.

I wonder what happened to Grant Searle's website? I have a lot of the code stashed away but there was a ton of cool stuff on there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 18, 2019, 06:33:04 am
These day its still common to share main system RAM between the CPU and GPU, but its done differently.

Today caches are used on all sorts of CPUs even small ones that run under 100MHz. This means the CPU does not always need to be poking and prodding at RAM in order to execute every single instruction. For code that loops around a lot (this is usually where speed matters the most) all of the instructions end up inside the cache and so the CPU completely stops reading code from RAM while for any temporary calculations there are usually plenty of registers to keep things in. So once things are cached the access to RAM is just to move the final computation results in and out of RAM and even that happens in large blocks of cache writebacks (Dynamic RAM usually loves large burst accesses due to pipelining). All this was required to push CPUs into the 100s of Mhz since main system RAM could not keep up.

So this means you can actually take the RAM away from the CPU for many cycles at a time and it won't even notice. Also modern DRAM can easily be run  at 100MHz or more and the wide burst access nature of caches means you can benefit from having a really wide RAM bus such as 64 bit, 128 bit... etc to get even more speed out of it even tho the CPU might only be 16 or 32bit (In graphics cards 512 bit wide RAM buses are not uncommon because they really need lots of bandwidth).

All of this means plenty of RAM bandwidth can be leftover from the CPU and can be used for the GPU. The bus arbitrator can split the bandwidth however it wants between them (Not the usual fixed 50/50 split that interleaved access did in the old days). But it also means that the video output hardware has to have some cache of its own as it will not be guaranteed RAM access at a moments notice. The CPU might be in the middle of a cache writeback and is taking up the bus for the next say 16 cycles or a DRAM refresh cycle might be happening, so the video hardware must have enough pixels in its own internal buffer to keep outputting the image while it waits to finally get to the RAM and catch up.

If you are after a ton of graphics horsepower you could just give the GPU its own set of RAM chips with a huge wide bus to make sure it really has a firehose worth of guaranteed memory bandwidth and then implement a bus MUX that lets the CPU use the memory when the GPU is idle and video output is in blanking, or have the GPU listen to commands from the CPU of what to put into graphics memory. But for a retro computer project that is way overkill since on a decent FPGA this would have the graphics horsepower surpassing early 3D graphics accelerator cards in PC such as the Voodoo
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 18, 2019, 08:33:46 am
Personally I'd have put a Z80 soft core and an SDRAM controller on the FPGA and called it 80% done :D

But for a retro computer project that is way overkill since on a decent FPGA this would have the graphics horsepower surpassing early 3D graphics accelerator cards in PC such as the Voodoo

I guess my motivations may be hard to understand for some as I could achieve all this by just putting it ALL onto the FPGA, but my original intention was to learn how to build a computer from scratch (having been given the desire to do so by stumbling across Grant Searle's page) and learn some electronics skills on the way.  I'm now working with a system I want other people to be able to build who want to go along the same journey I did - although it involves a lot of SMT parts now as my soldering skills have developed and an FPGA graphics card certainly IS overkill, it just seems too good an opportunity for me to miss to be able to just plug my little home-made computer into my living room TV and play Pong on it with the family.

(https://i.ibb.co/P9r24jM/20190730-184211.gif) (https://ibb.co/nnwXfmB)

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.

The CPU runs at 8 MHz (or 4 MHz, if you want to experience true 80's CP/M!).  So you think there would be no noticeable slow-down if I were to shut down memory access for ~73% of the time while the FPGA is accessing the frame buffer to draw the visible area of the screen?  To me, knowing little about this sort of stuff, that equates to slowing the computer down by almost three quarters?

Part of the reason for this post was to discuss the best way to interface the FPGA with the computer - frame buffer in computer RAM, or gated via the FPGA, for example.  Both have positives and negatives, I just don't have the knowledge or experience to understand their weight and balance the options properly, if that makes sense?

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!

Ah, my mistake.  I was a little surprised it was so low actually, considering I was comparing it against an Altera Cyclone II (which I have currently) which is much older and only has a little less.

The LX45 is VERY promising - a little expensive for what I'm trying to do, but would make life VERY easy as I could have an internal dual-port frame buffer that could give me resolutions up to 640x480 with 4 bit colour depth using a LUT, and still have over 100 KB free for the LUT, buffers, character set(s) and even sprites... And the best thing?  It's available in TQFP, which I consider still reasonably easy to solder (have never tried BGA... other than using a frying pan, don't see how it could be done at home). Hmmmm.... thanks SiliconWizard, that's a great suggestion.  :-+

I use VGA (or composite) for this retro stuff because retro machines just look weird on LCD displays generally and I have a lot more monitors with VGA and only a couple things with HDMI. It's also a lot easier to wire VGA.

I wonder what happened to Grant Searle's website? I have a lot of the code stashed away but there was a ton of cool stuff on there.

True, VGA was my original intention when I started this post, but having had HDMI suggested as not being impossible, I think it'd be far more future-proof to use that instead.  I'm concerned VGA is diminishing in popularity these days - it will only get harder to get hold of TVs / monitors with VGA inputs, and whilst I've built a 'retro' computer, I'm trying to keep in mind future availability of parts (partly hence the move to SMT components as some are like gold dust in DIP form).

Grant's site seems to have been deleted, according to the site message - so it doesn't look like the domain has expired, it looks more like an intentional removal of the site.  :-//

EDIT:

I made a mistake - the LX4 is NOT available in TQFP, only BGA or wafer, which means I can't use it unfortunately (my SMT-soldering-fu isn't that strong!)  At least, not unless I find a PCB manufacturer who is willing to solder it to the PCB for me as part of the fabrication process.  I tend to use JLCPCB, so I've contacted them to find out if they will do it as part of their new SMT-assembly service.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 18, 2019, 09:52:40 am
With a FPGA you can go as far as you want to go. You can just implement a RAM buffer that gets drawn to the screen if that's what you are after. But you can then add on things like hardware graphics acceleration if you want to have the graphics seen on the 16bit game consoles back in the day. Sound can also be implemented in the same FPGA giving you emulation of the popular chiptune or FM synthesizer chips.

But if you just want to output video from a RAM framebuffer then you can get something like the Solomon Systech SSD1963 in a LQFP128 package:
https://www.buydisplay.com/download/ic/SSD1963.pdf (https://www.buydisplay.com/download/ic/SSD1963.pdf)

While it is called a "LCD Display Controller" its actually outputting a RGB video bus that can be turned into VGA via a DAC or into HDMI via a RGB to HDMI converter chip. The input to it is just a memory bus so you connect it to your Z80 in the same way you would connect SRAM or any other peripheral chip (Tho it is 3.3V so you might need level shifting). The framebuffer is internal inside the chip and it can run at up to 110MHz so any retro CPU will not be too fast for it. Its essentially a video card in a chip.

But the downside of using such a ready made solution is that it can't emulate anything else. So if you have existing software that expects to talk to certain video hardware then it wont work here, but replacing this chip with a FPGA lets you customize its memory mapping and registers in a way that mimics some existing video chip in some retro computer and allows the existing software to run on it.

In a way a FPGA is kinda cheating if you are after the genuine retro computer building experience. Having to breadboard 1 to 10 chips and running 10 to 100s of wires just to add some peripheral to your computers memory bus. But with a FPGA you just edit a few lines of code on your PC and load the new firmware into the FPGA and boom suddenly your computer has 3 extra GPIO ports and a PWM output. Few more lines of code and suddenly you also have a floating point coprocessor in your computer, some more core and you have a separate programmable DSP core in there too. Need more grunt? Okay copy paste 3 more of those DSP cores to now have a quad core DSP on the bus. Doing the same in the 80s would requires a few suitcases worth of boards hanging off your computer, these days its just adding some more code into a FPGA chip sitting on the bus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Canis Dirus Leidy on October 18, 2019, 10:07:06 am
Yes, 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.
And also a programmable palette (in combination with bit planes video RAM ) made life somewhat easier for a programmer, when your target machine (https://zx-pk.ru/content/136-Vektor-06C-sovetski-bog-tcveta-i-zvuka) don't have hardware sprites:
[attach=1] [attach=2] [attach=3]

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.
*cough* MSX (https://www.chibiakumas.com/z80/msx.php) *cough* This standard explicitly prescribed that all access to video memory should be made only through the ports of the video controller.

Part of the reason for this post was to discuss the best way to interface the FPGA with the computer - frame buffer in computer RAM, or gated via the FPGA, for example.  Both have positives and negatives, I just don't have the knowledge or experience to understand their weight and balance the options properly, if that makes sense?
Well, if you look at PC video chips from EGA/VGA/Early SVGA era (like GD542x family (http://www.s100computers.com/My System Pages/VGA_16_Board (Cirrus)/GD542x Technical Reference Manual.pdf) or ET4000 (http://bitsavers.informatik.uni-stuttgart.de/components/tsengLabs/Tseng_Labs_ET4000_Graphics_Controller_1990.pdf)), you will see that video memory was actually isolated from CPU bus. All that the processor could see was an intermediate buffer and translation logic, creating the illusion of direct access to video memory.

P.S. And talking about resistor-based DACs. Little Chinese trick:
[attach=4]
Instead of R-2R ladder he (or she, or whatever) used SMD resistor arrays for making binary weighted resistors values.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 18, 2019, 10:19:44 am
I use VGA (or composite) for this retro stuff because retro machines just look weird on LCD displays generally and I have a lot more monitors with VGA and only a couple things with HDMI. It's also a lot easier to wire VGA.

My Sonoko project uses three VGA LCD-screens, a VGA service card, and a VGA KVM. NEC VGA LCD-screens are 17inc and were bought new. Personally, I do not like HDMI because it consumes too much bandwidth on wires and on the circuit, and products are even more expensive. The HDMI KVM version costs double, cabling is much more expensive. This is a premium if you are on super modern technology, and e.g. the Advoli TA6 is a PCIe GPU card with nothing but HDMI via LAN outputs, but ... this stuff is a no-way unless you are in business with a squad of engineers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 18, 2019, 02:49:33 pm
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.

The CPU runs at 8 MHz (or 4 MHz, if you want to experience true 80's CP/M!).  So you think there would be no noticeable slow-down if I were to shut down memory access for ~73% of the time while the FPGA is accessing the frame buffer to draw the visible area of the screen?  To me, knowing little about this sort of stuff, that equates to slowing the computer down by almost three quarters?

Well, nope. The interleaving suggestion implied that the RAM would actually be accessed faster, so the CPU wouldn't see a difference. To pull that off, you would of course need a fast enough RAM (which should be no problem with a modern SDRAM chip or even SRAM), and clocking the MMU faster. Also, to keep things simple, you'd have to have the CPU and video clock frequencies multiple.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 18, 2019, 04:40:14 pm
If you want to play with (crude) graphics hardware, have a look at some of the early arcade games I've done.

https://github.com/james10952001

I've made them quite modular so you can easily mix & match pieces. The old Atari B&W games are cool because the video hardware is entirely independent of the CPU which just writes into RAM and then the hardware continuously reads these RAM locations and uses them to address object ROMs that result in objects on the screen. Originally this used standard SRAM with data selectors but in some of these I just made it dual ported RAM which makes it super easy to "wire" it up to whatever CPU you want. The object ROMs are easily customized as well to display whatever characters you want, and the schematics for the original hardware are readily available. Hack away.

I should add that these are all targeted to the same $12 FPGA board that Grant used, and in fact if you poke around there's a PCB in that repository for a daughter board that plugs right into that FPGA and has sockets for RAM, keyboard, micro SD, etc.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 18, 2019, 07:02:29 pm
With a FPGA you can go as far as you want to go. You can just implement a RAM buffer that gets drawn to the screen if that's what you are after. But you can then add on things like hardware graphics acceleration if you want to have the graphics seen on the 16bit game consoles back in the day. Sound can also be implemented in the same FPGA giving you emulation of the popular chiptune or FM synthesizer chips.

Hmm.. if I can get an AY-3-8910 implementation up and running on the same FPGA as the graphics, that'd be great and save me a lot of kerfuffle with the sound card using a genuine chip, which I'm having timing problems with at 8 MHz at the moment.

On that note, I'd like to include a keyboard handler as well - the thought crossed my mind that I might actually be able to include a USB host (or USB-to-go, at least), so that I could plug a USB keyboard in without having to depend on dwindling supplies of PS2 keyboards.  A quick search earlier showed me that an IP is available for USB-to-go for the Spartan, but looks like it could be costly to buy/licence.

...But the downside of using such a ready made solution is that it can't emulate anything else. So if you have existing software that expects to talk to certain video hardware then it wont work here, but replacing this chip with a FPGA lets you customize its memory mapping and registers in a way that mimics some existing video chip in some retro computer and allows the existing software to run on it.

You're right, using an FPGA is cheating - but I might take a look at the video chip you mentioned as an alternative.  My system is highly modular, so I could develop an FPGA-based video/sound/keyboard card AND one based on separate and more authentic discrete chips for those features and leave the choice of which they'd prefer to the person building the system.
[/quote]

And also a programmable palette (in combination with bit planes video RAM ) made life somewhat easier for a programmer, when your target machine (https://zx-pk.ru/content/136-Vektor-06C-sovetski-bog-tcveta-i-zvuka) don't have hardware sprites:
(Attachment Link) (Attachment Link) (Attachment Link)

Спасибо - I wish my Russian was better and I could read the writing, but I think I get the idea.

*cough* MSX (https://www.chibiakumas.com/z80/msx.php) *cough* This standard explicitly prescribed that all access to video memory should be made only through the ports of the video controller.

Yes, a friend of mine has been recommending I look at the MSX architecture for tips, I'm starting to see why now.  So passing data via IO calls to the FPGA is a viable proposition then.  I can see this method being quite useful for things like clearing the screen, or drawing rectangles and other basic shapes using only a handful of IO instructions.  I'm going to have to give some serious thought to what sort of instructions I'll want to implement in the video controller.

A gold-standard outcome for me would be to create a video controller that enables my computer to produce graphics for half-decent games.  Initially I see things like Pong and Breakout being easy enough, but I'd like to simulate the kind of 80's games that were commonplace on the 8-bit systems of the day.  As the 80's computers I'm familiar with all used interleaved memory frame buffers, so I'm assuming these sorts of games would still be possible using the MSX method, as the MSX managed it?

Well, if you look at PC video chips from EGA/VGA/Early SVGA era (like GD542x family (http://www.s100computers.com/My System Pages/VGA_16_Board (Cirrus)/GD542x Technical Reference Manual.pdf) or ET4000 (http://bitsavers.informatik.uni-stuttgart.de/components/tsengLabs/Tseng_Labs_ET4000_Graphics_Controller_1990.pdf)), you will see that video memory was actually isolated from CPU bus. All that the processor could see was an intermediate buffer and translation logic, creating the illusion of direct access to video memory.

Yes, I figured having a buffer would be helpful as the FPGA may not be able to access the frame buffer immediately on receipt of a command without causing tearing.  I'm still not 100% convinced I fully understand how it'll work with the Z80 sending commands/data to the FPGA via an IO port, but I'm sure I'll get my head around it at some point.

CP/M was designed to use VT100 and VT220 terminal, hence the FPGA needs to implement a simple VDU, or the SOC needs to implement a simple serial link with a decent FIFO to use an external VT100.

Yes, I'm intending to emulate the VT100 terminal and handle ANSI-escape codes in the video controller.  Grant's Multicomp VHDL does a good job of that already.

Well, nope. The interleaving suggestion implied that the RAM would actually be accessed faster, so the CPU wouldn't see a difference. To pull that off, you would of course need a fast enough RAM (which should be no problem with a modern SDRAM chip or even SRAM), and clocking the MMU faster. Also, to keep things simple, you'd have to have the CPU and video clock frequencies multiple.

You mean the FPGA would read the 'frame buffer' in the Z80's logical memory space into an internal buffer really quickly, then pass that out as a pixel stream?  Otherwise surely the frame buffer would be sending data at the rate the screen mode requires, which means 73% of the time it would be sending data and locking the Z80 out?  Not sure I understand this fully.

If you want to play with (crude) graphics hardware, have a look at some of the early arcade games I've done.
...Hack away.

Ah thanks for that james_s - will take a good look over the weekend. :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 18, 2019, 07:39:32 pm
I guess my motivations may be hard to understand for some
I understand it and respect it, even if I don't personally feel the attraction (anymore).

To paraphrase an old proverb, maybe Daoist, "The man who knows no stories is a fool. The man who knows many stories is wise. The man who knows one story is dangerous." The Old Ones have bequeathed many useful stories to us through their artifacts. I urge you to look at what other designers were doing in the 1980s when tasked to write a display engine. Even a close reading through the programmer's manual of some of these older systems will give you some flavor of their concerns and the clever tricks they used to get (then) high-performance video out of (today) low-performance hardware while holding to an accessible price point.

But you have to know your medium before you can create a useful artifact. Digital design is not a qualitative discipline. There is no substitute for looking at timing diagrams and characteristics tables, establishing cause and effect, looking up propagation delays, and doing the sums. For example,
Quote
no noticeable slow-down if I were to shut down memory access for ~73% of the time while the FPGA is accessing the frame buffer to draw the visible area of the screen
isn't a very useful question. The better question is, how much slowdown would there be if...? To reckon that, we have to look at the Timing section of the Z80 CPU User Manual, UM0080. For example, if you look at the instruction fetch cycle you'll see that the last 2T of the M1 cycle is spent "refreshing", where the Z80 doesn't care what's on the bus but still drives some of the address pins as a convenience to users of then-new DRAM, and that the Z80's proper business is done at the end of T2. We also know that our memory system can service instruction reads in 2T, and that, if we are using SRAM or a DRAM controller that handles its own refresh, the Z80's refresh cycle is wasted time. What if we simply disconnect those pins from the data bus at T3, hold the read value in a latch for the convenience of the Z80, and let other hardware access the bus instead? You just found a £10 note in the sofa cushions, depending on what kind of deal your company was able to score on DRAM. :)

Back to cases. Having written out some ins and outs, you might then look at I/O read and write machine cycles, and see that they are 4T in length. For I/O writes, we see that all address, control, and data of interest are available in T2. If all our devices are fast enough to have completed the write by the end of T2, we can just disconnect the Z80 from the bus and let the system bus free for other business during TW* (third beat) and T3 (fourth beat). For I/O reads, we see that all the address and control are once again available in T2, but the CPU doesn't read the data until the second half of T3. So, again assuming that our devices are fast enough, we will have our read data by the end of T2 and need only hold it for the CPU through TW and T3. We can then unhook the Z80 from the bus at the end of T2 and go about our other business. Cool, another £10 in the cushions!

Now we look at loads and stores. We see that memory write cycles are 3T in length, and that our snappy little jig has become instruction-dependent math rock. But [attachimg=1]! The Z80, like most other processors of the time, allows bus cycles to be stretched to accommodate slow hardware. We can insert one TW to lengthen the cycle to 4T and keep the rhythm, taking note of the penalty in order to answer our original question. Having done that, we look again at the memory write cycle and see that data and address are valid by the end of T1, but the !WR signal isn't valid until the end of T2. We can assume by the end of T1 that, if !MREQ is asserted and !RD is not, !WR will be asserted by the end of T2, and prepare accordingly. The rest of the write cycle follows that of I/O out cycles with the exception of the wait state we inserted, and we can likewise disconnect the CPU from the bus for TW and T3 without the Z80 any the wiser. £10! As for loads, we see that they too are 3T in length, so to keep the rhythm let's add the wait state and mark the penalty. Looking at our extended read cycle, we once again see that data isn't sampled until the end of T3 (fourth beat, as TW was inserted as the third beat). If our memories are fast enough, we can sample the data at the end of T2 just as we did for the I/O and hold it for the CPU, while we unhook the CPU from the bus and use the last 2T for our own business. £10!

Finally let's look at the interrupt request/acknowledge cycle, which is at minimum 5T long, and now we've gone to playing experimental jazz. But we will know what kind of cycle it is by the end of T1, and know it is an interrupt if we see !M1 asserted and neither !MREQ nor !IORQ asserted. In our system design we have a decision to make: do we want to pass the vector cycle through to the system bus, or handle it off the system bus? If you pass it through, you can treat it much the same as any other memory read cycle but generate the !WAIT signal and hold the received vector for 5T longer than otherwise, which we will mark into the penalty column. If you prefer to handle it off the system bus, you do the same with the !WAIT signal but disconnect the CPU from the bus and supply the vector by your choice of means. Your call. In either case, to keep the rhythm we have to stretch the interrupt cycle out to 8T. A 50p coin is better than nothing. ;D The NMI cycle is just a dummy instruction fetch with a runt pulse on !MREQ in T3 which we can ignore because the CPU would be off the bus anyway. £1!

The overall effect, then, is that we have introduced some ancillary logic to the Z80 so that it can vacate the system bus for 2T out of every 4T, at the cost of memory access by the CPU taking 14.3% longer than theoretically possible, and a modest hit to interrupt latency which in practice may not mean all that much. In doing so we have saved millions of RAM chips and tens of millions of pounds. Going a little bit out of brief, while the video system is not actively fetching frame buffer data, its 2T cycles could be borrowed to service other peripherals, for example, to buffer up sprite data, service disk controllers, or output PCM audio. Going very far afield, it may be evident that, instead of display DMA, we could place a second Z80 with much the same ancillary logic, sync them up, and have them both run at nearly full speed out of the same memory and I/O space, with the usual caveats about multiprocessing. If you were feeling especially naughty, you could pull the wool over the second CPU's data lines and feed it NOP instructions while exploiting its program counter as an address generator for the video output (beware, people have been knighted (https://en.wikipedia.org/wiki/ZX81) for doing this sort of thing).

Quote
Part of the reason for this post was to discuss the best way to interface the FPGA with the computer - frame buffer in computer RAM, or gated via the FPGA, for example.  Both have positives and negatives, I just don't have the knowledge or experience to understand their weight and balance the options properly, if that makes sense?
The word salad I wrote above is a walk through the sort of thinking the Old Ones utilized in many of the 1980s home computer designs, starting with the need to compete vigorously on both BOM cost and performance. The IBM PC, coming from its mainframe background and the culture of modularity, could not engage in this level of coupling. Either approach is certainly feasible. Which one is more desirable is a systems-level decision that depends, in part, on the desired display size and depth, and in turn the desired pixel rate, but also on cost, code size, flexibility, programmer convenience, and so on. "Better than the Amstrad" is an open-ended brief that could encompass anything from the tightly-coupled home computer systems as napkin-designed here, to an ISA bus bridge to a CGA/VGA/EGA/Hercules card rescued from the scrap pile. In any case, there will be side effects which you also have to pursue down the line and decide to live with for your application.

Oh, if you want to play USB host, the SL811HS is a classic choice, which incidentally can also be configured as a device should you wish to link your system to your PC. Be advised that USB HID can be a bit of a hairball.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 18, 2019, 08:09:10 pm
You are worried a bit too much about the FPGA implementation of the memory, framebuffer and access methods.

A lot of the retro ways of doing things in 80s computers are optimizations to get the thing working with as few chips as possible that containin as few transistors as possible in order to make a cost effective computer that a home user could afford. But modern FPGAs are rather large so keeping down the number of gates is not so important while you can now cheaply buy a few megabytes of SRAM with 10ns access time (So a max clock speed of about 100 MHz). This means such optimization tricks to reduce transistor count and memory usage are not required to make the design fit into a reasonably sized FPGA.

So if you connect all your components to the pins of a FPGA you can implement your graphics card in any way you like. The block RAM inside FPGAs is naturally dual port anyway and allows being written to at the same time as its being read out of and can typically run at >100MHz. This means you can implement access to the memory in any way you wish. Infact it would be perfectly possible to have 8 of those Z80s talking to the same RAM inside the FPGA simultaneously, doing read/write access to the same memory locations and all at the full 8MHz speed on each Z80. Due to external modern SRAM having 10ns access times the same is possible even withe external memory chips. But since you have only one Z80 this means that 90% of the available memory bandwidth is left unused and so can be utilized by any of the video or graphics acceleration hardware built in the FPGA without slowing down the Z80 at all.

So just pick whatever graphics architecture you would like to have and implement it in the FPGA. You can also implement multiple ones at the same time, like have a register command based interface and memory mapped simultaniusly, or have multiple modes like PC graphics cards do where you get various text or graphics modes that provide different advantages (Some provide lots of resolution and colors, some very few but take less CPU horsepower to use).

That being said the modern way of handling graphics acceleration in PCs is in the form of "draw calls". The GPU memory is available to read/write from the CPU as it wishes, but GPU memory tends to be in physically separate memory chips for speed reasons, so the GPU just forwards the read/write operations trough to its memory. Then the way that the GPU is made to do work is that the CPU places a list of things to do into its memory, each item on that list is a draw call and its a structure containing information of what you want the GPU to do ranging from "Set pixel 23,500 to color 255,255,255" to "Draw bitmap located at 0x554600 (512x512 RGBA 32bit) into framebuffer at coordinates 84,46 with alpha blending enabled" to "Apply the matrix transformation [0.45,1,1,0,5.4,5.5 .....] to the array of 16384 points in XYZ located at 0x7755000" to "Load the shader script bytecode at 0x5477400 into 128 shader units and run in parallel on the entire framebuffer" and so on and so on.... This list can be as long as you like and is typically built these days by a API like OpenGL or DirectX with the help of the graphics drivers. Once this "cooking recipe" structure is in the GPUs memory it is told to execute it and the GPU will run along on on its own without the CPUs intervention and some miliseconds later the delicious resulting image will be sitting there in another location of video memory. If the video output hardware is also pointing to that location in memory as its framebuffer than the image will also be sent out via HDMI so that your eyes can also enjoy the delicious image the GPU has baked for you.

This draw call approach is by far not the only solution to doing this, but its a solution that fits well on modern computers because the CPU can just throw this few kilobyte large "cooking recipe" and go do something more important while the GPU independantly works hard on baking the recipe without hogging any of the CPUs resources.

Obviously implementing all the draw calls of a modern graphics card is an insanely huge task, but in order to get some impressive graphics going you only need a few simple ones. Things like filling a rectangle with a single color or drawing one bitmap on top of another bitmap, perhaps also with transparency effects and alpha blending. Later on you might want to add support for 2D transformation matrices as that requires little hardware but lets you implement the stuff that for example the SNES can do in Mode 7. All of this can result in graphics that surpass the 16bit console era because you have a unfair advantage of having 10 times more memory bandwidth than they did. But for 8bit games what you will find the most useful is tilemap and sprite support since this requires very little data to be manipulated by the slow CPU, so its very fast even on wimpy old chips.

Oh and you want to avoid things like USB. Yes you can get a USB host IP module for a FPGA but that will only implement the actual USB port and its transfer protocol (glorified UART), it still needs the higher level protocols that initialize USB devices and drivers to talk to them. This will need a CPU to handle, so you will likely end up with a softcore CPU inside your FPGA that's actually more powerful than the Z80 itself, sitting there to run drivers for USB devices. If you want mouse and keyboard stick to the simple PS/2
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 18, 2019, 09:56:46 pm
For example, if you look at the instruction fetch cycle you'll see that the last 2T of the M1 cycle is spent "refreshing"...
The overall effect, then, is that we have introduced some ancillary logic to the Z80 so that it can vacate the system bus for 2T out of every 4T, at the cost of memory access by the CPU taking 14.3% longer than theoretically possible, and a modest hit to interrupt latency which in practice may not mean all that much...

I suspect I'm going to be reading and analysing what you've written here for months to come.  :o  But from what I can gather, there's the opportunity to steal cycles from the Z80 and open the address and data buses up to peripherals (like the video controller) whilst the Z80 is pausing for breath in the middle of its memory/IO cycles?  That's some major optimisation!!  Did you design these systems back in the 80's?

(beware, people have been knighted (https://en.wikipedia.org/wiki/ZX81) for doing this sort of thing).

Haha - yes, I'm aware there's quite a few hacks in the old Sinclair ZX80 and ZX81 (and even in the later Spectrums, I believe) to get them to display video inbetween reading the keyboard, or something? I remember there being a reason why the screen blanks out when you press a key...

Either approach is certainly feasible. Which one is more desirable is a systems-level decision that depends, in part, on the desired display size and depth, and in turn the desired pixel rate, but also on cost, code size, flexibility, programmer convenience, and so on. "Better than the Amstrad" is an open-ended brief that could encompass anything from the tightly-coupled home computer systems as napkin-designed here, to an ISA bus bridge to a CGA/VGA/EGA/Hercules card rescued from the scrap pile. In any case, there will be side effects which you also have to pursue down the line and decide to live with for your application.

That's really what I wanted to know - is there some big reason NOT to go for one approach over another.  I'm thinking for the sake of simplicity, I'll go with the Z80 only having a simple IO connection to the FPGA.  At least in the first instance - I can always change to an alternative method of interfacing later if the need arises, I guess.

Oh, if you want to play USB host, the SL811HS is a classic choice, which incidentally can also be configured as a device should you wish to link your system to your PC. Be advised that USB HID can be a bit of a hairball.

Well, I'm aware there's a significant software overhead due to the vast range of HID devices - I would literally just be looking for basic keyboard reading - but perhaps I'll have to stick to PS2 then.

You are worried a bit too much about the FPGA implementation of the memory, framebuffer and access methods.

I guess this stems from my lack of experience with FPGAs.  I'm learning quite quickly from this forum that FPGAs are actually blisteringly fast and flexible beyond belief - at least to my inexperienced mind.  :scared:

So if you connect all your components to the pins of a FPGA you can implement your graphics card in any way you like. The block RAM inside FPGAs is naturally dual port anyway and allows being written to at the same time as its being read out of and can typically run at >100MHz. This means you can implement access to the memory in any way you wish. Infact it would be perfectly possible to have 8 of those Z80s talking to the same RAM inside the FPGA simultaneously, doing read/write access to the same memory locations and all at the full 8MHz speed on each Z80. Due to external modern SRAM having 10ns access times the same is possible even withe external memory chips. But since you have only one Z80 this means that 90% of the available memory bandwidth is left unused and so can be utilized by any of the video or graphics acceleration hardware built in the FPGA without slowing down the Z80 at all.

And that's exactly the kind of answer I needed - perhaps I have been overly concerned about the speed of the design, but that's born out of a lack of knowledge.  I did admit that I'm no expert in this field and have been learning as I've gone along.  ;D  So basically, I should just crack on with my preferred design and see how it goes.  These FPGAs are so fast and flexible that most of the magic will be done in the VHDL?


This draw call approach is by far not the only solution to doing this, but its a solution that fits well on modern computers because the CPU can just throw this few kilobyte large "cooking recipe" and go do something more important while the GPU independantly works hard on baking the recipe without hogging any of the CPUs resources.

This was one of the possible options floating around in my head for the IO-based interface.  The Z80 could just send a load of commands and data to the FPGA which would buffer it into a FIFO (if needed - the FPGA will likely not need to buffer much as it's so much quicker, I'm guessing) and the FPGA would perform operations on those commands into the frame buffer whilst it's being read and streamed to the output by the video signal generation part.  That's the other thing I need to remember about FPGAs - they're not one computation block, all their components run in parallel with each other.

Obviously implementing all the draw calls of a modern graphics card is an insanely huge task, but in order to get some impressive graphics going you only need a few simple ones. Things like filling a rectangle with a single color or drawing one bitmap on top of another bitmap, perhaps also with transparency effects and alpha blending. Later on you might want to add support for 2D transformation matrices as that requires little hardware but lets you implement the stuff that for example the SNES can do in Mode 7. All of this can result in graphics that surpass the 16bit console era because you have a unfair advantage of having 10 times more memory bandwidth than they did. But for 8bit games what you will find the most useful is tilemap and sprite support since this requires very little data to be manipulated by the slow CPU, so its very fast even on wimpy old chips.

Absolutely - I think this will be the biggest area for development then.  The actual architecture of the graphics card sounds like it will be really simple, aside from level converters for the 5v to 3v3 and some basic IO address decoding, there will be little else other than the FPGA and HDMI output.  In fact, I suppose there's no reason why I can't integrate the IO address decoding into the FPGA as well?  This is getting easier by the minute!  ;D

Oh and you want to avoid things like USB. Yes you can get a USB host IP module for a FPGA but that will only implement the actual USB port and its transfer protocol (glorified UART), it still needs the higher level protocols that initialize USB devices and drivers to talk to them. This will need a CPU to handle, so you will likely end up with a softcore CPU inside your FPGA that's actually more powerful than the Z80 itself, sitting there to run drivers for USB devices. If you want mouse and keyboard stick to the simple PS/2

 :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 19, 2019, 12:20:09 am
If you want to learn how to design a computer system from the ground up, start designing your own RISC-V RV32I core. It's got only 37 instructions (if I can count lol), and there is a full-blown gcc compiler for it, so you can use real-deal C/C++! Once you have a core, you can start designing peripherals and figuring out how to connect them to the CPU bus, than at some point you will realize you need DMA controller to send data around without CPU involvement - this will force you to implement a multi-master bus so that peripheral can do bus mastering as well as the CPU core, etc. There is almost no limit to how far you can go with this - implementing multi-core system, adding support for external expansion buses (like PCI, or PCI Express), and so on!

For video I really recommend using HDMI because it's so ridiculously easy to implement in its most basic form (RGB-24bit output, video-only), and lower resolutions aren't very taxing on FPGA performance-wise or layout.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 19, 2019, 12:31:47 am
Just wanting to be clear... Most people are talking about implementing DVI-D, not HDMI, even though they use the same physical architecture and low-level coding scheme. True HDMI is a step up, and involves adding data islands, audio, BCH codes and so on...

Best reference documents for DVI-D are the Digital Display Working Group's specifications.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 19, 2019, 03:46:44 am
I suspect I'm going to be reading and analysing what you've written here for months to come.  :o  But from what I can gather, there's the opportunity to steal cycles from the Z80 and open the address and data buses up to peripherals (like the video controller) whilst the Z80 is pausing for breath in the middle of its memory/IO cycles?  That's some major optimisation!!
You do have the gist of it correct. You don't need to pay too much mind to the ramblings of an animated professor in a lecture. Try a drier summary: a system bus, designed for 2T bus cycles, can be time-multiplexed into 4T frames of two fixed time slots, each 2T long (one bus cycle). Each slot is dedicated to an independent master(s), each slot which may perform up to one bus cycle every frame. You can place some glue logic between the Z80 bus (or any other master(s) of your choice) and the system bus to connect/disconnect the master's address, data, and control signals to/from the bus at the beginning/end of its time slot, to smooth over timing differences between the 2T system bus and the Z80's 4T cycles, to hold data received from the system bus until the master is ready for it, and to keep the Z80's machine cycles synchronized with its time slot. The 1980s-era home computer, in 127 words.

If you're a visual learner, print out and clip out the timing diagrams from the Timing section of the Z80 data sheet and lay them on a table, with each start of T1 aligned vertically. Use another sheet of paper to cover from the end of T2 onward and observe that you have enough information to start a cycle. Have scissors handy to cut the memory cycles at the beginning of T3 and introduce one TW of space between. Print/cut out another set, maybe in a different color, and lay them out offset by 2T from the first set. Shuffle them around and examine the interplay.

Quote
Did you design these systems back in the 80's?
No, I was just a boy at that time, but I gave one of the Amiga designers a ride to San Francisco once. :)  I did have a few of those 8-bit machines and a couple of 16-bit machines, and fell in passionate, enduring love with PEEK and POKE. I followed the demo scene for a bit later on, even tried to write a few screens that turned out nothing to write home about.

Quote
That's really what I wanted to know - is there some big reason NOT to go for one approach over another.  I'm thinking for the sake of simplicity, I'll go with the Z80 only having a simple IO connection to the FPGA.  At least in the first instance - I can always change to an alternative method of interfacing later if the need arises, I guess.
You would need to design the multiplexed bus into the system from the beginning. There's always the next machine, right? >:D  If you're using private, single-ported frame buffer RAM, the video system doesn't master the system bus, so time-multiplexing the system bus would be a needless complication, especially if there is already a "normal" DMA controller in the system. Time-multiplexing may still be useful on the private frame buffer side, to arbitrate between the pixel serializer, the graphics coprocessor, and the system bus interface. As powerful as FPGAs are, they're not quite quantum computers and there will still be single resources that must be shared by multiple clients. DRAM chips, even with their multifarious burst modes, still take a moment to close a row and open a new one.

I will call your attention to the timing diagrams for memory vs. I/O accesses, and point out that I/O accesses are 1T longer than memory accesses, by design. That may add up when moving a lot of data from system memory to the frame buffer without DMA. I'll also point out that there are 16-bit load/store instructions which save one or two instruction fetches for every two bytes, and may be more convenient (and faster) for programming, but there are no 16-bit I/O instructions as far as I can tell.

Since you do have the full address bus at the FPGA's disposal, and you prefer not to use a memory-mapped window into frame buffer RAM, I offer the idea of mapping individual registers into a 4kB or so block of address space rather than using a single command/data register pair.

Quote
Well, I'm aware there's a significant software overhead due to the vast range of HID devices - I would literally just be looking for basic keyboard reading - but perhaps I'll have to stick to PS2 then.
Fair enough. You can add-on USB later if one day you happen to wake up really ambitious and feel like porting code from MSX USBorne project :)  For the SL811HS you need only two addresses in I/O space, eight data lines, and the usual bus handshaking signals, which could fit very easily on an expansion board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 19, 2019, 04:49:44 am
Just wanting to be clear... Most people are talking about implementing DVI-D, not HDMI, even though they use the same physical architecture and low-level coding scheme. True HDMI is a step up, and involves adding data islands, audio, BCH codes and so on...
Isn't all of that stuff optional? My memory on HDMI spec is rather rusty atm.
But whatever - the point is - it works, and fundamentally it's just a couple of counters and few comparators to figure out blanking areas - which incidentally you will need for VGA, the only difference is output SERDES. But on the other hand you get full 24bit color space to work with without a need for any sort of DACs (of which you'll need three for VGA - again if my memory serves me), and you need just 8 pins + few auxiliary ones like HPD and I2C channel, instead of a ton of pins to external parallel DACs. And you get a clear path for upgrade if you ever decide for it - this one is the most important for me (even more so that I'm working on DisplayPort module so that I can go up beyond FullHD).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 19, 2019, 07:19:37 am
I'll go with the Z80 only having a simple IO connection to the FPGA

With a physical Z80 cpu chip? at 5V? having the FPGA's IO at 3.3V?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 19, 2019, 07:43:22 am
Just wanting to be clear... Most people are talking about implementing DVI-D, not HDMI, even though they use the same physical architecture and low-level coding scheme. True HDMI is a step up, and involves adding data islands, audio, BCH codes and so on...
Isn't all of that stuff optional? My memory on HDMI spec is rather rusty atm.
But whatever - the point is - it works, and fundamentally it's just a couple of counters and few comparators to figure out blanking areas - which incidentally you will need for VGA, the only difference is output SERDES. But on the other hand you get full 24bit color space to work with without a need for any sort of DACs (of which you'll need three for VGA - again if my memory serves me), and you need just 8 pins + few auxiliary ones like HPD and I2C channel, instead of a ton of pins to external parallel DACs. And you get a clear path for upgrade if you ever decide for it - this one is the most important for me (even more so that I'm working on DisplayPort module so that I can go up beyond FullHD).

If it doesn't have video guard bands, TERC4 data islands and the data island that defines the display format it isn't HDMI, it's just DVI...

Let me know if you need a hand or advice with DisplayPort. A few years ago I knew the older spec backwards, and got 4k streams going on a few different boards... These might help:

https://github.com/hamsternz/FPGA_DisplayPort

https://github.com/hamsternz/DisplayPort_Verilog
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 19, 2019, 09:13:10 am
If you want to learn how to design a computer system from the ground up, start designing your own RISC-V RV32I core...

One thing at a time, asmi.  :o ;)

For video I really recommend using HDMI because it's so ridiculously easy to implement in its most basic form (RGB-24bit output, video-only), and lower resolutions aren't very taxing on FPGA performance-wise or layout.

Yes, I'm sold on HDMI and will be building with that end goal in mind.  Plus the Spartan 6 - my FPGA of choice, it seems - appears to have hardware support for HDMI in its IO blocks.

The 1980s-era home computer, in 127 words.

You make it sound so simple...  :o  ;D

No, I was just a boy at that time, but I gave one of the Amiga designers a ride to San Francisco once. :)  I did have a few of those 8-bit machines and a couple of 16-bit machines, and fell in passionate, enduring love with PEEK and POKE. I followed the demo scene for a bit later on, even tried to write a few screens that turned out nothing to write home about.

Oh wow - I loved my Amiga(s).  I had an A500+ and then upgraded to the A1200 with a hard drive when I went to university.  They were going to rule the world - then the PC happened.  ::)  PEEK and POKE were a couple of the first commands I created for my system's monitor program.  They were like dark magic back when I was a kid in the 80's.

I will call your attention to the timing diagrams for memory vs. I/O accesses, and point out that I/O accesses are 1T longer than memory accesses, by design. That may add up when moving a lot of data from system memory to the frame buffer without DMA. I'll also point out that there are 16-bit load/store instructions which save one or two instruction fetches for every two bytes, and may be more convenient (and faster) for programming, but there are no 16-bit I/O instructions as far as I can tell.

Well, I'll have to wait to get a prototype up and running to see the performance of the IO interface and decide if I need to look at something different.  I'm not a professional games programmer, so I'm not talking about blockbuster graphics, parallax scrolling and FMV when I talk about what I want from game graphics, but I guess it still waits to be seen what the interface will be capable of.  I'm aware that memory access is faster than IO access because of the extra commands and the additional WAIT state that the Z80 inserts into IO cycles, I'm just not sure how that will play out practically - I'm hoping the difference will not be noticeable.

Since you do have the full address bus at the FPGA's disposal, and you prefer not to use a memory-mapped window into frame buffer RAM, I offer the idea of mapping individual registers into a 4kB or so block of address space rather than using a single command/data register pair.

Let me make sure I understand this - any writes to the appropriate memory space would be picked up by the FPGA and read into internal memory which effectively shadows the system's memory 'window'?  Actually, that would be really useful to transport large amounts of data from the system into the GPU.  Rather than using a sequence of, say, (a minimum of) 64 IO writes to create a sprite in the GPU's memory, the whole thing could be copied into the RAM 'window' using the faster memory commands...

I'll go with the Z80 only having a simple IO connection to the FPGA

With a physical Z80 cpu chip? at 5V? having the FPGA's IO at 3.3V?

Yes, a physical Z80 at 5v and the FPGA at 3.3v.  I did mention earlier that I'd be level-shifting the voltages between the system and GPU, probably using 74LVC buffers or transparent latches or whatever, so don't panic.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 19, 2019, 09:50:40 am
Yes, a physical Z80 at 5v and the FPGA at 3.3v.  I did mention earlier that I'd be level-shifting the voltages between the system and GPU, probably using 74LVC buffers or transparent latches or whatever, so don't panic.  ;D

no panic, just, I did this stuff two years ago, and it consumed a lot of precious time, hence, reconsidering it, I have some regrets about my past choices. Anyway, I am not here to motivate or demotivate people, so do as you wish. Just, if I were in you, I would about to add extra chips on the PCB.

There are 3.3V Z80 compatible cores.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 19, 2019, 10:25:40 am
(https://jeelabs.org/img/2017/DSC_5808b.jpg)
Like this (https://jeelabs.org/article/1714b)  :D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 19, 2019, 05:22:18 pm
There are some CPUs, such as the 6800 for which there are not (at least not open source) any cycle-accurate softcores. The Z80 however already has more than one very well tested softcore that works just like the real thing, no need to have a real phyiscal Z80 in the mix if you already have the FPGA. The softcore can do everything the original can and much more if you wish.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 19, 2019, 07:49:11 pm
There are some CPUs, such as the 6800 for which there are not (at least not open source) any cycle-accurate softcores. The Z80 however already has more than one very well tested softcore that works just like the real thing, no need to have a real phyiscal Z80 in the mix if you already have the FPGA. The softcore can do everything the original can and much more if you wish.

Well, I'm building this GPU for a hardware Z80 system.  Whilst I appreciate that the FPGA could do everything my hardware system does, that's not the point of this little project.  Perhaps an FPGA is total overkill, though.

I've been looking a little more closely at the Spartan LX45 and it's looking less and less likely that I'll be able to use it, even if I could justify the cost.  I think BGA is a step too far for my soldering skills and equipment at this stage, and the sheer number of pins on those FPGAs will stretch my DipTrace licence past breaking point.  One way around it is to just use one the cheap development boards and plug that straight into my 'GPU card'.  Limited IO, but with the FPGA, SDRAM, clock and programming circuitry done for me...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: ledtester on October 19, 2019, 07:49:50 pm
You might be interested in the video chip being developed for the 8-bit guy's "Dream Machine":

(starts at 9:50)

https://youtu.be/sg-6Cjzzg8s?t=9m50s
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 19, 2019, 08:03:42 pm
Oh wow - I loved my Amiga(s).  I had an A500+ and then upgraded to the A1200 with a hard drive when I went to university.  They were going to rule the world - then the PC happened.  ::)  PEEK and POKE were a couple of the first commands I created for my system's monitor program.  They were like dark magic back when I was a kid in the 80's.
Excellent. That gives me a touchstone to explain some things by analogy. By the way, you didn't have anything important to do this weekend, did you? https://archive.org/details/Amiga_Hardware_Reference_Manual_1985_Commodore   >:D  :-DD

Just for interest, you may be aware there are HDL implementations of the Amiga OCS that might be imported directly into your design, with mimimal modifications. A Z80 driving the OCS chip set could make for a pretty wild experiment, even at 1/2 the memory bandwidth.

Quote
Well, I'll have to wait to get a prototype up and running to see the performance of the IO interface and decide if I need to look at something different. I'm not a professional games programmer, so I'm not talking about blockbuster graphics, parallax scrolling and FMV when I talk about what I want from game graphics, but I guess it still waits to be seen what the interface will be capable of.  I'm aware that memory access is faster than IO access because of the extra commands and the additional WAIT state that the Z80 inserts into IO cycles, I'm just not sure how that will play out practically - I'm hoping the difference will not be noticeable.
Digital design is still not a qualitative discipline ;) , but I'll bite anyway. 75% of theoretical bandwidth won't be much noticeable for relatively low-intensity usage like ping-pong or the like. But also see below.

Quote
Let me make sure I understand this - any writes to the appropriate memory space would be picked up by the FPGA and read into internal memory which effectively shadows the system's memory 'window'?  Actually, that would be really useful to transport large amounts of data from the system into the GPU.  Rather than using a sequence of, say, (a minimum of) 64 IO writes to create a sprite in the GPU's memory, the whole thing could be copied into the RAM 'window' using the faster memory commands...
That would be the memory-mapped window into frame buffer RAM I mistakenly believed you disfavored, but yes, I do think it's a very good idea. I'd also be sure it services reads as well. In fact, once it is servicing both reads and writes, you could make the window very large, like a megabyte give or take, and perhaps scrap the bank switching entirely. Then you have something very much like Amiga chip RAM, in that whatever memory isn't being used by the display can be used by the Z80 for general purposes and/or graphics...

But I was actually proposing that you memory- (or I/O-) map the control registers, using the system bus control/address/data signals to more or less directly read/write registers inside the FPGA and control the video hardware, analogous to the common idiom of using 74377 or similar ICs with suitable decoding as byte-wide input-output ports. C pseudocode:
Code: [Select]
const struct my_video_chip *video = 0xDFF000; /* ;) */
void setpalettecolor_reg(uint8_t index, uint8_t red, uint8_t green, uint8_t blue)
{
  video->palette[index].red = red;
  video->palette[index].green = green;
  video->palette[index].blue = blue;
}
void enabledisplay_reg()
{
  video->displayenable |= 1; /* SET 0, (HL) */
}

Quote
DipTrace
You could always switch horses to KiCAD. #justsayin
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 19, 2019, 08:15:30 pm
Well, I'm building this GPU for a hardware Z80 system.  Whilst I appreciate that the FPGA could do everything my hardware system does, that's not the point of this little project.  Perhaps an FPGA is total overkill, though.

I've been looking a little more closely at the Spartan LX45 and it's looking less and less likely that I'll be able to use it, even if I could justify the cost.  I think BGA is a step too far for my soldering skills and equipment at this stage, and the sheer number of pins on those FPGAs will stretch my DipTrace licence past breaking point.  One way around it is to just use one the cheap development boards and plug that straight into my 'GPU card'.  Limited IO, but with the FPGA, SDRAM, clock and programming circuitry done for me...

The LX45 is a very nice, very large (by hobby standards) FPGA, I would say that for what you are describing it is massively overkill. Just to put things in perspective, an entire 8 bit computer including the CPU (Grant's Multicomp for example) or any of the bronze age arcade games I've recreated fit comfortably within the ancient and tiny (by current standards) EP2C5T144C8 FPGAs which you can get ready to go on a little dev board for around $12. There is lots of middle ground too, if you want Xilinx the LX9 is an inexpensive and very capable part you can get in a reasonably hobbyist friendtly TQFP package. You can also interface a development board directly to your existing Z80 project and use that for prototyping and then once you have a design implemented that you are satisfied with you can look at the consumed resources and select a less expensive FPGA sufficient for your design and build more tidy custom hardware. One of the really awesome things about FPGAs is that it's very easy to make large portions of the code very portable, a lot of my learning was accomplished by porting projects I found from one platform to another.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: rstofer on October 19, 2019, 09:10:21 pm
It might be worthwhile to compare the capabilities of the XL45 and any of the Artix 7 devices, perhhaps even something as small as the 50T
https://www.xilinx.com/support/documentation/selection-guides/7-series-product-selection-guide.pdf (https://www.xilinx.com/support/documentation/selection-guides/7-series-product-selection-guide.pdf)
https://www.xilinx.com/support/documentation/data_sheets/ds160.pdf (https://www.xilinx.com/support/documentation/data_sheets/ds160.pdf)

I think even the Artix 7 50T has more resources than the XL45 and certainly the 100T which is becoming quite common completely dwarfes the XL45.  The 35T is somewhat smaller than the XL45 if that matters.

None of that resources stuff matters much when compared to the fact that the old Spartan 6 devices are not supported by Vivado and the ISE 14.7 version is the last release of ISE and it is no longer supported.  Yes, I still use it for my Spartan 3 projects but, for new stuff, I'm using the Artix 7 chips and Vivado.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: rstofer on October 19, 2019, 09:36:27 pm
Just for a checkpoint, I have the Pacman game running on a Spartan3E 1200 chip
https://www.xilinx.com/support/documentation/data_sheets/ds312.pdf (https://www.xilinx.com/support/documentation/data_sheets/ds312.pdf)
This is much smaller than the XL45
https://www.xilinx.com/support/documentation/data_sheets/ds160.pdf (https://www.xilinx.com/support/documentation/data_sheets/ds160.pdf)

Pacman rolls around like a BB in a bowling alley on that Spartan 3E in terms of logic, see attached PDF

There is a Z80 core, the graphics display and all of the IO pins and it fits easily in the 3E so it will darn sure fit in the XL45
Note, however, that over 2/3 of BlockRAM is used.  This is typical of most cores; we want a lot of RAM.  There a lot going on with the graphics and PROMs.

This is the board I chose to use.  It's pricey for what it was but at the time it was high end.
https://store.digilentinc.com/nexys-2-spartan-3e-fpga-trainer-board-retired-see-nexys-4-ddr/ (https://store.digilentinc.com/nexys-2-spartan-3e-fpga-trainer-board-retired-see-nexys-4-ddr/)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 19, 2019, 10:12:24 pm
Excellent. That gives me a touchstone to explain some things by analogy. By the way, you didn't have anything important to do this weekend, did you? https://archive.org/details/Amiga_Hardware_Reference_Manual_1985_Commodore   >:D  :-DD

Not now...  :popcorn:

Just for interest, you may be aware there are HDL implementations of the Amiga OCS that might be imported directly into your design, with mimimal modifications. A Z80 driving the OCS chip set could make for a pretty wild experiment, even at 1/2 the memory bandwidth.

Ooh, that sounds like the kind of Frankenstein experiment that just might bear some interesting and very warped fruit...  I wouldn't profess to have a tenth the skills required to do something like that, though.  Whilst I cut my teeth programming on the Amiga, it was with Blitz Basic more than anything else and I never got anywhere near the metal, as it were.

That would be the memory-mapped window into frame buffer RAM I mistakenly believed you disfavored, but yes, I do think it's a very good idea...

Well, I disfavoured the idea of a full frame buffer in the Z80's memory space, specifically.  It would have been prohibitively small and/or meant I would have to modify my (basic) MMU and system bus to accommodate multiple masters on the address and data buses.  That was a little further down the rabbit hole than I care to venture at the moment.  However, a simple shadowing of a small amount of memory (e.g. 4 KB as you suggested) into the FPGA would be easy enough to implement and require no modifications to the system buses at all.

I'd also be sure it services reads as well.

That would require some modification of the host system,  but it wouldn't be impossible I guess.  The easiest way for me to do that would be to keep one of the memory sockets empty, which would provide a 512 KB window that the FPGA could intercept the reads and writes to..  Half a meg would be more than big enough for a frame buffer for the resolutions I'm wanting to use, and would allow double-buffering on all the major screen modes if I was able to substitute that window for 512 KB of RAM on the FPGA via SDRAM, for example... hmmm... Tempting...

Using the SDRAM on the FPGA seems to me and my inexperienced mind to be a lot more complicated than using dual-port RAM in the FPGA itself.  Can anyone convince me otherwise?  If I can make use of the SDRAM easily, without any major drawbacks or slowdowns, then I needn't worry about using a big, expensive FPGA with lots of internal RAM...

But I was actually proposing that you memory- (or I/O-) map the control registers, using the system bus control/address/data signals to more or less directly read/write registers inside the FPGA and control the video hardware, analogous to the common idiom of using 74377 or similar ICs with suitable decoding as byte-wide input-output ports.

I thought that was what I was intending to do previously?  My plan was to use IO port calls to address registers in the FPGA?

Quote
DipTrace
You could always switch horses to KiCAD. #justsayin

Oh I've had this discussion with others before.  When I first dipped my toes in the waters of electronics a couple of years ago, to start looking at documenting the tweaks and changes I was making to Grant's simple breadboard computer designs, I tried using KiCAD.  The experience left me comparing it to older versions of Blender.  If you don't know your 3D graphics software, Blender is an open-source 3D software program that can produce professional-quality 3D models, renders, even films and games.  The power it has under the hood is amazing.  But the UI cripples it and puts up an almost vertical learning curve before you even try to do anything.

KiCAD is like that for me - I just cannot get on with it, can't commit the time to learn it.  I found myself spending more time looking up how to do simple things and create patterns for components that weren't there, that I searched around and found DipTrace.  Yes, I'm limited to 500 pins per schematic for DipTrace (I'm on a free 'hobby' licence), but it's so damn easy to use and makes wonderful PCB designs with none of the complexity of KiCAD that I've put up with the pin limit and it's only become a problem now, when I'm looking at FPGAs that potentially use up all that pin count with one part.  I've actually started using EasyEDA now for this GPU design and whilst setting up the schematic is okay, I'm dreading designing the PCB...

The LX45 is a very nice, very large (by hobby standards) FPGA, I would say that for what you are describing it is massively overkill. Just to put things in perspective, an entire 8 bit computer including the CPU (Grant's Multicomp for example) or any of the bronze age arcade games I've recreated fit comfortably within the ancient and tiny (by current standards) EP2C5T144C8 FPGAs which you can get ready to go on a little dev board for around $12.

Well, the reason I'm looking at something as overkill as the LX45 is primarily for the RAM size.  I need something large enough to hold a frame buffer internally, so that it can be dual-ported and spit out a pixel stream whilst it's being written to (allowing for timed writes so as not to cause screen tearing, obviously).  Now, if someone can tell me that the FPGA could easily use an attached SDRAM chip for the frame buffer and be able to form a coherent pixel stream without slowing writes down so much that performance would suffer over the internal 'dual-port' design, then I'd be all for getting a smaller, older, cheaper FPGA to do the job.  For one, it'd be hand-solderable and easier to integrate into a custom card for my system and two, it'd probably fit within my 500-pin design limit so I could keep the design within software I am happy working with, so I can't over-emphasise how important a design 'win' an SDRAM frame buffer would be.

As it is, anything in a BGA form-factor will either require me to spend a fortune getting it assembled at point of manufacture and limit my choices to chips the PCB manufacturer offers, or restrict me to making an FPGA dev board socketable into my custom PCB for my system, which will cause headaches as it probably won't fit within my stacking PCB form-factor without modification (removal of power sockets from the dev board etc).

There is lots of middle ground too, if you want Xilinx the LX9 is an inexpensive and very capable part you can get in a reasonably hobbyist friendtly TQFP package.

Yes, I've been looking at this as the best Spartan 6 I can get in a TQFP package.  Will mean lower-res / less colours, but it'll still be within my design brief.

You can also interface a development board directly to your existing Z80 project and use that for prototyping and then once you have a design implemented that you are satisfied with you can look at the consumed resources and select a less expensive FPGA sufficient for your design and build more tidy custom hardware. One of the really awesome things about FPGAs is that it's very easy to make large portions of the code very portable, a lot of my learning was accomplished by porting projects I found from one platform to another.

Well, that's what I'll be doing initially - I'm waiting on an LX16 dev board to arrive from overseas.  I'll be connecting that up to my system via jumpers and a 74LVC-infested breadboard whilst I test the system and develop the VHDL for it.  Once it's done, like you say, I'm not restricted to only using it on LX16s...

I think even the Artix 7 50T has more resources than the XL45 and certainly the 100T which is becoming quite common completely dwarfes the XL45.  The 35T is somewhat smaller than the XL45 if that matters.

None of that resources stuff matters much when compared to the fact that the old Spartan 6 devices are not supported by Vivado and the ISE 14.7 version is the last release of ISE and it is no longer supported.  Yes, I still use it for my Spartan 3 projects but, for new stuff, I'm using the Artix 7 chips and Vivado.

I haven't looked at the Artix range - it's handy to note that Spartan 6's aren't supported in the latest development software, though - thanks rstofer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 19, 2019, 10:19:03 pm
(http://www.downthebunker.com/chunk_of/stuff/public/boards/fpga-sp2-150-gb-adv.jpg)
SP2-150, for GameBOY ADV

This one is 5V tollerant, and it's interfaced with a GameBOY ADV.

Is the FPGA 5v tolerant, or have you done the level conversions yourself?  I can't see much in the way of voltage conversion on those boards?

This was another thing that struck me when I start drawing up the schematic with the LX9 that I was unaware of before - it actually requires 3.3v, 1.8v and 1.2v (or similar, I'm running from memory)?

So I can't just run all the address, data and control lines from the Z80 side through some 74LVC components to translate them down to 3.3v?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 19, 2019, 10:42:34 pm
Is the FPGA 5v tolerant, or have you done the level conversions yourself? 

It was made this way because the FPGA is already 5V tolerant. Certain SP2 were, but starting from SP3 they are all 3.3V. The purpose was to simplify stuff, especially the PCB, which is very small.

Voltage level shifters are fine (2), but ... well, that stuff runs at 50Mhz, not so high speed, but enough to cause signal integrity issues(1), and thus requires more cure. There were a couple of bugs with my first batch of PCB. Then I redesigned them.

(1) Ok, today I own a decent MSO, debugging that stuff is easier than years ago.
(2) you can even use a 5V tollerant CPLD as voltage-adapter, it's a good trick, and it might help routing the the PCB. In my case, I used it to adapt 32bit data + 32bit address + 9bit control from a 5V CPU to 3.3V SP3-500. It was a must, because I realy *HATE* every 68020 softcore, hence I wanted an ASIC chip. Now I am using Coldfire v1, and they are already 3.3V. Easy life, less problems, more fun.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 19, 2019, 11:22:05 pm
Using a gigantic FPGA in order to get enough internal block RAM for a framebuffer is not the right way to go about it. Video cards have been using SDRAM and prior to that SRAM and even regular DRAM to implement framebuffers for many, many years. I'm not going to say that it's "easy" but one of the things SDRAM is specifically designed to be good at is pumping in/out blocks of data synchronously which is precisely what video is doing. Look at some video cards from the late 90s to mid 2000's, these are often made with discrete ICs and relatively easy to tell what's going on. Interfacing to external memory is one of the things FPGAs are optimized to do, they have lots of IO pins and some of them even have onboard dedicated SDRAM interfaces.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 20, 2019, 02:55:40 am
Using a gigantic FPGA in order to get enough internal block RAM for a framebuffer is not the right way to go about it. Video cards have been using SDRAM and prior to that SRAM and even regular DRAM to implement framebuffers for many, many years. I'm not going to say that it's "easy" but one of the things SDRAM is specifically designed to be good at is pumping in/out blocks of data synchronously which is precisely what video is doing. Look at some video cards from the late 90s to mid 2000's, these are often made with discrete ICs and relatively easy to tell what's going on. Interfacing to external memory is one of the things FPGAs are optimized to do, they have lots of IO pins and some of them even have onboard dedicated SDRAM interfaces.
Video cards are also known for requiring (and making good use of) very high memory bandwidth. But it just isn't possible in anything other than BGA packages, as it requires a lot of pins - even the very modest (by video card standards) 64-bit interface requires close to 100 pins to implement, but 128/256 bit interfaces are more popular, and even 512 bit ones are not unheard of. Moreover, most GPUs are modular and each submodule has it's own memory controller, so this requires even more pins to implement as each controller needs to have it's own set of address/command pins. For example RTX 2080 Ti has 11 memory controllers (it's actually the cut-down version of a die which has 12 memory controllers)!
Also since BGA packages provide signal integrity that is far superior to any leaded packages, DDR2 and up memory chips are only available in BGA packages.

Now, I personally love reasonable-pitch BGAs and always choose them over any other packages, but I know some people have some sort of anti-BGA religion, which is why I'm bringing this up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 20, 2019, 03:01:09 am
Are you forgetting that this is being built to work with an 8 bit Z80? I don't think it needs to be anything super fancy, there's no point in making the video card powerful enough to deal with more data than the host CPU is capable of sending to it. We're not talking about modern high power GPUs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 20, 2019, 07:40:59 am
Using internal block RAM in FPGAs has a range of advantages, so if a big enough FPGA can be had cheaply enough its a good idea to use it.

Firstly the internal RAM blocks are naturaly dual port and that often comes in usefull, then they are separate blocks that slot together like legos to build RAM of various sizes, so you can have multiple smaller memories that can be accessed in parallel rather than one big memory that everyone needs to get multiplexed to. This last part gives it an insanely high memory bandith too. For the DIYer probably the best of all that it doesn't need any external components and so zero pins to hook up.

But if you want lots of resolution and the ability to bitblit bitmaps around in the 'GPU' (You will need that on a 8bit CPU as that thing will be awfuly slow at pushing pixels around manualy) then you will need more RAM than you can get in reasonably priced FPGAs. The easiest option is SRAM since you just throw an address on its pins and the data shows up, and you can buy it up to about 8MB for a reasonable price. When the Z80 wants to access it you just switch over the CPUs memory bus to the SRAM pins and after its done switch it back to the GPU. Perhaps also add a latch on the bus so you can perform access to SRAM at full speed (~100MHz) and quickly return control back to the GPU while the latch holds the current memory translation on the Z80s bus for its casual 8MHz clock to get around to grabbing the data. You can also use SDRAM, DDR, DDR2, DDR3 and such on FPGAs just fine but its a lot more complex. These memories need some initialization and use pipelining (You execute a read on this cycle but get the data 8 cycles later) so they prefer if you access them in large burst operations while needing to be refreshed by the controller to retain data. Also DDR needs proper length matched traces so you can't just wirewrap wire it together. But as a reward for using any of those complex DRAMs you get gigabytes of RAM for cheep.(Not that useful on a 8bit system tho)

However graphics systems in game consoles have often used a combination of external DRAM and RAM internal to the video chip. Since these chips generate the image live as it is being sent out means that they need to look at a lot of things simultaneously to decide on the color of just one pixel. With the typical memory of the time running in the handful of MHz this made it only fast enough to do 1 or 2 read transaction per pixel. To get around this only the large data is kept in external RAM like actual image data, while other things are kept in lots of tiny internal RAMs inside the video chip, this is things like the color pallete, sprite locations, text charactermaps, sometimes tilemaps... Then as years went by and memory got faster and provided enough bandwidth to perform a handful of operations per one pixel we got more color depth, more layers, transparency, parallax scrolling and all that lovely eye candy. These improvements don't put all that much extra burden on the CPU as the GPU is doing the heavy work of throwing the extra pixels around. The CPU is still just giving it a bunch of coordinates where to draw things, so you can get some amazing graphics from a Z80 if you give it a powerful graphics chip.

But yeah for things that you are doing i wouldn't worry about memory bandwidth since modern memory is so much faster that it will be fast enough for anything.

EDIT: Oh and you would most definitely not want to have your graphics memory directly on the Z80 memory bus, not only does that create multi-master whoes its also slows things down while providing seemingly no real benefit. Its much easier to just connect the FPGA pins to the Z80 bus and have it act as a "gatekeeper" to separate graphics RAM. The FPGA will look to the Z80 like just another SRAM chip so it can read and write to it just the same, but since the FPGA is sitting in between it can hand over the RAM to the graphics hardware whenever the CPU is not using it. A small part of this same "RAM window" memory range can also be used to hold the graphics hardware registers and any other peripherals you might want to have (sound, keyboard etc..)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2019, 09:58:08 am
Using a gigantic FPGA in order to get enough internal block RAM for a framebuffer is not the right way to go about it. Video cards have been using SDRAM and prior to that SRAM and even regular DRAM to implement framebuffers for many, many years. I'm not going to say that it's "easy" but one of the things SDRAM is specifically designed to be good at is pumping in/out blocks of data synchronously which is precisely what video is doing. Look at some video cards from the late 90s to mid 2000's, these are often made with discrete ICs and relatively easy to tell what's going on. Interfacing to external memory is one of the things FPGAs are optimized to do, they have lots of IO pins and some of them even have onboard dedicated SDRAM interfaces.

Okay, so SDRAM is a definite possibility then, which opens the field in terms of FPGA options right up.  I can look at a TQFP 5v-tolerant FPGA (there must be a few around still, or perhaps even the odd one still being made?), strap an SDRAM to it and let it rip.

Also since BGA packages provide signal integrity that is far superior to any leaded packages, DDR2 and up memory chips are only available in BGA packages.

Now, I personally love reasonable-pitch BGAs and always choose them over any other packages, but I know some people have some sort of anti-BGA religion, which is why I'm bringing this up.

I have nothing against BGA generally, except I've never had to solder one and (at least it looks like) it requires specialist equipment to get the job done with any level of confidence.  I don't have the funds to throw at an IR reflow oven, so the best option I would have is to build my own - the videos on YT don't fill me with confidence, though.  And I'm stepping a looong way away from one of my goals, which was for my computer to be build-able by just about anyone with a little confidence with a soldering iron.

The other issue with BGAs is that I would likely have to switch from 2-layer PCBs to 4-layer if the BGA grid is dense enough, with cost implications there too.

Are you forgetting that this is being built to work with an 8 bit Z80? I don't think it needs to be anything super fancy, there's no point in making the video card powerful enough to deal with more data than the host CPU is capable of sending to it. We're not talking about modern high power GPUs.

Indeed.  I'm designing for an 8 MHz Z80 system, from an era when a single DIP-chip would handle the CRT by outputting a composite, UHF or RGB (if you're lucky) signal.  If it can handle vector graphics or a handful of sprites and a bitmap or tiled background on a 320x240 screen so that I can play Pong or Bubble Bobble, I'll be overjoyed.  Anything else will be a bonus.  ;D

The CPU is still just giving it a bunch of coordinates where to draw things, so you can get some amazing graphics from a Z80 if you give it a powerful graphics chip.

This is what I'm intending to do with the GPU - have the CPU pass instructions/coordinates/sprite and bitmap setup data to the GPU, then have the GPU throw the bytes around the frame buffer.

But yeah for things that you are doing i wouldn't worry about memory bandwidth since modern memory is so much faster that it will be fast enough for anything.

 :-+  Marvellous, that's good to know.

EDIT: Oh and you would most definitely not want to have your graphics memory directly on the Z80 memory bus, not only does that create multi-master whoes its also slows things down while providing seemingly no real benefit. Its much easier to just connect the FPGA pins to the Z80 bus and have it act as a "gatekeeper" to separate graphics RAM. The FPGA will look to the Z80 like just another SRAM chip so it can read and write to it just the same, but since the FPGA is sitting in between it can hand over the RAM to the graphics hardware whenever the CPU is not using it. A small part of this same "RAM window" memory range can also be used to hold the graphics hardware registers and any other peripherals you might want to have (sound, keyboard etc..)

Okay, so how about this for the interface to the GPU?  My current MMU design gives me up to 8x 512 KB chip sockets. Socket 1 is SRAM, Socket 8 is ROM, 2-7 can be anything you want.  If I 'remove' Socket 7 for example, there will be no RAM/ROM in the system trying to reply to the Z80 when it addresses that particular 512KB memory range.  I can then get the FPGA to accept all RD/WRs to that 512 KB window and treat them as direct access to the GPU's frame buffer and registers.  512 KB will only use a tiny fraction of the SDRAM on the other side of the FPGA, but will give the Z80 a huge area to load/assemble bitmaps, sprites, LUTs, symbols into.

Does that sound like a workable plan?

EDIT:

I know this sounds like I'm going back on my original statement that I didn't want a frame buffer in the system memory, but this isn't quite the same thing as an 80's multiplexed frame buffer and all the bus arbitration that would come with it.  This is physically removing a chunk of the system's memory and having the FPGA replace it, if that makes sense?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 20, 2019, 11:29:54 am
Okay, so how about this for the interface to the GPU?  My current MMU design gives me up to 8x 512 KB chip sockets. Socket 1 is SRAM, Socket 8 is ROM, 2-7 can be anything you want.  If I 'remove' Socket 7 for example, there will be no RAM/ROM in the system trying to reply to the Z80 when it addresses that particular 512KB memory range.  I can then get the FPGA to accept all RD/WRs to that 512 KB window and treat them as direct access to the GPU's frame buffer and registers.  512 KB will only use a tiny fraction of the SDRAM on the other side of the FPGA, but will give the Z80 a huge area to load/assemble bitmaps, sprites, LUTs, symbols into.

Does that sound like a workable plan?

EDIT:

I know this sounds like I'm going back on my original statement that I didn't want a frame buffer in the system memory, but this isn't quite the same thing as an 80's multiplexed frame buffer and all the bus arbitration that would come with it.  This is physically removing a chunk of the system's memory and having the FPGA replace it, if that makes sense?

Yes exactly the FPGA would act as a memory in that whole 512KB area.

But the FPGA can also do some address decoding of its own to map some hardware control registers into the first 1KB of its 512KB address space while the rest is a window into video RAM. This gives you the area to control the video hardware (Like choosing at what address the framebuffer is for double or tripple buffering, selecting video modes, holding sprite tables etc...). You can also have a register that offsets the 512KB RAM window around letting you roam across 64MB of video memory for example. (Old cartridge based consoles heavily relied on banking to fit the large ROMs into the limited memory space)

Having access to video memory from the CPU is quite useful since you don't need to implement GPU functionality to load images and tables into video memory, instead you just load it in yourself. Also the CPU can use this memory as part of its program. For example if you are making a game you can use the sprite table to hold the position and type of enemy characters on screen rather than keeping this data separate in CPU RAM and then having to update the sprite table in video memory on every frame.

But the main benefit to have video RAM separated and behind a FPGA is that the video RAM can run at full speed. The FPGA can only draw pixels as fast as it can write them to memory so having 10 times faster memory means it can draw 10 times more pixels per second.

Tho the memory bandwidth is more important if you go the modern drawcall route since that tends to keep everything in RAM, rather than the fully hardware based tilemaps and sprites that generate graphics on the fly without writing to RAM at all. On the other hand the drawcall route is more flexible as it can draw any image on to any other image while simultaneously modifying the image, compared to sprites and tilemaps tend to be limited to fixed sizes and grid patterns. But you can still package up tilemap functionality in the form of a draw call like "Draw tilemap(at 0x5000) using tileset(at 0x7200) into framebuffer(at 0x1000 with the offset 944,785)"

As for vector graphics, home game consoles don't use them all that much in 2D. Its usually 3D when vector graphics get hardware acceleration, but at that point the GPU also often ends up having features like matrix math for fast manipulation of 3D points and texture mapping/shading to make those triangles look pretty and textured rather than being flat solid colored triangles. In the past this 3D functionality was hardwired in the GPU (like tilemaps and sprites are hardwires to work in a certain way) as part of its fixed rendering pipeline that takes the 3D models and turns them into a image (like 2D tilemaps turn into a image). Later on this was made flexible by breaking the process up in to steps so the GPU could be asked trough additional drawcalls to do extra fancy eye candy in between the transitional rendering steps. Even later programmable sharers ware introduced and that made GPUs flexible enough to be used as a giant math coprocessor to mine cryptocurencies, encode video and run physics simulations.

So yeah you could generate 3D graphics similar to a N64 on that Z80 if that FPGA had hardware 3D graphics. But getting all of that to work would be a huge project (Doable by a single person but would take a very long time).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 20, 2019, 03:40:41 pm
Well, nope. The interleaving suggestion implied that the RAM would actually be accessed faster, so the CPU wouldn't see a difference. To pull that off, you would of course need a fast enough RAM (which should be no problem with a modern SDRAM chip or even SRAM), and clocking the MMU faster. Also, to keep things simple, you'd have to have the CPU and video clock frequencies multiple.

You mean the FPGA would read the 'frame buffer' in the Z80's logical memory space into an internal buffer really quickly, then pass that out as a pixel stream?  Otherwise surely the frame buffer would be sending data at the rate the screen mode requires, which means 73% of the time it would be sending data and locking the Z80 out?  Not sure I understand this fully.

I mean the RAM would be accessed alternately from the CPU and the video controller, in like "access slots". The CPU would not be "locked out", since its own access slot would always be available. Sure the video controller would have more slots available than the CPU, but you just need to clock this fast enough so that the slot allocated to the CPU is less than or equal to the minimum memory access time for the CPU (I don't remember about memory access with the Z80, but I'd guess a typical memory access would be more than 1 cycle, thus this should not be hard to get with even a moderately fast RAM chip.)

As I said, to do this in a simple manner, the CPU and video controller clocks should be synchronized and frequencies should be multiple. For instance, if the video controller needs 3 times as much bandwidth, the RAM access would have 4 slots, 1 for the CPU, and 3 for the video controller. The memory access (MMU?) clock would be 4 times the CPU clock here for instance, and the RAM would be accessed at this elevated frequency (which would still not be that fast for a modern RAM chip). Note that it would be relatively easy to do with SRAM, as long as its access time fits the requirements. With typical SDRAM, not so much: implementing such accesses in slots would cause issues because they would typically not be consecutive, introducing possibly unacceptable latencies (yes SDRAM doesn't "like" fully random accesses).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on October 20, 2019, 06:05:23 pm
I don't think you will find a 5V tolerant TQFP FPGA, but I don't think that is really all that big of a problem. Look at the schematic for the Terasic DE2 board I have, (manual is downloadable) the FPGA it uses is not 5V tolerant but the GPIO can be interfaced to 5V logic without problems. Each IO pin has a dual diode between IOVcc and Gnd followed by a resistor so the diodes prevent the pin from getting pulled too high and the resistor limits the current that can be dissipated by the diodes. It's not as good as proper level shifting but in practice I have used it many times without issues. At the speeds a vintage Z80 runs you can get away with quite a lot.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: langwadt on October 20, 2019, 06:18:59 pm
I don't think you will find a 5V tolerant TQFP FPGA, but I don't think that is really all that big of a problem. Look at the schematic for the Terasic DE2 board I have, (manual is downloadable) the FPGA it uses is not 5V tolerant but the GPIO can be interfaced to 5V logic without problems. Each IO pin has a dual diode between IOVcc and Gnd followed by a resistor so the diodes prevent the pin from getting pulled too high and the resistor limits the current that can be dissipated by the diodes. It's not as good as proper level shifting but in practice I have used it many times without issues. At the speeds a vintage Z80 runs you can get away with quite a lot.

and afaict the Z80 is TTL input levels so it'll with work with 3.3V input and the usual wimpy TTL high is already limiting the output current, The Xilinx datasheets usually say it is ok to use the ESD diodes for voltage limiting as long as the input current is limited to something like 20mA and the total is less than the sink on that supply
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 20, 2019, 07:46:49 pm
The easiest way for me to do that would be to keep one of the memory sockets empty, which would provide a 512 KB window that the FPGA could intercept the reads and writes to..  Half a meg would be more than big enough for a frame buffer for the resolutions I'm wanting to use, and would allow double-buffering on all the major screen modes if I was able to substitute that window for 512 KB of RAM on the FPGA via SDRAM, for example... hmmm... Tempting...
You got this.  :-+

Quote
Using the SDRAM on the FPGA seems to me and my inexperienced mind to be a lot more complicated than using dual-port RAM in the FPGA itself.  Can anyone convince me otherwise?  If I can make use of the SDRAM easily, without any major drawbacks or slowdowns, then I needn't worry about using a big, expensive FPGA with lots of internal RAM...
I confess that it is a bit more complicated than using a block RAM, and your system will have to be built to accommodate a response that will take several, possibly varying clock cycles to come back, but that doesn't mean you have to do it all yourself when plenty of open IP cores exist to help you out. Some FPGA design suites will even generate and parametrize DDR/DDR2/DDR3 controllers to your order. Often they will present an interface similar to a synchronous SRAM, but occasionally will be full-fledged bus slaves conforming to whatever standard. Wishbone is common in the open hardware world. It's designed to be modular so that you can simply omit complications that you don't want or need. The Simple Bus Architecture (https://en.wikipedia.org/wiki/Simple_Bus_Architecture) is a minimized version of Wishbone in exactly that vein. Also, the Z80 doesn't do everything all at once, and you don't need to either. Consider using a FIFO inside the FPGA to hold pixel data, maybe even a whole scan line ahead. Pipelining is very much your friend.

Quote
Oh I've had this discussion with others before.  When I first dipped my toes in the waters of electronics a couple of years ago
KiCAD 4 was a hot mess two years ago, absolutely. The UI wasn't very good or consistent. There were three separate layout toolsets, each with their own particular commands. The library editors were simply awful, which was a real problem in practice. Eagle was far better put together.

Fast forward a couple of years, with the help of the universe-destroyers at CERN and a full-time project manager KiCAD 5 has blossomed quite a bit. The symbol/footprint librarians have been given extra, dearly needed love. There's an interactive push-and-shove router. The three layout toolsets have been unified and rationalized. The whole thing now feels a bit less like a student project and more like a workflow for people to use. Even our gracious host Dave, who worked at Altium by the way, has been moderately impressed with it, even if some of the pro-level conveniences are lacking. If it's been a couple of years since you've had a look, I encourage you to give the latest a fresh hour or two. Be aware that there is still no whole-board autorouter built into KiCAD, and you would need to use an external application for autorouting such as FreeRouting, TopoR, etc. Personally I don't consider that a problem as I prefer more control over where my traces go and how they get there. But, if that's a deal-breaker for you, fair enough, I won't push it.

As a general rule a designer should expect to create their own symbols for any devices out of the ordinary, and treat their presence in the standard or contributed libraries as a happy accident. There are universal librarian softwares and services, who maintain a library of symbols and footprints in a master format and translate them on-demand to whatever eCAD software you have. That doesn't imply that any given universal symbol is well-laid-out or available for that part you need right now. So a decent footprint/symbol editor and librarian is a must.

Disclaimer, I've not used any of the pro-level software, but I cut my teeth on Eagle 4.x and was happy with it until my designs approached the free tier's size/layer/field-of-use restrictions. Now that Autodesk has made Eagle part of a cloud service, it's a hard pass.

With typical SDRAM, not so much: implementing such accesses in slots would cause issues because they would typically not be consecutive, introducing possibly unacceptable latencies (yes SDRAM doesn't "like" fully random accesses).
Two comments: The delays of an activate-precharge cycle might not be noticed within a 125ns Z80 clock cycle, never mind a 375ns memory cycle. There should be plenty of time even with single data rate SDRAM to complete a burst of 8 or 16 bytes into a pixel FIFO and perform any byte read/write from host or blitter that might or might not be waiting, in a fixed rhythm. Second, the Z80 was designed to make DRAM usage easy, with the row address on the bus early. With some clever SDRAM controller programming, the row address can be likewise passed along early to the SDRAM chip to open the row early, allowing usage of slower DRAM, maybe even the good old asynchronous DRAM chips which are still available, but at closer to $1 per megabyte than $1 per gigabit. Still I think it's overkill for the present application.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 21, 2019, 05:43:31 am
As a general rule a designer should expect to create their own symbols for any devices out of the ordinary, and treat their presence in the standard or contributed libraries as a happy accident. There are universal librarian softwares and services, who maintain a library of symbols and footprints in a master format and translate them on-demand to whatever eCAD software you have. That doesn't imply that any given universal symbol is well-laid-out or available for that part you need right now. So a decent footprint/symbol editor and librarian is a must.

Disclaimer, I've not used any of the pro-level software, but I cut my teeth on Eagle 4.x and was happy with it until my designs approached the free tier's size/layer/field-of-use restrictions. Now that Autodesk has made Eagle part of a cloud service, it's a hard pass.

I have been using Altium Designer for quite a few years and despite it being a professional tool and its large library of parts i still end up drawing most of the symbols and footprints myself.

There are certain style guides i want components to conform to, the way they are named, the way i want supplier links for ordering. But above all is how the symbol is drawn. I like to arrange the pins in certain ways to make for a neat schematic, for MCUs i like the peripherals written down on the pin rather than just being called "PB3", sometimes i draw extra things inside the IC rectangle to make it more clear what the chip is doing(Like logic ICs or MUXes or Digital pots etc). So its almost as fast to just draw my own rather than modify there library component to fit my liking.

The important part is that the editors for symbols and footprints are pretty good. I can draw a 100 pin IC in <10 minutes if the pin names can be copy pasted from a pinout table in the datasheet and this includes arranging the pins around to my liking. The footprint for that same chip in TQFP or BGA form takes another 3 minutes because Altium has a footprint generation wizard that supports almost all sensible package types where you just enter about 3 to 10 dimensions from the drawing and it spits out a footprint that includes a 3D model.

Not saying Altium is the best PCB tool because it still does some things badly and sometimes crashes in weird ways, but it does do some things right like library creation (But lets not speak about maintaing large libraries as they have a long way to go there)

With typical SDRAM, not so much: implementing such accesses in slots would cause issues because they would typically not be consecutive, introducing possibly unacceptable latencies (yes SDRAM doesn't "like" fully random accesses).
Two comments: The delays of an activate-precharge cycle might not be noticed within a 125ns Z80 clock cycle, never mind a 375ns memory cycle. There should be plenty of time even with single data rate SDRAM to complete a burst of 8 or 16 bytes into a pixel FIFO and perform any byte read/write from host or blitter that might or might not be waiting, in a fixed rhythm. Second, the Z80 was designed to make DRAM usage easy, with the row address on the bus early. With some clever SDRAM controller programming, the row address can be likewise passed along early to the SDRAM chip to open the row early, allowing usage of slower DRAM, maybe even the good old asynchronous DRAM chips which are still available, but at closer to $1 per megabyte than $1 per gigabit. Still I think it's overkill for the present application.

Yeah modern SDRAM is so fast the FPGA would be able to present it like its SRAM to the slow 8MHz Z80 since the SDRAM could be clocked so much faster that the FPGA has time to select the appropriate row, execute a read and clock the data trough the pipeline in the time the Z80s read access happens. Or if it got really unlucky and was right in a refresh cycle when that happened maybe the FPGA can pull on the Z80s WAITn line to halt it a bit.

The extra complexity comes in the GPU where to use the full speed of SDRAM it has to be built to cope with the RAMs pipelined fashion. So performing reads and writes in large bursts and making sure it always has something in the pipeline so that it doesn't end up sitting there waiting for data to come in. Yes all modern digital computing is heavily pipelined because its required to get the high clock speeds, but it comes at a price.

Since you probably don't need more than a few megabytes of memory i think SRAM is a safer choice. It is truly random access and has no confusing pipelining.

I have worked with FPGAs here and there and pipelining still hurts my brain as when writing pipelined HDL code its hard to keep track of what register is holding the data for what cycle of the pipeline. I usually tend to have to resort to drawing a timing diagram of the whole thing so that i can visually see how many cycles something is behind or in front of something and then turn that timing diagram into code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2019, 10:24:11 am
But the FPGA can also do some address decoding of its own to map some hardware control registers into the first 1KB of its 512KB address space while the rest is a window into video RAM. This gives you the area to control the video hardware (Like choosing at what address the framebuffer is for double or tripple buffering, selecting video modes, holding sprite tables etc...). You can also have a register that offsets the 512KB RAM window around letting you roam across 64MB of video memory for example. (Old cartridge based consoles heavily relied on banking to fit the large ROMs into the limited memory space)

Yes, I really like this idea.  It side-steps the whole issue of using a narrow bottleneck in the IO ports to speak to the GPU and transfer data a byte at a time, and using multiple IO calls to write or read data (setting the register first, then writing or reading from it in the next IO call) and the compulsory WAIT state for each IO transaction.  It also opens up the Z80's 16-bit memory operations.  Not seeing many negatives - I'm sure my little Z80 can handle only having 3.5 MB of 'system' memory space rather than the full 4 MB.  It's a far cry from the 80's when it would only have 64 KB to squeeze a frame buffer and everything else into...  ::)

Having access to video memory from the CPU is quite useful since you don't need to implement GPU functionality to load images and tables into video memory, instead you just load it in yourself. Also the CPU can use this memory as part of its program. For example if you are making a game you can use the sprite table to hold the position and type of enemy characters on screen rather than keeping this data separate in CPU RAM and then having to update the sprite table in video memory on every frame.

Nice. Could even copy the character set from ROM in the FPGA to a symbol table in RAM on power-up and allow the Z80 to change it for a customisable symbol set. Lots and lots and lots of possibilities...

But the main benefit to have video RAM separated and behind a FPGA is that the video RAM can run at full speed. The FPGA can only draw pixels as fast as it can write them to memory so having 10 times faster memory means it can draw 10 times more pixels per second.

Might come back to this further down as the discussion is turning more towards using SRAM instead of SDRAM... not sure there'd be much of a performance penalty for substituting SRAM as it sounds like SDRAM has its shortcomings.  As I'm working with an 8-bit processor running at a modest clock speed, I can't see it needing to make use of the SDRAM's pipelined architecture.  Sure, the FPGA will appreciate it, but with such low screen resolutions and such, I'm thinking SRAM will be a much easier choice for me to deal with.

Tho the memory bandwidth is more important if you go the modern drawcall route since that tends to keep everything in RAM, rather than the fully hardware based tilemaps and sprites that generate graphics on the fly without writing to RAM at all. On the other hand the drawcall route is more flexible as it can draw any image on to any other image while simultaneously modifying the image, compared to sprites and tilemaps tend to be limited to fixed sizes and grid patterns. But you can still package up tilemap functionality in the form of a draw call like "Draw tilemap(at 0x5000) using tileset(at 0x7200) into framebuffer(at 0x1000 with the offset 944,785)"

I think the bandwidth will be important either way, as the sprites, tilemaps and symbol table will all be in RAM rather than ROM.  The symbol table holding the ASCII char set for example, will be read from RAM so that the user can customise the look of it if they desire.  Same with sprites and tile maps - not much use unless they are customisable.

As I said, to do this in a simple manner, the CPU and video controller clocks should be synchronized and frequencies should be multiple. For instance, if the video controller needs 3 times as much bandwidth, the RAM access would have 4 slots, 1 for the CPU, and 3 for the video controller. The memory access (MMU?) clock would be 4 times the CPU clock here for instance, and the RAM would be accessed at this elevated frequency (which would still not be that fast for a modern RAM chip). Note that it would be relatively easy to do with SRAM, as long as its access time fits the requirements. With typical SDRAM, not so much: implementing such accesses in slots would cause issues because they would typically not be consecutive, introducing possibly unacceptable latencies (yes SDRAM doesn't "like" fully random accesses).

I'm all for keeping this as simple as possible, hence going for the 'memory window' approach rather than interleaving access to shared memory - I've never used SDRAM and know next to nothing about using it, so perhaps the fastest SRAM I can reasonably get hold of would be the best choice for the FPGA's frame buffer?  I use 55ns SRAM for the system memory, would need to be a fair bit faster for the FPGA to improve it's pixel draw rate I guess.

I don't think you will find a 5V tolerant TQFP FPGA, but I don't think that is really all that big of a problem. Look at the schematic for the Terasic DE2 board I have, (manual is downloadable) the FPGA it uses is not 5V tolerant but the GPIO can be interfaced to 5V logic without problems. Each IO pin has a dual diode between IOVcc and Gnd followed by a resistor so the diodes prevent the pin from getting pulled too high and the resistor limits the current that can be dissipated by the diodes. It's not as good as proper level shifting but in practice I have used it many times without issues. At the speeds a vintage Z80 runs you can get away with quite a lot.

Okay, sounds good.  If the Z80 can talk directly to the FPGA it would make things a fair bit simpler.

and afaict the Z80 is TTL input levels so it'll with work with 3.3V input and the usual wimpy TTL high is already limiting the output current, The Xilinx datasheets usually say it is ok to use the ESD diodes for voltage limiting as long as the input current is limited to something like 20mA and the total is less than the sink on that supply

I'm using a CMOS Z80 and mostly HCT glue logic, apart from a couple of LS parts in the MMU that the FPGA would be exposed to the outputs from.  That's promising info though - so it could be possible to just connect the FPGA directly to the system's address and data lines?  I have a 3.3v power rail in the system that the FPGA would be powered from.

KiCAD 4 was a hot mess two years ago... Fast forward a couple of years, with the help of the universe-destroyers at CERN and a full-time project manager KiCAD 5 has blossomed quite a bit. The symbol/footprint librarians have been given extra, dearly needed love. There's an interactive push-and-shove router. The three layout toolsets have been unified and rationalized. The whole thing now feels a bit less like a student project and more like a workflow for people to use. Even our gracious host Dave, who worked at Altium by the way, has been moderately impressed with it, even if some of the pro-level conveniences are lacking. If it's been a couple of years since you've had a look, I encourage you to give the latest a fresh hour or two.

Okay, I'll give it another go.  Being limited to 500 pins and 2 layers in my PCB schematic and PCB work is a bit of a bind for me, especially now looking at these FPGAs with pin counts in the hundreds. Heh, I'm even looking at some DIY reflow oven tutorials on YT.  I'm sure I read somewhere that someone used to do BGA soldering with their frying pan?  :o

Be aware that there is still no whole-board autorouter built into KiCAD, and you would need to use an external application for autorouting such as FreeRouting, TopoR, etc. Personally I don't consider that a problem as I prefer more control over where my traces go and how they get there. But, if that's a deal-breaker for you, fair enough, I won't push it.

It's not a deal breaker, but it has been a good reason to stay with DipTrace all this time and work within the licence limits.  I need to really just sit down with an hour or two to spare and put together one of my computer's card schematics in KiCAD and route the PCB and see how it goes.

As a general rule a designer should expect to create their own symbols for any devices out of the ordinary, and treat their presence in the standard or contributed libraries as a happy accident.

Of course, and I have been doing that with DipTrace.  The big difference is that I haven't had to do it that often and, when I have, it has been for relatively obscure parts.  The process of creating a new component and its associated footprint is also pretty easy and straightforward.  The only thing that grips me with DipTrace is that it could be slightly more automated in net naming and attaching. Having to manually click on Every. Single. Pin. on a 16-bit address bus and select the next net address line in the list to link to it is a little tedious.  And that's just a 16-bit address bus...  I noticed the other day while playing with EasyEDA that it automatically increments the net name when you click on the next pin - so linking D0-D7 to a RAM chip is as simple as clicking, entering the first net name 'D0', then 6 more clicks on the rest of the data pins and you're done.  Some thought has gone into that UX.

Since you probably don't need more than a few megabytes of memory i think SRAM is a safer choice. It is truly random access and has no confusing pipelining.

Okay, SRAM it is.  I certainly don't need any extra confusion - I haven't written a single line of VHDL yet, so this is going to be a steep-enough learning curve for me without adding in extra complexity.  :o

I have worked with FPGAs here and there and pipelining still hurts my brain as when writing pipelined HDL code its hard to keep track of what register is holding the data for what cycle of the pipeline. I usually tend to have to resort to drawing a timing diagram of the whole thing so that i can visually see how many cycles something is behind or in front of something and then turn that timing diagram into code.

Righto, thanks Berni.  Steer clear of SDRAM, got it.  ;) :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: migry on October 21, 2019, 04:15:36 pm
Well I have been playing around with hobbiest (read low cost) FPGA boards (both Xilinx and Altera) for the past year, with a particular interest in VGA/video generation and retro computing. So I am going to chip in my 10 cents worth.

Firstly I would recommend visiting YouTube and watching the videos of "Land Boards, LLC" as I think their videos are a perfect fit for answering your questions. I found this channel only recently. They have several videos on implementing Grant Searle's design on a couple of cheap FPGA boards one of which is a Cyclone II board which you might have. They also sell on Tindie and in their videos show a Static RAM expansion board (no idea if this can still be bought). BTW - I have no connection with this company. My interest was the videos they show of the cheap Chinese ZR-Tech Cyclone IV FPGA board. They keep mentioning their GitHub repository, so I think you are likely to find everything you need right there!

Without knowing your level of FPGA, RTL, electronics and video experience/knowledge it is difficult to give accurate advice, but I would suggest start with simple video generation using VGA. There are many text only VGA displays to be found (e.g. OpenCores) which are a great starting point. You will need to get familiar with how video displays work, horizontal and vertical sync and video timings. What is interesting is that todays HDMI "video" is based on the old CRT analogue video standards of yesteryear. Again there is lots of tutorials on the web and YouTube, just one can be found on the FPGA4fun website. Text only video needs little memory so will fit in any FPGA and use internal RAM blocks. VGA allows you to look at the R,G,B and syncs using a scope (if you have one). This can be very educational.

If you want a graphics video solution, then you need frame buffer memory. The problem I faced was that if you want to fit the frame buffer only in internal RAM blocks, this means a very expensive FPGA. Most hobbiest boards use FPGAs with the smallest amount of RAM blocks, to keep the cost low. Adding a fast Static RAM is the easiest way to go, but some FPGA boards don't have enough spare I/O. Some hobbiest FPGA boards have a large SDRAM, but these are not so easy to understand and operate (again check out Hamster's website), and access speed can be an issue. For example one of the retro computer designs (MISTer???) doesn't use the on-board DDR(?)RAM, but adds an external RAM of some kind. So even these clever coders couldn't get the required bandwidth from the on-board memory.

Just FYI, my own solution, is that I designed my own Cyclone II FPGA board/PCB and incorporated a 12ns 128k bytes Static RAM. Even then there were signals crossing multiple clock domains and this caused me a lot of problems  ???  (I am no expert but then I'm no noob).

The "Land Boards" solution added a small daughter PCB with a SRAM for video and CPU memory.

BTW Digilent do a relatively low cost Artix-7 board which has a large fast SRAM, so that's worth a consideration. I have one. FYI, powering this board needs careful attention (otherwise expect lots of USB problems).

Once you have got experience with the "simple" VGA solution, then by all means investigate HDMI. As others have mentioned "Hamster_NZ" has done some excellent work implementing HDMI and his website is a wealth of knowledge. I have re-coded his code in Verilog and ported to a number of different FPGAs. One hurdle is finding a way to hook up the HDMI socket. There are certainly boards which incorporate a HDMI socket but they tend to be more expensive. Some HDMI implementation use LVDS channels from the FPGA directly, but others implement HDMI using an Analogue Devices chip (which might be an easier solution - I do not have one of these boards to try out). I have a board from Numato with HDMI in and out connectors. Also from Numato I bought a HDMI PMOD board, and this has worked well.

The downside of HDMI is that if it doesn't work, it is not so easy to debug. I ported my Verilog to a Cyclone II. I appear to get sync, but the video is wrong. I have run simulations and the channel data packets look correct. I have no idea how to start to debug this! Advice welcomed  :-+

Have fun. and post from time to time with updates or further questions

regards...
--migry


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 21, 2019, 10:04:54 pm
     Hmmm.   OP:  Can you definitively say what resolution you want for an 8 bit computer?  Earlier you said you wanted XXXkb.  Also, will you have a text mode with addressable modifiable font?  Will the font be dedicated in memory, or use a system memory?  How many colors?  Color palette?  Different video modes on different lines on the screen?  Sprites?

     The problem is with a video controller, you have ram access which is demanding and cannot be part of separate system mory of your 8 bit cpu core, so, is something like a cheap Atari 800 graphics design, the video processor and CPU's memory are intertwined and with a minimum VGA output with X colors, your video output will eat a lot of bandwidth.

     If 64kb is enough, and you want an all internal no ram design, look for a PLD/FPGA with at least 1 megabit internal so it may hold everything with some extra space, otherwise, at the level you seem to be at I strongly recommend buying an existing development eval board for either Altera or Xilinx with a VGA or HDMI out and at least 1 DDR/DDR2 ram chip at minimum.  Make sure the eval board is documented well and not a Chinese only demo code which you cannot dissect to your liking.

Example all in 1, 144pin qfp PLD (no boot prom needed, 1 single supply voltage, I narrowed the selection to 64kbyte and 128kbyte)
https://www.digikey.com/products/en/integrated-circuits-ics/embedded-fpgas-field-programmable-gate-array/696?FV=ii1290240%7C1329%2Cii1677312%7C1329%2Cii691200%7C1329%2C-8%7C696%2C16%7C13077&quantity=0&ColumnSort=1000011&page=1&stock=1&nstock=1&k=max10&pageSize=25&pkeyword=max10 (https://www.digikey.com/products/en/integrated-circuits-ics/embedded-fpgas-field-programmable-gate-array/696?FV=ii1290240%7C1329%2Cii1677312%7C1329%2Cii691200%7C1329%2C-8%7C696%2C16%7C13077&quantity=0&ColumnSort=1000011&page=1&stock=1&nstock=1&k=max10&pageSize=25&pkeyword=max10)

Yes, this is not the cheapest, but it is an all in 1 IC with single supply, no external parts except for video dac (use a 4x74HC574 and resistors if you like) and TTL 3.3v-5v translator IC for data bus, though, you might get away with schottky diode camps and series resistors on the inputs coming from your 5v digital logic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2019, 11:09:28 pm
Firstly I would recommend visiting YouTube and watching the videos of "Land Boards, LLC" as I think their videos are a perfect fit for answering your questions. I found this channel only recently. They have several videos on implementing Grant Searle's design on a couple of cheap FPGA boards one of which is a Cyclone II board which you might have. They also sell on Tindie and in their videos show a Static RAM expansion board (no idea if this can still be bought). BTW - I have no connection with this company. My interest was the videos they show of the cheap Chinese ZR-Tech Cyclone IV FPGA board. They keep mentioning their GitHub repository, so I think you are likely to find everything you need right there!

Thanks migry, that's a great recommendation - I'll take a look.  :-+

Without knowing your level of FPGA, RTL, electronics and video experience/knowledge it is difficult to give accurate advice...

FPGA level - absolute beginner, never tried programming one (yet)  ;)
RTL level - what's that?  :o
Video experience - I taught my mum and dad how to use their first VHS back in the 80's?  :-\

However, I make up for all that lack of knowledge/experience with a very inquisitive mind, eagerness to learn and able to listen to good advice.  I built my computer (image earlier in this conversation) using those attributes with no prior education or experience in electronics, so I'm confident I might get halfway to achieving my goal of reasonable 8-bit graphics.  That's not to say I think this will be a walk in the park! ;D

...but I would suggest start with simple video generation using VGA. There are many text only VGA displays to be found (e.g. OpenCores) which are a great starting point. You will need to get familiar with how video displays work, horizontal and vertical sync and video timings.

Yes, I've gone through Grant Searle's VHDL code to see how he did his text display and have read up on the video display inner workings - frame rates, pixel clocks, hsync/vsync, back porch/display/front porch, have seen videos on generating a VGA signal using nothing more than 74-series counter logic etc.  I'm hoping I don't annoy everyone here too much that I can't ask questions further down the line on the software (VHDL) aspect of the design.  ;)

Text only video needs little memory so will fit in any FPGA and use internal RAM blocks.

Yep, see the screen resolutions table further down this reply - I've calculated how much memory each screen mode will require (though I'm not 100% certain they're totally correct, but I'm a beginner!) All the colour modes are using a colour LUT, so I'm calculating one byte per pixel for a maximum of 256 colours on screen at any one time out of a palette of... lots.


     Hmmm.   OP:  Can you definitively say what resolution you want for an 8 bit computer?  Earlier you said you wanted XXXkb.  Also, will you have a text mode with addressable modifiable font?  Will the font be dedicated in memory, or use a system memory?  How many colors?  Color palette?  Different video modes on different lines on the screen?  Sprites?

(https://i.ibb.co/5Lm0yst/Untitled.png) (https://imgbb.com/)

Above is a table of screen modes that I calculated I could fit into a relatively small (<64 KB) memory space, if I was going to go with an FPGA of sufficient size and complexity.  Larger memory would allow more colours, but 640x480 is my intended maximum resolution.  The lower resolution modes would be achieved using pixel stretching, or whatever the correct term is for duplicating the same pixel horizontally and the same line vertically to reduce the effective resolution.  The output that the TV would see would always be 640x480 (obviously I'm using PAL timings).

Mode 0 will be the text mode.  This is going to be the first screen mode I try to implement, as there is plenty of VHDL out there doing this already, Grant Searle's code for example.

The text mode, and any subsequent 'non-text' modes which will still be capable of displaying text as well as graphics, will initially use a symbol table in ROM.  My intention as I develop the VHDL design is to copy that table to RAM (if there is sufficient, naturally) at power-up and read it from RAM when displaying text, giving the user the option of changing the design of those symbols (changing fonts, for example, or allowing the use of special characters as graphics tiles).

Currently, it looks as though I'll be using a fast SRAM to store the frame buffer, character tables, colour LUT, sprites etc.  But initially, I'll be using whatever is available in the FPGA as this will be the easiest (and fastest) solution whilst I develop the FPGA design.  Once I have the text mode working, I can start looking to implement a graphics mode in a resolution that will fit in the available FPGA RAM, but will look to move on to using an external dedicated SRAM chip to open up the screen resolutions etc.

The interface will be a 512 KB 'hole' in the system memory, which the FPGA will monitor for read/writes and action accordingly, and provide a few registers at certain memory locations to control things like clearing the screen, text colour etc.

     If 64kb is enough, and you want an all internal no ram design, look for a PLD/FPGA with at least 1 megabit internal so it may hold everything with some extra space, otherwise, at the level you seem to be at I strongly recommend buying an existing development eval board for either Altera or Xilinx with a VGA or HDMI out and at least 1 DDR/DDR2 ram chip at minimum.  Make sure the eval board is documented well and not a Chinese only demo code which you cannot dissect to your liking.

There are two issues with getting an FPGA with a large enough internal memory - otherwise I'd go straight for the Spartan 6 LX45 (or a more modern equivalent) - that's price and, most importantly, the package the FPGA comes in.  I don't have the equipment or skills to reflow a 484-pin BGA onto one of my PCBs.  I'm researching building a reflow oven and learning to use less restrictive (but less user-friendly) design software, but it could be a long time before I have the equipment and confidence to try soldering a £50 BGA onto a home-designed board.

I have a Spartan 6 LX16 dev board on its way with 32 MB SDRAM and a breakout HDMI connector that I can wire to the dev board, so that base is covered.  I already have a VGA connector, as well, so I can try either option whilst experimenting with the FPGA design.

Example all in 1, 144pin qfp PLD (no boot prom needed, 1 single supply voltage, I narrowed the selection to 64kbyte and 128kbyte)
https://www.digikey.com/products/en/integrated-circuits-ics/embedded-fpgas-field-programmable-gate-array/696?FV=ii1290240%7C1329%2Cii1677312%7C1329%2Cii691200%7C1329%2C-8%7C696%2C16%7C13077&quantity=0&ColumnSort=1000011&page=1&stock=1&nstock=1&k=max10&pageSize=25&pkeyword=max10 (https://www.digikey.com/products/en/integrated-circuits-ics/embedded-fpgas-field-programmable-gate-array/696?FV=ii1290240%7C1329%2Cii1677312%7C1329%2Cii691200%7C1329%2C-8%7C696%2C16%7C13077&quantity=0&ColumnSort=1000011&page=1&stock=1&nstock=1&k=max10&pageSize=25&pkeyword=max10)

Yes, this is not the cheapest, but it is an all in 1 IC with single supply, no external parts except for video dac (use a 4x74HC574 and resistors if you like) and TTL 3.3v-5v translator IC for data bus, though, you might get away with schottky diode camps and series resistors on the inputs coming from your 5v digital logic.

Okay, they're interesting devices...  No, they're not cheap but there's a huge plus straight away - they're hand-solderable LQFP packages and have reasonable amounts of internal RAM... thanks for the suggestion. :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 21, 2019, 11:58:58 pm
For video mode, use a 480p, @ 27Mhz clock for your video out.  This is the standard for all TVs HDMI making outputting that a breeze.  Use the 640x480 for 4:3 centered inside and expand to 720x480 for 16:9.

Go for the 1.28mbit Max10 as it is only 3$ more than the 512kbit.  With this, you will be able to superimpose color text ontop of the 320x240x256 color paletted graphics as well as full vertical height colored sprites.

Remember, you can still store the palette in registers instead of ram, allowing for 1 bank immediate with all the colors being updated during the v-sync for clean pallet animation transitions.

  Internally, run the IC at 4x27Mhz, 108Mhz, (feed it 27mhz and use the internal PLL to 4x or 6x or 8x the source clock, use the PLL output to drive your dac or hdmi transmitter clock)  well within the Max10's 200Mhz+ abilities.  This gives you multiple reads per pixel with the dumbest logic, including the ability to superimpose the text font of 640x480, or 720x480 for 16:9 on top of the 1/4 res 256 color 320x480 graphics mode + multiple colored sprites.

Use internal 2 port ram, 1 read only for video output, having 4-8 reads per pixel at 108Mhz core. (doubling all your video mode specs, otherwise, you have something like 16 read slots per pixel making that read port up to a 16 channel read port with a multiplexed address input and latched data outputs)  An a second read/write port for your CPU access.

In fact, there is enough in this Max 10 to make an entire Atari 130xe with 6502 emulation & graphics and sound...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: langwadt on October 22, 2019, 12:12:10 am
how many are you going to build? when you can get FPGA,RAM,PSU and flash on a board for ~$20 I'd think you'll have to make quite a few to make it cheaper
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 22, 2019, 12:18:29 am
There are two issues with getting an FPGA with a large enough internal memory - otherwise I'd go straight for the Spartan 6 LX45 (or a more modern equivalent) - that's price and, most importantly, the package the FPGA comes in.  I don't have the equipment or skills to reflow a 484-pin BGA onto one of my PCBs. 
Why do you need such a large package? Spartan-7 devices up to S50 are available in a FTGB196 package, which was specifically designed to be fully broken out on a 4 layer board, which are very cheap nowadays. This package has 100 user IO pins (2 banks containing 50 pins each), which should be plenty for your needs. And you can easily solder it using just a hot air gun.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 22, 2019, 12:46:11 am
With "effort", that Max10's PLL and LVDS transmitters are fast enough to directly drive 480p DVI. (HDMI compatible, but, no sound or EDID support)  Though, you will still need proper ESD protection on the HDMI port. with load termination resistors to adapt the voltages.

OR:
http://www.ti.com/product/TFP410/samplebuy (http://www.ti.com/product/TFP410/samplebuy)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 22, 2019, 03:23:25 am
With "effort", that Max10's PLL and LVDS transmitters are fast enough to directly drive 480p DVI. (HDMI compatible, but, no sound or EDID support)  Though, you will still need proper ESD protection on the HDMI port. with load termination resistors to adapt the voltages.
Spartan-7 and Artix-7 support TMDS natively, easily outputting 720p and (with some effort) even 1080p on almost any pins (48 out of 50 pins in a bank can be used as differential pairs, and each pair has a pair of ISERDES/OSERDES bound to them).
As for ESD, I love TPD12S521 - it combines ESD protection for main data lanes, and voltage level translator 5 V <-> 3.3 V for DDC, CEC and HPD lines.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 22, 2019, 06:15:16 am
Yep i recommend using the DVI serialiser chip that BrianHG suggested. It makes DVI as simple as VGA since you just put the RGB data into the chip rather than into a DAC, all happening at nice low clockspeed parallel speeds, so its easy to even do 1080p 60Hz

As for memory organization i would recommend you keep the color pallete and character ROM inside the FPGA block RAM. These memories are accessed pretty much on every pixel and are small enough to fit easily fit into it, so it will save you a lot of accesses to external memory. Only keep the large stuff that wont fit inside in the external memory such as framebuffers, tilemaps, drawcall tables...

As for graphics modes id say you could combine modes because you have plenty of bandwidth. Like for example having a 640x480 text mode overlayed across a 640x480 graphics mode with 16 or even 256 colors. Gives you a easy fast way to show text on top of graphics. Tho for any sort of games you probably don't want a oldchool PC CGA like graphics mode anyway as the Z80 might be kinda slow at drawing to it. To make good looking games you probably want tilemap modes like the SNES. The video hardware in that game system has 4 layered tilemaps each using its own color pallete with an additional sprite layer on top. The layers are transparently blended together and can be independently moved around in pixel granularity. This is how the SNES does parallax scrolling that gives 2D platform games the impressive visuals.

EDIT:
Here is a good example of parallax scrolling put to good use: https://www.youtube.com/watch?v=VL7jR1NN4p0&feature=youtu.be&t=837 (https://www.youtube.com/watch?v=VL7jR1NN4p0&feature=youtu.be&t=837)
Its on a Sega Genesis/Megadrive so it has similarly powerful graphics hardware to the SNES but works a bit differently.
The impressive things on the SNES generally use the famed Mode 7: https://www.youtube.com/watch?v=H6u7Nk6_L50&feature=youtu.be (https://www.youtube.com/watch?v=H6u7Nk6_L50&feature=youtu.be)
The hardware behind that is actually not that advanced, its just so called Affine transfromation in the video chip combined with some clever game programming. These transformation just need multiply and addition operations so a FPGA can calculate them in a single clock cycle at high speed using hardware multiplier blocks.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 22, 2019, 12:58:33 pm
...Go for the 1.28mbit Max10 as it is only 3$ more than the 512kbit.  With this, you will be able to superimpose color text ontop of the 320x240x256 color paletted graphics as well as full vertical height colored sprites.

Thank you - I appreciate the guidance as one thing I've come to realise during this discussion is that there is so much choice in FPGAs alone, not counting the different ways of interfacing to the system and connecting additional memory, that I'm getting quite confused by it all.

The only question I have about the Max10 is will be able to output direct to HDMI at 720x480?  I know the Spartans I've been looking at have SERDES support built-in.


In fact, there is enough in this Max 10 to make an entire Atari 130xe with 6502 emulation & graphics and sound...

Well, that's the next thing - with all that space left over, it would be remiss of me NOT to put an AY-3-8910 sound generator (or something else) in there.  That would save me an entire (troublesome) PCB in my system... but where does that stop, I guess?  ::)


how many are you going to build? when you can get FPGA,RAM,PSU and flash on a board for ~$20 I'd think you'll have to make quite a few to make it cheaper

A handful initially - one or two, maybe.  The whole thing is a one-off prototype at the moment, but I have intentions down the line to open the design up for people who want to have a go at building it and maybe try to make some of my costs back.


Why do you need such a large package? Spartan-7 devices up to S50 are available in a FTGB196 package, which was specifically designed to be fully broken out on a 4 layer board, which are very cheap nowadays. This package has 100 user IO pins (2 banks containing 50 pins each), which should be plenty for your needs. And you can easily solder it using just a hot air gun.

Purely to have enough internal RAM to hold the frame buffer.  If it has the RAM I need and can drive an HDMI output without too much hassle, it sounds like a good idea.


With "effort", that Max10's PLL and LVDS transmitters are fast enough to directly drive 480p DVI. (HDMI compatible, but, no sound or EDID support)

It would be nice to have sound too.  :(

Though, you will still need proper ESD protection on the HDMI port. with load termination resistors to adapt the voltages.

OR:
http://www.ti.com/product/TFP410/samplebuy (http://www.ti.com/product/TFP410/samplebuy)
Spartan-7 and Artix-7 support TMDS natively, easily outputting 720p and (with some effort) even 1080p on almost any pins (48 out of 50 pins in a bank can be used as differential pairs, and each pair has a pair of ISERDES/OSERDES bound to them).
As for ESD, I love TPD12S521 - it combines ESD protection for main data lanes, and voltage level translator 5 V <-> 3.3 V for DDC, CEC and HPD lines.

Okay, so the TFP410 and a MAX FPGA are starting to look like the best option (the issues soldering the Spartan packages are a big hurdle, unfortunately) - will I need something like the TPD12S521 for ESD protection if I'm using a TFP410?


As for memory organization i would recommend you keep the color pallete and character ROM inside the FPGA block RAM. These memories are accessed pretty much on every pixel and are small enough to fit easily fit into it, so it will save you a lot of accesses to external memory. Only keep the large stuff that wont fit inside in the external memory such as framebuffers, tilemaps, drawcall tables...

Yes, that makes sense.  I think I'm going to try my best to keep it ALL in the internal block RAM if I can, with a view to expanding into external RAM as I get more experienced and comfortable with the design, VHDL and FPGAs in general.

I think I mentioned several times that I intend to keep the charset in ROM and copy it to RAM when the FPGA is turned on - just to clarify, now I understand a little more about the FPGA architecture, as I understand it the charset will be in RAM anyway, just re-instated to its default data every time the FPGA is turned on, so changing the charset/symbol table will be possible from the get-go.

To make good looking games you probably want tilemap modes like the SNES. The video hardware in that game system has 4 layered tilemaps each using its own color pallete with an additional sprite layer on top. The layers are transparently blended together and can be independently moved around in pixel granularity. This is how the SNES does parallax scrolling that gives 2D platform games the impressive visuals.

Yes, that sounds like an achievable goal - though I'm going to take baby steps getting there, building on the basic text-only mode and improving it as I learn.

Here is a good example of parallax scrolling put to good use: https://www.youtube.com/watch?v=VL7jR1NN4p0&feature=youtu.be&t=837 (https://www.youtube.com/watch?v=VL7jR1NN4p0&feature=youtu.be&t=837)

I thought you were going to link me to something like Shadow of the Beast on the Amiga. ;D  Do you think what I'm designing would be capable of that sort of output (perhaps at a lower resolution?) 

The impressive things on the SNES generally use the famed Mode 7: https://www.youtube.com/watch?v=H6u7Nk6_L50&feature=youtu.be (https://www.youtube.com/watch?v=H6u7Nk6_L50&feature=youtu.be)
The hardware behind that is actually not that advanced, its just so called Affine transfromation in the video chip combined with some clever game programming. These transformation just need multiply and addition operations so a FPGA can calculate them in a single clock cycle at high speed using hardware multiplier blocks.

That's impressive stuff - some might say almost black magic for a Z80 to be able to pull off?!  (I know it's the power of the FPGA doing the gruntwork, but still, the Z80 would get the credit)  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 22, 2019, 03:33:11 pm
Yeah you will be able to fit it all into internal block RAM no problem as long as you keep framebuffers small since those tend to be the largest. Indeed taking baby steps is the way to go. The VGA using 74xxx series logic is an excellent video to demonstrate how you would also develop video output on a FPGA. First you need to build a video timing generator, then once that is working set up pixel coordinate counters, feed the counters directly into the RGB data lines to make sure they generate the counting color pattern you expect, then hook up some memory between the counters and RGB lines to actually generate some images. Once you have that you essentially have a working video card where you can slowly tack on features such as a text mode, or tilemaps. This sort of progressive workflow is excellent especially for starting out since you will have enough to learn as it is and probably won't be interested in design validation trough simulators and timing analysis from the start. But once you had enough headaches debugging a non working design on real hardware you start to see why HDL simulators and writing test benches are a good idea. But still getting a cheap FPGA devboard and just having at it with simple projects is the best way to start.

As for what is possible, all the videos i have linked are perfectly possible on a Z80 with grunty enough video hardware. This also includes "Shadow of the Beast" for the Amiga, all the pretty multi-layer scrolling is the hard work of the video hardware. Each layer is its own image that is being transparently overlayed by the video chip. Additionally the Amiga has bitblit functionality so this is essentially a crude 2D GPU that can move and draw images in memory on its own while the CPU is free for other tasks. So the CPU here has very little work to do as its only running the game logic, updating positions of all enemies, changing coordinates of the layers to make them move in that sweet parallax way and commanding the bitlit to fill in the edges with more of the level as needed.

This video hardware is the reason why graphics on consoles looked so impressive while PC games looked like crap in comparison despite having faster CPUs. The PCs for a long time had very dumb video hardware that could only barf out a framebuffers contents to the monitor and that's it(ignoring text mode). So the CPU had to work hard and draw every single pixel. To get 3D graphics on PCs they had to cheat in all sorts of ways using raycasting, so early 3D games like Wolfenstein3D, Doom, Quake etc. are not actually rendering in 3D, but is actually a 2D world made to look 3D trough graphics trickery. By the time PCs got fast enough to render proper textured polygon 3D graphics, the consoles already had hardware accelerated 3D chips in the Sony PS1 and Nintendo N64 that could look way better and run smoother. Its when PCs got hardware 3D accelerator cards like the Voodoo, that's when they could finnaly rival console graphics.

Even today graphics cards are the ones driving 3D towards looking ever more impressive. Even as CPUs hit the clock speed barrier 15 year ago they kept getting faster at an exponential rate, mainly thanks to the inherently parallel nature of graphics tasks, while 15 years ago graphics cards might have had 16 processing cores in them today they have >1000 cores being fed data from a huge array of DDR memory chips at terabits per second. For a modern PC to render a beautiful highly detailed 3D scene all the CPU has to do is load in all the models and textures, give it the draw call instruction list and say "Hey GPU please render this for me". A few miliseconds later using trillions of math operations and gigabytes of data moved around out pops the finished image while the CPU was doing absolutely nothing.

EDIT:
Oh and if you wan to learn about the various graphics tricks that are used everywhere this is one of the best youtube channels for it:
https://www.youtube.com/watch?v=nBzCS-Y0FcY&feature=youtu.be&t=2310 (https://www.youtube.com/watch?v=nBzCS-Y0FcY&feature=youtu.be&t=2310)
The linked video is one of his more impressive things where he created a polygonal 3D rendering engine in pure C++ code running on the CPU, so it guides you trough all the ideas and math that are used under the hood to generate 3D graphics. Its completely impractical because its slow, but it shows exactly how it works because its coded from the ground up without any graphics library. In his other videos he goes into all sorts of other really common graphics algorithms that are used everywhere like for example the affine transform, vector drawing, pathfinding, colision detection, game physics, edge detection, image processing... etc
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 22, 2019, 08:46:03 pm
Well, that's the next thing - with all that space left over, it would be remiss of me NOT to put an AY-3-8910 sound generator (or something else) in there.  That would save me an entire (troublesome) PCB in my system... but where does that stop, I guess?  ::)
Two notes as preface: 1. There are MOS 6581 (https://github.com/alvieboy/ZPUino-HDL/tree/master/zpu/hdl/zpuino/contrib/NetSID/src) IP cores available, which you can instantiate just like any other VHDL entity, hook up address/data buses, supply with appropriate clocks, and connect to the DAC of your choice. 2. Back in my home computer days, sound programming was my specialty. Over the course I have developed some Opinions on this matter. :)

The Amiga sound hardware was remarkably simple, and it's worth considering as a guide. Each channel isn't much more than a period down-counter, an address up-counter, a sample length down-counter, and a few double-buffered latches. Being relatively insensitive to latency, a double-buffer for sample data allows you to take your sweet time reading the next sample(s) from memory and simplifies its integration into the system. Very likely you have hardware multipliers on the FPGA for volume control, AM effects, and so on. I2S is a standard interface to audio codecs and is pretty easy to use for just digital output: a continuously-running clock, a shift register, and a word (left/right channel) select is about it.

Remember when I half-jokingly suggested putting a Z80 core on the FPGA? Does that perchance remind you of any Sega console's sound hardware? ;) You wouldn't have to worry about DMA at all, just let the software do it...

Quote
Purely to have enough internal RAM to hold the frame buffer.  If it has the RAM I need and can drive an HDMI output without too much hassle, it sounds like a good idea.
You can use those block RAMs as FIFOs very easily (example user guides from Xilinx (https://www.xilinx.com/support/documentation/ip_documentation/fifo_generator/v12_0/pg057-fifo-generator.pdf), Altera (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_fifo.pdf)). You can stream the entire next raster line from the external RAM into them at the fastest pace it allows then deal with it locally according to the pixel rate, a la hierarchical memory (https://en.wikipedia.org/wiki/Memory_hierarchy). In fact, this allows you to decouple the RAM clock from the pixel clock which makes your job a lot easier, enough that you can incorporate existing DRAM/SDRAM/DDR controller cores to expand the framebuffer (or can we now call it "chip") memory without limit.

Quote
I thought you were going to link me to something like Shadow of the Beast on the Amiga. ;D  Do you think what I'm designing would be capable of that sort of output (perhaps at a lower resolution?) 
Eventually. :)  Multi-playfields are largely about memory organization and bandwidth. One key is to decouple the pixel fetch start/stop timing, memory addressing, and row stride from the display window start/stop timing, so that the former can be moved around independently of the latter, and only require that the CPU redraw the columns/rows that would be revealed in the next frame before moving the pixel start address around. Another key observation is that Amiga etc. video memory was often planar-organized (https://en.wikipedia.org/wiki/Planar_(computer_graphics)) to conserve frame buffer memory and use the memory cycles allocated to the pixel data most efficiently. With bit planes being indexed, addressed, and fetched entirely independently, the addition of a dual-playfield mode requires no modifications to the memory fetching system, only a bit of steering logic in the pixel pipeline and a priority encoder to establish Z-index relationships. Have as many playfields as you like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: rstofer on October 22, 2019, 10:28:02 pm
For pixel graphics, there is no reason that both sides of the BlockRAM need to have the same word width.  The CPU can read/write in bytes while the graphics controller can grab up some huge number of bits at a time.

https://www.xilinx.com/support/documentation/user_guides/ug473_7Series_Memory_Resources.pdf (https://www.xilinx.com/support/documentation/user_guides/ug473_7Series_Memory_Resources.pdf)  About page 21

In theory, and I concede to never having tried it, you could organize the video side of the BlockRAM word width to be an entire scan line.

https://www.xilinx.com/support/documentation/user_guides/ug473_7Series_Memory_Resources.pdf (https://www.xilinx.com/support/documentation/user_guides/ug473_7Series_Memory_Resources.pdf)

Of course, with dual port memory, you don't need to do this but it might be a technique to just grab the entire raster line into the pixel shift register during horizontal retrace.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 23, 2019, 12:16:13 am
With "effort", that Max10's PLL and LVDS transmitters are fast enough to directly drive 480p DVI. (HDMI compatible, but, no sound or EDID support)

It would be nice to have sound too.  :(

Understand that DVI transmitter cores are free available.  I'm not sure about HDMI (maybe copyrights, but a public domain transmitter may exist), however when saying sound, this means whatever your sound generator generates, you would need re-sample convert any audio generated to the standard fixed 48Khz audio within the HDMI standard.  Also, HDMI is YUV not RGB like DVI, so, you will also need a color space converter.  (easy peasy as it is nothing more than 3x3 multiply adds...)

Now, the Max10 can run upt to 400Mhz internal and the LVDS serial bus up to 750Mhz.  That means 720p capability, but with only 128kb ram and an 8bit cpu, you are not striving for this...
You have enough logic and hardware multipliers to do the colorspace conversions.
You have the internal dual port ram speed to superimpose translucent text with animated color character fonts.
Enough registers galore to control playfield, sup-pixel video offset of font tiles for smooth scrolling tricks, number of bytes per line with margins.
Also, on your video output mux output layers with translucent colors, don't forget to add pixel / sprite collision detection registers.

In the max10, you should be able to make an enhanced 16 bit version of a 6502 processor running at over 108Mhz, maybe at 8x27Mhz video clock of 216Mhz.  It would make a SNES look like a snail.

You would never have to worry about external Dram access or memory interleave timing.

With all the FPGAs ram as a dual block, one side would be a dedicated video and audio generator while the other would have interrupt free access to an external CUP, or an internal soft-core cpu.

Yes, on my video designs, I have my video read port only side set to 32 bit (note that I have 30bit color video, or 24 bit color with 8bit alpha blend channel) and my other side set to 256bit (I have access to 128bit DDR2 memory modules, yes this speed is needed for a 4 layer 1080p video blender)  In your case, you would want 8bit or 16bit on your read only video output port as you only go up to 256 colors if you want to use 1 byte per pixel.  It also makes access to you font bitmap easily addressable to any byte in ram.   You did say this is for an 8-bit computer.  On the CPU processor side, you can choose 8, 16, 32 bit if you like, but realize you may need to use a byte write enable depending on how your CPU or graphics image processor may move individual bytes around for effects like fill, copy, clear and stencil.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 23, 2019, 01:24:05 am
With "effort", that Max10's PLL and LVDS transmitters are fast enough to directly drive 480p DVI. (HDMI compatible, but, no sound or EDID support)

It would be nice to have sound too.  :(


If the H/W can do DVI-D video, it can also do HDMI with audio. Once you get video working, have a look at this project that implements the HDMI data islands required for proper HDMI video+audio support;

https://github.com/charcole/NeoGeoHDMI

But consider it a stretch goal!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 23, 2019, 05:36:15 am
A thing I would really appreciate is a PCI Video framebuffer, made on neat and fully documented design.
VDU and 2D primitives to support X11 are all it needs to have.

There are PCI bridges to local legacy bus (kind of ISA, 16bit, with fixed address, and IRQ), hence even a simple VGA controller for 8-bit computer can be interfaced.

Not too bad, at all, and this would be seriously appreciated on non-x86 workstations where the only good thing you can do is:
- adding a Matrox M1/M2
- hacking an ATI XL

Both were reverse engineered, hence the support for what the hardware can really do is limited to the 20%

a miniPCI Video Card made on FPGA would be a super premium 


ah, sweet dreams ... are made of this :D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 23, 2019, 02:31:02 pm
A thing I would really appreciate is a PCI Video framebuffer, made on neat and fully documented design.
PCI is quite a simple bus, with full specification publicly available. So I don't see any major obstacles in implementing this. Essentially PCI is nothing more than a DMA channel into the system memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: langwadt on October 23, 2019, 03:38:48 pm
With "effort", that Max10's PLL and LVDS transmitters are fast enough to directly drive 480p DVI. (HDMI compatible, but, no sound or EDID support)

It would be nice to have sound too.  :(

Understand that DVI transmitter cores are free available.  I'm not sure about HDMI (maybe copyrights, but a public domain transmitter may exist), however when saying sound, this means whatever your sound generator generates, you would need re-sample convert any audio generated to the standard fixed 48Khz audio within the HDMI standard.  Also, HDMI is YUV not RGB like DVI, so, you will also need a color space converter.  (easy peasy as it is nothing more than 3x3 multiply adds...)

afaik HDMI supports both YUV and RGB
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 23, 2019, 04:00:06 pm
Yeah you will be able to fit it all into internal block RAM no problem as long as you keep framebuffers small since those tend to be the largest. Indeed taking baby steps is the way to go... But still getting a cheap FPGA devboard and just having at it with simple projects is the best way to start.

I think I'm going to make a start fairly soon with my Cyclone II.  Yes it's old, but I should be able to get a VGA text display up and running, perhaps even with some basic graphics, in the short term.  When the Spartan 6 (LX16) dev board turns up, I'll move development to that and start looking at the switch to HDMI and building out the resolutions a little further, with more work on the GPU side to flesh out the graphics capabilities.

As far as the Intel MAX 10 series (https://www.intel.co.uk/content/dam/www/programmable/us/en/pdfs/literature/pt/max-10-product-table.pdf) goes, I agree they're the probably the best I can get in a package that I am (and more importantly, others are) able to solder by hand.  I'm thinking for the sake of another fiver (~$6), I'll get the 10M50 which has over 200 KB of RAM and should give me all the room I need to do what I want with the graphics and sound.

This leads me on to choice of a development board for the 10M50, though.  Sheesh - they're not cheap for a hobbyist at my level!  I've had a look at these two:

AliExpress DE10 Lite 10M50 CPLD Development Board with VGA (https://www.aliexpress.com/item/32842850135.html) - £74
AliExpress 10M50 Eval Kit with HDMI (https://www.aliexpress.com/item/32680316361.html) - £130

Now, out of the two I prefer the 10M50 Eval Kit - yes, it's nearly £50 more expensive, but it has less rubbish on it that I won't use taking up IO pins and it has an HDMI port built-in.

Anyone have any opinions on these or suggestions for alternatives?

...So the CPU here has very little work to do as its only running the game logic, updating positions of all enemies, changing coordinates of the layers to make them move in that sweet parallax way and commanding the bitlit to fill in the edges with more of the level as needed.

I guess there's no reason why the FPGA won't be a graphics co-processor and blitter in one device if I can build those functions into it.  What was it, jhpadjustable?  Agnus, Denise and Paula rolled into one? ;)


Two notes as preface: 1. There are MOS 6581 (https://github.com/alvieboy/ZPUino-HDL/tree/master/zpu/hdl/zpuino/contrib/NetSID/src) IP cores available, which you can instantiate just like any other VHDL entity, hook up address/data buses, supply with appropriate clocks, and connect to the DAC of your choice.

Yes, I've found AY-3-891x VHDL code as well, so it looks relatively easy to sort out.  It could just be consideration how I get that audio data down the line to the TV.

2. Back in my home computer days, sound programming was my specialty. Over the course I have developed some Opinions on this matter. :)

Ah, pull up a chair and have a beer.  I may need to pick your brains later on when (if!) I get to the point of sorting out audio in VHDL!! ;)

The Amiga sound hardware was remarkably simple, and it's worth considering as a guide. Each channel isn't much more than a period down-counter, an address up-counter, a sample length down-counter, and a few double-buffered latches. Being relatively insensitive to latency, a double-buffer for sample data allows you to take your sweet time reading the next sample(s) from memory and simplifies its integration into the system. Very likely you have hardware multipliers on the FPGA for volume control, AM effects, and so on. I2S is a standard interface to audio codecs and is pretty easy to use for just digital output: a continuously-running clock, a shift register, and a word (left/right channel) select is about it.

You make it sound so easy!  :o  I can just about play the theme tune to Red Dwarf on a keyboard.  There endeth my knowledge and skills on the subject of audio and music!  ;D  I2S? Audio codecs? Digital output?  So I could output in MP3 or something?

You can use those block RAMs as FIFOs very easily (example user guides from Xilinx (https://www.xilinx.com/support/documentation/ip_documentation/fifo_generator/v12_0/pg057-fifo-generator.pdf), Altera (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_fifo.pdf)). You can stream the entire next raster line from the external RAM into them at the fastest pace it allows then deal with it locally according to the pixel rate, a la hierarchical memory (https://en.wikipedia.org/wiki/Memory_hierarchy). In fact, this allows you to decouple the RAM clock from the pixel clock which makes your job a lot easier, enough that you can incorporate existing DRAM/SDRAM/DDR controller cores to expand the framebuffer (or can we now call it "chip") memory without limit.

Okay, that's an interesting idea for when/if I get round to using external RAM (it'd make the FPGA choice a lot cheaper!)  Set up a couple of pixel stream FIFOs in internal RAM and use the external SDRAM to burst-read into the one not being read from at that moment, so access to the external RAM would be in short bursts to read the contents, allowing the GPU to access it for data writes etc. in-between?

Eventually. :)  Multi-playfields are largely about memory organization and bandwidth. One key is to decouple the pixel fetch start/stop timing, memory addressing, and row stride from the display window start/stop timing, so that the former can be moved around independently of the latter, and only require that the CPU redraw the columns/rows that would be revealed in the next frame before moving the pixel start address around. Another key observation is that Amiga etc. video memory was often planar-organized (https://en.wikipedia.org/wiki/Planar_(computer_graphics)) to conserve frame buffer memory and use the memory cycles allocated to the pixel data most efficiently. With bit planes being indexed, addressed, and fetched entirely independently, the addition of a dual-playfield mode requires no modifications to the memory fetching system, only a bit of steering logic in the pixel pipeline and a priority encoder to establish Z-index relationships. Have as many playfields as you like.

There's a heck of a lot of jargon in there I just don't understand - "pixel fetch start/stop timing", "row stride", "display window start/stop timing"... so much to learn.  Is there a book on this stuff anywhere, or a website, or more YT videos?  I have yet to sit down with some spare time and go through some of the linked videos in the YT links people have made in previous replies, though...

Understand that DVI transmitter cores are free available.  I'm not sure about HDMI (maybe copyrights, but a public domain transmitter may exist), however when saying sound, this means whatever your sound generator generates, you would need re-sample convert any audio generated to the standard fixed 48Khz audio within the HDMI standard.  Also, HDMI is YUV not RGB like DVI, so, you will also need a color space converter.  (easy peasy as it is nothing more than 3x3 multiply adds...)

Just clear up a little confusion for me - DVI sort of equals HDMI?  Would I be able to use an HDMI connection to a TV with a DVI IP core?

The colour space converter sounds like a simple bit of VHDL to add to the project, but what about the audio conversion?  Are there IP cores for that sort of thing?

Also, on your video output mux output layers with translucent colors, don't forget to add pixel / sprite collision detection registers.

That'll come later, but yes I'll need to think about how to add collision detection etc.

You would never have to worry about external Dram access or memory interleave timing.

I do like the sound of that.  It's just a high price to pay and I can see that I'll want to try to overcome the issues with external RAM so that I can use a smaller/cheaper FPGA.

...but realize you may need to use a byte write enable depending on how your CPU or graphics image processor may move individual bytes around for effects like fill, copy, clear and stencil.

Huh? Sorry, I don't follow.  Could you expand on this a little, please?   :-\


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 23, 2019, 05:44:18 pm
I mean, if someone develops a simple video card for 8-bit computer, I know to add a PCI interface to it: via PLX chip. Already done, my team has the know/how and a dev-board to manage it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 23, 2019, 06:02:05 pm
Yes having the video output hardware and blitter in the same FPGA makes a lot of sense since both need access to graphics RAM. Its not all that difficult to MUX the memory bus inside the FPGA around to different parts that need it. That blitter will let you move things around in RAM at easily >10 times higher speed than the Z80 could.

In fact you can even use the same graphics RAM to hold audio data too. Typically memory is not needed for that since the audio from the 8bit era tend to be just chiptune like for example the Commodore SID chip. But later on MOD music became popular since it had the flexibility of wave files but was still small in size. This does need a memory to hold the audio samples in RAM for quick access and would be quite a lot of work for a Z80 to turn into wave audio to send to a DAC. So if you want an audio chip that can play pretty much anything you might want to have a MOD player in a FPGA that can play these files from memory without the CPUs intervention. But for a start its best to stick to some basic analog synthesis to generate beeps when you write to its register since that can be written and tested in HDL in a few hours if you know what you are doing.

For audio output out of the FPGA i would just simply have it generate a fast PWM signal that gets smoothed by a RC filter into analog audio. It only takes about 5 lines of code to write a PWM generator in HDL and everyone has a spare resistor and capacitor laying around. Makes for surprisingly high quality audio when the PWM is running fast enugh. But if you want proper hifi quality audio you can always add a I2S DAC chip to the pins. The I2S bus is almost the same as SPI so its really easy to generate in HDL too. You still could not play back MP3 tho because decoding MP3 requires quite a bit of floating point math and im sure your poor Z80 wouldn't enjoy that. It could be possible if you also added a floating point math coprocessor to the FPGA so that the math could run nice and fast, but this is really pushing the Z80 into things its really not meant to do.

As for HDMI and DVI. Pretty much DVI is part of the HDMI feature set. It uses the same 3 data + 1 clock diff pair with the same signaling levels and uses the same TDMS encoding to AC balance the signal and provide error correction. Both DVI and HDMI support the RGB color format, but HDMI can additionally also handle YUV. Its all still just glorified LVDS video with fancy encoding on top. What HDMI does differently is sneaking extra data into the video blanking periods, this is where audio and other stuff is sent, and there is support for encrypting the whole video stream via HDCP (This is just the movie industry trying to keep people from pirating stuff, but its hilariously ineffective). But all this is why you can create a DVI to HDMi adapter by simply cutting apart two cables and splicing together the right pairs, both are almost the same thing just on a different connector.

Id say for a start stick to raw VGA directly from the pins so that you can learn all about video timings in a way that is easy to look at with a scope. Its easy to then turn that into DVI by pretty much just running the exact same signals into a DVI serializer/encoder block rather than straight out the pins. Just get a cheap FPGA board and play around rather than worrying about it. You can always buy a bigger board later on. Just keep in mind that porting code between two FPGAs of the same vendor is pretty easy, porting it to a FPGA from a different vendor is usually not easy at all (The HDL code is perfectly portable but any hardware specific blocks like block RAM and FIFOs are not) and you have to relearn a completely different IDE.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 23, 2019, 06:18:16 pm
I mean, if someone develops a simple video card for 8-bit computer, I know to add a PCI interface to it: via PLX chip. Already done, my team has the know/how and a dev-board to manage it.
If the only thing you want from the card is to hold a bitmap and output it via some interface, this can be done using Vivado with zero HDL code: MIG to interface with framebuffer memory, PCIE to AXI bridge to read/write data to the framebuffer from the host, "Video Frame Buffer Read" to stream frame from memory, VIC and PHY of your choice to actually output the video to the interface of your choice.
But a video card is far from being only "framebuffer adapter". In addition to all of above it needs to provide some kind of drawing and composition functions. This is even more important if your CPU is very slow. And this is the hard part.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 23, 2019, 07:06:02 pm
I guess there's no reason why the FPGA won't be a graphics co-processor and blitter in one device if I can build those functions into it.  What was it, jhpadjustable?  Agnus, Denise and Paula rolled into one? ;)
Eventually ;) Paula's duties included ADCs for the game port, DACs for audio, the UART (you probably already have one) and floppy disk I/O (you probably don't have one). Those don't directly translate to the FPGA model, but she can be there in spirit.

Quote
Ah, pull up a chair and have a beer.  I may need to pick your brains later on when (if!) I get to the point of sorting out audio in VHDL!! ;)
I'm more of a Verilog guy but cheers, I'll keep an eye out and help out where I can. :)

Quote
You make it sound so easy!  :o  I can just about play the theme tune to Red Dwarf on a keyboard.  There endeth my knowledge and skills on the subject of audio and music!  ;D  I2S? Audio codecs? Digital output?  So I could output in MP3 or something?
Not even Popcorn? For shame! Anyway... codec has an archaic definition of a full-duplex digital-analog converter, an ADC and DAC in one package, usually with a common clock and common framing signals. I should have said ADC/DAC or something like that. MP3 output would be possible, but doesn't seem very interesting due to the lack of direct output devices and the latency, and the rather large number of gates required. TOSlink might be cool, if you have a use for it. The nice thing about all this extra hardware is that you can place footprints on the board for it and not stuff them, or stuff them and just not hook your HDL up to them, leaving them as exercises for the experimenter.

Quote
Okay, that's an interesting idea for when/if I get round to using external RAM (it'd make the FPGA choice a lot cheaper!)  Set up a couple of pixel stream FIFOs in internal RAM and use the external SDRAM to burst-read into the one not being read from at that moment, so access to the external RAM would be in short bursts to read the contents, allowing the GPU to access it for data writes etc. in-between?
Better than that, you can use a single FIFO and fill it whenever you feel like it and there's room. You don't need to double buffer because they're inherently semi-dual ported. But you've got the general idea right.

Quote
There's a heck of a lot of jargon in there I just don't understand - "pixel fetch start/stop timing", "row stride", "display window start/stop timing"... so much to learn.  Is there a book on this stuff anywhere, or a website, or more YT videos?  I have yet to sit down with some spare time and go through some of the linked videos in the YT links people have made in previous replies, though...
The Amiga HRM I linked earlier is an excellent, accessible resource that's fit for people with basic programming and hardware knowledge. While they won't tell you much about the gate-level implementation, Chapter 3, Playfield Hardware, describes the general concepts of raster video display in the context of the specific case of the Amiga OCS. Translating from my language to theirs, pixel fetch is called data fetch, row stride is approximately equivalent to playfield width, and display window is display window.

Quote
Huh? Sorry, I don't follow.  Could you expand on this a little, please?   :-\
I believe he's referring to the rather common possibility that an external RAM chip's external data bus is more than one byte wide, and therefore has a few extra byte-select signals that need to be considered when writing only part of its total width. I think you'll find this ISSI pseudo-static RAM in a hobbyist-friendly TSOP-II package (https://www.digikey.com/products/en?mpart=IS66WV51216EBLL-55TLI&v=706) and its datasheet accessible and interesting. Its byte write enables are UB# and LB#. They're much like an extra set of chip enables for each separate byte, so that only the desired byte parts of the two-byte-wide bus are driven or sampled. The truth table on datasheet page 3 and timing diagrams throughout may help.

So if you want an audio chip that can play pretty much anything you might want to have a MOD player in a FPGA that can play these files from memory without the CPUs intervention.
As someone who is not completely unknown to the exotica branches of the Amiga audio community... Hard-coding the MOD format in HDL? Just... no. It will only get in the way. I would strongly suggest, for simplicity, borrowing the Amiga's audio architecture whole, and letting the main CPU be interrupted at however many ticks per second to adjust the DMA/pitch/volume registers as needed. That way it's much easier to borrow channels for sound effects over/under the music (if desired), and allows for 16-bit samples, various packed tracker module formats or multichannel formats like FastTracker, and formats that are not reducible to the drum-machine tracker paradigm, such as TFMX. We've got to give the poor Z80 something to do, haven't we? ;D

Since this isn't for a proprietary product, IMHO it's worth leveraging any open IP cores that can help rather than do all that from scratch. I think MP3 needs more than a floating point coprocessor, probably closer to a complex math accelerator with its own (small) program store to do IDCTs and such.

Quote
(The HDL code is perfectly portable but any hardware specific blocks like block RAM and FIFOs are not) and you have to relearn a completely different IDE.
But most logic synthesizers will be able to infer memory from HDL, perhaps with a bit of coaxing, and FIFOs are just control logic around those memories, no? At the speeds of interest, fabric implementation of FIFO functionality would do, no?

But a video card is far from being only "framebuffer adapter". In addition to all of above it needs to provide some kind of drawing and composition functions. This is even more important if your CPU is very slow. And this is the hard part.
CGA outputs video. It's in the form of a card. What exactly are you insinuating here?   :box:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 23, 2019, 07:39:37 pm
As someone who is not completely unknown to the exotica branches of the Amiga audio community... Hard-coding the MOD format in HDL? Just... no. It will only get in the way. I would strongly suggest, for simplicity, borrowing the Amiga's audio architecture whole, and letting the main CPU be interrupted at however many ticks per second to adjust the DMA/pitch/volume registers as needed. That way it's much easier to borrow channels for sound effects over/under the music (if desired), and allows for 16-bit samples, various packed tracker module formats or multichannel formats like FastTracker, and formats that are not reducible to the drum-machine tracker paradigm, such as TFMX. We've got to give the poor Z80 something to do, haven't we? ;D

Since this isn't for a proprietary product, IMHO it's worth leveraging any open IP cores that can help rather than do all that from scratch. I think MP3 needs more than a floating point coprocessor, probably closer to a complex math accelerator with its own (small) program store to do IDCTs and such.

Quote
(The HDL code is perfectly portable but any hardware specific blocks like block RAM and FIFOs are not) and you have to relearn a completely different IDE.
But most logic synthesizers will be able to infer memory from HDL, perhaps with a bit of coaxing, and FIFOs are just control logic around those memories, no? At the speeds of interest, fabric implementation of FIFO functionality would do, no?

Well i didn't mean a fully autonomous MOD file format player that could read a .mod file byte by byte. Just audio hardware that is well suited for playing it back like having the ability to play back various wave samples from memory at various pitch with multiple channels. Makes it easy to have very impressive sound without a ton of HDL code or a lot of CPU effort to play it.

Yeah its possible for the compiler to infer block RAM into a design, but i never really trusted it with doing that since small details in the way you implement it in HDL can make the compiler refuse to do it because it might not look similar enough to the hardware block. But it is not only for block ram, similar goes for other hardware features like PLLs, hardware assisted serdes, DDR pin drivers, retiming flipflops inside IO pin logic etc... So offten the way it is done for block RAM is that an abstraction layer is put in place where a HDL file holds the implementation module for the block RAM and upon porting it you are supposed to replace the implementation with your vendors one and implement any logic around it to get it to provide the same signals (Like flip some lines around, add a latch if it needs it, make the reset work the same way...).

And overall the vendors tools often provide a sizable collection of useful auto generated building blocks. This ranges from simple stuff like a RAM or FIFO to interfaces like DDR2 memory controllers to stuff like heavily chip optimized FFT, DDS, FIR filters etc... And goes on to even broader tools that generate entire systems like Altera Qsys that automatically generates memory and streaming buses to connect components such as softcores, memory, peripherals etc... magically taking care of stuff like bus width and timing adaption, multimaster bus arbitration, addressing etc... (I actually quite miss that tool when working with Lattice chips)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 23, 2019, 09:53:28 pm
If the only thing you want from the card is to hold a bitmap and output it via some interface, this can be done using Vivado with zero HDL code: MIG to interface with framebuffer memory, PCIE t

PCI, not PCIe, and I want to the PCI stuff done via PLX. I don't want anything done in FPGA regarding the PCI. I have a lot of experience with PCI, and not a thing I want to handle in FPGA.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 23, 2019, 09:54:13 pm
Well i didn't mean a fully autonomous MOD file format player that could read a .mod file byte by byte. Just audio hardware that is well suited for playing it back like having the ability to play back various wave samples from memory at various pitch with multiple channels. Makes it easy to have very impressive sound without a ton of HDL code or a lot of CPU effort to play it.
That I can absolutely agree with. As I mentioned to nockieboy upthread, each channel isn't much more than a handful of down-counters and double-buffers attached to a DMA channel. Then multiply, sum, and ship to the DAC.

Quote
Yeah its possible for the compiler to infer block RAM into a design, but i never really trusted it with doing that since small details in the way you implement it in HDL can make the compiler refuse to do it because it might not look similar enough to the hardware block. But it is not only for block ram, similar goes for other hardware features like PLLs, hardware assisted serdes, DDR pin drivers, retiming flipflops inside IO pin logic etc... So offten the way it is done for block RAM is that an abstraction layer is put in place where a HDL file holds the implementation module for the block RAM and upon porting it you are supposed to replace the implementation with your vendors one and implement any logic around it to get it to provide the same signals (Like flip some lines around, add a latch if it needs it, make the reset work the same way...).

And overall the vendors tools often provide a sizable collection of useful auto generated building blocks. This ranges from simple stuff like a RAM or FIFO to interfaces like DDR2 memory controllers to stuff like heavily chip optimized FFT, DDS, FIR filters etc... And goes on to even broader tools that generate entire systems like Altera Qsys that automatically generates memory and streaming buses to connect components such as softcores, memory, peripherals etc... magically taking care of stuff like bus width and timing adaption, multimaster bus arbitration, addressing etc... (I actually quite miss that tool when working with Lattice chips)
All very good points.

I haven't played very deeply in the extra tools of Quartus and never even opened up Platform Designer. That looks really handy. Next time I have an FPGA project in front of me I'm going to have to play with that. This is why I come here  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 23, 2019, 09:56:24 pm
But a video card is far from being only "framebuffer adapter". In addition to all of above it needs to provide some kind of drawing and composition functions. This is even more important if your CPU is very slow. And this is the hard part.

I said with the minimal 2D functions to support X11.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 24, 2019, 02:48:54 am
For pixel graphics, there is no reason that both sides of the BlockRAM need to have the same word width.  The CPU can read/write in bytes while the graphics controller can grab up some huge number of bits at a time.

The SEGA Geneis (Megadrive) uses a similar idea with the uPD41264 chip made by NEC :D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2019, 04:32:41 am
...but realize you may need to use a byte write enable depending on how your CPU or graphics image processor may move individual bytes around for effects like fill, copy, clear and stencil.

Huh? Sorry, I don't follow.  Could you expand on this a little, please?   :-\

Ok, understand that the biggest cheat you have going for you when using the MAX10 internal static ram block is that on one side, for your dedicated video graphics and sprites and audio output, you will use an 8 bit port with an address which points to each individual byte.  You can get 1 new byte read 216 million times a second while only needing 1/8 for a true 256 color paleted image, another access cycle for a font byte image lookup, another for a sprite and another 4 or so once every H-sync for audio data.  Sorta like the Amiga Paula and Denise.

(This is separate of you global screen offset controls generally used for oversized image scrolling)  Now, if you also want a Blitter like the Amiga Agnus, this would involve reading a reference graphic and reading the destination display memory, working out the source image transparent stencil bits, within logic registers, paste over the destination read source memory so you are effectively singling out individual bits, then writing that logic register's result back into the destination display memory.  This is the hassle of pasting graphics with transparent bits where you also may want to shift left and right the bits of the source image data to move a pasted graphic 1 pixel at a time onto a bitplane style graphics.  Having this hardware blitter remover you 8 bit CPU from doing this manually when you want to paint brush images onto a bitplane style display.  You have the luxury because of the Max10's speed, logic density, and that dual port ram's nature to place such an image blitter on the 8 bit port side, or on the CPU read/write port side, or even half and half.

In 256 color, byte per pixel mode, just read the source rectangle graphic data and only write the pixel bytes to the destination if the stencil isn't transparent.  Wow, so much simpler but you need a whole lot of video memory to keep every pixel a single byte.  (This would make an insane arcade machine for 20 years ago, but you would want at least 2 full video page memories.)  (I wish the Amiga 1000 had 2mb chipram with an allowable 8 ram and worked with 8bit and 16bit pixels only, no bitplane rubbish, it would have flown except for the slow logic of the 1984 era when it was engineered, all they had to do was get the ram working at 28.6Mhz instead of 14.3Mhz, and 2mb of it the cpu didn't need to go any faster.  The price of memory would have been the killer.)

On the other side of you dual port memory you may also use a wider bus like 16 bits to interface with your CPU, however, what I am saying is if you do so, in Altera's/Intel's dual port memory configuration tool, you have a byte-enable feature which allows when writing to your dual-port ram's 16 bit side, writing to only the high or low 8 bits, or both.  This write-masking is necessary for CPUs doing an 8 bit write accessing a 16 bit wide ram.  Otherwise, your CPU will need to do a 'Read-Modify-Write' to write only 8 bits on that side.

Now everything I'm telling you is possible with relative ease since you do not have to wait for any external ram cycles and having to cache read and write bursts from external dram and it's controller.  You do not need to pipe anything at all.  However, going the other route with large external memory and speed, you can always simulate a bitplane display for your 8 bit cpu and just have 16 bit word pixels and do everything like a software emulator which grants you some enormous flexibility, but you will always be refresh generating a display, a page behind with dedicated buffers to cache memory with tons of wasted dram reads to address single bytes in the middle of larger bursts just to get to those single key important bytes whenever you need random access.  Otherwise, you will be either engineering a smart cache mechanism, or slowing everything down to even faster DDR memory's precharge and post charge cycles.   Normal DRam in some cases wont be any faster, but sequential bursts will be like lightning in comparison.  Other than painting a line of video,  how often does that happen in a 8 bit cpu world which has no smart cache.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2019, 07:11:53 am
Just so we are clear, there exist cheaper FPGAs with more than 1 megabit pr internal ram out there, but, you would need a VCCIO and VCC core supply & bootprom.  Example:


1.9 megabit core for 16$  (Good for animated 360x240x256colors with 2 fame buffers for animation plus another 80kb for software)
It also has double the logic elements...
https://www.digikey.com/product-detail/en/lattice-semiconductor-corporation/LFE5U-45F-6BG256C/220-2198-ND/9553911 (https://www.digikey.com/product-detail/en/lattice-semiconductor-corporation/LFE5U-45F-6BG256C/220-2198-ND/9553911)
https://www.mouser.com/ProductDetail/Lattice/LFE5U-45F-6BG256C?utm_term=LFE5U-45F&qs=w%2Fv1CP2dgqpblS%252b2xYE99A%3D%3D&utm_campaign=LFE5U-45F-6BG256C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice (https://www.mouser.com/ProductDetail/Lattice/LFE5U-45F-6BG256C?utm_term=LFE5U-45F&qs=w%2Fv1CP2dgqpblS%252b2xYE99A%3D%3D&utm_campaign=LFE5U-45F-6BG256C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice)

Eval board is expensive since it comes with a 3.8Megabit FPGA, but, it gives you play room.

Also, the serdes on this Lattice part is fast enough to directly drive DVI/HDMI 1080p.
You'll be using so few IOs that a 4 layer PCB would be fine.
And you can still place a single DDR2/3 ram chip on the PCB if you like...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 24, 2019, 04:56:46 pm
Also, the serdes on this Lattice part is fast enough to directly drive DVI/HDMI 1080p.
Nope, no SERDES on that part. Anyway, Lattice requires a subscription license to use SERDES-enabled chips so it would be useless to open-hardware hobbyists if it did. The BGA package is also a bit impractical, the comparatively generous 0.80mm pitch notwithstanding.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 24, 2019, 05:07:29 pm
Also, the serdes on this Lattice part is fast enough to directly drive DVI/HDMI 1080p.
Nope, no SERDES on that part. Anyway, Lattice requires a subscription license to use SERDES-enabled chips so it would be useless to open-hardware hobbyists if it did.

Yes. The only ECP5 parts that have SERDES are the LFE5UMxx.
http://www.latticesemi.com/en/Products/FPGAandCPLD/ECP5 (http://www.latticesemi.com/en/Products/FPGAandCPLD/ECP5)

One way of evaluating it AND get a free license for this part is to buy a VERSA kit: http://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP55GVersaDevKit (http://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP55GVersaDevKit)
(I think the license is restricted to the part used on this board:  LFE5UM5G-45F, but a lot can be done with it!)

There are promotional prices on those boards on a regular basis. I bought the VERSA board for the ECP3 a few years ago for $99. The VERSA ECP5 is about $250 and occasionally can be had for $99 too.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2019, 08:17:11 pm
Also, the serdes on this Lattice part is fast enough to directly drive DVI/HDMI 1080p.
Nope, no SERDES on that part. Anyway, Lattice requires a subscription license to use SERDES-enabled chips so it would be useless to open-hardware hobbyists if it did.

Yes. The only ECP5 parts that have SERDES are the LFE5UMxx.
http://www.latticesemi.com/en/Products/FPGAandCPLD/ECP5 (http://www.latticesemi.com/en/Products/FPGAandCPLD/ECP5)

One way of evaluating it AND get a free license for this part is to buy a VERSA kit: http://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP55GVersaDevKit (http://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/ECP55GVersaDevKit)
(I think the license is restricted to the part used on this board:  LFE5UM5G-45F, but a lot can be done with it!)

There are promotional prices on those boards on a regular basis. I bought the VERSA board for the ECP3 a few years ago for $99. The VERSA ECP5 is about $250 and occasionally can be had for $99 too.
I'm sorry, yes, you are correct for getting the 3 gigabit to work, so, 1080p is out.  But for 480p, the standard DQs are fast enough, especially if you user DDR IOs, and the earlier posted verilog DVI/HDMI out serialiser is manually written which does not require the use of Lattice's embedded serdes function.  All it requires is 4 parallel balanced DQ ports which can serial shift at 216Mhz (108Mhz DDR) from a single bank clock.  The chip I listed can handle that with ease.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 24, 2019, 08:50:13 pm
All it requires is 4 parallel balanced DQ ports which can serial shift at 216Mhz (108Mhz DDR) from a single bank clock.  The chip I listed can handle that with ease.

Oh, yeah. I guess maybe even lower-end Lattice FPGAs could do this.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 24, 2019, 09:08:08 pm
All it requires is 4 parallel balanced DQ ports which can serial shift at 216Mhz (108Mhz DDR) from a single bank clock.  The chip I listed can handle that with ease.
AFAIK HDMI requires a pixel clock to be at least 25 MHz, which corresponds to 250 Mbps per data lane (1:10 serialization). So 216 Mbps is not going to be enough.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2019, 09:21:12 pm
All it requires is 4 parallel balanced DQ ports which can serial shift at 216Mhz (108Mhz DDR) from a single bank clock.  The chip I listed can handle that with ease.
AFAIK HDMI requires a pixel clock to be at least 25 MHz, which corresponds to 250 Mbps per data lane (1:10 serialization). So 216 Mbps is not going to be enough.
Ok, 270Mhz then, still well within the Lattice part I mentioned which can do 500Mhz serial data on the DDR pins.

Generic DDRX1 Outputs With Clock and Data Aligned at Pin (GDDRX1_TX.SCLK.Aligned) Using PCLK Clock Input - Figure 3.9: All Devices — -8 500 — -7 500 — -6 500 Mb/s...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 25, 2019, 05:58:09 am
Yeah Lattice are the most cost effective FPGAs that you can still easily buy and get proper software for. The  nice bank per buck ECP5 family is fast enough to do it.

The HDMI spec calls for a pixel clock of at least 25 Mpixels/s. For 24bit RGB this means each of the 3 diff pairs carries 8 bits per pixel but the encoding increases that to 10bit so the minimum bitrate of a HDMI link is 25M*100 = 250 Mbit

In general a lot of FPGAs will have some form of "baby serdes" on some or most pins. These are sometimes just a DDR buffer but more often are 1:4 serdes. This brings the bitrate down to only being 1/8 per signal in the FPGA fabric as that requires the signals to be generally under about 200MHz. The ECP5 family does include this functionality on the left and right banks and according to the datasheet will run at between 624Mbit and 800Mbit (depends on speed grade). So this means its 2 or 3 times faster than the minimum HDMI spec.

Even if you don't use the right bank to get this functionality you still get DDR buffers on all banks in the ECP5 and those get 500Mbit (regardless of speed grade) but as a downside you only get 1:2 reduction in signal speed so you have to deal with two 250MHz SDR streams in the FPGA fabric and that does take some careful design to run fast enough. Its possible that maybe the code generator in the Lattice Diamond IDE can add a larger ratio sredes in the logic fabric, but i think the code generator always wants the nice pin with hardware 1:4 and 1:7 reduction.

I think the Lattice Crosslink family has some even faster buffers in the IO pins.

So for low resolutions not a problem. Its things like 1080p that would be a problem since the lowest you can get away with is 130MHz pixel clock and this means 1.3Gbit per lane. Im pretty sure no FPGA out there can do that with regular IO functionality so proper dedicated serdes is a must for that and yeah the prices of those FPGAs tend to be ridiculous.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 25, 2019, 06:31:57 am
So for low resolutions not a problem. Its things like 1080p that would be a problem since the lowest you can get away with is 130MHz pixel clock and this means 1.3Gbit per lane. Im pretty sure no FPGA out there can do that with regular IO functionality so proper dedicated serdes is a must for that and yeah the prices of those FPGAs tend to be ridiculous.
Xilinx 7 series at speed grade of 2 and above can officially do 1250 Mbps, and unofficially does 1080p@60 (1480 Mbps or something like that). "High performance" banks can go to 1600 Mbps, but it only supports Vccio of 1.8V and below.
I think Xilinx did a right thing to integrate up to 1:8 SERDES (can be increased up to 1:14 by cascading) into each and every IO pin tile, as users can pick pins which are more convenient from layout point of view, instead of reading through manual to figure out which ones are they supposed to use.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 25, 2019, 06:51:39 am
Oh that's certainly a nice development from Xilinix. I haven't seen such high IO speeds from reasonably priced FPGAs before.

Anyway my point was that most modern FPGAs out there have enough IO performance to easily meet the minimum HDMI speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Canis Dirus Leidy on October 25, 2019, 08:54:32 am
By the way. ZX Evolution (http://nedopc.com/zxevo/zxevo_eng.php): FPGA (ACEX 1K) assisted ZX Spectrum compatible computer with enhanced graphic modes and VGA-compatible (due to internal scandoubler) video output. Copying it exactly makes no sense (unless Mr. Wells lends his time machine), but a glimpse into the Verilog code (http://svn.zxevo.ru/listing.php?repname=pentevo) may be useful.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2019, 10:06:58 am
Right, so... just to clear up any confusion (on my part!  :o) and to reach a general consensus amongst the professionals (you guys!  ;D), can we agree on an FPGA I should choose, bearing in mind my wish-list (listed below for clarity, in order of priority)?

MUST:

NICE TO HAVE:

The MAX 10 (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/max-10/m10_overview.pdf) is looking like a good option, but with all this talk of Lattice and knowing there are even more manufacturers out there, I'd like to get a good indication of which one you think will fit the bill for me?  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 25, 2019, 11:15:11 am
Yeah Lattice is the 3rd biggest player in the FPGA market. They specialize in being lower cost than the big leading two. Tho the tools on Lattice are not quite as good while still flowing the same free basic version and expensive as hell full version scheme.

Since the cost of the chip is not that high of a priority for you you better stick to Intel or Xilinx as they have better tools. Personally i enjoy Intel/Altera tools the most and i really like the Qsys/SOPC builder tool that wires up your digital computing systems auto-magically.

Previous Altera MAX series tended to be 5V tolerant but the MAX10 not anymore. Then again if your chips are TTL it will all work on 3.3V signals just fine as long as there are resistors to limit current, or you can just use a single 8bit logic buffer to do it proper since the data bus is only 8 bits wide anyway. You still get the around 600 to 700Mbit serial IO performance so HDMI should be just fine, but having 90KB of internal block RAM is going to be quite expensive on it.

For a start just look around at what dev boards you can get from the vendor you like. Be prepared to pay $50 and up for a decent one (But sometimes >$100). The decently sized boards always have some form of SRAM or SDRAM or DDR2 on them. HDMI tends to be rare but if it has VGA its probably good enough for now as you can likely add your own HDMI port later on. (Remember you want to first learn how to use these FPGAs so start simple)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on October 25, 2019, 02:54:18 pm
If this is your first such development, I would personally still start with VGA first. And maybe consider HDMI later on, when all the rest works and I've gotten more proficient. VGA is still easier to implement, and easier to debug. Some people seem to make it look as though HDMI is just a picnic, but they fail to tell you that they probably spent hours getting it right back when they started. And now of course it all looks very easy. Just saying, do as you wish and don't mind me. Now if the HDMI spec is mainly to select an appropriate FPGA that you know will allow you to do HDMI later on, that's a valid point.




Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2019, 04:38:07 pm
Now if the HDMI spec is mainly to select an appropriate FPGA that you know will allow you to do HDMI later on, that's a valid point.

Absolutely it is.  I don't want to mess around too much swapping FPGAs as I develop - I'd rather get the 'end game' FPGA, and learn from the ground-up on that.  I'm assuming, of course, that there's no real reason I can't develop a VGA output on a dev board with HDMI fitted?  Or offer VGA AND HDMI as outputs on the final version, for example?

Yeah Lattice is the 3rd biggest player in the FPGA market. They specialize in being lower cost than the big leading two. Tho the tools on Lattice are not quite as good while still flowing the same free basic version and expensive as hell full version scheme.

Purely out of interest, is there anything on the expensive-as-hell full version software that a beginner like me would want?

Since the cost of the chip is not that high of a priority for you you better stick to Intel or Xilinx as they have better tools. Personally i enjoy Intel/Altera tools the most and i really like the Qsys/SOPC builder tool that wires up your digital computing systems auto-magically.

The cost is still a priority, just not quite as high as the factors before it in the list.  ;)

The only thing holding me back from the MAX 10 series is the cost of the evaluation board, but I can stretch to it if needs be - I just want to make sure no-one's going to pipe up after I've ordered one with a comment along the lines of, "Haven't you checked out the Costmin LogicBlaster IV?  It does everything you want, packs 200KB of RAM, makes the tea and takes your dog for a walk and the dev board includes HDMI and VGA and only costs £50..."  Because that would make me cry...  ;D

Oh, I also meant to say that I have no preference for VHDL over Verilog at all - it's just that the only exposure I've had to FPGA code is via Grant Searle's Multicomp code, which is in VHDL, hence I've spoken about VHDL in this discussion but don't mean to exclude Verilog.  I'm right at the start with this project, so I am ultimately extremely flexible in which path I take.

Previous Altera MAX series tended to be 5V tolerant but the MAX10 not anymore. Then again if your chips are TTL it will all work on 3.3V signals just fine as long as there are resistors to limit current, or you can just use a single 8bit logic buffer to do it proper since the data bus is only 8 bits wide anyway.

System Interface Considerations:
ALL the chips in my computer that would connect to the FPGA are either 74HCT buffers for data / address / most command signals, or the CMOS Zilog Z80 itself for a couple of control signals (and these will be going TO the Z80 FROM the FPGA and are active-low with 5v pull-ups on them).

The only area for potential variation is in the address bus (from the MMU), which may have HCT, HC or LS logic driving the extended address lines.

You still get the around 600 to 700Mbit serial IO performance so HDMI should be just fine, but having 90KB of internal block RAM is going to be quite expensive on it.

The 10M50 (https://www.intel.co.uk/content/dam/www/programmable/us/en/pdfs/literature/pt/max-10-product-table.pdf) is the most attractive proposition, I think, with 200 KB of RAM in it.

For a start just look around at what dev boards you can get from the vendor you like. Be prepared to pay $50 and up for a decent one (But sometimes >$100). The decently sized boards always have some form of SRAM or SDRAM or DDR2 on them. HDMI tends to be rare but if it has VGA its probably good enough for now as you can likely add your own HDMI port later on. (Remember you want to first learn how to use these FPGAs so start simple)

Well, the 10M50 is available on a dev board with HDMI on it.  That would provide me with a good hardware example to work from and all I'd need to worry about would be getting the FPGA set up properly to display something on it.  I could always wire up a VGA socket as well and go that path first.  It's darn expensive (https://www.intel.com/content/www/us/en/programmable/products/boards_and_kits/dev-kits/altera/kit-max-10m50-evaluation.html) though.  :palm:

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Canis Dirus Leidy on October 25, 2019, 05:34:34 pm
Well, the 10M50 is available on a dev board with HDMI on it.  That would provide me with a good hardware example to work from and all I'd need to worry about would be getting the FPGA set up properly to display something on it.  I could always wire up a VGA socket as well and go that path first.  It's darn expensive (https://www.intel.com/content/www/us/en/programmable/products/boards_and_kits/dev-kits/altera/kit-max-10m50-evaluation.html) though.  :palm:
Come to the Cyclone 10 side, we have cookies (https://www.aliexpress.com/item/33050240958.html)!  >:D (and QFP package (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/pt/cyclone-10-lp-product-table.pdf))

P.S. But HDMI have another problem: high-speed signals PCB routing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on October 25, 2019, 05:48:13 pm
The premium features tend to be the same with all the vendors. Things like faster compilation trough the use of more cores and partial recompilation (This is more useful than it sounds because even simple designs can sometimes compile for minutes even on a fast PC) and it usually also unlocks a large set of IP blocks for full use. The free version also usually will not compile for the ridiculously large FPGAs that cost 1000s of dollars per chip.

The set of IP blocks mentioned before tend to  be available in the free version in there crippled form with a "death timer". This is a counter buried deep inside the encrypted IP block that is set to run out in abut 2 hours of running at typical clock speeds. Once it runs out it kills the IP block and renders it unusable. This is nice in that it lets you use it, but not so nice that the FPGA has to be rebooted to get it to work again after the timer runs out. Unluckily the DDR2 controller tends to be once of these crippled premium IPs.

That dev board you linked is actually a pretty good deal. The MAX10 chip on that board is very expensive, i couldn't find the price for the exact part but the slower speed grade version of that chip costs 135 USD if you ware to buy a single one off DigiKey as a mere mortal, so the exact one should be even more expensive. Its actually cheaper to buy the board and desolder the chip rather than buying the chip new(go ahead and try to buy this chip). Tho if you are a commercial costumer and have good relations with Intel they will give you way way cheaper deals directly, especially if you ask for 1000 of them (They likely won't even respond if you ask anything under 100). This is why i brought up that chips with this much memory are expensive, but is also a very powerful chip. For integer math speed it could rival the performance of modern CPUs in PCs (This is why FPGAs got used for cryptocurency mining before GPU compute and ASICs came around). And yet this is actually still a low "low cost FPGA" compared to the other chips they make.

Verilog or VDHL it does not matter. Both are supported by all vendors. I personally prefer Verilog because its simpler and involves less fancy syntax typing. Not that one or the other is better, just my taste went with Verilog after trying one and the other. You can mix VHDL and Verilog in the same project and compile it together anyway.

As for having ready to go hardware, yes that is very useful with FPGAs as they often have a lot of support circuitry (Gazilion power rails, boot memory, config pins) and you always get a JTAG programmer on dev board included. Often this JTAG programmer can be rewired to connect to an external FPGA to turn the dev board into a universal programmer for that vendors chips.

Its your decision what you want to spend the money on but that MAX10 dev board is a pretty good deal for what you get. You can always add a VGA port onto the IO headers to start off there and PWM audio output via a single pin. Believe me you will want to take things slowly because getting into FPGAs is quite a learning curve(Id say significantly more so than with MCUs) but lucky for you that VGA video generation is one of the very nice beginner projects. This is mainly because you can slowly build on it in steps and each incremental step is simple enough to debug purely using a logic analyzer and no simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Canis Dirus Leidy on October 25, 2019, 06:04:48 pm
Unluckily the DDR2 controller tends to be once of these crippled premium IPs.
Ahem. Due to these
Package type - NOT BGA where possible due to hand-soldering requirement
you can forget about this IP restriction.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2019, 09:46:43 pm
Well, the 10M50 is available on a dev board with HDMI on it.  That would provide me with a good hardware example to work from and all I'd need to worry about would be getting the FPGA set up properly to display something on it.  I could always wire up a VGA socket as well and go that path first.  It's darn expensive (https://www.intel.com/content/www/us/en/programmable/products/boards_and_kits/dev-kits/altera/kit-max-10m50-evaluation.html) though.  :palm:
Come to the Cyclone 10 side, we have cookies (https://www.aliexpress.com/item/33050240958.html)!  >:D (and QFP package (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/pt/cyclone-10-lp-product-table.pdf))

P.S. But HDMI have another problem: high-speed signals PCB routing.
The internal ram bits on that Cyclone10 are too few for the OP to completely contain his project.  If the OP wanted a SDRam version, then that dev board would be fine, but when developing the opensource graphics board, he would need a FPGA with enough IOs for the SDRam and other stuff which may not be possible when porting his project to the 144pin TQFP version of the Max10.  With such a setup, the op will need to engineer a multiport SDRam controller which cache banks for display refresh.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2019, 10:04:54 pm
If this is your first such development, I would personally still start with VGA first. And maybe consider HDMI later on, when all the rest works and I've gotten more proficient. VGA is still easier to implement, and easier to debug. Some people seem to make it look as though HDMI is just a picnic, but they fail to tell you that they probably spent hours getting it right back when they started. And now of course it all looks very easy. Just saying, do as you wish and don't mind me. Now if the HDMI spec is mainly to select an appropriate FPGA that you know will allow you to do HDMI later on, that's a valid point.
Your right, I have too many years of experience in FPGA video and make it seem too easy.
I also picked the MAX10 144pin with all ram inside since the OP's development of a display controller can operate 100% internally without worries about Dram interface errors and logic.

The design is simple enough that the user can make 5 of his own 2$ dev boards PCBs from JLPCB, but yet again, I'm talking from experience I have with Intel chips.

One thing about FPGA analog VGA video out, remember, use a 5V TTL level shifter/line driver when sending the HS and VS!!!  Some monitors work fine feeding 3.3v TTL on these 2 signals, some just wont even turn on, and some monitors sit on the edge turning on, then off, or the syncs go haywire.  The OP wont know what hit him if he makes the mistake of using 3.3v for HS and VS outputs then many third party users start experiencing problems...  |O   A 5v powered 74HCT04 with 3 outputs paralleled for extra drive current for each sync signal should work fine.  At the inputs of the '04, I usually add a single 470ohm pullup to 3.3v since Altera's high drive on their IO pins have an unusual current pull curve as they reach the VCCIO and this just cleans that up a little when driving 3 cmos inputs in parallel on a 5v CMOS part.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2019, 10:18:53 pm
For the HDMI interface, the Max10 dev board used this IC when interfacing with the HDMI for ESD protection and to deal with the 5V DDC signals:
https://www.digikey.com/product-detail/en/texas-instruments/TPD12S016PWR/296-29690-1-ND/2762248 (https://www.digikey.com/product-detail/en/texas-instruments/TPD12S016PWR/296-29690-1-ND/2762248)

It does the ESD protection and level shifts/converts the 5v DDC I2C signals from the HDMI to the FPGA's 3.3v.

It is used in the Max 10 DEV board mentioned above.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on October 25, 2019, 11:03:34 pm
I don't know why you guys keep stressing about 1080p

I'd suggest setting the maximum to 1280x720 or 1366x768 (HD Ready resolution on cheap TVs)

720p is a standard resolution that should be accepted by everything, and you'd have both 16:9 or 4:3 resolutions, and you can double pixels to do 640x360, or 4 pixels blocks to get 320x180 ... scaling by 1.5x gets 960x720 to stretch 640x480...

Could you maybe use something like SiI8784 https://www.semiconductorstore.com/pages/asp/DownloadDirect.asp?sid=1572019820392 (https://www.semiconductorstore.com/pages/asp/DownloadDirect.asp?sid=1572019820392) - to convert an analogue signal to HDMI ? 
You could use a fast microcontroller and 3 r2r dacs to produce the rgb/ypbpr signal/ and output to the sil chip which then converts to hdmi.

or SiI9136 ... takes up to 36 bit per pixel digital signal and output hdmi : datasheet (https://www.latticesemi.com/view_document?document_id=51622)

edit : this last 9136 chip is used in some cheap 20$ devices (https://www.amazon.com/Color3-Advanced-Processing-Device-010000-002/dp/B00BUUV4X6) and someone made a blog about it : https://hackaday.io/project/122480-eecolor-color3 (https://hackaday.io/project/122480-eecolor-color3)

and this board uses the 9136 and the download on the page has lots of cool documentation and code for 9136 : https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&No=1067&PartNo=4 (https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&No=1067&PartNo=4)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 26, 2019, 03:12:30 am
For the HDMI interface, the Max10 dev board used this IC when interfacing with the HDMI for ESD protection and to deal with the 5V DDC signals:
https://www.digikey.com/product-detail/en/texas-instruments/TPD12S016PWR/296-29690-1-ND/2762248 (https://www.digikey.com/product-detail/en/texas-instruments/TPD12S016PWR/296-29690-1-ND/2762248)

It does the ESD protection and level shifts/converts the 5v DDC I2C signals from the HDMI to the FPGA's 3.3v.
I prefer TPD12S521 (http://www.ti.com/product/TPD12S521) chip - it does the same thing, but it support "flow-through" routing to avoid having any stubs thus improving signal integrity (see attachment).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2019, 03:37:14 am
For the HDMI interface, the Max10 dev board used this IC when interfacing with the HDMI for ESD protection and to deal with the 5V DDC signals:
https://www.digikey.com/product-detail/en/texas-instruments/TPD12S016PWR/296-29690-1-ND/2762248 (https://www.digikey.com/product-detail/en/texas-instruments/TPD12S016PWR/296-29690-1-ND/2762248)

It does the ESD protection and level shifts/converts the 5v DDC I2C signals from the HDMI to the FPGA's 3.3v.
I prefer TPD12S521 (http://www.ti.com/product/TPD12S521) chip - it does the same thing, but it support "flow-through" routing to avoid having any stubs thus improving signal integrity (see attachment).
The TPD12S521 (http://www.ti.com/product/TPD12S521) chip does not level voltage translate the I2C DDC lines, at least, it is not mentioned anywhere at all in it's data sheets.
The TPD12S016PWR specifically describes the logic shifter gates with their internal wiring and specs.  The data sheet of the TPD12S521only shows a mosfet inside it, though there is one sentence which says:
"To begin the design process the designer needs to know the 5V_SUPPLY voltage range and the logic level, LV_SUPPLY, voltage range."
But, nothing else...  Typical TexasInstruments crummy modern data sheets...

BTW, the TPD12S016PWR specifically says:
"Auto-direction Sensing I2C Level Shifter with One-shot Circuit to Drive a Long HDMI Cable (750-pF Load)"
With a specific image of this internal logic at the bottom of page 14 in the data sheet.

To be safe, without any mention from TI, I would feel better with my FPGA using the TPD12S016PWR unless I get a letter from TI guaranteeing the same function in the TPD12S521.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 26, 2019, 03:50:38 am
The TPD12S521 (http://www.ti.com/product/TPD12S521) chip does not level voltage translate the I2C DDC lines, at least, it is not mentioned anywhere at all in it's data sheets.
Description, second paragraph, first sentence. "The low-speed control lines offer voltage-level shifting to eliminate the need for an external voltage level-shifter IC."

Quote
The TPD12S016PWR specifically describes the logic shifter gates with their internal wiring and specs.  The data sheet of the TPD12S521only shows a mosfet inside it
Yes, that's a bidirectional level shifter. See NXP app note AN10441 (https://www.nxp.com/docs/en/application-note/AN10441.pdf) for a detailed explanation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2019, 04:03:58 am
The TPD12S521 (http://www.ti.com/product/TPD12S521) chip does not level voltage translate the I2C DDC lines, at least, it is not mentioned anywhere at all in it's data sheets.
Description, second paragraph, first sentence. "The low-speed control lines offer voltage-level shifting to eliminate the need for an external voltage level-shifter IC."

Quote
The TPD12S016PWR specifically describes the logic shifter gates with their internal wiring and specs.  The data sheet of the TPD12S521only shows a mosfet inside it
Yes, that's a bidirectional level shifter. See NXP app note AN10441 (https://www.nxp.com/docs/en/application-note/AN10441.pdf) for a detailed explanation.
Your correct, sorry....
It's odd that on page 7 they only show an upward facing FET like symbol.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 26, 2019, 04:19:35 am
To be safe, without any mention from TI, I would feel better with my FPGA using the TPD12S016PWR unless I get a letter from TI guaranteeing the same function in the TPD12S521.
I actually use it on my FPGA board:
https://i.imgur.com/RVsPWrI.jpg
I can assure you that it really works just fine :-+ Moreover, it also provides a current limiter for HDMI port's power line, also the destination voltage (on the FPGA side) for DDC/HPD/CEC lines doesn't have to be 3.3 V - it can be any voltage from 1 to 3.3 V.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 26, 2019, 05:14:09 am
It's odd that on page 7 they only show an upward facing FET like symbol.
But that really is all there is to it. Select an NMOS with (Vgs(on) < Vcclow - margin) and (Vds(max) > Vcchigh). Connect the gate to Vcclow, the source to the low-voltage signal, and the drain to the high-voltage signal. Add pull-ups to the respective Vcc on each signal input. You have just completed a bidirectional digital level shifter, perfectly sufficient for several hundreds of kilohertz. Feel free to work out what happens when neither side is pulling low, when the drain side is pulled low, and when the source side is pulled low. It's genius.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 26, 2019, 05:05:15 pm
I actually use it on my FPGA board:
https://i.imgur.com/RVsPWrI.jpg (https://i.imgur.com/RVsPWrI.jpg)
I can assure you that it really works just fine :-+ Moreover, it also provides a current limiter for HDMI port's power line, also the destination voltage (on the FPGA side) for DDC/HPD/CEC lines doesn't have to be 3.3 V - it can be any voltage from 1 to 3.3 V.

Very impressive, asmi  :-+ - how did you make that board?  I presume it was done in a reflow oven?  Is it 4-layer?  Done in KiCAD or something professional?



As for the TPD12S521, will I need this with a TFP410 (http://www.ti.com/lit/ds/slds145c/slds145c.pdf)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2019, 08:42:13 pm
I actually use it on my FPGA board:
https://i.imgur.com/RVsPWrI.jpg (https://i.imgur.com/RVsPWrI.jpg)
I can assure you that it really works just fine :-+ Moreover, it also provides a current limiter for HDMI port's power line, also the destination voltage (on the FPGA side) for DDC/HPD/CEC lines doesn't have to be 3.3 V - it can be any voltage from 1 to 3.3 V.

Very impressive, asmi  :-+ - how did you make that board?  I presume it was done in a reflow oven?  Is it 4-layer?  Done in KiCAD or something professional?



As for the TPD12S521, will I need this with a TFP410 (http://www.ti.com/lit/ds/slds145c/slds145c.pdf)?
??? Your link is for the wrong datasheet.  Get the right one from TIs website and see what it says...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2019, 08:55:55 pm
 Use this NXP ic if you want HDMI with digital audio support:
https://www.digikey.com/product-detail/en/nxp-usa-inc/TDA19988BHN-C1551/568-12058-ND/2780351 (https://www.digikey.com/product-detail/en/nxp-usa-inc/TDA19988BHN-C1551/568-12058-ND/2780351)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 26, 2019, 09:27:20 pm
??? Your link is for the wrong datasheet.  Get the right one from TIs website and see what it says...

Darn it, pasted the wrong link, sorry.  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 26, 2019, 10:32:24 pm
Use this NXP ic if you want HDMI with digital audio support:
https://www.digikey.com/product-detail/en/nxp-usa-inc/TDA19988BHN-C1551/568-12058-ND/2780351 (https://www.digikey.com/product-detail/en/nxp-usa-inc/TDA19988BHN-C1551/568-12058-ND/2780351)
Note, external HDMI transmitters are almost useless to the hobbyist due to NDA and licensing restrictions, unless you are fortunate enough to find a leak with enough information (https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/i2c/tda998x_drv.c) to get started.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2019, 11:40:51 pm
Use this NXP ic if you want HDMI with digital audio support:
https://www.digikey.com/product-detail/en/nxp-usa-inc/TDA19988BHN-C1551/568-12058-ND/2780351 (https://www.digikey.com/product-detail/en/nxp-usa-inc/TDA19988BHN-C1551/568-12058-ND/2780351)
Note, external HDMI transmitters are almost useless to the hobbyist due to NDA and licensing restrictions, unless you are fortunate enough to find a leak with enough information (https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/i2c/tda998x_drv.c) to get started.
The chip I listed which is freely available without NDA as well as the data sheet doesn't have HDCP, the true roadblock for hobbyists.  HDMI transmitters with and without audio is allowed.  The hobbyist just isn't allowed to use HDMI's logo or claim authenticated HDMI output in their documentation.

I've never had problems with getting such ICs unless HDCP was built in, however, I've been using Analog Devices HDMI transmitters.  NXP may require a license.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 27, 2019, 12:50:39 am
Very impressive, asmi  :-+ - how did you make that board?  I presume it was done in a reflow oven?  Is it 4-layer?  Done in KiCAD or something professional?
This specific one is a six layer board, manufactured by WellPCB for $145 for 10 boards. There is 512 Mbytes of DDR3L memory onboard. I've designed it in Orcad Professional, but it should be possible to do it in KiCAD. I'm actually working on a board for Spartan-7 FPGA and DDR2 memory in KiCAD - the goal is to do it in 4 layers, as this project is meant for beginners - I'm going to publish all sources once I actually make the board and verify that it works. I will also place HDMI out connector on this board because Spartan-7 can also drive HDMI out directly.

As for the TPD12S521, will I need this with a TFP410 (http://www.ti.com/lit/ds/slds145c/slds145c.pdf)?
I didn't need it because Artix FPGA that I have on this board is capable of driving HDMI interface directly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 27, 2019, 02:52:05 pm
DDR3L

DDR3, the most complex stuff to be designed and handled, especially for beginners.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 27, 2019, 05:51:48 pm
DDR3, the most complex stuff to be designed and handled, especially for beginners.
That's what I thought too in the past. But once I actually tried that, it turned out be much easier than I ever expected it to be.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 27, 2019, 06:16:43 pm
DDR3, the most complex stuff to be designed and handled, especially for beginners.
That's what I thought too in the past. But once I actually tried that, it turned out be much easier than I ever expected it to be.
Ignoring some of the advanced features and if you don't care about shaving every last half clock latency cycle and running them at full tilt speed possible, your controller just about the same as a DDR2 controller.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 27, 2019, 06:33:06 pm
DDR3L? Isn't that the stuff that explodes if you turn it off wrong?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 27, 2019, 06:49:44 pm
Ignoring some of the advanced features and if you don't care about shaving every last half clock latency cycle and running them at full tilt speed possible, your controller just about the same as a DDR2 controller.
I meant from the HW design standpoint. At least for me DDR3 layout seemed much harder than it actually turned out to be. At least for lower speeds (400 MHz is rather low for DDR3), which is what Spartan-7 and Artix-7 support. Going higher requires using Kintex-7, which is significantly more expensive.
For controller I just use MIG (Memory Interface Generator) - it's free and easy to work with.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 27, 2019, 06:51:42 pm
DDR3L? Isn't that the stuff that explodes if you turn it off wrong?
Well it didn't explode on me...yet ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 27, 2019, 11:51:32 pm
Ok, we at at a point where the OP, 'nockieboy' has enough info to make a decision:

A: project must not have BGA, or it can have BGA.
If it cant have BGA, the OP must select to either go with a low cost older FPGA with DRAM, or an all in 1 IC solution like the MAX10 144pin QFP.

When using the older FPGA and DRAM, the op must contend with a more complex PCB, multiple power supply voltages, ram chips and bootprom.


B: Price sensitivity.  If 1 BGA IC is allowed, the Lattice 16$ for 1 chip IC with almost 2 megabit internally pretty much kills everything else in logic density and memory.  Lattice being the third largest FPGA vendor still has relatively decent toolset.  However, you would still need a bootprom and a second regulator for the VCC core voltage.


C: design complexitity.
The TFP410 DVI Transmitter solves the headache of creating and testing his own DVI output serializer core (I realize that home made verilog examples of such a core already exist, but this can be extra work).

Now, with the video modes mentioned, anything he chooses will work, it the development effort and needed and if there will be room for special treats.

If I want a tiny PCB, 1 main IC and HDMI plug, the MAX10 eliminates a lot of complexity and may be possible to be done on a 5$ for 10x 2 layer PCB***. (You really need to know what you are doing and basically the bottom layer is basically a flood-fill GND with a few short trace jumps)

I would make this board a stand alone with a connector for the 8bit MCU board.  I would also offer to make the IC's onboard ram useable as the 8bit cpu's system memory.

If the op went with the larger 2mbit Lattice part, he has the density and speed to offer something like 12 new 256 color sprites, any width up to the width of the screen, with a translucent colors, on every new line of video, from anywhere within the block of system memory, in real time without any overhead.  With the max 10, he could get away with something like 8 sprites at the 180/or/160x240 mode.

For such a project, I would personally recommend using the standard SMPTE 480p base mode of 720x480, 16:9, 27Mhz reference clock as it will work on any PC monitor as well as any TV sold today.  If the op wants 640x480, just center crop the image. (make a black bar an the left and right of the image.)  Also, this standard mode makes integrating the standard HDMI embedded 48Khz stereo audio easy as the exact standard specs are well defined.  Using the 25Mhz VGA 640x480 will add an obstacle upgrade path for embedded audio in the future.

This project is nothing more than a large number of start and stop sequence counters, driving another set of counters look-up memory, use the contents to look up more memory to point to alternate contents of same chunk of memory, and shift the right final content to a palette memory then to feed the DVI transmitter, or feed the internal DVI serializer.

This is why I said in an earlier post, run the internal display memory at 16x the speed of the output pixel feed, you you can read and use each read address to point to another place in ram, 15 times before creating your final resulting pixel.  You may want to make your video memory 16 bits wide so you can access 16 bit words each time allowing a 16bit palette to be stored withing system memory instead of special dedicated registers or memory block.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 28, 2019, 08:03:58 am
Quote
When using the older FPGA and DRAM, the op must contend with a more complex PCB, multiple power supply voltages, ram chips and bootprom.
A x16 pseudo-static RAM is not especially layout-sensitive, any more than an SRAM, and is fine running at 3.3V at several tens of megahertz.

Quote
However, you would still need a bootprom
Sort of true. A 25 series SPI flash and a dozen pins of header should be plenty, and makes it easy to plug in a USBasp or similar SPI master.

Quote
this standard mode makes integrating the standard HDMI embedded 48Khz stereo audio easy
But the TFP410 doesn't. Where does the audio go in?

Quote
16-bit palette
There's a point at which one can and should say "screw palettes, we have enough color bits." 4k colors is about that point. More important, it's about as much data as you'd want to push around with a Z80 and a blitter.

There's also a point at which a designer learns that there are a crapload of tradeoffs to be made, and (hopefully) to avoid the second-system effect.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 28, 2019, 05:46:55 pm
Ok, we at at a point where the OP, 'nockieboy' has enough info to make a decision:

A: project must not have BGA, or it can have BGA.
If it cant have BGA, the OP must select to either go with a low cost older FPGA with DRAM, or an all in 1 IC solution like the MAX10 144pin QFP.

When using the older FPGA and DRAM, the op must contend with a more complex PCB, multiple power supply voltages, ram chips and bootprom.

I'm still waiting on my Spartan 6 dev board, but realise it has SDRAM, not DRAM, on board.  I'd like to be able to test out some DRAM to see how difficult it would be to use it as video RAM in place of internal RAM blocks in the FPGA... If it is viable (both from a complexity AND performance standpoint) then it would be preferable to getting an expensive FPGA with loads of internal RAM.

The MAX10 is tempting, but it's very expensive.  :-\

I have no issue with adding RAM chips and bootprom, even multiple supply voltages so long as it doesn't get TOO complicated (which is highly subjective, I know).  It looks like I'm going to have to switch to KiCAD to design the board no matter what FPGA package / GPU design I go for, as DipTrace's 500 pin/2-layer limit won't cut it with this project.  :o

BGA is definitely out, though, unless/until I build a suitable reflow oven and get the process stable enough to risk running BGA chips through it.

B: Price sensitivity.  If 1 BGA IC is allowed, the Lattice 16$ for 1 chip IC with almost 2 megabit internally pretty much kills everything else in logic density and memory.  Lattice being the third largest FPGA vendor still has relatively decent toolset.  However, you would still need a bootprom and a second regulator for the VCC core voltage.

Sorry, not sure I read that right - Lattice do a $16 FPGA with 2 megabit internal RAM?!?!? :wtf:  That changes the game entirely - if that's correct, I'll get started on a reflow oven straight away and would offer the PCB with the FPGA already soldered if I ever put it into production! :o

Have you mentioned this part already in the conversation?  If so, forgive me as I must have missed the specs (and thus the implications) for it.

C: design complexitity.

If the op went with the larger 2mbit Lattice part, he has the density and speed to offer something like 12 new 256 color sprites, any width up to the width of the screen, with a translucent colors, on every new line of video, from anywhere within the block of system memory, in real time without any overhead.  With the max 10, he could get away with something like 8 sprites at the 180/or/160x240 mode.

Yeah, okay, so I'm seeing that I should really get a grip of this fear of BGA soldering and tackle it head on.

For such a project, I would personally recommend using the standard SMPTE 480p base mode of 720x480, 16:9, 27Mhz reference clock as it will work on any PC monitor as well as any TV sold today.  If the op wants 640x480, just center crop the image. (make a black bar an the left and right of the image.)  Also, this standard mode makes integrating the standard HDMI embedded 48Khz stereo audio easy as the exact standard specs are well defined.

Sounds reasonable to me.  Naive/stupid question - would getting a 27MHz clock from a 25MHz clock source be non-trivial?  All the dev boards I've seen have a 25MHz clock source.

This project is nothing more than a large number of start and stop sequence counters, driving another set of counters look-up memory, use the contents to look up more memory to point to alternate contents of same chunk of memory, and shift the right final content to a palette memory then to feed the DVI transmitter, or feed the internal DVI serializer.

You make it sound so easy...  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 28, 2019, 07:24:43 pm
Quote
this standard mode makes integrating the standard HDMI embedded 48Khz stereo audio easy
But the TFP410 doesn't. Where does the audio go in?

Yes of course, this is still a consideration - there must be alternatives that will integrate an audio source into the data stream, though?

Quote
16-bit palette
There's a point at which one can and should say "screw palettes, we have enough color bits." 4k colors is about that point. More important, it's about as much data as you'd want to push around with a Z80 and a blitter.

Yes, I was starting to wonder if it wouldn't just be easier to shunt around 2-bytes-per-pixel if I have the memory space for a 4-bit colour space unrestricted by a palette size.  Of course, using internal RAM in the FPGA will still limit my memory size, and doubling the size of the required video RAM will likely either restrict my maximum resolution for 4-bit colour or restrict me to a colour LUT for the screen resolutions that don't have the memory space for 4-bit colour.  Just not sure about the practicalities of using both methods in an FPGA?

There's also a point at which a designer learns that there are a crapload of tradeoffs to be made, and (hopefully) to avoid the second-system effect.  ;)

I'm hoping to avoid the second-system effect - although, as I'll be learning as I go, there's bound to be improvements and embellishments I can make by going back over old code - but I do, however, have a pretty clear end goal in mind.  :phew:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 28, 2019, 09:41:20 pm
B: Price sensitivity.  If 1 BGA IC is allowed, the Lattice 16$ for 1 chip IC with almost 2 megabit internally pretty much kills everything else in logic density and memory.  Lattice being the third largest FPGA vendor still has relatively decent toolset.  However, you would still need a bootprom and a second regulator for the VCC core voltage.

Sorry, not sure I read that right - Lattice do a $16 FPGA with 2 megabit internal RAM?!?!? :wtf:  That changes the game entirely - if that's correct, I'll get started on a reflow oven straight away and would offer the PCB with the FPGA already soldered if I ever put it into production! :o

Have you mentioned this part already in the conversation?  If so, forgive me as I must have missed the specs (and thus the implications) for it.

$15.86 for 1, $13.94 each for 25, $13.36 each for 100.
A few pages ago: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2752240/#msg2752240 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2752240/#msg2752240)

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...)

As for easy, you really need to plan thing out ahead and choose an HDL and stick with it.  I personally use System Verilog and keep my modules simple stupid enough that they would still work under any compiler, even those which are regular Verilog.

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...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on October 28, 2019, 10:50:19 pm
Sounds reasonable to me.  Naive/stupid question - would getting a 27MHz clock from a 25MHz clock source be non-trivial?  All the dev boards I've seen have a 25MHz clock source.
Rational clock synthesis isn't that bad. Most PLLs on FPGAs can do it just by configuring and instantiating a module. Here's an example from FPGA4FUN's HDMI (really DVI-D) project, which declares an instance of the Xilinx digital clock manager (https://www.xilinx.com/support/documentation/ip_documentation/dcm_module.pdf) and configures it to multiply the pixel clock by 10, then declares a clock buffer to force the result onto the chip's low-skew clock distribution networks. You could add a .CLKFX_DIVIDE parameter likewise, replacing the default of 1 to achieve a non-integer overall ratio.
Code: [Select]
DCM_SP #(.CLKFX_MULTIPLY(10)) DCM_TMDS_inst(.CLKIN(pixclk), .CLKFX(DCM_TMDS_CLKFX), .RST(1'b0));
BUFG BUFG_TMDSp(.I(DCM_TMDS_CLKFX), .O(clk_TMDS));  // 250 MHz
Some of the lower end FPGAs that don't have onboard clock synthesizers can make use of an offboard clock synthesizer, such as the Si5351, but those can be harder to configure and you must account for delays to and from the synthesizer manually. In either case, clock domain crossing can be a bit tricky if you need other buses to get things done promptly on command. FIFOs, even in their degenerate case of double-buffering with an S-R latch, are an easy and sometimes cheap, but limited and not necessarily prompt way to get clock domain crossing done.

Yes of course, this is still a consideration - there must be alternatives that will integrate an audio source into the data stream, though?
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. HDMI and DVI-D are basically identical at the electrical level. 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.

Quote
Yes, I was starting to wonder if it wouldn't just be easier to shunt around 2-bytes-per-pixel if I have the memory space for a 4-bit colour space unrestricted by a palette size.  Of course, using internal RAM in the FPGA will still limit my memory size, and doubling the size of the required video RAM will likely either restrict my maximum resolution for 4-bit colour or restrict me to a colour LUT for the screen resolutions that don't have the memory space for 4-bit colour.  Just not sure about the practicalities of using both methods in an FPGA?
It's just an if-then statement that turns into a mux. When you're more conversant with HDL, you'll see. :)

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.

fpga4fun.com has much fine introductory reading on FPGAs and some gratifying beginner projects. As a reward you can work all the way through the interfacing material to their HDMI example (really just DVI-D, but enough that you would probably understand where to inject logic for audio and so on once you have the spec) and SDRAM. You could even get a head start as most FPGA software has a (limited) simulator suite available, which you can use to display the output waveforms of your design without a board in hand. You'll also want to know how to build virtual test benches for your design to provide stimuli to your design in simulation, say, fake CPU bus cycles or outside clock sources.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 28, 2019, 11:23:45 pm
Sounds reasonable to me.  Naive/stupid question - would getting a 27MHz clock from a 25MHz clock source be non-trivial?  All the dev boards I've seen have a 25MHz clock source.

This problem can be pretty trivial with a bit of planning.

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).

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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 29, 2019, 02:45:06 am
If the OP is making his own board, or is expecting to, he can always change the crystal oscillator from 25Mhz to 27Mhz.
This may allow for slower core PLLs on different FPGA, however, if he uses the PLL setup wizard, he would just type in the wizard the source clock frequency and the desired output clocks & the wizard would handle this all on it's own.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 29, 2019, 03:58:51 am
If the OP is making his own board, or is expecting to, he can always change the crystal oscillator from 25Mhz to 27Mhz.
This may allow for slower core PLLs on different FPGA, however, if he uses the PLL setup wizard, he would just type in the wizard the source clock frequency and the desired output clocks & the wizard would handle this all on it's own.

I must be old school. I find the wizards are:

- slow to use - a simple change takes a long time

- somewhat inconsistent on their output esp between tool versions.

- very sensitive to inputs (esp when your desired frequencies are a nice decimal number)

- The generated code need tweaking if you use the generated clocks to do something special (e.g. drive SERDES) as you have to add or remove clock buffers, and when you do this you can't use the wizard to regenerate the code

- unless you know what output constraints you have within the clocking resources of the FPGA you just end up trying things and seeing if you get lucky. It isn't a recipe for a well-engineered design

- for me, they often seem to have different ideas of what a "close enough" solution is. Usually a better "close enough" solution exists

But my biggest grip is that they fill your code base with code that is "(c) Vendor X" with an explicit license, that isn't compatible with open projects:

Do a quick search for for

    site:github.com "Copyright(C)" "by Xilinx, Inc"

Here's an example:

Code: [Select]
-- System Generator version 11.1 VHDL source file.
 --
 -- Copyright(C) 2009 by Xilinx, Inc.  All rights reserved.  This
 -- text/file contains proprietary, confidential information of Xilinx,
 -- Inc., is distributed under license from Xilinx, Inc., and may be used,
 -- copied and/or disclosed only pursuant to the terms of a valid license
 -- agreement with Xilinx, Inc.  Xilinx hereby grants you a license to use
 -- this text/file solely for design, simulation, implementation and
 -- creation of design files limited to Xilinx devices or technologies.
 -- Use with non-Xilinx devices or technologies is expressly prohibited
 -- and immediately terminates your license unless covered by a separate
 -- agreement.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 29, 2019, 04:20:17 am
I must be old school. I find the wizards are:
You don't need to actually generate any code with the wizard. I use clocking wizard to calculate all coefficients, and then just place them into my own MCMM/PLL instantiation code. I just couldn't be bothered to calculate this stuff myself ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on October 29, 2019, 04:21:35 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 :) ).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on October 29, 2019, 04:22:47 am
I must be old school. I find the wizards are:
You don't need to actually generate any code with the wizard. I use clocking wizard to calculate all coefficients, and then just place them into my own MCMM/PLL instantiation code. I just couldn't be bothered to calculate this stuff myself ::)

^^^^^^

This is most likely the optimal way to use the clocking wizard.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi 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).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy 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:

Video side:

GPU utility:

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?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy 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
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG 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?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG 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 (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...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy 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).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy on October 30, 2019, 06:39:18 pm
@BrianHG
thanks!  :D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy 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.   ^-^
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: legacy 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi 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!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy 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 (http://www.asic-world.com/verilog/index.html) 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?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable 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 (https://www.intel.com/content/www/us/en/programmable/support/support-resources/knowledge-base/solutions/rd06102014_970.html) 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).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni 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.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: langwadt on November 01, 2019, 12:08:35 am
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.

and it is freaking annoying, because sometimes somewhere  in the ten pages of silly warnings something important is hidden
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 01, 2019, 03:52:45 am
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.

and it is freaking annoying, because sometimes somewhere  in the ten pages of silly warnings something important is hidden

Hun, yes, with Altera, I turned off the 32bit integer warning, however, when I compile, I get no other warnings.
I used to when I started, but I once I started coding with individual projects for individual .v modules, and I coded for 0 warnings, (only after around 4 years of using Quartus) no more warnings, even when my main project use all the child .v modules into my authentic design.

It's a hassle, but it locks you down to proper coding and using the tool properly.  And now, only important warnings or errors show up in the build log.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 01, 2019, 11:32:08 am
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 (https://www.intel.com/content/www/us/en/programmable/support/support-resources/knowledge-base/solutions/rd06102014_970.html) explicit width specification on constants to suppress the warning.

Yes, found the same page last night - the code doesn't read as clearly now, but by replacing 1's and 0's with 1'b1s and 1'b0s, the warnings have mostly gone away now.  :-+

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.

Chalk it up to my inexperience in this field, and my not-insignificant OCD when it comes to compilation errors.  |O

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.

Of course, I attached both files earlier in the thread.  I'll probably attach updated copies in this message as well.

Another note, it helps readability to use the C conventions for the case of constants (all caps) vs. variables (not all caps).

The dangers of cut 'n' paste code.  ;)

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;

Okay, I think I follow, although I've had to go off and look at Blocking and Non-Blocking, registers vs wires and all kinds of stuff.  Can't remember who said it, but they were right when they said I'd learn a load of stuff just getting a blank screen to display... I haven't even gotten near wiring this up yet!  Attached at the bottom are the two updated files with all the changes made.

Can I assume that the non-blocking <= assignment operators are okay in the context in which I'm using them?

*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.)

Sheesh there is so much to learn...  :o

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.

You lost me here.  x and y are wires with 10-bit values.  I can't make them a single on/off bit - unless you're talking about creating a couple more registers to use as single-bit flags to indicate whether we're in the display area or not?

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.)

Ah okay, I understand.  Well, I'm trying to crawl before I walk or run, so I'm not going to add in loads of elements that I won't be using for a while, but that's certainly a consideration down the line. 

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.

Sure thing - okay, so I've moved the display area to the start of the v_count and h_count range; hopefully I've got the localparams right for the relevant values, I've added a 'blanking' output to the sync_generator which goes high whenever the generator is in the vertical blanking area.  No doubt I'll need to add one for h_count as well to make sure the RGB values are black when in those areas.

EDIT:

Obviously there's errors in the attached files - I'm working through those right now.  ::)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 01, 2019, 01:46:01 pm
Updated files without the errors!  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 01, 2019, 04:38:47 pm
Just a thought regarding the CPU part itself. Of course you could consider using a Z80 core in the FPGA you're going to use. But if you still want a true CPU IC, you could consider the Z180 series. They are software compatible with the Z80, but contain many improvements and embedded peripherals, and there are 3.3V versions as well. The Z8L180 is readily available for instance (at least at Mouser)... so unless you really want to go for a true, vintage Z80, that would be sometthing to consider.

https://en.wikipedia.org/wiki/Zilog_Z180
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 01, 2019, 10:48:21 pm
Just a thought regarding the CPU part itself. Of course you could consider using a Z80 core in the FPGA you're going to use. But if you still want a true CPU IC, you could consider the Z180 series. They are software compatible with the Z80, but contain many improvements and embedded peripherals, and there are 3.3V versions as well. The Z8L180 is readily available for instance (at least at Mouser)... so unless you really want to go for a true, vintage Z80, that would be sometthing to consider.

https://en.wikipedia.org/wiki/Zilog_Z180

I still might create a CPU card with the Z180 on it - I've got a couple of Z180's and Z280's lying around with that purpose in mind, but for the moment I'm using a good old-fashioned DIP Z80 chip (a 10MHz one admittedly, but otherwise quite similar to my first computer).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 03, 2019, 01:29:34 am
Ok, what the non-blocking statement ( <= ) does and a bit on making optimized fast compact code:  What I'm describing here is a little of whats going on inside the compilers mind, and how it wires gates in the FPGA according to the example verilog code.  Remember, there is no single core math unit in these FPGAs, whatever you write is literally constructed by wiring masses of gates inside the FPGA.  All these wires have lengths, propagation delays, and the gates' inputs have capacitive loads which further slows everything down.  This primer gives you an example of coding technique to be aware of to achieve a minimal gate count FPGA core which is fast as possible and lowest power consuming design.  (If you wanted a central math processing unit, you literally need to code one into existence and wire it up into your design.)

See attached image: (if you got a color printer, print this one)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=865642)

There are 3 simplified versions of code in the illustration.

In V1, the 'hsync' is generated just like in the op 'nockieboy' first 'Sync Generator' code.
You have the 10 bit register ''[9:0]''  h_count, which is truly 10 D flipflops.  At the 10 data inputs of the 10 D flipflops, all parallel clocked by the (positive edge of 'clk'), the 10 Q outputs h_count is sent through a bunch of gates added to a fixed 1 bit value of '1', with that new 10 bit result fed back into the 10 D inputs of the 10 D flipflops which is the 10 bit register 'h_count'

Now, to make that 'hsync' wire, those 10 Qs of h_count need to be wired to a set of gates which subtract it from the 10 bit parameter number 'HS_STA' to check to see if the result is not negative, while more wiring of the 10 Qs of 'h_count' are fed into another mass of gates to SIMULTANEOUSLY subtract that same 10 bit 'h_count' with the 10 bit parameter value of 'HS_END' to see if the result is negative, and finally, those 2 comparisons checks are ANDed together, inverted generating a final single WIRE result labeled 'hsync'.

To understand what is happening, the compiler and fitter has to wire up the FPGA with all these gates to make to 2 comparisons as well as the +1 for the counter itself.  Now, find a TTL data book with a 8bit - 8bit adder/subtract with negative flag.  How many gates are there?  The FPGA has to do this 2 fold, with 10 bit numbers each.  (Ignoring the compiler optimizations for now.)  With all that signalling and load, how clean will the 'hsync' wire be if it is driving an IO pin and any other set of logic gates in your design?   Remember, things like load and delay of routing all these wires in the FPGA are taken into account even though you as the programmer aren't specifically told by the compiler other than after a design is compiled, X number of MHz is the best your design will achieve without errors.

In V2, this one is identical to V1 except that I changed 'hsync' from a wire into a register.  The reason why this is an improvement is because, throughout the FPGA, all of the 'D' flipflops clock inputs have a dedicated hard-wiring making sure that all their outputs are parallel.  Example, if your clock is 1 MHz, at the D input of the D flipflop register which is the 'hsync' register, when a clock comes in, the 10 bit 'h_count' with a matched clock will change to it's new value, those 10 bits will go through the mass of gates which are the 2 subtractions and & gate to determine if the number is within 'HS_STA' and 'HS_END', then that result will be presented to the D input of the 'hsync' D flipflop register, however, (and this is the SYNCHRONOUS magic), the Q of the 'hsync' register will not change until the next clock.  This means that after all the number comparing, if the result takes 1ns, 5ns ,6ns,10ns, 15.2ns, 33.8ns, or any number less than 1000ns (I said 1MHz clock as an example), with that mess of gates, that D input may even be filled with glitches/noise/invalid states, as long as the correct result is ready by the next rising clock, that Q output as well as all the Qs of all the registers in your design will all snap to their new values at the same time.

So with this V2, if your 'hsync' register drives an IO pin, or if the 'hsync' is used elsewhere in your design, it will be a fast clean signal which is valid within a fraction of the rising positive edge of the 'clk' signal.  The 1 negative here is that the 'hsync' result is now delayed by 1 clock, but in this case, it is easy enough to subtract 1 from the 'HS_STA' and 'HS_END' parameters.  This change will allow the FPGA compiler to construct a much higher maximum operating frequency for your design, especially if the 'hsync' signal is used elsewhere in your design.

Now in 'V3', the goal here is to make the design operate as fast as possible no mater what the values of  'HS_STA' and 'HS_END'.  The change I made was turn the 'hsync' register into an equivilant clocked SR-Flipflop.  The code I wrote was if the 'h_count' = 'HS_STA', to turn on the 'S' in the flipflop.  Looking above, at the equivilant adder/subtraction and the complex web of gates required for the math, compare all that required to perform an '=' test function which would only be 10 XOR gates whose outputs feed a single 10 input NOR gate.  (This is all it takes to create the function: does 'A=B'?)  That A=B function would run sub nanosecond in the FPGA compared to a 10bit number A minus 10bit number B function, originally requiring 2 of them in parallel.  Just the input load of all those gates in the subtract function slows things down, never mind the delay in each gate as well as the extra length in all the routed wiring.  The second half, if 'h_count' = 'HS_END', turns on the R of the SR-Flipflop clearing it to low.  The load in wiring of this on the FPGA silicon is a fraction of the above code, except for 1 caveat:  If 'h_count' never reaches 'HS_STA', then 'hysnc' will never turn on, or if 'hsync' is on and the 'h_count' never reaches 'HS_END', the 'hsync' will never turn off.

For legibility, the code in the graphic image in plain text:
Code: [Select]
Many things omitted for simplicity sake but at the top:

module sync_gen ( clk, hsync, hcount );

parameter   HS_STA = 10  ;  //Turn on hsync signal position
parameter   HS_END = 210 ;  //Turn off hsync signal position

input  clk;
output hsync;
output hcount;

---------------------------------
V1
---------------------------------

reg [9:0]    h_count;
wire         hsync;


assign       hsync   =  ~((h_count >= HS_STA) & (h_count < HS_END));


always @(posedge clk) begin

    h_count  <=  h_count + 1;  // Without a reset limit, the h_count will run 0 to 1023.

end

---------------------------------
V2
---------------------------------

reg [9:0]    h_count;
reg          hsync;


always @(posedge clk) begin

    h_count  <=  h_count + 1;

    hsync    <=  ~((h_count >= HS_STA) & (h_count < HS_END));

end

---------------------------------
V3
---------------------------------

reg [9:0]    h_count;
reg          hsync;


always @(posedge clk) begin

    h_count  <=  h_count + 1;

if (h_count == HS_STA) begin
  hsync <= 1;
end else if (h_count == HS_END) begin
  hsync <= 0;
end

end

---------------------------------
endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2019, 06:35:14 pm
Ok, what the blocking statement ( <= ) does and a bit on making optimized fast compact code:  What I'm describing here is a little of whats going on inside the compilers mind, and how it wires gates in the FPGA according to the example verilog code.  Remember, there is no single core math unit in these FPGAs, whatever you write is literally constructed by wiring masses of gates inside the FPGA.  All these wires have lengths, propagation delays, and the gates' inputs have capacitive loads which further slows everything down.  This primer gives you an example of coding technique to be aware of to achieve a minimal gate count FPGA core which is fast as possible and lowest power consuming design...

Wow - thanks BrianHG!  :clap:

If I'm doing it right, the v3 counter implementation in Quartus II is quoting an Fmax of 217.2 MHz for clk (that's including the vga01.v top level as well).

It still amazes me when I have to keep reminding myself that the code I'm writing has a physical consequence in the FPGA - so what appears to me to be the easiest way of programmatically achieving a task may actually be quite costly in terms of hardware.  :o

I haven't had a lot of time to look at my code or the hardware this weekend as I've been working, but I've got the FPGA connected to one of my LCD monitors via VGA with just GND, HSYNC and VSYNC connected at the moment.  I've messed with the clock timing and tried connecting it at 25 MHz, which showed a corresponding incorrect frequency input on the LCD monitor, but if I get anywhere near the right frequency for VSYNC and HSYNC, the screen is just blank for a few seconds then goes into power saving, so I'm guessing the LCD is (correctly) not detecting any RGB input and is going to sleep as a result.  I was hoping to be able to get the menu up and see what screen resolution was reported, but it seems I need to get RGB signals up and running first.  :-BROKE

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 03, 2019, 06:58:22 pm
Sometimes its better to write HDL code from the perspective of circuit design rather than from a perspective of programming.

For example for the given task try to imagine a approximate digital circuit that does this job and then write HDL code that would act like such a circuit. Instead of instruction cycles or operations think of it in terms of logic gates, MUXes, D flip flops, adders, lookup tables...etc Since this is what ends up in the FPGA.

That's a bit odd that the monitor refuses to display a blank signal. But it should be easy to generate some RGB by just outputting the X Y counter values as pixels to get a colorful pattern. Tho take care that you must output black in the blanking periods! Monitors tend to calibrate the black level during blanking and you can get weird colors if you output other things during that (It can be pretty monitor specific).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 03, 2019, 09:55:12 pm
Ok, what the blocking statement ( <= ) does and a bit on making optimized fast compact code:  What I'm describing here is a little of whats going on inside the compilers mind, and how it wires gates in the FPGA according to the example verilog code.  Remember, there is no single core math unit in these FPGAs, whatever you write is literally constructed by wiring masses of gates inside the FPGA.  All these wires have lengths, propagation delays, and the gates' inputs have capacitive loads which further slows everything down.  This primer gives you an example of coding technique to be aware of to achieve a minimal gate count FPGA core which is fast as possible and lowest power consuming design...

Wow - thanks BrianHG!  :clap:

If I'm doing it right, the v3 counter implementation in Quartus II is quoting an Fmax of 217.2 MHz for clk (that's including the vga01.v top level as well).

It still amazes me when I have to keep reminding myself that the code I'm writing has a physical consequence in the FPGA - so what appears to me to be the easiest way of programmatically achieving a task may actually be quite costly in terms of hardware.  :o

Next, now you know what the '<=' function does, basically a bundle of final flipflops latching the outputs of all the synthesized logic gates which are required to perform the boolean algebra on the right of that blocking function, all of them tied to the same dedicated network clock @(posedge...), it's time to take a look at your sync code and what your top hierarchy screenshot within quartus looks like.  (For the top, I still use quartus's block diagram entry for the IO pins and my Veriliog appears as 1 master or multiple wired block diagram modules...)

When your ready, post here your latest syncgen.v when you are ready...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2019, 10:44:52 pm
Next, now you know what the '<=' function does, basically a bundle of final flipflops latching the outputs of all the synthesized logic gates which are required to perform the boolean algebra on the right of that blocking function, all of them tied to the same dedicated network clock @(posedge...), it's time to take a look at your sync code and what your top hierarchy screenshot within quartus looks like.  (For the top, I still use quartus's block diagram entry for the IO pins and my Veriliog appears as 1 master or multiple wired block diagram modules...)

When your ready, post here your latest syncgen.v when you are ready...

Not a lot has changed as I've not had much time this weekend to do anything, but here's the latest snapshot of my code attached.

it's time to take a look at your sync code and what your top hierarchy screenshot within quartus looks like.  (For the top, I still use quartus's block diagram entry for the IO pins and my Veriliog appears as 1 master or multiple wired block diagram modules...)

Not sure what you mean by 'top hierarchy screenshot'?  Do you mean the pin assignments? Here's a screenshot of my Quartus II workbench, if that helps:

(https://i.ibb.co/h28bfkc/Untitled.png) (https://ibb.co/NWY5SXr)

I'm not convinced that's what you're after, though.  I haven't used Quartus' block diagram tool to design the hierarchy, I just created the first file (vga01.v) and went from there, creating sync_generator.v and referring to it in vga01.v.  Sorry if I'm being vague or missing an obvious request, it's been a loooong day.  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 03, 2019, 10:56:52 pm
I wonder if the polarity of HSYNC and/or VSYNC are wrong for the chosen resolution.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on November 04, 2019, 12:45:24 am
I ran up a simulation....

You need to be sure if LINE and SCANLINES are terminal counts, or are the total number. Currently your h_counter goes from  0 to 800 (801 counts), and v_counter goes from 0 to 525 (526 lines).

General suggestion (take them or leave them):

- You need to be clear about what is internal state, and what is exposed. Currently the x & y outputs feel bad.

- Your reset should reset all state (even if it is only for simulation).

- I am not sure why you have "posedge reset" in your always. I don't think it is needed.

Here's what I would do:

- Reset all outputs and state in the reset clause

- keep h_counter and v_counter for internal use only, and change the x & y outputs to be reg not wires.

- Keep LINES and SCANLINES as a total count, so compare to LINES-1 or SCANLINES-1 as the test for resetting the counters/

- Likewise keep HS_STA & HS_END the count where it starts, so remove the "-1" from the localparam and put it in the test.

- Try to avoid ternary operators - usage tends to be very idiomatic, so are a common source of bugs

- Unless you are careful, there is going to be ambiguity about when vsync pulse starts and ends. I suggest you testboth h_count and v_count to decide when to assert vsync. So if you want it to be aligned with the start of the visible pixels use "if (h_count == LINES-1 && v_count == VS_STA-1)" and ""if (h_count == LINES-1 && v_count == VS_END-1)" as the tests when to set the vsync outputs.

This might not give you the fastest design, nor the most compact code, but it will help you avoid lots of subtle bugs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2019, 03:32:30 am
I ran up a simulation....

You need to be sure if LINE and SCANLINES are terminal counts, or are the total number. Currently your h_counter goes from  0 to 800 (801 counts), and v_counter goes from 0 to 525 (526 lines).

General suggestion (take them or leave them):

- You need to be clear about what is internal state, and what is exposed. Currently the x & y outputs feel bad.

- Your reset should reset all state (even if it is only for simulation).

- I am not sure why you have "posedge reset" in your always. I don't think it is needed.

Here's what I would do:

- Reset all outputs and state in the reset clause

- keep h_counter and v_counter for internal use only, and change the x & y outputs to be reg not wires.

- Keep LINES and SCANLINES as a total count, so compare to LINES-1 or SCANLINES-1 as the test for resetting the counters/

- Likewise keep HS_STA & HS_END the count where it starts, so remove the "-1" from the localparam and put it in the test.

- Try to avoid ternary operators - usage tends to be very idiomatic, so are a common source of bugs

- Unless you are careful, there is going to be ambiguity about when vsync pulse starts and ends. I suggest you testboth h_count and v_count to decide when to assert vsync. So if you want it to be aligned with the start of the visible pixels use "if (h_count == LINES-1 && v_count == VS_STA-1)" and ""if (h_count == LINES-1 && v_count == VS_END-1)" as the tests when to set the vsync outputs.

This might not give you the fastest design, nor the most compact code, but it will help you avoid lots of subtle bugs.

Note that your code is just as compact and fast as the original because the LINES, VS_STA, VS_END, HS_STA, HS_END,... are all parameters, or constants, so, the compiler works out the -1 ahead of time.  No sweat at all, however, if the OP changes these constants to loadable registers which he can be written to by the Z80 CPU, allowing software defined new video modes, then those '-1' will come into play and add gates to the design.

Quote
- You need to be clear about what is internal state, and what is exposed. Currently the x & y outputs feel bad.

I feel the same, I believe the sync generator should be 100% positive logic.  Meaning positive hsync / vsync / an active video region output which crops the active visual area (a requirement for most DVI/HDMI serializers), and additional optional signals to trigger video timing specific events which may be fixed to the master h_count and v_count.  Any visual display address / graphics /memory pointers, counters and sub-alignment positioning in the 'active video region' should be in the separate graphics image generator.  Remember, a second new X/Y coordinate counter is only another 20 register flipflops max.

I'm waiting a day, however, I'll make a few suggestions to the ops sync generator which will solve those -1's without a -1 in the code, and solve that 1 clock delay with regards to the other variables, including the picture_enable_h and picture_enable_v signal (together = picture_enable).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2019, 03:48:52 am
@nockieboy, some questions:

1. Do you have an oscilloscope?
2. Which cyclone II board do you have?
3. Which version of quartus are you using?
4. Are you willing to use Quartus graphics design entry?  (Not for coding, your verilog coding will stay the same, but, just to wire your verilog modules to the IO pins and potentially a few xxxx.v modules together.  This will allow you to easily drop in or take out modules or remove them on the fly and see how your graphics pipe is affected as well as the CPU interface.  It will allow you to easily invert IO pins, or, enable a global PLL.  You can always make a now top hierarchy later-on, or, even tell quartus automatically generate you a top 'MyProject.v' verilog code of your illustrated schematic.  Quartus has a feature to automatically generate a design block of each of your 'xxxx.v' source codes which you may place within your schematic layout, including multiple instances. )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 04, 2019, 06:45:25 am
Not sure what you mean by 'top hierarchy screenshot'?  Do you mean the pin assignments? Here's a screenshot of my Quartus II workbench, if that helps:

(https://i.ibb.co/h28bfkc/Untitled.png)

I'm not convinced that's what you're after, though.  I haven't used Quartus' block diagram tool to design the hierarchy, I just created the first file (vga01.v) and went from there, creating sync_generator.v and referring to it in vga01.v.  Sorry if I'm being vague or missing an obvious request, it's been a loooong day.  :o

I do also like to use the graphical schematic entry for the top module since its a bit easier to see where things are going. The user interface on that schematic editor is absolutely terrible (Its directly from the 90s) but that seams to be the case for all the vendors.

By the way there is also a window called the "RTL view" that turns the synthesized HDL back into a schematic:
(https://surf-vhdl.com/wp/wp-content/uploads/2015/11/fir_filter_4_RTL-view.jpg)

This view is a very useful sanity check to see if the compiler understood your code in the way you intended. You can see individual flip flops, adders, muxes etc... and how it wired them up. Its the best place to see what sort of optimization shortcuts the compiler has taken (It loves to reuse blocks/signals, simplify down logic, remove unnecessary logic etc...). Its pretty messy since its auto generated but clear enough to be useful with a bit of highlighting by clicking nets and blocks.

This is however still NOT how it is actually wired inside the FPGA, but simply input to the mapper that crams the functionality in actual FPGA elements. You can get a view of how the FPGA elements are wired up by opening the "Architecture view" to get a similar looking autogenerated schematic but this time with real hardware blocks in it and how they are configured. This makes it a lot more difficult to read so this view is not as useful. An even more bare metal view is the "Chip planner view". It shows you a map of the FPGAs silicon die with all of the elements inside it, allowing you to peek into each one and see how its wired up and configured. It gives you a nice view of whats is going on physically in there but is near impossible to follow signals around. It is however very useful in checking that certain blocks got configured as you expect, most useful for IO blocks in cases where you want to use special IO pin functionality like DDR, reclocking, built in serdes, delay tuning etc...

(http://we.easyelectronics.ru/uploads/images/00/00/60/2011/04/16/045570.png)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2019, 10:16:33 am
Brief update - have wired up the MSB RGB outputs to the VGA connector through 270R resistors to try and get some kind of output (haven't bothered with a resistor ladder to merge the LSB outputs as they're not used yet anyway).  Here's the result:

(https://i.ibb.co/gmQG0Yg/20191104-092002.gif) (https://ibb.co/VJbdF6B)

Clearly an issue with sync pulses or timing somewhere...  The image is a GIF, by the way, so you can see the issue if you click on the image.

I wonder if the polarity of HSYNC and/or VSYNC are wrong for the chosen resolution.

Fair point - I've tried the output with reversed polarity on the hsync and vsync outputs and the monitor just goes to sleep, so it would appear the polarity is correct as I do get some sort of output currently...?

You need to be sure if LINE and SCANLINES are terminal counts, or are the total number. Currently your h_counter goes from  0 to 800 (801 counts), and v_counter goes from 0 to 525 (526 lines).

Good point, I hadn't noticed that.  This is where I start to make silly mistakes - basic maths.  ::)

- Reset all outputs and state in the reset clause

- keep h_counter and v_counter for internal use only, and change the x & y outputs to be reg not wires.

- Keep LINES and SCANLINES as a total count, so compare to LINES-1 or SCANLINES-1 as the test for resetting the counters/

- Likewise keep HS_STA & HS_END the count where it starts, so remove the "-1" from the localparam and put it in the test.

- Try to avoid ternary operators - usage tends to be very idiomatic, so are a common source of bugs

- Unless you are careful, there is going to be ambiguity about when vsync pulse starts and ends. I suggest you testboth h_count and v_count to decide when to assert vsync. So if you want it to be aligned with the start of the visible pixels use "if (h_count == LINES-1 && v_count == VS_STA-1)" and ""if (h_count == LINES-1 && v_count == VS_END-1)" as the tests when to set the vsync outputs.

This might not give you the fastest design, nor the most compact code, but it will help you avoid lots of subtle bugs.

Okay, I've tweaked the reset clause to reset hsync and vsync as well - is there anything else I should reset in there?  I'll leave LINE and SCANLINES as they are with the -1 as I'll likely be changing them in the future to regs so they can be changed by the host CPU.

As for the ternary operators comment - so it would be preferable to use full if-else conditionals instead?  Is that purely because of the possibility of user error in writing or interpreting the ternary operators or because of discrepancies in how Quartus II implements them?


Quote
- You need to be clear about what is internal state, and what is exposed. Currently the x & y outputs feel bad.

I feel the same, I believe the sync generator should be 100% positive logic.  Meaning positive hsync / vsync / an active video region output which crops the active visual area (a requirement for most DVI/HDMI serializers), and additional optional signals to trigger video timing specific events which may be fixed to the master h_count and v_count.  Any visual display address / graphics /memory pointers, counters and sub-alignment positioning in the 'active video region' should be in the separate graphics image generator.  Remember, a second new X/Y coordinate counter is only another 20 register flipflops max.

I popped the X & Y counters in the sync generator because it seemed like the easiest way to get some sort of graphical output at the time.  Also, that's how the demo code did it that I borrowed from. ;)
 Naturally, I'm literally starting out with Quartus, Verilog and FPGAs in general, so am happy to accept feedback and suggestions on improvements. 

I'm waiting a day, however, I'll make a few suggestions to the ops sync generator which will solve those -1's without a -1 in the code, and solve that 1 clock delay with regards to the other variables, including the picture_enable_h and picture_enable_v signal (together = picture_enable).

 ;D

@nockieboy, some questions:

1. Do you have an oscilloscope?

Yes.  It's barely up to anything (and my skills using it are also pretty poor - remember, I'm not an electronics engineer and this isn't my day job!) but it's a 20 MHz Hitachi V-212.  I got it cheap off eBay a year or two back when I was breadboard-prototyping my Microcom and didn't know that a logic analyser would have been far more useful.   ^-^

2. Which cyclone II board do you have?

One of those cheap ones off eBay.  Here's an example (https://www.ebay.co.uk/itm/ALTERA-FPGA-Cyslonell-EP2C5T144-Minimum-System-Learning-Development-Board/401255830236).

3. Which version of quartus are you using?

Quartus II 64-Bit Version 13.0.1 Build 232 06/12/2013 SJ Web Edition.  It was indicated to be the last version that supports the Cyclone II.

4. Are you willing to use Quartus graphics design entry?

I'm certainly happy to give it a go.  I'm fumbling around with Quartus II, trying to learn the ropes as I go, so I'm more than happy to find out about features like this that could help.  :-+

(Not for coding, your verilog coding will stay the same, but, just to wire your verilog modules to the IO pins and potentially a few xxxx.v modules together.  This will allow you to easily drop in or take out modules or remove them on the fly and see how your graphics pipe is affected as well as the CPU interface.  It will allow you to easily invert IO pins, or, enable a global PLL.  You can always make a now top hierarchy later-on, or, even tell quartus automatically generate you a top 'MyProject.v' verilog code of your illustrated schematic.  Quartus has a feature to automatically generate a design block of each of your 'xxxx.v' source codes which you may place within your schematic layout, including multiple instances. )

Sounds very useful - I'll see what I can find out about it!  ;D

I have included my full project folder as a .zip archive for info if anyone is playing along at home.  I'm not convinced I fully understand the clock setup and timing / TimeQuest Timing Analysis part of the project very well at all.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2019, 10:46:57 am
@nockieboy, some questions:

1. Do you have an oscilloscope?
Yes.  It's barely up to anything (and my skills using it are also pretty poor - remember, I'm not an electronics engineer and this isn't my day job!) but it's a 20 MHz Hitachi V-212.  I got it cheap off eBay a year or two back when I was breadboard-prototyping my Microcom and didn't know that a logic analyser would have been far more useful.   ^-^

Good enough.  Check the hsync and vsync being sent to your monitor.  Make sure the pulse is clean and at least 4v p-p.  Preferably 5v.  If you are driving your monitor with a 3.3v-3.6v hsync, it may do some funny things...  This is random based on the monitor's internal circuitry.  If the sync it too low, IE you are driving the monitor HS/VS with an FPGA IO directly, there are 2 thing you will need to try.
1> buffer the signal through a 74HC04 inverter, or 74HC245 buffer powered with 5v.  I like to drive the HS and VS into 3 gates each in parallel, and tie each of the 3 outputs in parallel to get a good current output to drive the monitor cable.
2> if the IO on the FPGA is a true 5v output, but the monitor cable load is weakening it too much, a 220Ohm to 330Ohm pullup resistor to 5v may work.

(Option #1 is better, it also separates the FPGA IO from direct connection to a wire on a VGA plug which may blow the FPGA or cause internal malfunction.)


If you use 2 channels, placing 1 probe on hsync and the second on a R/G/B pin, you should see if you get a regular pattern or not.

Also, sync polarity doesn't matter any monitor which can take in VGA with modes as high at 1280x720 or above.  If your mode is not standard with wrong polarity, the monitor should potentially only have bad picture horizontal/vertical size and position unless the sync timing is not associated with the picture.

 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2019, 11:20:55 am
Check the hsync and vsync being sent to your monitor.  Make sure the pulse is clean and at least 4v p-p.  Preferably 5v.  If you are driving your monitor with a 3.3v-3.6v hsync, it may do some funny things...  This is random based on the monitor's internal circuitry.

Aha - that'll be the problem then, I'm driving HSYNC and VSYNC directly from the FPGA pins.  Only R, G and B are going via 220R resistors...  :-BROKE

My scope is showing nice clean signals on HSYNC and VSYNC, but only 3.3v p-p, which is to be expected - so the monitor is picking up some information (i.e. the R, G and B signals) but not necessarily the proper sync signals.  It shows a 640x480x60 screen resolution in the menu, but as you can see from the gif I posted previously, the sync is out.

If the sync it too low, IE you are driving the monitor HS/VS with an FPGA IO directly, there are 2 thing you will need to try.
1> buffer the signal through a 74HC04 inverter, or 74HC245 buffer powered with 5v.  I like to drive the HS and VS into 3 gates each in parallel, and tie each of the 3 outputs in parallel to get a good current output to drive the monitor cable.

I don't have too many HC parts lying around, they're all HCT, but I'll see what I can do.

If you use 2 channels, placing 1 probe on hsync and the second on a R/G/B pin, you should see if you get a regular pattern or not.

There's definitely a regular pattern - can see that on the monitor, it's just skewed and rolling because of the sync problems.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 04, 2019, 11:23:57 am
That picture does look like it might have some sort of HSYNC issue.

If electronics are not your main thing then you are actually doing pretty well since FPGAs are pretty far from regular programming. An oscilloscope is one of the most useful tools for debugging electronics, no other tool gives the same deal of universal insight into what circuits are doing. You do usually want to have a digital scope for digital circuits so that you can one shot capture communication buses and decode them. But video luckily involves stable repeating patterns so a analog scope can still be quite useful when triggered from vsync or hsync.

But there is a trick with FPGAs. You can build a logic analyzer in the same chip as the cirucit. Quartus has a tool for doing this called SignalTap:
(https://raw.githubusercontent.com/wiki/mist-devel/mist-board/signaltap_2.jpg)

You give it a list of signals you want to monitor and how much memory to use and it generates a logic analyzer for that, taps off those signals and adds it to the design. Next time you compile your design this logic analyzer will be included in the final output and once loaded into the FPGA listens on JTAG. Then you can just click connect in SignalTap and it will allow you to interact with this logic analyzer to start captures, configure triggers etc... In some cases this is more useful than an actual logic analyzer because you have essentially 100s of logic channels available, allowing you to monitor entire counters like a bus. But because its using internal block ram means that you typically won't be making captures longer than a few thousands of samples.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2019, 11:55:35 am
Well, that sorted the problem - thanks BrianHG!  :-+

Clearly my monitor wasn't happy with the 3.3v sync signals - I found a 74AHC541 in my box of bits and am now running the vertical and horizontal sync signals through one of these line drivers powered at 5v and am getting a nice stable output:

(https://i.ibb.co/BfFX87L/20191104-114222.jpg) (https://ibb.co/Zf7nywd)

It's surprising how pleased I am at getting four overlapping squares to display on a monitor!!! Haha!  :-DD

If electronics are not your main thing then you are actually doing pretty well since FPGAs are pretty far from regular programming.

Programming isn't my main thing, either, although I'm much better at it than electronics!  Never let it be said that I don't enjoy a challenge... :o

An oscilloscope is one of the most useful tools for debugging electronics, no other tool gives the same deal of universal insight into what circuits are doing. You do usually want to have a digital scope for digital circuits so that you can one shot capture communication buses and decode them. But video luckily involves stable repeating patterns so a analog scope can still be quite useful when triggered from vsync or hsync.

And the frequency isn't so high either - I had been using the scope originally to debug my breadboard computer running at 4 MHz, these signals are in the KHz ranges which is much more comfortable ground for my old 'scope.  ;)

But there is a trick with FPGAs. You can build a logic analyzer in the same chip as the cirucit. Quartus has a tool for doing this called SignalTap:...
You give it a list of signals you want to monitor and how much memory to use and it generates a logic analyzer for that, taps off those signals and adds it to the design.

Wow!  That's really useful - specially if you have a decent amount of RAM in the FPGA.  :-+

Work calls again, but when I get some more time to work on this I'll set up a resistor ladder to merge the two bits for R, G and B on the breadboard so I can try out the full colour palette.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2019, 12:27:28 pm
Well, that sorted the problem - thanks BrianHG!  :-+

Clearly my monitor wasn't happy with the 3.3v sync signals - I found a 74AHC541 in my box of bits and am now running the vertical and horizontal sync signals through one of these line drivers powered at 5v and am getting a nice stable output:

(https://i.ibb.co/BfFX87L/20191104-114222.jpg) (https://ibb.co/Zf7nywd)

It's surprising how pleased I am at getting four overlapping squares to display on a monitor!!! Haha!  :-DD
;)   :clap:  HCT is actually better for converting the FPGA 3.3v to 5v since it's inputs have a trigger threshold at TTL levels instead of mid 5v, or 2.5v.  Any will work, like 74HCT, 74ACT, and other variants.  (You would have never figured this one out without me.  This one nearly destroyed a huge demo I had 10 years ago since my home test monitors were studio grade monitors whose sync inputs would work perfectly with a 0.7vp-p sync...  The cheap PC screens didn't like that 3.3v.)

Take a day to learn how to make a top hierarchy block diagram in quartus.  Make your now functioning project's 2 xxx.v files into 2 separate block and wire them on a block diagram.  (Save your current project and start a new one...)

***Remember when defining the inputs and outputs.  Output bus pins in quartus look like ' Red[7..0] ', not 'Red[7:0] ' like you see in verilog.  It's the only BIG gripe I have with Quartus as its a drawback from their pre-verilog days of quartus 1 ...  Once you are ready, I'll show you a few tricks which will make all your outputs parallel without delays, even as you add modules in-between, like my OSD character generator.  I also recommend going on youtube and searching beginners guide to quartus block diagram entry, or similar to get you going.  Include generating a sheet symbol for verilog source files/code in quartus...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2019, 08:23:50 am
For info, Grant Searle has put his site back up at searle.wales (http://searle.wales).

It seems his ISP took the site down for breach of terms and conditions due to the high traffic it was generating.  :-DD

I'm trying to get my head around hierarchy block diagrams, but it's really slow going.  Initially I was concerned that Quartus II 3.0 sp1 didn't support that feature, but it just seems it's deeply buried somewhere.  Then I got sidetracked looking at character generators (the next big step for my design) and today, hopefully, I'll have some time to work on block diagrams again!!!  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2019, 08:47:29 am
You should be thinking of making your own character generator, but first, you need to clean up your sync generator.
In Quartus, making a 'New' block diagram file is a key feature, not a hidden one.
Setting that .bdf (block diagram file) as the top hierarchy is also standard.

Double clicking on the the middle of the file to add pins and generic logic, or even library megafunctions is also standard.

What might be a little hidden is opening your .v file in the directory, then 'Generating sheet symbol' (I think it's called this, it's been a decade...)L:
File>Create/Update>Create symbol files for current file.

The verilog must have no errors for this to work.

Once generated, in your .bdf,  double click in a blank area to add a new symbol/component.  Click on user generated symbols and place the symbol on the sheet.

You should see a symbol labeled with you verilog name with all the input and output pins and buses.

In the furture, if you want to edit your verilog code for that symbol in your block diagram, you may just double click on it's symbol in your block diagram.  If you add inputs or outputs and you want them to appear on that symbol in you block diagramm, you will need to re: ' File>Create/Update>Create symbol files for current file. ' to update the symbol with the new IO pins.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2019, 10:52:59 am
You should be thinking of making your own character generator, but first, you need to clean up your sync generator.

Yes, must try not to get ahead of myself.  :-\

In Quartus, making a 'New' block diagram file is a key feature, not a hidden one.
Setting that .bdf (block diagram file) as the top hierarchy is also standard.

Sure is. Just wasn't obvious to a completely new beginner like me yesterday who only knew about creating .v files!  :scared:

I found a really handy tutorial (https://www.flc.losrios.edu/docs/FLC-Documents/Instruction/Engineering/lab/Lab1%20-%20Quartus%20Tutorials.pdf) (actually a university/college worksheet) with step-by-step instructions on how to create the two types of project (one based on code, the other on a diagram), create blocks for them both and use them both in a top-level project as diagram symbols.  I also learned about creating simulations, too!  ;D

This is as far as I've gotten:

(https://i.ibb.co/N1xghPh/Untitled.png) (https://ibb.co/rbkKPSP)

Not great - I've inputs and outputs on sync_generator that don't connect to anything on vga01, which is annoying.  Will go look at that.

Code for vga01.v and sync_generator.v attached for info, as I've changed vga01.v a bit to show colour bars instead of squares now.

EDIT:

Updated diagram:

(https://i.ibb.co/1b41qGr/Untitled.png) (https://ibb.co/ZNb58zB)

EDIT 2:

From looking at this second diagram, it seems I should move the pix_en generation from vga01 to sync_generator, as it would make more sense for it to be there unless I'm likely to need it in vga01 at any point in the future there?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2019, 01:21:25 pm
Updated diagram:

(https://i.ibb.co/mCy8TRz/Untitled.png) (https://ibb.co/XZ58LWJ)

This is giving me errors, though, when I try to compile:

Code: [Select]
Info (12128): Elaborating entity "vga01" for hierarchy "vga01:inst"
Error (12014): Net "vga01:inst|x[8]", which fans out to "vga01:inst|vga_r", cannot be assigned more than one value
Error (12015): Net is fed by "vga01:inst|sync_generator:display|x[8]"
Error (12015): Net is fed by "vga01:inst|x[8]"
Error (12014): Net "vga01:inst|x[7]", which fans out to "vga01:inst|vga_g", cannot be assigned more than one value
Error (12015): Net is fed by "vga01:inst|sync_generator:display|x[7]"
Error (12015): Net is fed by "vga01:inst|x[7]"
Error (12014): Net "vga01:inst|x[6]", which fans out to "vga01:inst|vga_b", cannot be assigned more than one value
Error (12015): Net is fed by "vga01:inst|sync_generator:display|x[6]"
Error (12015): Net is fed by "vga01:inst|x[6]"
Error (12014): Net "vga01:inst|inDisplay", which fans out to "vga01:inst|vga_r", cannot be assigned more than one value
Error (12015): Net is fed by "vga01:inst|sync_generator:display|inDisplayArea"
Error (12015): Net is fed by "vga01:inst|inDisplay"

Trying to look these up, but it's not obvious (to me at least) what the problem is.  I'm obviously doing something very stupid...  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 06, 2019, 01:28:39 pm
That error to me looks like there are multiple outputs trying to drive 3 bits of net" x" and "inDisplay". You might have an output or input back to front.

Oh and by the way your inDisplay signal is probably the same as a signal that RGB buses tend to call the DE signal (Display Enable). This is a signal that is high whenever pixels inside the viewing area are being sent. Some LCD panels use that instead of Hsync and Vsync
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2019, 01:41:34 pm
Your RGB 2 wire buses are driving output pins are single wires each.  Remove the doubled pins and rename the output pins R[0], G[0], B[0] to:

R[1..0]
G[1..0]
B[1..0]

Quartus will understand that those outputs are a collective of pins grouped as a bus with 2 wires going to 2 pins.

This come in handy when you have an output group, like in my design, I have a 256bit ram data bus.  Could you imagine my block diagram with 256 individual BIDIR IOs instead of one single one labeled RDQ[255..0]...

Also, you do not need to label the buss wires as they will take their name from the output pins automatically.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2019, 02:39:23 pm
That error to me looks like there are multiple outputs trying to drive 3 bits of net" x" and "inDisplay". You might have an output or input back to front.

Okay, it compiles now - I just had to remove this block from vga01.v:

Code: [Select]
// create a 640x480 synch and pixel
   sync_generator #(640,480) display(
      .clk(clk),
      .reset(rst),
      .x(x),
      .y(y),
      .DE(DISP_EN)
   );

I forgot to remove that block, so the HDL was trying to set up two connections to vga01 - one in code, the other in the diagram?

Quartus will understand that those outputs are a collective of pins grouped as a bus with 2 wires going to 2 pins.

This come in handy when you have an output group, like in my design, I have a 256bit ram data bus.  Could you imagine my block diagram with 256 individual BIDIR IOs instead of one single one labeled RDQ[255..0]...

 :o Yikes.

Also, you do not need to label the buss wires as they will take their name from the output pins automatically.

Ah okay, thanks - the info I found online (from Intel, no less) stated in one of the steps to label the bus, so I did. Happy to hear about shortcuts, though. ;)

Talking of which, I'm really liking this diagram method of connecting blocks up - seems much less stressful than the code method!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2019, 03:51:25 pm
 |O  Okay, so it compiles but I'm getting no image - the screen is going into standby. 

I've attached the files for vga01 and sync_generator with all the latest modifications I've made - they all compile fine into symbols and as part of the main project, but I'm getting nothing out at the monitor.  Below is a pic of the top-level diagram:

(https://i.ibb.co/fQBpvm6/Untitled.png) (https://ibb.co/vDgPY2y)

I've even tried swapping HSYNC/VSYNC around in case I'd got the pin assignments wrong, but to no avail - I'm not sure what's going wrong to be honest.  Have attached project files in case anyone wants to take a look.

EDIT:

For info, the pin assignments are identical to the project VGA01 - which I've uploaded to the FPGA and tested and that works fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 06, 2019, 05:17:41 pm
Instead of looking trough your code for the problem im just going to give you some tips on debugging it.

First choice of action is a oscilloscope. Look at what the pins are doing because this is quick and easy to do, for tracking down the basic mistakes like wonky or missing clocks, swapped signals etc...

Then if it still does not lead you to any findings have a look at that "RTL View" and see what the compiler has compiled. Since you have basicaly put together the same thing in a diferent way means it should also compile into circuitry that is similar. Try to make sense of the connections in there and if there is something weird that can point you into where exactly the issue might be.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2019, 06:31:59 pm
 :palm: :palm: :palm:

Fixed it.  I'd linked the reset line to both blocks, but had only inverted the signal in one of them - forgetting to invert the signal to the other, so one was held in permanent reset.  |O

All working again now.  ;D

Previous image of diagram is still current, more or less, except for the inversions on the reset inputs for each block (I've removed the code inverting reset in sync_generator).  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 07, 2019, 09:18:51 am
Here we go, I cleaned up your sync generator.  You had a few bugs.  Now, I don't have Quartus installed anymore and I just typed it in a text editor, so please bear with possible errors.  Once you understand my changes, you may remove anything you don't like:

Code: [Select]
// (default 640x480) 60Hz VGA Driver
// but can take parameters when initialised
// to output sync signals for any screen
// resolution
//
//                          |- LINE
//        __________________________ ____|
//       |                          |    |
//       |                          |    |
//       |               |    |
//       |               |    |
//       |      DISPLAY AREA        |    |
//       |                          |    |
//       |                          |    |
//       |                          |    |
//       --------------------------------- V_RES
//       |                          |
//       |                          |
//       ---------------------------- SCANLINES

module sync_generator(
// inputs
input wire pclk, // base pixel clock
input wire reset, // reset: restarts frame
// outputs
output reg pc_ena    // ***** New pixel clock enable ...  For now, you will use pc_ena[0] which divides the clock by 2.
output reg hde, // Horizontal Display Enable - high when in display area (valid drawing area)
output reg vde, // Vertical Display Enable - high when in display area (valid drawing area)
output reg hsync, // horizontal sync
output reg vsync, // vertical sync
output reg [9:0] h_count, // current pixel x position
output reg [9:0] v_count // current line y position
);

// default resolution if no parameters are passed
parameter H_RES = 640; // horizontal display resolution
parameter V_RES = 480; // vertical display resolution

// no-draw area definitions
// ***** switched to parameters so you can edit these on quartus' block diagram editor.
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH   = 96;
parameter H_BACK_PORCH  = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH  = 33;

// total screen resolution
localparam LINE = H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_BACK_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_BACK_PORCH; // total scan lines (inc. vertical blanking area)

// useful trigger points
localparam HS_STA = H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1;// horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF

/*  moved above
reg [9:0] h_count; // line position
reg [9:0] v_count; // SCANLINES position
reg [9:0] z_count; // Frame counter for CPU animation
*/

// keep x and y bound within the display area
/* obsolete
assign x = (h_count < H_RES) ? h_count : (H_RES - 1'b1); // x = H_RES-1 if current pixel is after display area
assign y = (v_count < V_RES) ? v_count : (V_RES - 1'b1); // y = VS_END-1 if v_count is outside display area
*/
   // generate a 25 MHz pixel strobe
   //reg [15:0] cnt;
   //reg pix_en;

   always @(posedge clk)
pc_ena <= pc_ena + 1'b1;  // This is tempoary

// handle signal generation
always @(posedge clk)                    // I removed ', posedge reset)', since it adds a gate to the CLK input of all the registers in your design slowing down that trigger edge
begin
if (reset) // reset to start of frame
begin
h_count <= 1'b0;
v_count <= 1'b0;
hsync   <= 1'b0;
vsync   <= 1'b0;
vde     <= 1'b0;
hde     <= 1'b0;
end
else
begin
if (pc_ena) // once per pixel
begin

if (h_count == H_RES - 1)
begin
HDE <= 1'b0;
end


// check for generation of HSYNC pulse
if (h_count == HS_STA)
begin
hsync <= 1'b1; // turn on HSYNC pulse
end
else if (h_count == HS_END)
hsync <= 1'b0; // turn off HSYNC pulse

// check for generation of VSYNC pulse
if (v_count == VS_STA)
begin
vsync <= 1'b1; // turn on VSYNC pulse
end
else if (v_count == VS_END)
vsync <= 1'b0; // turn off VSYNC pulse

// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin
h_count <= 1'b0;
HDE     <= 1'b1;  // Turn on horizontal video data enable

if (v_count == SCANLINES - 1) // ****** Now that it's time to increment the H count, this is when you would check if the V-count should be cleared.  End of SCANLINES
begin
v_count <= 1'b0;
VDE     <= 1'b1;   // Turn on vertical video data enable
end
else
begin                                             // ****** If the v_count isn't being cleared, you go ahead and add 1 to the v_count
v_count <= v_count + 1'b1;           // increment v_count to next scanline
if (v_count == V_RES - 1)   VDE <= 1'b0 ; // Turn off  vertical video data enable
end
end
else
h_count <= h_count + 1'b1;           // otherwise, just increment horizontal counter
if (h_count == H_RES - 1)  HDE <= 1'b0 ;  // Turn off  vertical video data enable

/*  ****** BUG *****  Moved into the correct place at the the end of a horizontal line, where you increment the v_count increment, or clear it. see 16 lines above
// reset v_count and blanking at bottom of screen
if (v_count == SCANLINES - 1) // end of SCANLINES
begin
v_count <= 1'b0;
end
*/  ***** End of bug ******

end
end
end

/******* Error ****** this must synchronous with you video clock, however, I recognize this was probably just a last minute patch.
always @(posedge clk)
begin
DE <= (h_count < H_RES) && (v_count < V_RES);
end
/********

endmodule


Now, here is a new module to add to your project.  It mutes the RGB data values when the raster is outside the active display area.  (Once again, I just typed it in notepad.)  It belongs just before your output pins.  Again, read comments inside it.

Code: [Select]
//  This module will force mute mute the RGB video output data outside the active video display area
//  This module will also generate the vid_de_out use by many DVI transmiters
//  This module, as an example, also has all the inputs and outputs used along the pixel pipe
//  it illustrates since there is a pixel delay in the video switch, the syncs and video enables are also delayed
//  making the output picture window perfectly parallel with the vidoe coming in, then being fed out.

module vid_out_stencil(
input wire pclk,
input wire reset,
input wire pc_ena,      // Pixel clock enable
input wire hde_in, // Horizontal Display Enable - high when in display area (valid drawing area)
input wire vde_in, // Vertical Display Enable - high when in display area (valid drawing area)
input wire hs_in, // horizontal sync
input wire vs_in, // vertical sync

input wire [RGB_hbit:0] r_in,
input wire [RGB_hbit:0] g_in,
input wire [RGB_hbit:0] b_in,

output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,

output reg [RGB_hbit:0] r_out,
output reg [RGB_hbit:0] g_out,
output reg [RGB_hbit:0] b_out,

output reg vid_de_out      // Actual H&V data enable required by some DVI encoders/serializers
);

parameter RGB_hbit    = 1;  // 1 will make the RGB ports go from 1 to 0, eg [1:0].  I know others prefer a '2' here for 2 bits
parameter HS_invert   = 0;  // use a 1 to invert the HS output, the invert feature is only for this video output module
parameter VS_invert   = 0;  // use a 1 to invert the VS output, the invert feature is only for this video output module


always @(posedge clk)
begin
if (reset) // global reset
begin

// not in use for this module

end
else
begin
if (pc_ena) // once per pixel
begin

hde_out <= hde_in;             // since the this video muting switch algorythm delays the output by 1 pixel clock,
vde_out <= vde_in;             // all the video timing reference signals will also get the 1 pixel delay treatment to keep the output aligned perfectly.
hs_out  <= hs_in ^ HS_invert ; // the invert feature is only for this video output module
vs_out  <= vs_in ^ VS_invert ; // the invert feature is only for this video output module

if ( hde_in && vde_in )
begin
de_out <= 1'b1 ; // turn on video enable for DVI transmitters
r_out  <= r_in ; // copy video input to output
g_out  <= g_in ; // copy video input to output
b_out  <= b_in ; // copy video input to output
end
else
begin
de_out <= 1'b0 ; // turn off video enable for DVI transmitters
r_out  <= 0    ; // Mute video output to black
g_out  <= 0    ; // Mute video output to black
b_out  <= 0    ; // Mute video output to black
end

end
end
end
endmodule


Now, the next thing you need to do is use the IOs from this example, and make a new picture pattern generator which does not use the sync generators H&V counters, but, generates it's own internally using this example IO port setup:

Code: [Select]
module vid_pattern_generator(
input wire pclk,
input wire reset,
input wire pc_ena,      // Pixel clock enable
input wire hde_in, // Horizontal Display Enable - high when in display area (valid drawing area)
input wire vde_in, // Vertical Display Enable - high when in display area (valid drawing area)
input wire hs_in, // horizontal sync
input wire vs_in, // vertical sync


output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,

output reg [RGB_hbit:0] r_out,
output reg [RGB_hbit:0] g_out,
output reg [RGB_hbit:0] b_out

);

parameter RGB_hbit    = 1;  // 1 will make the RGB ports go from 1 to 0, eg [1:0].  I know others prefer a '2' here for 2 bits


always @(posedge clk)
begin
if (reset) // global reset
begin



end
else
begin
if (pc_ena) // once per pixel
begin

// ***************  insert generator code here
// ***************  also remember to pass through the hde,vde,hs_out,vs_out
// ***************  in the future, numerous delay sizes may be needed if you are performing functions which take multiple clocks before a true pixel becomes valid

end
end
end // always @clk
endmodule


Let me know when you are done, because, after I've gone over your new pattern generator, your next step is to place either your first text, or, graphics.

Additional: Please place you quartus screenshots on this forum, I'm having trouble with your picture server & since this thread may last long on the forum, it is a good idea to have the photos here.  (If you want a compact picture file size, lossless, use the .png file format...)

***** DON'T forget to update the graphic symbol for the changes I made to you sync generator.  The order of the IO pins have been changes and I changed the available parameters on the block diagram symbol.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 07, 2019, 09:30:37 am
Is there a specific reason why not to reuse the X and Y counters from the sync generator?

You will always need to know the pixel X Y coordinates so why not use a counter that already counts this. Only thing i would add is a "pixel_increment" signal that goes high for 1 clock cycle every time it steps onto the next pixel. This can then pace the pixel generation logic at slower speeds than the clock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 07, 2019, 10:20:49 am
Is there a specific reason why not to reuse the X and Y counters from the sync generator?

You will always need to know the pixel X Y coordinates so why not use a counter that already counts this. Only thing i would add is a "pixel_increment" signal that goes high for 1 clock cycle every time it steps onto the next pixel. This can then pace the pixel generation logic at slower speeds than the clock.
Yes.  The counters are good for generating a pattern, especially in a simple design.  However, there are a few advantages to getting used to having a separate what we could more truly call an address counter generator which doe not rely on multiply and add to point to a position in ram specifically.

First advantage.  You notice I separated the display enables into horizontal and vertical, HDE & VDE.  to create a synchronous new H&V counter, one could approach the counters like this:

--------------------------------------------------------------------------------------------------------------
hde_out <= hde_in;
vde_out <= vde_in;

if (~vde) begin  // regardless of the display geometry and timing, the new
   vcount <=0 ;  // vertical count clears immediately after a video frame has finished
  end else begin
                  if (~hde_in && hde_out ) vcount <= vcount +1;  // regardless of the display geometry and timing, the new
                                                                                        // vertical count increments immediately after a video line is finished
                                                                                       // giving time for address generators to do their math and ram access cycles
                  if (~hde) begin
                     hcount <= 0;
                 end else begin
                      hcount <= hcount +1;
                     end
------------------------------------------------------------------------------------------------------------------------------------
Now, the hcount and vcount coming out of the sync generator may be re-aligned with reference to the active picture area to re-center position the picture, the above code with minimal gates will always clear and increment you picture coordinates right after the display activity has ended, giving you maximum time to perform additional actions/access within the same block of system memory to do thing like, copy over memory to fill a sprite, copy memory for audio dac, read a display list for what the video mode of the next line of video should be and where it's display memory is located.

Now, this is a preference as I know that such logic will only eat another 24 logic registers for a full 1024x1024.  This will also increase your FMAX as these counters may now be located right at the inputs of your dual port ram which quartus now only has to route HDE and VDE from your sync generator to wherever the ram address may be in the FPGA.

Remember, the current sync generator only generates a vde, hde, vsync, hsync.  Wait till we add

sprite1.thru.8_hstart
sprite1.thru.8_vstart
sprite1.thru.8_vstop
vertical_interrupt1.thru.2

Stopping here already makes 26 x 10 bit number compares on the hcount and vcount to generate their windowed coordinates.  Adding that to using the same counters to generate additional raster coordinates will kill the FMAX in such a slow old FPGA.

I'm targeting a high speed FMAX so that with a simple dual port ram, on the graphics read side, if the ram is operating at 6x the pixel clock speed, say 150Mhz, for each pixel drawn, I can access 6 different words of system ram and still have the second port 100% dedicated to the CPU interface.

With these 6 access, we will for example, read a top ascii text window layer, loop that output into a resolver for the font memory base address and read that letters correct pixel, another access cycle for reading a font color map.  Also, access graphics memory for a graphics mode.  And since these modes usually are bitplane, they'll only eat 1-2 of my access time slots.  The remainder access slots 3-6 will be used for a hardware rectangle read / modify / write command which will accelerate clear, carriage return scroll text, paste a bitplane picture from one location in memory into another with an optional transparent color 0.  With the 2 megabit Lattice part, an 8Mhz Z80 would be able to basically run a simplified Doom type game with all the sorted character graphic images pre-rendered in the OP's 160x120 256 color mode.


Hmmm, the only ugly thing would be a triangle filling engine.  Thankfully, there is another thread here on this FPGA forum covering that exact topic, with source code...  With a core 150Mhz clock and 8MHZ cpu, the dedicated CPU memory access port if free over 95% of the time for sophisticated triangle, rectangle and circle geometry engine.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 10:39:03 am
Here we go, I cleaned up your sync generator.  You had a few bugs.

Thanks!  :-+

Well done, by the way, writing all that in a text editor - there were only a couple of typos in variable names, otherwise it all compiled into symbol files just fine.  ;D

Now, the next thing you need to do is use the IOs from this example, and make a new picture pattern generator which does not use the sync generators H&V counters, but, generates it's own internally using this example IO port setup:

Okay, working on it now...  :-/O

Additional: Please place you quartus screenshots on this forum, I'm having trouble with your picture server & since this thread may last long on the forum, it is a good idea to have the photos here.  (If you want a compact picture file size, lossless, use the .png file format...)

Righto - don't know why I got into the habit of externally-hosting the images, but there's no particular reason I still do it.  :-+

***** DON'T forget to update the graphic symbol for the changes I made to you sync generator.  The order of the IO pins have been changes and I changed the available parameters on the block diagram symbol.

No worries. Will get back to you (hopefully) shortly!  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 07, 2019, 11:04:44 am
Well yes for counting frame buffer memory addresses you would want to use a separate counter that resets on Vsync. But for other things having X Y tends to be more useful.

For text and tile maps id use grids that are 8 16 32 or something and round the total area to a round power of 2 number so that you can get the index by simply bit shifting and so zero logic is needed to calculate the index from X Y (Yes this wastes memory space but is very useful for smooth scrolling). Also since these are small and often accessed id stick them into separate memory blocks so that you can generate text and color it within a single clock cycle. When deciding about sprites its also common that you need to compare a bunch of registers to the X and Y coordinates. All of it being essentially combinational logic that can work in the background for multiple clock cycles if needed since pixels come out at such a slow rate. You can easily give yourself a 1 pixel head start to it by delaying Hsync output by one pixel so that the pipeline is full and ready when the pixels really start moving out to the monitor.

Anyway many ways to skin a cat, none of them necessarily more correct, just different in there own way.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 11:30:12 am
Okay, vid_pattern_generator.v below for your perusal and criticism.  ;)

I haven't tried it out on the FPGA yet as I'm sure there'll be some feedback and changes I need to make!  I was undecided about how to implement the x, y counters - but the method I've gone with is this one; all the time pc_ena is HIGH (pixels are being drawn), I increment the X and Y counters - so they should range from 0-639 for x and 0-479 for y, or indeed whatever maximum value the current screen resolution goes up to.

As they're counting, the only check that is made is against H_RES to reset x at the end of each scan line.  I don't check y at all as that will stop counting when pc_ena goes LOW and get reset during VSYNC.

As soon as pc_ena goes LOW, the counters no longer increment and when there is a VSYNC pulse, the counters are reset, ready for pc_ena to go HIGH at the start of the next frame and allow them to count again.

Does that sound reasonable, or is there a better way?

Code: [Select]
module vid_pattern_generator(

input wire pclk,
input wire reset,
input wire pc_ena, // Pixel clock enable
input wire hde_in, // Horizontal Display Enable - high when in display area (valid drawing area)
input wire vde_in, // Vertical Display Enable - high when in display area (valid drawing area)
input wire hs_in, // horizontal sync
input wire vs_in, // vertical sync


output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,

output reg [RGB_hbit:0] r_out,
output reg [RGB_hbit:0] g_out,
output reg [RGB_hbit:0] b_out

);

parameter RGB_hbit = 1; // 1 will make the RGB ports go from 1 to 0, eg [1:0].  I know others prefer a '2' here for 2 bits

// default resolution if no parameters are passed
parameter H_RES = 640; // horizontal display resolution
parameter V_RES = 480; // vertical display resolution

// set up x & y position counters
reg [9:0] x, y;

always @(posedge pclk)
begin
if (reset) // global reset
begin

// reset position counters
x <= 1'b0;
y <= 1'b0;

end // global reset
else
begin
if (pc_ena) // once per pixel
begin

// Generate some colour bars based on x value
r_out[RGB_hbit] <= x[8];
g_out[RGB_hbit] <= x[7];
b_out[RGB_hbit] <= x[6];

// pass through hde, vde, hs_out, vs_out
hde_out <= hde_in;
vde_out <= vde_in;
hs_out <= hs_in;
vs_out <= vs_in;

// update the position counters
// all the time pc_ena is HIGH, we're in a valid drawing area so
// the counters can be incremented and checked against the
// supplied screen resolution
// reset X & increment Y at end of scanline
if (x == H_RES - 1) // end of line
begin
x <= 1'b0; // reset X
y <= y + 1'b1; // increment Y to next scanline
end
else // not at end of scanline, so just increment X
x <= x + 1'b1;

end // pc_ena
else
begin

// Check for VSYNC and reset X & Y if VSYNC is HIGH
if (vs_in)
begin
x <= 1'b0;
y <= 1'b0;
end
else
begin
// do nothing
end

end // !pc_ena

end // !global reset

end // always @clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 07, 2019, 11:54:32 am
Here's a trick:

----------------------------
                 if (~hde_in) begin
                     x <= 0;
                 end else begin
                      x <= x +1;
                     end
-----------------------------
OR --- your choice ---
----------------------------
                 if (hde_in) begin
                     x <= x + 1;
                 end else begin
                      x <= 0;
                     end
-----------------------------

What's happening here is while the horizontal enable is OFF, the x counter is kept at 0.
When the horizontal enable is high, the x counter counts.  This is elegant since the X position is 0 right after the display is disabled and goes to 1 right at the second active pixel while continuing to count up.

Vertical has 1 additional trick...

-------------------------------------
if (~vde_in) begin
   y <=0 ;  // vertical count=0 after the picture area is finished and stays at 0 while the vertical DE is not enabled
  end else begin
                  if (~hde_in && hde_out ) y <= y +1;  // the trick.... When the horizontal DE line ends by going low, at that 1 pixel
                                                                              // while the horizontal DE output is still high since it's delayed
                                                                              // by 1 pixel clock, the vertical counter will increment by 1.
                                                                              // Using an input  ANDED with a 1 clock delayed copy of that input is
                                                                             // is commonly used to trigger a single shot / one shot action every time
                                                                            // an input transitions from high to low, or low to high depending on your ~...
  end
------------------------------------

What going on here, is that during the first line of the vertical DE, since it was previously cleared, it starts at 0.
It wont increment until the end of the first horizontal line meaning that at the next line, the Y counter will already be at 1.

Operating like this, if you have a variable HDE and VDE window anywhere in your raster at any size, the X and Y counters will be at their next ready valid numerical state immediately after each line has ended and the frame has ended.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 12:14:06 pm
Operating like this, if you have a variable HDE and VDE window anywhere in your raster at any size, the X and Y counters will be at their next ready valid numerical state immediately after each line has ended and the frame has ended.

Fantastic - works beautifully and is quite small and neat, a great combination.  ;D

[attach=1]  [attach=2]

One thing I've noticed - there's more colour bars... Is the x counter incrementing properly?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 01:05:25 pm
For text and tile maps id use grids that are 8 16 32 or something and round the total area to a round power of 2 number so that you can get the index by simply bit shifting and so zero logic is needed to calculate the index from X Y (Yes this wastes memory space but is very useful for smooth scrolling).

I'd be hoping that I could just ignore the least significant bits of the x and y counters to get the tile index?  Say my tiles are 8x16 (I was originally planning on 8x8, but it seems it should actually be 8x16? I might just stretch the y-axis by 2 though to keep memory use down initially).  So for example:

Code: [Select]
tile_x = x[9:4];
tile_y = y[9:5];

Surely that'd be quicker than messing around with bit shifts, or am I misunderstanding what you've written and we're talking about the same thing?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 07, 2019, 01:15:21 pm
For text and tile maps id use grids that are 8 16 32 or something and round the total area to a round power of 2 number so that you can get the index by simply bit shifting and so zero logic is needed to calculate the index from X Y (Yes this wastes memory space but is very useful for smooth scrolling).

I'd be hoping that I could just ignore the least significant bits of the x and y counters to get the tile index?  Say my tiles are 8x16 (I was originally planning on 8x8, but it seems it should actually be 8x16? I might just stretch the y-axis by 2 though to keep memory use down initially).  So for example:

Code: [Select]
tile_x = x[9:4];
tile_y = y[9:5];

Surely that'd be quicker than messing around with bit shifts, or am I misunderstanding what you've written and we're talking about the same thing?

Yes this is bit shifting, just rewireing bits with some offset. On a FPGA such a operation is free as its done inside the signal routeing hence why its so useful.

The reason for also keeping the map size a power of 2 is so that you can build the address for the map memory by simply going
Code: [Select]
assign tilemap_addr = {tile_y,tile_x};
This means that on a 640x480 screen with 8 pixel tiles you would instead of having 80 tiles wide have 128 tiles wide by using a 7bit wide tile_x register. So you waste memory by having more tile memory than is needed to fill the screen, but it also allows the CPU to draw and update tiles outside the visible area. This is how infinite smooth scroling is implemented on most game consoles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 07, 2019, 01:24:30 pm
Operating like this, if you have a variable HDE and VDE window anywhere in your raster at any size, the X and Y counters will be at their next ready valid numerical state immediately after each line has ended and the frame has ended.

Fantastic - works beautifully and is quite small and neat, a great combination.  ;D

(Attachment Link)   (Attachment Link)

One thing I've noticed - there's more colour bars... Is the x counter incrementing properly?
I think you can now invert the hsync and vsync output to get the standard VGA output sync polarity.  Now with the 5v buffered outputs, your monitor should accept the signal.

As for text, you are correct, take a look at my text generator, though it might need a little touch-up to be wired in place of your video generator.  You'll also note in my code that I am ignoring the LSB on the H&V counters in my code.  This is to make each dot in my 8x8 font 2 pixels wide and 2 pixels tall.

I'll take a look at the code tonight and maybe do a little patch for you.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 02:17:27 pm
This means that on a 640x480 screen with 8 pixel tiles you would instead of having 80 tiles wide have 128 tiles wide by using a 7bit wide tile_x register. So you waste memory by having more tile memory than is needed to fill the screen, but it also allows the CPU to draw and update tiles outside the visible area. This is how infinite smooth scroling is implemented on most game consoles.

Sounds like an effective way to do it, but I might have to leave that for a while until I have an FPGA with enough RAM.   The Spartan 6 arrived today, but I'm still waiting on the cable programmer for it.  ::)

I think you can now invert the hsync and vsync output to get the standard VGA output sync polarity.  Now with the 5v buffered outputs, your monitor should accept the signal.

Okay, that's strange.  I've inverted the HSYNC and VSYNC by changing the parameters on vid_out_stencil, and I'm now getting fuzzy edges to the colour bars and screen blanking several times a second.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 07, 2019, 02:31:54 pm
This means that on a 640x480 screen with 8 pixel tiles you would instead of having 80 tiles wide have 128 tiles wide by using a 7bit wide tile_x register. So you waste memory by having more tile memory than is needed to fill the screen, but it also allows the CPU to draw and update tiles outside the visible area. This is how infinite smooth scroling is implemented on most game consoles.

Sounds like an effective way to do it, but I might have to leave that for a while until I have an FPGA with enough RAM.   The Spartan 6 arrived today, but I'm still waiting on the cable programmer for it.  ::)

I think you can now invert the hsync and vsync output to get the standard VGA output sync polarity.  Now with the 5v buffered outputs, your monitor should accept the signal.

Okay, that's strange.  I've inverted the HSYNC and VSYNC by changing the parameters on vid_out_stencil, and I'm now getting fuzzy edges to the colour bars and screen blanking several times a second.
Your going to have to check the outputs with your scope.  It sounds like the 5v high isn't reaching or maintaining 5v.  With the shorter pulses of a positive sync, the monitor might see the signal better meaning the signal is still operating at the edge of functionality.  For now, just use a positive sync unless you want to scope your 74xxx CMOS buffer's output.

Do you have you CMOS buffer's output tied 4 in parallel like I recommended to give you a higher current drive?  If you monitor have 75ohm load on the sync signals instead of 1kohm, it also may have a high level of around 4v instead of 5v.

Is your vsync also going through the buffer the same way?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 03:30:23 pm
Do you have you CMOS buffer's output tied 4 in parallel like I recommended to give you a higher current drive?  If you monitor have 75ohm load on the sync signals instead of 1kohm, it also may have a high level of around 4v instead of 5v.

Is your vsync also going through the buffer the same way?

VSYNC and HSYNC are both unchanged in that they're both going through the buffer as before.

One thing is that I'm only using one output from the buffer for HSYNC and VSYNC.  Might try the multiple-parallel outputs and see if that improves the image with inverted sync signals then!  :-/O

Oh, I'm also dabbling with trying to build a character generator and am fast realising I know nothing about how to interface a block with a memory block etc...  :o

EDIT:

Yes, that sorted it.  I've only used two outputs per sync signal for the moment, but it's working fine inverted now with no misbehaviour.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 07, 2019, 03:57:13 pm
Oh, I'm also dabbling with trying to build a character generator and am fast realising I know nothing about how to interface a block with a memory block etc...  :o
You need Verilog's memory syntax. (ETA: oops, it's not a keyword)
Code: [Select]
reg [7:0] mem [127:0];
always @ (posedge clk) begin
  if (we)
    mem[write_address] <= d;
  q <= mem[read_address]; // q doesn't get d in this clock cycle
end
Note well, that's a non-blocking assignment so adjust your time machine accordingly.

Recommended HDL coding styles handbook (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/qts/qts_qii51007.pdf), p13 and on, for more examples.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 03:58:14 pm
Okay, so for a character generator, this is what I'm thinking:

Replace the vid_pattern_generator with a vid_char_generator.  It will share all the inputs and outputs of the vid_pattern_generator, but with some extras:


This will allow the vid_char_generator to compute the current tile address from the internally-generated x & y coordinates, send that address to the video memory and receive a character index back.

Then it will compute a pixel address for that character in the character memory, based on the character index and current x & y coordinates, which will return a single bit of information based on whether the current pixel is background- or foreground-coloured depending on the character in that tile....  Does that make sense?  Am I over-complicating it, because there seems like a lot going here?  :scared:

I would load a font file (OSD_FONT.MIF) and LUT (osd_mem.mif) into the character memory and, initially at least, the video memory will be garbage - but populating that with useful data is a few steps away yet.

I'm a little confused looking at osd_generator.v, but then I don't have a good map in my head of what should be happening here anyway, so understanding it is proving difficult.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 07, 2019, 04:48:51 pm
Okay, so for a character generator, this is what I'm thinking:

Replace the vid_pattern_generator with a vid_char_generator.  It will share all the inputs and outputs of the vid_pattern_generator, but with some extras:

  • An 8-bit data input from video memory.
  • A xx-bit address to video memory.
  • A CE (chip enable) to video memory.
  • An xx-bit address output to character memory.
  • An 1-bit data input from character memory.
  • A CE to character memory.
CE is only relevant in discrete implementations where the memory needs to be kept from driving a shared bus. Here, memory is always chip-enabled and you just have write-enables and maybe read-enables. Or, if you prefer to have the tool infer memory from generic HDL, you only have write-enables and are always reading every clock. If you want to hold read data, add your own register.

Quote
This will allow the vid_char_generator to compute the current tile address from the internally-generated x & y coordinates, send that address to the video memory and receive a character index back.

Then it will compute a pixel address for that character in the character memory, based on the character index and current x & y coordinates, which will return a single bit of information based on whether the current pixel is background- or foreground-coloured depending on the character in that tile....  Does that make sense?  Am I over-complicating it, because there seems like a lot going here?  :scared:
No, that's about the size of it. Now you see why I was encouraging you to do a plain old framebuffer to start :)

Block RAMs are commonly used in synchronous mode, which means you'll have a one-cycle delay through each memory. You can get ahead of it such as by reading the next character index or bitmap ahead of time and buffering the data, or you can push other business back such as by applying a two-clock delay to the display enable to the rest of the display system. If you want to give yourself something other than garbage or nothing to stare at, use an initial task to preload a character bitmap or two and to fill the text memory with something. Writing this from sleep-deprived memory:
Code: [Select]
initial begin
  integer i;
  for (i=0; i<255; i++) begin
    charmem[0+i*8] = 8'b00010000 ^ {i[0]{8}}; // invert top half according to bit 0 of tile index
    charmem[1+i*8] = 8'b00101000 ^ {i[0]{8}}; // to give you an easy way to see if you're
    charmem[2+i*8] = 8'b01000100 ^ {i[0]{8}}; // actually reading the tile map
    charmem[3+i*8] = 8'b10000010 ^ {i[0]{8}};
    charmem[4+i*8] = 8'b11111110 ^ {i[1]{8}}; // invert bottom half according to bit 1 of tile index
    charmem[5+i*8] = 8'b10000010 ^ {i[1]{8}};
    charmem[6+i*8] = 8'b10000010 ^ {i[1]{8}};
    charmem[7+i*8] = 8'b00000000 ^ {i[1]{8}};
  end
end

initial begin
  integer i;
  integer j;
  for(i=0;i<80;i=i+1)
    for(j=0;j<25;j=j+1)
      tilemap[i] = i + j;
end

I'm using byte-wide memory here because it's easier to illustrate. You can select just one bit of the read port for output by [x[2:0]] bit-selecting the output wire or reg (but not the memory directly, iirc).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2019, 10:33:17 pm
CE is only relevant in discrete implementations where the memory needs to be kept from driving a shared bus. Here, memory is always chip-enabled and you just have write-enables and maybe read-enables. Or, if you prefer to have the tool infer memory from generic HDL, you only have write-enables and are always reading every clock. If you want to hold read data, add your own register.

Ah yes, of course - makes sense.

Quote
This will allow the vid_char_generator to compute the current tile address from the internally-generated x & y coordinates, send that address to the video memory and receive a character index back.

Then it will compute a pixel address for that character in the character memory, based on the character index and current x & y coordinates, which will return a single bit of information based on whether the current pixel is background- or foreground-coloured depending on the character in that tile....  Does that make sense?  Am I over-complicating it, because there seems like a lot going here?  :scared:
No, that's about the size of it. Now you see why I was encouraging you to do a plain old framebuffer to start :)

You're not kidding!  ???

I think I understand the concept now though - I just need to get my head around making the right connections in Quartus and setting the memory up properly.  There's a template for new memory objects in the New.. menu, but then on a website I found some code that I've re-purposed into this:

Code: [Select]
module ROM_font (

input [11:0] address,
output [7:0] data,
input wire read_en

);

reg [7:0] mem [0:8192];

assign data = (read_en) ? mem[address] : 8'b0;

initial begin
$readmemb("OSD_FONT.MIF", mem);
end

endmodule

This should read a file in the project (borrowed from BrianHG's altera_osd_20kbit files) which contains the character definitions into memory.  Except I don't think it's loading it into memory - I think it's loading into hardware, so it's creating a 'ROM' in the sense that it can't be written to, but I get the feeling it's an extremely wasteful way of doing it.   Please correct me if I'm wrong.  Isn't there a megafunction or wizard of some kind I need to use to create a RAM/ROM area, or does Quartus do this for me by inferring my intentions from the code?

If you want to give yourself something other than garbage or nothing to stare at, use an initial task to preload a character bitmap or two and to fill the text memory with something. Writing this from sleep-deprived memory:

Yes, I could read a file into memory like with the font file above. I thought the RAM would contain random values, so I wouldn't have to load anything initially to see something come out on the screen... is that not the case then?  Is RAM pre-initialised to zeros or something?

I'm using byte-wide memory here because it's easier to illustrate. You can select just one bit of the read port for output by [x[2:0]] bit-selecting the output wire or reg (but not the memory directly, iirc).

Would it be better to return a byte (an entire row from the selected character) and bit-select from that returned value, or configure the 'ROM' to just return the bit in question pointed to by x & y?  What's the difference in terms of the 'ROM' code?  Is it as simple as:

Code: [Select]
module ROM_font {
    output [7:0] data,
    ...

... to return a byte, or:

Code: [Select]
module ROM_font {
    output data,
    ...

... to return a bit?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 03:14:52 am
EDIT:

Yes, that sorted it.  I've only used two outputs per sync signal for the moment, but it's working fine inverted now with no misbehaviour.  :-+
Ok, if 1 x 74AC/HC CMOS buffer was on the line when using negative sync to drive the monitor cables, and 2 in parallel work with any sync polarity, can you see why I said 2 pages ago, 'USE 3 CMOS BUFFERS in parallel....'  Your monitor appears to have a 75 Ohm termination resistor on it's sync lines and they might be using a schmitt trigger meaning that the drive would need to clear almost 4v by the time it reaches the monitors internal circuitry...  If you are now using 2, go to 3, otherwise, on a warm day, when your 74AC/HC CMOS buffer warms up, and it's drive switch resistance drops a bit, of your 5v power supply may be a still valid 4.75v, you will wonder which your monitor's picture has begun to get interference.  Your other choice is to use a single line driver buffer designed to drive a 25ohm load, or a transistor buffer.  With one of those, the sync signal will reach your monitor with the full 0-5v swing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 03:26:03 am
Operating like this, if you have a variable HDE and VDE window anywhere in your raster at any size, the X and Y counters will be at their next ready valid numerical state immediately after each line has ended and the frame has ended.

Fantastic - works beautifully and is quite small and neat, a great combination.  ;D

(Attachment Link)   (Attachment Link)

One thing I've noticed - there's more colour bars... Is the x counter incrementing properly?

Show me your code.  You may have your X&Y counter outside the:
-----------------------------------------------------------------
         if (pc_ena)   // once per pixel
         begin
-----------------------------------------------------------------
Meaning it may be running at 50MHz instead of 25MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 08, 2019, 04:40:43 am
This should read a file in the project (borrowed from BrianHG's altera_osd_20kbit files) which contains the character definitions into memory.  Except I don't think it's loading it into memory - I think it's loading into hardware, so it's creating a 'ROM' in the sense that it can't be written to, but I get the feeling it's an extremely wasteful way of doing it.   Please correct me if I'm wrong. Isn't there a megafunction or wizard of some kind I need to use to create a RAM/ROM area, or does Quartus do this for me by inferring my intentions from the code?
You can use the generic HDL to be portable, or you can instantiate and configure vendor modules to get vendor features, or you can use the megawizard to configure the vendor modules to get vendor features and pointy-clicky satisfaction. Mostly, it's a style matter. Quartus will indeed infer your block RAM intentions if your code walks, talks, and quacks enough like a duck. If not, you can use a ramstyle pragma to specify the style of RAM you want to use. https://www.intel.com/content/www/us/en/programmable/quartushelp/current/index.htm#hdl/vlog/vlog_file_dir_ram.htm (https://www.intel.com/content/www/us/en/programmable/quartushelp/current/index.htm#hdl/vlog/vlog_file_dir_ram.htm)

That ROM_font module has two big problems: one, it is asynchronous. From p15 of the coding style handbook: "Because memory blocks in the newest devices from Altera are synchronous, RAM designs that are targeted towards architectures that contain these dedicated memory blocks must be synchronous to be mapped directly into the device architecture. For these devices, asynchronous memory logic is implemented in regular logic cells." Two, it is sized incorrectly. Specify memory sizes in words rather than bits, much as you would a two-dimensional array, but mind the off-by-one error. 256 tiles of 16 rows each would be sized as reg [n:0] mymemory [0:(256*16)-1] regardless of the register width n.

Quote
Yes, I could read a file into memory like with the font file above. I thought the RAM would contain random values, so I wouldn't have to load anything initially to see something come out on the screen... is that not the case then?  Is RAM pre-initialised to zeros or something?

I think it's customary that block RAMs are initialized to zero upon power-up unless otherwise specified. In simulation, block RAMs are usually initialized to X so that you can see when you're reading from memory that you haven't written to (whether initially or in your logic) and trace how far the consequences reach.

Quote
Would it be better to return a byte (an entire row from the selected character) and bit-select from that returned value, or configure the 'ROM' to just return the bit in question pointed to by x & y?  What's the difference in terms of the 'ROM' code?  Is it as simple as:
I suggest byte-wide character bitmap "ROM" and external bit-selection with a look toward the future. If you decide to make the character bitmap block writable by the host, synthesis won't have to try to infer a dual-port RAM with dissimilar widths on each port, and won't have to guess/decide a possibly incorrect bit-endianness, because you will have specified it explicitly in logic. Whether you bit-select inside or outside the ROM_font module is a matter of style. Personally, I'd treat the x8 ROM as a x8 ROM all round and do the assign bit_out = rom_font_data[~xpos[2:0]]; outside of the ROM_font module, in case you might eventually reuse the bit selector for the frame buffer. That said, I've not done HDL projects too much larger than this, so FPGA old hands feel free to roast me if I'm doing it wrong.  :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 05:02:38 am
Ok, I've cleaned up my OSD generator, commented on everything and it gives a much better starting point.
We will make changes to make things better and touch up the font into standard 8 bit bytes, but as an introduction, this shows how the basics of how one of Intel's memory function is called and configured.

Code: [Select]
module osd_generator ( clk, pc_ena, hs_in, vs_in, osd_ena_out, osd_image, hde_out, vde_out, hs_out, vs_out,
wren_disp, wren_font, wr_addr, wr_data );

// To write contents into the display and font memories, the wr_addr[15:0] selects the address
// the wr_data[7:0] contains a byte which will be written
// the wren_disp is the write enable for the ascii text ram.  Only the wr_addr[8:0] are used as the character display is 32x16.
// the wren_font is the write enable for the font memort.  Only 2 bits are use of the wr_dataa[1:0] and wr_addr[12:0] are used.
// tie these ports to GND for now disabling them

input  clk, pc_ena, hde_in, vde_in, hs_in, vs_in ;

output osd_ena_out ;
reg    osd_ena_out ;
output [2:0] osd_image ;
output hde_out, vde_out, hs_out, vs_out;


input wren_disp, wren_font;
input [15:0] wr_addr;
input [7:0] wr_data;

reg   [9:0] disp_x,dly1_disp_x,dly2_disp_x;
reg   [8:0] disp_y,dly1_disp_y,dly2_disp_y;

reg   dena,dly1_dena,dly2_dena,dly3_dena,dly4_dena;
reg   [7:0] dly1_letter, dly2_letter;

reg   [7:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe;


wire [12:0] font_pos;
wire [8:0]  disp_pos;
wire [2:0]  osd_image;


parameter   PIPE_DELAY =  4;   // This parameter selects the number of pixel clocks which the output VDE and syncs are delayed.  Only use 2 through 9.

// ****************************************************************************************************************************
// LPM_RAM_DP Quartus dual port memory function
// ****************************************************************************************************************************
wire [7:0] sub_wire0;
wire [7:0] letter = sub_wire0[7:0];
// w access = 'b1100000a aaaaaaaa
altsyncram altsyncram_component_osd_mem ( .wren_a ( wren_disp ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[8:0]), .address_b (disp_pos[8:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire0));


defparam
altsyncram_component_osd_mem.intended_device_family = "Cyclone",
altsyncram_component_osd_mem.operation_mode = "DUAL_PORT",
altsyncram_component_osd_mem.width_a = 8,
altsyncram_component_osd_mem.widthad_a = 9,
altsyncram_component_osd_mem.width_b = 8,
altsyncram_component_osd_mem.widthad_b = 9,
altsyncram_component_osd_mem.lpm_type = "altsyncram",
altsyncram_component_osd_mem.width_byteena_a = 1,
altsyncram_component_osd_mem.outdata_reg_b = "CLOCK1",
altsyncram_component_osd_mem.indata_aclr_a = "NONE",
altsyncram_component_osd_mem.wrcontrol_aclr_a = "NONE",
altsyncram_component_osd_mem.address_aclr_a = "NONE",
altsyncram_component_osd_mem.address_reg_b = "CLOCK1",
altsyncram_component_osd_mem.address_aclr_b = "NONE",
altsyncram_component_osd_mem.outdata_aclr_b = "NONE",
altsyncram_component_osd_mem.ram_block_type = "AUTO",
altsyncram_component_osd_mem.init_file = "osd_mem.mif";

// ****************************************************************************************************************************

wire [1:0] sub_wire1;
wire [1:0] osd_img = sub_wire1[1:0];
// w access = 'b111aaaaa aaaaaaaa
altsyncram altsyncram_component_osd_font ( .wren_a ( wren_font ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[12:0]), .address_b (font_pos[12:0]),
.data_a (wr_data[1:0]), .q_b (sub_wire1));
defparam
altsyncram_component_osd_font.intended_device_family = "Cyclone",
altsyncram_component_osd_font.operation_mode = "DUAL_PORT",
altsyncram_component_osd_font.width_a = 2,
altsyncram_component_osd_font.widthad_a = 13,
altsyncram_component_osd_font.width_b = 2,
altsyncram_component_osd_font.widthad_b = 13,
altsyncram_component_osd_font.lpm_type = "altsyncram",
altsyncram_component_osd_font.width_byteena_a = 1,
altsyncram_component_osd_font.outdata_reg_b = "CLOCK1",
altsyncram_component_osd_font.indata_aclr_a = "NONE",
altsyncram_component_osd_font.wrcontrol_aclr_a = "NONE",
altsyncram_component_osd_font.address_aclr_a = "NONE",
altsyncram_component_osd_font.address_reg_b = "CLOCK1",
altsyncram_component_osd_font.address_aclr_b = "NONE",
altsyncram_component_osd_font.outdata_aclr_b = "NONE",
altsyncram_component_osd_font.ram_block_type = "AUTO",
altsyncram_component_osd_font.init_file = "osd_font.mif";

// ****************************************************************************************************************************
// ****************************************************************************************************************************


//  The disp_x is the X coordinate counter.  It runs from 0 to 512 and stops there
//  The disp_y is the Y coordinate sounter.  It runs from 0 to 256 and stops there

assign disp_pos[4:0]  = disp_x[8:4] ;  // The disp_pos[4:0] is the lower address for the 32 characters for the ascii text.
assign disp_pos[8:5]  = disp_y[7:4] ;  // the disp_pos[8:5] is the upper address for the 16 lines of text


//  The result from the ascii memory component 'altsyncram_component_osd_mem'  is called letter[7:0]
//  Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.

//  Now, font_pos[12:0] is the read address for the memory block containing the font memory

assign font_pos[12:6] = letter[6:0] ;       //  Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0]  = dly2_disp_x[3:1] ;  //  select the font X coordinate with a 2 pixel clock DELAYES disp_x address.  [3:1] is used so that every 2 x pixels are repeats
assign font_pos[5:3]  = dly2_disp_y[3:1] ;  //  select the font y coordinate with a 2 pixel clock DELAYES disp_y address.  [3:1] is used so that every 2 y lines are repeats


//  The resulting font image, 2 bits since I made a 2 bit color atari font is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD[2] output color bit.

assign osd_image[1:0] = osd_img[1:0];
assign osd_image[2]   = dly2_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]
                                         // so, if we want to use letter[7] as an upper color bit, is needs to be delayed 2 pixel clocks so it will be parallel with the osd_img[1:0] read data

always @ ( posedge clk ) begin

if (pc_ena) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

hde_pipe[0]   <= hde_in;
hde_pipe[7:1] <= hde_pipe[6:0];
hde_out       <= hde_pipe[PIPE_DELAY-2];

vde_pipe[0]   <= vde_in;
vde_pipe[7:1] <= vde_pipe[6:0];
vde_out       <= vde_pipe[PIPE_DELAY-2];

hs_pipe[0]    <= hs_in;
hs_pipe[7:1]  <= hs_pipe[6:0];
hs_out        <= hs_pipe[PIPE_DELAY-2];

vs_pipe[0]    <= vs_in;
vs_pipe[7:1]  <= vs_pipe[6:0];
vs_out        <= vs_pipe[PIPE_DELAY-2];

// **********************************************************************************************


// This OSD generator's window is only 512 pixels by 256 lines.
// Since the disp_X&Y counters are the screens X&Y coordinates,
// I'm using an extra most significant bit in the counters to determine if the
// OSD ena flag should be on or off


if (disp_x[9] || disp_y[8]) dena <= 0;  // When disp_x > 511 or disp_y > 255, then turn off the OSD's output enable flag
else dena <= 1;                         // otherwise, turn on the OSD output enable flag.


if ( ~vde ) disp_y[8:0] <= 9'b111111111;  // preset the disp_y counter to max while the vertical display is disabled

  else if (hde_in && ~hde_pipe[0]) begin      // isolate a single event at the begining of the active display area

disp_x[9:0] <= 10'b0000000000; // clear the disp_x counter

if (!disp_y[8] | (disp_y[8:7] == 2'b11)) disp_y <= disp_y + 1;  //  only increment the disp_y counter if it hasn't reached it's end

end else if (!disp_x[9]) disp_x <= disp_x + 1;  // keep on addind to the disp_x counter until it reaches it's end.


// **********************************************************************************************
// *** These delay pipes registers are explaines in the 'assign's above.
// **********************************************************************************************

dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;

dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;

dly1_letter <= letter;
dly2_letter <= dly1_letter;

dly1_dena   <= dena;
dly2_dena   <= dly1_dena;
dly3_dena   <= dly2_dena;
dly4_dena   <= dly3_dena;

// **********************************************************************************************

osd_ena_out  <= dly2_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
                           // It needs to be delayes by the number of pixel clocks required for the above memories


end // ena
end // always@clk
endmodule


Before we make changes like addressing 80 columns, addressing anywhere withing a chunk of ram, I'll fetch out my palette and overlay generator which goes with this OSD generator.  This will allow you to simultaneously run your pattern generator and superimpose the OSD generator on top, with a semi transparent layer in the font and a palette for the font colors.  For now, you can just wire the 'OSD[2:0]' output's bits 0 to your r&g&b outputs.

Hint, in the block diagram editor, double click on a blank area and type 'WIRE'.  Place these on your schematic and label on the left the buss name and number of my OSD outputs and on the right place a wire and label your RGB pins names.

Also, for the write memory inputs, on the block diagram editor, double click on a blank area, and type GND, and insert 3 GND symbols and tie them to the inputs on the OSD generator module.

The osd text memory block .mif should contain a display font test text of all the characters.  You and edit the file in quartus to make it say anything you like.


Note: After the palette and we will tackle a true memory address generator which will allow text windows of any Z-size by any Y-size, pointing to any memory base address, with a hidden overscan or any text columns width.  Plus, variable X&Y font size and 16 foreground by 16 background colors, paletted and programable for each letter on the display.  We will also be embedding the font memory into the same memory as the ascii text ram which will also be you main 8bit cpu ram as well.  There should be no problem implementing the 256 color graphics as well, but, the resolution window will be puny and we might need to forgo it's palette.

ALSO: I need to you increase your output pixel bits to 4 for each R,G,B, that's 12 bit color, or,  4096 colors.  Do not erase your pattern generator, we will be still bringing it back soon for additional tests.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 07:36:10 am
I suggest byte-wide character bitmap "ROM" and external bit-selection with a look toward the future. If you decide to make the character bitmap block writable by the host, synthesis won't have to try to infer a dual-port RAM with dissimilar widths on each port, and won't have to guess/decide a possibly incorrect bit-endianness, because you will have specified it explicitly in logic. Whether you bit-select inside or outside the ROM_font module is a matter of style. Personally, I'd treat the x8 ROM as a x8 ROM all round and do the assign bit_out = rom_font_data[~xpos[2:0]]; outside of the ROM_font module, in case you might eventually reuse the bit selector for the frame buffer. That said, I've not done HDL projects too much larger than this, so FPGA old hands feel free to roast me if I'm doing it wrong.  :popcorn:

Yes, I'm going there.... I just want the OP to take a few steps inbetween since we will soon be having either an 8bit or 16bit wide dual port ram which will be sized to the maximum the FPGA can handle (parameter configurable so larger FPGA will also work), and the display text, font, text color, and a universal graphics mode will have a base pointer in that same ram which is loaded during the v-sync.  A string of bytes from that base pointer will be loaded into control registers containing all the graphics control metrics, updated every h-sync, making a fully programable display pretty much on par with a Super Nintendo, except with support for 640x480 in the text mode and 4 color bitplane graphics mode.  These functions, really just 2 counters with a variable increment at the end of each line, will include text rows/video modes with a programmable width which may be wider than the entire display screen.

First we needed enough to get his project running the pixel clock at 4x, 100MHz, yet with a 25MHz pixel out while verifying the characters and background graphics were scaling correctly without error & his graphics rendering pipe was functional.

In the future, if the OP wishes to upgrade to external DRAM, that 1 memory block will need to be converted into a cache memory for the external ram and the constructed image will need pre-fetching a line of video in advance.  This one gets nasty.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 10:21:35 am
Ok, if 1 x 74AC/HC CMOS buffer was on the line when using negative sync to drive the monitor cables, and 2 in parallel work with any sync polarity, can you see why I said 2 pages ago, 'USE 3 CMOS BUFFERS in parallel....'  Your monitor appears to have a 75 Ohm termination resistor on it's sync lines and they might be using a schmitt trigger meaning that the drive would need to clear almost 4v by the time it reaches the monitors internal circuitry...  If you are now using 2, go to 3, otherwise, on a warm day, when your 74AC/HC CMOS buffer warms up, and it's drive switch resistance drops a bit, of your 5v power supply may be a still valid 4.75v, you will wonder which your monitor's picture has begun to get interference.  Your other choice is to use a single line driver buffer designed to drive a 25ohm load, or a transistor buffer.  With one of those, the sync signal will reach your monitor with the full 0-5v swing.

I'm not deliberately ignoring advice, just trying to make do with the bits I have to hand - namely, a shortage of very short linking wires for the breadboard the sync driver is plugged into.  ::)  As usual for a beginner, I made do with two parallel outputs, found it worked and stopped there.  Have upped my game now and got three parallel outputs driving each sync signal now.  :-+

I've also got a bit of a loose connection somewhere... the fuzzy column edges and blinking came back earlier, but I suspect a bad connection on the breadboard around the driver output as some finger poking around that area sorted it.  :-/O  Can't wait for the EP4C dev board to arrive - that has a built-in VGA port and will help me focus entirely on the HDL development.

One thing I've noticed - there's more colour bars... Is the x counter incrementing properly?

Show me your code.  You may have your X&Y counter outside the:
-----------------------------------------------------------------
         if (pc_ena)   // once per pixel
         begin
-----------------------------------------------------------------
Meaning it may be running at 50MHz instead of 25MHz.

Ah yes, the x and y counters were outside the if (p_ena) conditional.  :palm:  I'll attach my code at the bottom of this post anyway, for the sake of having an archive of it if nothing else.

Speaking of which, I've got a string of folders (currently on number 4) for this project, at various stages.  I think I might just run with this current project now and get it onto github.  I had an accident earlier where I deleted a file I thought I didn't need anymore, and it turned out to be the current sync_generator file.  Had to go back to a previous post and use the cleaned-up code you'd posted to re-create the file again.  Repo is up on github (https://github.com/nockieboy/microcom_gpu) if you want the latest files.

You can use the generic HDL to be portable, or you can instantiate and configure vendor modules to get vendor features, or you can use the megawizard to configure the vendor modules to get vendor features and pointy-clicky satisfaction. Mostly, it's a style matter. Quartus will indeed infer your block RAM intentions if your code walks, talks, and quacks enough like a duck. If not, you can use a ramstyle pragma to specify the style of RAM you want to use.

No problemo, will stick to generic HDL as much as possible then - I was just getting confused between the output from a wizard and (what appears to me to be) very basic HDL code to create a memory block.

That ROM_font module has two big problems: one, it is asynchronous... Two, it is sized incorrectly. Specify memory sizes in words rather than bits, much as you would a two-dimensional array, but mind the off-by-one error. 256 tiles of 16 rows each would be sized as reg [n:0] mymemory [0:(256*16)-1] regardless of the register width n.

Ah okay, I should go read those documents a little more closely.  I suspect this is a moot point anyway as BrianHG is clearly working to a plan and this will get covered soon.

Ok, I've cleaned up my OSD generator, commented on everything and it gives a much better starting point.
We will make changes to make things better and touch up the font into standard 8 bit bytes, but as an introduction, this shows how the basics of how one of Intel's memory function is called and configured.

Thanks again BrianHG - I'll spend some time looking at this today.

Before we make changes like addressing 80 columns, addressing anywhere withing a chunk of ram, I'll fetch out my palette and overlay generator which goes with this OSD generator.  This will allow you to simultaneously run your pattern generator and superimpose the OSD generator on top, with a semi transparent layer in the font and a palette for the font colors.  For now, you can just wire the 'OSD[2:0]' output's bits 0 to your r&g&b outputs.

Righto, no problem - so I should be able to get this working at 32x16 as it is...  :o

Note: After the palette and we will tackle a true memory address generator which will allow text windows of any Z-size by any Y-size, pointing to any memory base address, with a hidden overscan or any text columns width.  Plus, variable X&Y font size and 16 foreground by 16 background colors, paletted and programable for each letter on the display.  We will also be embedding the font memory into the same memory as the ascii text ram which will also be you main 8bit cpu ram as well.  There should be no problem implementing the 256 color graphics as well, but, the resolution window will be puny and we might need to forgo it's palette.

Aye carumba! This is going to be MUCH better than the plain old 'white on black' text mode, maybe with a splash of colour, that I was thinking of...  ;D

Okay, off to go work on this...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 11:30:28 am
Now, for a little more pushing... Once you have integrated my latest OSD generator, and get it working, the next step will be to modify the current 2 bit , 2 color per pixel font memory into a 1 bit color, 8 bit wide font memory.  I've attached a new Atari font which is formatted the way @jhpadjustable likes it.  This means you need to adjust the read addresses, size and location, and at the 8 bit data output, you need to make an immediate 8:1 mux selector to draw the 1bit font image.

The new font files I've attached are in 2 formats.
#1, "osd_font_8x8bit_128char.mif", A quartus .mif format file which is internally used for it's built in LPM_RAM_DP / AltSyncram function.
#2, "osd_font_8x8bit_128char.rom" A raw binary file which is a raw 8 bit binary dump of the Atari font.  Quartus can also use these, however 10 years ago, the feature had bugs so I convert the binaries to .mif and use them that way in quartus.

You will need to change the AltSyncram function I used in the OSD generator.  Read up on Quartus' library function for that memories controls as you need to change everything to 8bit data.  This step will allow us to combine both the character and font memory into 1 large continuous ram block for your Z80 to access.

Show me first the current character generator working, then you will need to modify the font memory into 8bit wide, monochrome color mode and verify that is also working properly.


---------------------------------------------------------------------------------
Your next step after this will be both the merge and making the new ram block have 5 dedicated read ports running at the 25MHz pixel clock speed.  This means the ram is running at 125MHz and you have a 5 muxed address in and 5 muxed/latched datas out while the second port on the ram will now be a read/write port which will be dedicated to the Z80 and way int the future, perhaps some graphics acceleration functions.

------------------------------------------------------------------------------
VERY Important, each step of the way, keep track of your FMAX!!!  If a piece of code you generate along the way kills it below 150Mhz approximately, find out why and ask questions.  Because, if you go too far with a 75MHz FMAX, it may be tedious to fix the problem lateron.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 11:43:34 am

Aye carumba! This is going to be MUCH better than the plain old 'white on black' text mode, maybe with a splash of colour, that I was thinking of...  ;D

Okay, off to go work on this...
Nope, even with your current FPGA, you will achieve a font display with 16 foreground + 16 background colors, with 4096 paletted colors and 16 translucency levels! as your text mode will be superimposed on top of the bitplane and 256 color graphics mode which also have a programmable 4096 colors for each of those 256 paletted colors.  Yes, the letters color palette will set different levels of translucency for both the font's foreground and background.  This means 16 stage fading just by manipulating the font's palette.  All this with 80 column x 60 rows, all within 16kb.  Wait a sec, does your FPGA have 16kb?  If not, oh well, we'll use 40x30 mode for now and you will only need 4kb for now.

Each line of text will have X&Y pixel sizes of 1,2,3,4 pixel/line.  Basically a separate X&Y scale size.  Same goes for the bitplane and 256 color graphics modes.  And yes, the graphics have their own separate palette too....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 12:09:39 pm
@BrianHG

Just had to make a couple of corrections to osd_generator to get it to successfully compile a symbol file:

1) hde_in, vde_in added to ports in first line
2) Declared hde_out, vde_out, hs_out and vs_out as regs as they're given blocking assignments in an always in lines 130 onwards
3) Line 160 - if ( ~vde ) - changed to if ( ~vde_in )

For now, you can just wire the 'OSD[2:0]' output's bits 0 to your r&g&b outputs.

Hint, in the block diagram editor, double click on a blank area and type 'WIRE'.  Place these on your schematic and label on the left the buss name and number of my OSD outputs and on the right place a wire and label your RGB pins names.

I think I've done what you've asked correctly...  ???

The osd text memory block .mif should contain a display font test text of all the characters.  You and edit the file in quartus to make it say anything you like.

But osd_mem.mif should show something, right?  Should show all the ASCII chars on the screen, in theory?  I'm just getting a blank screen - no text at all, all black (at least it's not going into standby)?

ALSO: I need to you increase your output pixel bits to 4 for each R,G,B, that's 12 bit color, or,  4096 colors.  Do not erase your pattern generator, we will be still bringing it back soon for additional tests.

Ah, will this cause the issue above then?  I haven't done it yet - my output is restricted to 1-bit colour at the moment as I'm still using the 220R resistors in series with the R, G and B outputs.

Here's my current setup:

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 12:21:42 pm
You forgot to add a buss wires on the:
osd_image[2..0] output, and on that bus, write the label 'osd_image[2..0]'

Quartus will not associate the labels on your wires unless you tie them to a block diagram's IO somewhere with the same name.  It does this since you may name these buss wires anything, not necessarily the internal verilog names.

As for the rgb_in[1], again, you need to add a bus wires on the stencil's input and add rgb_in[1..0]'
Add 3 more wire symbols after the rgb_in[1] wires and add the rgb_in[0] wires shorting the 2 together to generate a full brightness image. Or, you can wire the 'osd_ena_out' into all 3 'rgb_in[0]' instead.  This will generate a differenct luminance located where the the OSD character generator is active.

ALSO, use a different osd_image[ # ] for each red,green,blue.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 12:50:25 pm
Oh wow - yes, got an output now:

[attach=1]

Not sure it's aligned correctly - perhaps needs to move right and down by 3 pixels in each axis?

I'm guessing the vertical bars are because the 32 vertical lines have been exceeded?

You forgot to add a buss wires on the:
osd_image[2..0] output, and on that bus, write the label 'osd_image[2..0]'

D'oh.  I thought Quartus would link the wires on the Wire to the correct block IO, but I guess several blocks could all have the same IO names...

Add 3 more wire symbols after the rgb_in[1] wires and add the rgb_in[0] wires shorting the 2 together to generate a full brightness image. Or, you can wire the 'osd_ena_out' into all 3 'rgb_in[0]' instead.  This will generate a differenct luminance located where the the OSD character generator is active.

The outputs for r[0]. g[0] and b[0] aren't connected to anything yet.  I'll need to set up a resistor ladder to make use of those outputs.  I'll put that on my to-do list.  ;)

ALSO, use a different osd_image[ # ] for each red,green,blue.

Spot on.  The first time I ran it on the FPGA I just got a white screen.   :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 01:01:31 pm
To fix the OSD outline, change the first 3 'WIRE' symbols you have to 2 INPUT AND gates.  Wire 1 input of each and gate to exactly what you have now, and, wire the second of each and gate's input to the OSD generators 'osd_ena_out' signal.

This will mute the OSD output's image when outside the active 32x16 box.

Also, I think your monitor might need the H and V size adjusted.  I thought my OSD generator had perfect alignment.
(This wouldn't be a problem with DVI...)

This originally was a superimposed window as a debug screen for my video enhancer project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 01:34:18 pm
To fix the OSD outline, change the first 3 'WIRE' symbols you have to 2 INPUT AND gates.  Wire 1 input of each and gate to exactly what you have now, and, wire the second of each and gate's input to the OSD generators 'osd_ena_out' signal.

This will mute the OSD output's image when outside the active 32x16 box.

Looking better already.  ;D

[attach=1]

Also, I think your monitor might need the H and V size adjusted.  I thought my OSD generator had perfect alignment.
(This wouldn't be a problem with DVI...)

 :palm:

Of course.. Auto-adjust fixed it straight away. There I was going straight for the complex problems, thinking it was a timing problem...  :-DD

Right, I've put together a 2-bit resistor ladder, so I now have 2-bit RGB output. 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2019, 01:52:46 pm
LOL.... Live and learn...

Anyways, the next step.  Now you will need to understand my OSD code.  You will recognize that except for the way I made the 2bit font, it pretty much operates as you figured all along except for those piped delays to match after the first ram's read's contents are ready, the next one being the font image lookup, has it's x&y pointers delayed so they come in parallel with the contents of the text memory.

Now, I want you to change my font ram weird 2 bit color into an 8 bit wide font, now only B&W.  Use the new 8bit wide font I posted 7 messages up.  Try to get it to work properly.  It should fit in easily, though, you will need to mux select 8:1 the output at the right position.  Your output image should now be 2 bit color.  1 bit B&W for the font, and 1 bit for the MSB, bit 7, in the character memory.  Let's see if you can keep everything perfectly pixel aligned.

Also take note of your current FMAX...

Also, copy the osd.c module into a new name and work with that one in the same project so you can swap modules to verify alignment.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 05:17:24 pm
Going to take this slowly, as that's how my mind works..  :o ;D

Now, I want you to change my font ram weird 2 bit color into an 8 bit wide font, now only B&W.  Use the new 8bit wide font I posted 7 messages up.

So here's my first attempt:

Code: [Select]
module vid_osd_generator ( clk, pc_ena, hde_in, vde_in, hs_in, vs_in, osd_ena_out, osd_image, hde_out, vde_out, hs_out, vs_out,
wren_disp, wren_font, wr_addr, wr_data );

// To write contents into the display and font memories, the wr_addr[15:0] selects the address
// the wr_data[7:0] contains a byte which will be written
// the wren_disp is the write enable for the ascii text ram.  Only the wr_addr[8:0] are used as the character display is 32x16.
// the wren_font is the write enable for the font memory.  Only 2 bits are used of the wr_data[1:0] and wr_addr[12:0] are used.
// tie these ports to GND for now disabling them

input  clk, pc_ena, hde_in, vde_in, hs_in, vs_in;

output osd_ena_out;
reg    osd_ena_out;
output [2:0] osd_image;
output hde_out, vde_out, hs_out, vs_out;
reg hde_out, vde_out, hs_out, vs_out;

input wren_disp, wren_font;
input [15:0] wr_addr;
input [7:0] wr_data;

reg   [9:0] disp_x,dly1_disp_x,dly2_disp_x;
reg   [8:0] disp_y,dly1_disp_y,dly2_disp_y;

reg   dena,dly1_dena,dly2_dena,dly3_dena,dly4_dena;
reg   [7:0] dly1_letter, dly2_letter;

reg   [7:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe;

wire [9:0] font_pos;
wire [8:0]  disp_pos;
wire [2:0]  osd_image;

parameter   PIPE_DELAY =  4;   // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

// ****************************************************************************************************************************
// SCREEN TEXT MEMORY
// ****************************************************************************************************************************
wire [7:0] sub_wire0;
wire [7:0] letter = sub_wire0[7:0];
// w access = 'b1100000a aaaaaaaa
altsyncram altsyncram_component_osd_mem ( .wren_a ( wren_disp ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[8:0]), .address_b (disp_pos[8:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire0));

defparam
altsyncram_component_osd_mem.intended_device_family = "Cyclone II",
altsyncram_component_osd_mem.operation_mode = "DUAL_PORT",
altsyncram_component_osd_mem.width_a = 8,
altsyncram_component_osd_mem.widthad_a = 9,
altsyncram_component_osd_mem.width_b = 8,
altsyncram_component_osd_mem.widthad_b = 9,
altsyncram_component_osd_mem.lpm_type = "altsyncram",
altsyncram_component_osd_mem.width_byteena_a = 1,
altsyncram_component_osd_mem.outdata_reg_b = "CLOCK1",
altsyncram_component_osd_mem.indata_aclr_a = "NONE",
altsyncram_component_osd_mem.wrcontrol_aclr_a = "NONE",
altsyncram_component_osd_mem.address_aclr_a = "NONE",
altsyncram_component_osd_mem.address_reg_b = "CLOCK1",
altsyncram_component_osd_mem.address_aclr_b = "NONE",
altsyncram_component_osd_mem.outdata_aclr_b = "NONE",
altsyncram_component_osd_mem.ram_block_type = "AUTO",
altsyncram_component_osd_mem.init_file = "osd_mem.mif";

// ****************************************************************************************************************************
// FONT MEMORY
// ****************************************************************************************************************************
wire [7:0] sub_wire1;
wire [7:0] char_line = sub_wire1;
// w access = 'b111aaaaa aaaaaaaa
altsyncram altsyncram_component_osd_font ( .wren_a ( wren_font ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[12:0]), .address_b (font_pos[9:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire1));
defparam
altsyncram_component_osd_font.intended_device_family = "Cyclone II",
altsyncram_component_osd_font.operation_mode = "DUAL_PORT",
altsyncram_component_osd_font.width_a = 8,
altsyncram_component_osd_font.widthad_a = 13,
altsyncram_component_osd_font.width_b = 8,
altsyncram_component_osd_font.widthad_b = 10,
altsyncram_component_osd_font.lpm_type = "altsyncram",
altsyncram_component_osd_font.width_byteena_a = 1,
altsyncram_component_osd_font.outdata_reg_b = "CLOCK1",
altsyncram_component_osd_font.indata_aclr_a = "NONE",
altsyncram_component_osd_font.wrcontrol_aclr_a = "NONE",
altsyncram_component_osd_font.address_aclr_a = "NONE",
altsyncram_component_osd_font.address_reg_b = "CLOCK1",
altsyncram_component_osd_font.address_aclr_b = "NONE",
altsyncram_component_osd_font.outdata_aclr_b = "NONE",
altsyncram_component_osd_font.ram_block_type = "AUTO",
altsyncram_component_osd_font.init_file = "osd_font_8x8bit_128char.mif";

// ****************************************************************************************************************************
// ****************************************************************************************************************************


//  The disp_x is the X coordinate counter.  It runs from 0 to 512 and stops there
//  The disp_y is the Y coordinate counter.  It runs from 0 to 256 and stops there

// Get the character at the current x, y position
assign disp_pos[4:0]  = disp_x[8:4] ;  // The disp_pos[4:0] is the lower address for the 32 characters for the ascii text.
assign disp_pos[8:5]  = disp_y[7:4] ;  // the disp_pos[8:5] is the upper address for the 16 lines of text

//  The result from the ascii memory component 'altsyncram_component_osd_mem'  is called letter[7:0]
//  Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.

//  Now, font_pos[12:0] is the read address for the memory block containing the character specified in letter[]

assign font_pos[9:3] = letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0] = dly2_disp_y[3:1] ;  // select the font y coordinate with a 2 pixel clock DELAYED disp_y address.  [3:1] is used so that every 2 y lines are repeats

// get the pixel from the x position within the character


//  The resulting 1-bit font image at x is assigned to the OSD[0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a second OSD[1] output color bit
assign osd_image[0] = char_line[dly2_disp_x[0]];
assign osd_image[1] = dly2_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]
                                         // so, if we want to use letter[7] as an upper color bit, is needs to be delayed 2 pixel clocks so it will be parallel with the osd_img[1:0] read data

always @ ( posedge clk ) begin

if (pc_ena) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

hde_pipe[0]   <= hde_in;
hde_pipe[7:1] <= hde_pipe[6:0];
hde_out       <= hde_pipe[PIPE_DELAY-2];

vde_pipe[0]   <= vde_in;
vde_pipe[7:1] <= vde_pipe[6:0];
vde_out       <= vde_pipe[PIPE_DELAY-2];

hs_pipe[0]    <= hs_in;
hs_pipe[7:1]  <= hs_pipe[6:0];
hs_out        <= hs_pipe[PIPE_DELAY-2];

vs_pipe[0]    <= vs_in;
vs_pipe[7:1]  <= vs_pipe[6:0];
vs_out        <= vs_pipe[PIPE_DELAY-2];

// **********************************************************************************************
// This OSD generator's window is only 512 pixels by 256 lines.
// Since the disp_X&Y counters are the screens X&Y coordinates, I'm using an extra most
// significant bit in the counters to determine if the OSD ena flag should be on or off.

if (disp_x[9] || disp_y[8])
dena <= 0; // When disp_x > 511 or disp_y > 255, then turn off the OSD's output enable flag
else
dena <= 1; // otherwise, turn on the OSD output enable flag

if (~vde_in)
disp_y[8:0] <= 9'b111111111; // preset the disp_y counter to max while the vertical display is disabled

else if (hde_in && ~hde_pipe[0])
begin // isolate a single event at the begining of the active display area

disp_x[9:0] <= 10'b0000000000; // clear the disp_x counter
if (!disp_y[8] | (disp_y[8:7] == 2'b11))
disp_y <= disp_y + 1; // only increment the disp_y counter if it hasn't reached it's end

end
else if (!disp_x[9])
disp_x <= disp_x + 1;  // keep on addind to the disp_x counter until it reaches it's end.

// **********************************************************************************************
// *** These delay pipes registers are explained in the 'assign's above
// **********************************************************************************************
dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;

dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;

dly1_letter <= letter;
dly2_letter <= dly1_letter;

dly1_dena   <= dena;
dly2_dena   <= dly1_dena;
dly3_dena   <= dly2_dena;
dly4_dena   <= dly3_dena;

// **********************************************************************************************
osd_ena_out  <= dly2_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
// It needs to be delayed by the number of pixel clocks required for the above memories

end // ena

end // always@clk

endmodule


But it wont compile - I'm stuck on this error:

Code: [Select]
Error (12152): Can't elaborate user hierarchy "vid_osd_generator:inst2|altsyncram:altsyncram_component_osd_font"

EDIT:

Oh hang on.  I've found a few more errors that may clear this up... watch this space.

EDIT 2:

I've changed altsyncram_component_osd_font as follows:

Code: [Select]
altsyncram altsyncram_component_osd_font ( .wren_a ( wren_font ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[9:0]), .address_b (font_pos[9:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire1));


Still getting errors:

Code: [Select]
Error (272006): In altsyncram megafunction, when OPERATION_MODE parameter is set to DUAL_PORT, total number of bits of port A and port B must be the same
Error (287078): Assertion error: The current megafunction is configured for use with the clear box feature and cannot be used when the clear box feature is disabled
Error (12152): Can't elaborate user hierarchy "vid_osd_generator:inst2|altsyncram:altsyncram_component_osd_font"
Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 3 errors, 15 warnings
Error: Peak virtual memory: 4601 megabytes
Error: Processing ended: Fri Nov 08 17:20:59 2019
Error: Elapsed time: 00:00:02
Error: Total CPU time (on all processors): 00:00:02
Error (293001): Quartus II Full Compilation was unsuccessful. 5 errors, 15 warnings


EDIT 3:

Fixed the first error:
Code: [Select]
wire [7:0] char_line = sub_wire1[7:0];
// w access = 'b111aaaaa aaaaaaaa
altsyncram altsyncram_component_osd_font ( .wren_a ( wren_font ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[9:0]), .address_b (font_pos[9:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire1);


All fixed now.  Time to see if it works... ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 05:41:19 pm
Yeah, that's not working as intended....

EDIT: Just had a hell of a time trying to attach that image - put it at the bottom in the end instead of inline, as the 'edit message' form was just not working!

Here's the current code:

Code: [Select]
module vid_osd_generator ( clk, pc_ena, hde_in, vde_in, hs_in, vs_in, osd_ena_out, osd_image, hde_out, vde_out, hs_out, vs_out,
wren_disp, wren_font, wr_addr, wr_data );

// To write contents into the display and font memories, the wr_addr[15:0] selects the address
// the wr_data[7:0] contains a byte which will be written
// the wren_disp is the write enable for the ascii text ram.  Only the wr_addr[8:0] are used as the character display is 32x16.
// the wren_font is the write enable for the font memory.  Only 2 bits are used of the wr_data[1:0] and wr_addr[12:0] are used.
// tie these ports to GND for now disabling them

input  clk, pc_ena, hde_in, vde_in, hs_in, vs_in;

output osd_ena_out;
reg    osd_ena_out;
output [2:0] osd_image;
output hde_out, vde_out, hs_out, vs_out;
reg hde_out, vde_out, hs_out, vs_out;

input wren_disp, wren_font;
input [15:0] wr_addr;
input [7:0] wr_data;

reg   [9:0] disp_x,dly1_disp_x,dly2_disp_x;
reg   [8:0] disp_y,dly1_disp_y,dly2_disp_y;

reg   dena,dly1_dena,dly2_dena,dly3_dena,dly4_dena;
reg   [7:0] dly1_letter, dly2_letter;

reg   [7:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe;

wire [9:0] font_pos;
wire [8:0]  disp_pos;
wire [2:0]  osd_image;

parameter   PIPE_DELAY =  4;   // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

// ****************************************************************************************************************************
// SCREEN TEXT MEMORY
// ****************************************************************************************************************************
wire [7:0] sub_wire0;
wire [7:0] letter = sub_wire0[7:0];
// w access = 'b1100000a aaaaaaaa
altsyncram altsyncram_component_osd_mem ( .wren_a ( wren_disp ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[8:0]), .address_b (disp_pos[8:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire0));

defparam
altsyncram_component_osd_mem.intended_device_family = "Cyclone II",
altsyncram_component_osd_mem.operation_mode = "DUAL_PORT",
altsyncram_component_osd_mem.width_a = 8,
altsyncram_component_osd_mem.widthad_a = 9,
altsyncram_component_osd_mem.width_b = 8,
altsyncram_component_osd_mem.widthad_b = 9,
altsyncram_component_osd_mem.lpm_type = "altsyncram",
altsyncram_component_osd_mem.width_byteena_a = 1,
altsyncram_component_osd_mem.outdata_reg_b = "CLOCK1",
altsyncram_component_osd_mem.indata_aclr_a = "NONE",
altsyncram_component_osd_mem.wrcontrol_aclr_a = "NONE",
altsyncram_component_osd_mem.address_aclr_a = "NONE",
altsyncram_component_osd_mem.address_reg_b = "CLOCK1",
altsyncram_component_osd_mem.address_aclr_b = "NONE",
altsyncram_component_osd_mem.outdata_aclr_b = "NONE",
altsyncram_component_osd_mem.ram_block_type = "AUTO",
altsyncram_component_osd_mem.init_file = "osd_mem.mif";

// ****************************************************************************************************************************
// FONT MEMORY
// ****************************************************************************************************************************
wire [7:0] sub_wire1;
wire [7:0] char_line = sub_wire1[7:0];
// w access = 'b111aaaaa aaaaaaaa
altsyncram altsyncram_component_osd_font ( .wren_a ( wren_font ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena),
.address_a (wr_addr[9:0]), .address_b (font_pos[9:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire1));
defparam
altsyncram_component_osd_font.intended_device_family = "Cyclone II",
altsyncram_component_osd_font.operation_mode = "DUAL_PORT",
altsyncram_component_osd_font.width_a = 8,
altsyncram_component_osd_font.widthad_a = 10,
altsyncram_component_osd_font.width_b = 8,
altsyncram_component_osd_font.widthad_b = 10,
altsyncram_component_osd_font.lpm_type = "altsyncram",
altsyncram_component_osd_font.width_byteena_a = 1,
altsyncram_component_osd_font.outdata_reg_b = "CLOCK1",
altsyncram_component_osd_font.indata_aclr_a = "NONE",
altsyncram_component_osd_font.wrcontrol_aclr_a = "NONE",
altsyncram_component_osd_font.address_aclr_a = "NONE",
altsyncram_component_osd_font.address_reg_b = "CLOCK1",
altsyncram_component_osd_font.address_aclr_b = "NONE",
altsyncram_component_osd_font.outdata_aclr_b = "NONE",
altsyncram_component_osd_font.ram_block_type = "AUTO",
altsyncram_component_osd_font.init_file = "osd_font_8x8bit_128char.mif";

// ****************************************************************************************************************************
// ****************************************************************************************************************************


//  The disp_x is the X coordinate counter.  It runs from 0 to 512 and stops there
//  The disp_y is the Y coordinate counter.  It runs from 0 to 256 and stops there

// Get the character at the current x, y position
assign disp_pos[4:0]  = disp_x[8:4] ;  // The disp_pos[4:0] is the lower address for the 32 characters for the ascii text.
assign disp_pos[8:5]  = disp_y[7:4] ;  // the disp_pos[8:5] is the upper address for the 16 lines of text

//  The result from the ascii memory component 'altsyncram_component_osd_mem'  is called letter[7:0]
//  Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.

//  Now, font_pos[12:0] is the read address for the memory block containing the character specified in letter[]

assign font_pos[9:3] = letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0] = dly2_disp_y[3:1] ;  // select the font y coordinate with a 2 pixel clock DELAYED disp_y address.  [3:1] is used so that every 2 y lines are repeats

// get the pixel from the x position within the character


//  The resulting 1-bit font image at x is assigned to the OSD[0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a second OSD[1] output color bit
assign osd_image[0] = char_line[dly2_disp_x[0]];
assign osd_image[2] = dly2_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]
                                       // so, if we want to use letter[7] as an upper color bit, is needs to be delayed 2 pixel clocks so it will be parallel with the osd_img[1:0] read data

always @ ( posedge clk ) begin

if (pc_ena) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

hde_pipe[0]   <= hde_in;
hde_pipe[7:1] <= hde_pipe[6:0];
hde_out       <= hde_pipe[PIPE_DELAY-2];

vde_pipe[0]   <= vde_in;
vde_pipe[7:1] <= vde_pipe[6:0];
vde_out       <= vde_pipe[PIPE_DELAY-2];

hs_pipe[0]    <= hs_in;
hs_pipe[7:1]  <= hs_pipe[6:0];
hs_out        <= hs_pipe[PIPE_DELAY-2];

vs_pipe[0]    <= vs_in;
vs_pipe[7:1]  <= vs_pipe[6:0];
vs_out        <= vs_pipe[PIPE_DELAY-2];

// **********************************************************************************************
// This OSD generator's window is only 512 pixels by 256 lines.
// Since the disp_X&Y counters are the screens X&Y coordinates, I'm using an extra most
// significant bit in the counters to determine if the OSD ena flag should be on or off.

if (disp_x[9] || disp_y[8])
dena <= 0; // When disp_x > 511 or disp_y > 255, then turn off the OSD's output enable flag
else
dena <= 1; // otherwise, turn on the OSD output enable flag

if (~vde_in)
disp_y[8:0] <= 9'b111111111; // preset the disp_y counter to max while the vertical display is disabled

else if (hde_in && ~hde_pipe[0])
begin // isolate a single event at the begining of the active display area

disp_x[9:0] <= 10'b0000000000; // clear the disp_x counter
if (!disp_y[8] | (disp_y[8:7] == 2'b11))
disp_y <= disp_y + 1; // only increment the disp_y counter if it hasn't reached it's end

end
else if (!disp_x[9])
disp_x <= disp_x + 1;  // keep on addind to the disp_x counter until it reaches it's end.

// **********************************************************************************************
// *** These delay pipes registers are explained in the 'assign's above
// **********************************************************************************************
dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;

dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;

dly1_letter <= letter;
dly2_letter <= dly1_letter;

dly1_dena   <= dena;
dly2_dena   <= dly1_dena;
dly3_dena   <= dly2_dena;
dly4_dena   <= dly3_dena;

// **********************************************************************************************
osd_ena_out  <= dly2_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
// It needs to be delayed by the number of pixel clocks required for the above memories

end // ena

end // always@clk

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 08, 2019, 06:52:41 pm
Nice work there
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 07:19:58 pm
Okay, I realised I was only passing a single bit to char_line to get the x position within the character, so now it's passing the 8-bit x position value.  But the characters were reversed in the x-axis on the screen, so I made the following change:

Code: [Select]
assign osd_image[0] = char_line[(8 - dly2_disp_x[2:0])];
... and now I'm getting this:

[attach=1]

It's printing every character twice... with some errors at the right hand edge (the last column of the last character on the screen is duplicated once).

EDIT:

Fixed the right-hand edge duplication of the last character column by adding in another delay for x:

Code: [Select]
dly3_disp_x <= dly2_disp_x;
Just got to sort the duplication of each character now...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2019, 07:45:10 pm
All sorted.  Just needed me to use bits 3:1 in x rather than 2:0 to prevent the duplication of characters - remembered you'd written something about that in the notes somewhere.  Removed the additional delay as it's no longer needed.  :-+

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 12:33:13 am
Good show  :-+ .  You see all the comments I've added to Verilog code are a must read.

Now:
1) please post the final OSD code so I can proof the working version.
2) Will you be working on the code this weekend? What time?
3) What is you current FMAX?  Which FPGA part# are you using?

Next steps:
1.  Set up the PLL to give you a 125Mhz clock.  This means we will change the PC_ENA coming out of your 'sync_generator' into a 4 bit number with a parameter in the sync generator which selects the maximum count of 4, then resets to 0.  All the attached graphics modules which had 1 wire input PC_ENA will now need PC_ENA[3:0], and all the if (PC_ENA) will change to if (PC_ENA[3:0] == 0).

What we have done here is make you system clock 5x speed, yet divide your pixel clock down to 1/5.  We chose 5 as a magic number and included feeding the PC_ENA full 4 bit phase throughout your design for 2 reasons:
     a) since when you eventually incorporate DVI inside the FPGA, the serial shift out clock is 10x the pixel clock and having the FPGA system feed a DDR IO with 125MHz, you get your 250megabit per second serializer clock with any FPGA, no fancy dedicated hardware serializers.
     b) We will be dedicating memory access time slots during those 5 points, so it is useful to have those 4 bits to allot synchronous events.  Also, the 16$ 2megabit ram lattice part is fast enough to run the entire core at 10x 250MHz, so having the 4 bit PC_ENA, you may just then change that clock divide parameter from 4 to 9 giving you 10 access slots per pixel output.

We should plan what time we are doing this if it is on the weekend...
Next step #2:  Copy and rename the OSD generator to graphics generator.  You will remove both dual port 'altsynccrams' and replace it with a new verilog module 'multiport_gpu_ram.v'.  In your new 'multiport_gpu_ram.v' you will place a single 'altsynccrams' which is 4Kilobytes, and you will make IO registers for:
5 read addressed [20 bit] (Your graphics system will handle a maximum 1 megabyte frame buffer), 5 auxiliary read commands[8bit], 5 data output[8bit], 5 passed through read addresses and 5 passed through auxiliary read commands, all synchronous to the PC_ENA[3:0] position 0, an active pixel cycle.  (WE WILL BEGIN by only specifying the IOs and their functions in the .v module and make sure you understand what everything if for as from this point on, you will be coding everything yourself...)

And IO wires for the second port on the synccram READ/WRITE port for 1 R/W address[20bit] 1 write enable[1 wire], data in[8bit], data out[8bit].  This port is for the Z80, and in future, advanced GPU accelerated processing function (blitter).

Inside the 'multiport_gpu_ram.v', you will have another module 'gpu_dual_port_ram_INTEL.v', where inside that one I'll show you how to configure Quartus' LPM_dualport ram/altsynccram.  This one verilog module, 'gpu_dual_port_ram_INTEL.v'  will change between XILINX & LATTICE as their dual-port memory function blocks have their own setup and parameters written out differently, but function identically.  Other than PLL settings, everything else we have in your GPU project will cross compile in all FPGA vendor 3 ecosystems as our verilog code is 'basement' level.  If the other compilers cant cope with this project, it is their fault...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 09, 2019, 03:57:59 am
Okay, I realised I was only passing a single bit to char_line to get the x position within the character, so now it's passing the 8-bit x position value.  But the characters were reversed in the x-axis on the screen, so I made the following change:

Code: [Select]
assign osd_image[0] = char_line[(8 - dly2_disp_x[2:0])];
Do you see the off-by-one error in this code? You'd do well to learn the bitwise operators (https://www.nandland.com/verilog/examples/example-bitwise-operators.html) and start thinking in binary. Especially the unary ~ operator, same as in C.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 04:47:49 am
Okay, I realised I was only passing a single bit to char_line to get the x position within the character, so now it's passing the 8-bit x position value.  But the characters were reversed in the x-axis on the screen, so I made the following change:

Code: [Select]
assign osd_image[0] = char_line[(8 - dly2_disp_x[2:0])];
Do you see the off-by-one error in this code? You'd do well to learn the bitwise operators (https://www.nandland.com/verilog/examples/example-bitwise-operators.html) and start thinking in binary. Especially the unary ~ operator, same as in C.
He had 2 errors, 1 was that my routine was setup for every 2 pixels to be the same, so, disp_x[2:0] should have been disp_x[3:1].  Next, the '8-' should have been '7-'.  As for the 'dly2_disp_x[]', it should actually be 'dly4_disp_x[]' as that bit selection is immediately at the final output, yet reading the font memory takes 2 clocks since it's address was presented.  I still need to proof 'nockieboy's' final code to make sure he knows whats going on and the final results aren't a fluke, or, he figured out about the 2 clock read cycle delay.

The next step after switching to 125MHz will be re-doing the ram and making a simultaneous 5 random port read at every new pixel with 1 huge chunk of 8 bit memory.  Then, a replacement of the X&Y counters for a software programmable address generator with vertical and  horizontal increment sizes and individual X&Y size scales of 1, 2, 3, 4 pixels/lines.  Then a 8 bit color map for the text character, 16 foreground and 16 background colors for each character, going through a 16 bit 16 color palette, 4 bit ARGB.  That's 12 bits 4096 RGB colors + 16 transparency levels since the text mode will sit on top of the graphics mode. (Will look like a TV studio text genlock on top of a video source) The text mode will eat 3 of the 5 access cycles.  The next one will be the 256 color graphic pixel / pixels data (sits below the varible transparency text layer) and the final memory one will be up to 16 sprites per line of video.  (These sit on top of the text layer, or below the text layer, but above the graphics layer.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 05:52:46 am
Okay, I realised I was only passing a single bit to char_line to get the x position within the character, so now it's passing the 8-bit x position value.  But the characters were reversed in the x-axis on the screen, so I made the following change:

Code: [Select]
assign osd_image[0] = char_line[(8 - dly2_disp_x[2:0])];
Do you see the off-by-one error in this code? You'd do well to learn the bitwise operators (https://www.nandland.com/verilog/examples/example-bitwise-operators.html) and start thinking in binary. Especially the unary ~ operator, same as in C.
Yes, I agree, the unary ~ operator instead of the '8-' or '7-' would give the compiler less headaches.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 09, 2019, 06:06:05 am
Yes, I agree, the unary ~ operator instead of the '8-' or '7-' would give the compiler less headaches.
I dunno, ~ just seemed more natural to me. "Be the bits you wish to see in the world."

Anyway this is turning out to be an interesting lab/demonstration in pair programming. I'm going to try to sit back as a good audience member and watch quietly. :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 08:07:08 am
Just personal notes:

The op is currently using a "Cyclone II EP2C5T144".
He has 4608 logic elements / IE 4608 register bits, or, 576 x 8 bit registers.
He has 119808 bits of ram.  Safely, he can make an 8 kilobyte ram plus another 2 kilobyte ram.

Current plan:
Configure main system memory 8 kilobytes.  Contains text, fonts, graphic data & some spare room for CPU in lo-res mode.

        - 1200bytes for 40x30 text mode, or, 4800 bytes for 80x60, or 2400 bytes for 80x30
        - Double the above bytes for text with 16 color foreground and 16 color background.
        - 1024 bytes for 128 character 8x8 font.  2048 bytes for 256 character font.  Double for 8x16 VGA quality font.

        - Additional 16 words by 16 bits for text mode palette.  (This one is small enough to fit in registers if needed.)
        - Additional 256 words by 16 bits for graphics palette.

I hope his next FPGA board is going to have at least 20 kilobytes of ram.  He will be able to make a full VGA grade 16 color text mode, or, 160x120 in 16 color mode.  160x120 in 256 color mode with 32 kilobytes.

The 16$ lattice FPGA can safely be configured to have 192 kilobytes (216kb with a few tricks) of ram (note: 320x240x256color = 75 kilobytes, 640x480x16color = 150kb, 320x240x65k truecolor = 150kb (LOL, an 8 bit computer with a full truecolor desktop background + text based window superimposed)) , plus some spare for palette and a fancy blitter with a command cache.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 10:32:39 am
Good show  :-+ .  You see all the comments I've added to Verilog code are a must read.

Absolutely.  The more comments, the better.  ;)

Now:
1) please post the final OSD code so I can proof the working version.
2) Will you be working on the code this weekend? What time?
3) What is you current FMAX?  Which FPGA part# are you using?

1) See attachment in this post
2) Likely, yes, but I can't commit to specific times with any certainty, but most likely in the evenings (so anything from 12pm-7pm your time?) - have to placate the missus somehow.  ;D
3) FMAX is currently 182.65 MHz, with a Restricted Fmax of 163.03 MHz.  Apparently limited due to high minimum pulse width violation (tch)?  It was around 200 MHz before the changes yesterday.  :-\

Next steps:
1.  Set up the PLL to give you a 125Mhz clock.  This means we will change the PC_ENA coming out of your 'sync_generator' into a 4 bit number with a parameter in the sync generator which selects the maximum count of 4, then resets to 0.  All the attached graphics modules which had 1 wire input PC_ENA will now need PC_ENA[3:0], and all the if (PC_ENA) will change to if (PC_ENA[3:0] == 0).

Is this right?

Code: [Select]
altsyncram altsyncram_component_osd_font ( .wren_a ( wren_font ), .clock0 (clk), .clock1 (clk), .clocken1 (pc_ena[3:0] == 0),
.address_a (wr_addr[9:0]), .address_b (font_pos[9:0]),
.data_a (wr_data[7:0]), .q_b (sub_wire1));

Hmm.. my monitor is saying 'out of range', quoting 19.5 KHz / 24 Hz...  either I've made a typo or there's a clock division error on PC_ENA.  If PC_ENA[3:0] == 0 is dividing  by 8, surely?  Or are my maths out?  That'll give a PC_ENA frequency of 15 MHz?

Using pc_ena[3:2] == 0 gives an output the monitor can understand, though, even though it's a little... wrong.  I think there's a memory timing issue here?

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 10:44:46 am
Yes, I agree, the unary ~ operator instead of the '8-' or '7-' would give the compiler less headaches.
I dunno, ~ just seemed more natural to me. "Be the bits you wish to see in the world."

Anyway this is turning out to be an interesting lab/demonstration in pair programming. I'm going to try to sit back as a good audience member and watch quietly. :)

Yep, I changed this earlier - I knew the 8 - ... was a complete hack, but I didn't have time to look up a better way to do it.  Using ~ didn't occur at the time!  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 10:47:42 am
Ok, in sync_gen.v, the 'pc_ena' should read:
---------------------------------------------------
if (pc_ena == PIX_CLK_DIVIED) pc_ena <= 0;
else pc_ena <= pc_ena +1;
---------------------------------------------------

Make 'PIX_CLK_DIVIED' a parameter and make the default value 4.


In the ' if (pc_ena[3:2] == 0)   // once per pixel '
it should read:
if (pc_ena[2:0] == 0)     // for now, use [2:0] on your small FPGA...
^^^^ Change this one everywhere!!!

This means a single pixel advance will happen 1 clock after the 'PIX_CLK_DIVIED' value makes pc_ena[3:0] = to 0.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 10:54:04 am
Your PLL clock should have a ratio of X10/2 for 125MHz.


Your current FMAX slowdown is due to this line:
assign osd_image[0] = char_line[(~dly4_disp_x[3:1])];

Though correct, since osd_image[0] is not a register, this is just a mass of gates.  For now, you are clearing 125MHz and we will be fixing this later on.

If 'osd_image[0]' was a register, this would give an additional clock cycle for the bit selector to do select bits 7 through 0, then that output would be shifted off to the and gates and video stencil.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 10:56:26 am
Looking good again.  :)

Fmax has dropped to 162.31 MHz though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 11:04:53 am
Your PLL clock should have a ratio of X10/2 for 125MHz.

My board's clock is 50 MHz... that would make the PLL clock 250 MHz.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 11:06:50 am
FMAX going up and down can mean logic has been simplified out due to design change, or errors.

Now, look as my post about the 2 sub modules you need to make:

'multiport_gpu_ram.v'
and
'gpu_dual_port_ram_INTEL.v'

Begin with the ''multiport_gpu_ram.v''. 
begin the module with all the inputs and outputs labeled as you like.
Make a second clock and clock enable input for the Z80 cpu port side.  It's nice just to have it there...

Add at least these 1 parameters:
Maximum address bit (name it what you like, this one will configure the maximum size of memory)

As a strategy, keep the address ports all 20bit, even if you configure the memory to 10 bits.  You will bury the address wiring limit inside the ram module only, but you still wan to pass all 20 bits through the module whether you use them or not.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 11:07:54 am
Your PLL clock should have a ratio of X10/2 for 125MHz.

My board's clock is 50 MHz... that would make the PLL clock 250 MHz.  :-//
My bad...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 11:22:15 am
Next step #2:  Copy and rename the OSD generator to graphics generator.  You will remove both dual port 'altsynccrams' and replace it with a new verilog module 'multiport_gpu_ram.v'.  In your new 'multiport_gpu_ram.v' you will place a single 'altsynccrams' which is 4Kilobytes, and you will make IO registers for:

Okay, with you so far (I think) - see attached file.

5 read addressed [20 bit] (Your graphics system will handle a maximum 1 megabyte frame buffer), 5 auxiliary read commands[8bit], 5 data output[8bit], 5 passed through read addresses and 5 passed through auxiliary read commands, all synchronous to the PC_ENA[3:0] position 0, an active pixel cycle.

Need to confirm I'm reading this right - you want 5x 20-bit read address buses, 5x 8-bit read buses, 5x 8-bit data buses, and 5x pass-thru address buses and 5x pass-thru command buses???!?!

How does this fit into the dual-port paradigm?  I thought it was bad enough trying to get a dual-port memory chip, let alone a five-port one!

Any chance of some single-syllable clarification on this next step?  :o  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 11:40:26 am
You will only have a  dual port ram which will be inside the ''gpu_dual_port_ram_INTEL.v'' module.

The 'multiport_gpu_ram.v' doesn't have the 'altsyncram_component_gpu_ram' in it, it will have the ''gpu_dual_port_ram_INTEL.v'' called in it where you will unify the that dual memory's IO ports.

What the 'multiport_gpu_ram.'v contains is a 5:1 mux for all those address inputs, each selected during the pena[2:0] 5 phases 0 through 4, then feeds that 1 result address into the read address of 1 read port of the dual port ram hidden inside the ''gpu_dual_port_ram_INTEL.v'' module.  Then take the data coming out and latch that data into the correct 1 of five data output registers which are all parallel represented as 8 x 8bit outputs.

Since our ram will now run at 125MHz, having it's ENA hard wired to 1/ON, we can feed the 5 read address and latch the 5 sequential data outputs into 5 sequential registers making that ram appear to have 5 parallel read ports running at 25MHz.

With you 25MHz pixel port, you can now fetch the character memory, then fetch the font pixel, then feed that output from 1 same block of memory, instead you will now need to deal with different base memory address.  This is the next step after the 5 port ram works.

As for the second dedicated read/write port for the 8 bit CPU, that one will be a pass-through.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 11:48:12 am
Remember, except for the 8bit CPU ports, make all the outputs I specified into separate registers.
The core issue will be the MUX selector and how you parallel delay the piped function to maintain FMAX.
For now, keep it basic and remember to use a register at each point.

This means that the memory which once took 2 clocks from in to out, will now also have additional piped stages for the address and data output to consider, and also all the final results will need to land back on pena[2:0] phase 0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 12:21:53 pm
Remember, except for the 8bit CPU ports, make all the outputs I specified into separate registers.
The core issue will be the MUX selector and how you parallel delay the piped function to maintain FMAX.
For now, keep it basic and remember to use a register at each point.

This means that the memory which once took 2 clocks from in to out, will now also have additional piped stages for the address and data output to consider, and also all the final results will need to land back on pena[2:0] phase 0.

Okay, this is where I am so far with multiport_gpu_ram.v:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena, // Pixel clock enable
input clk_host, // Host (Z80) clock input
input hc_ena, // Host (Z80) clock enable

// address buses (input)
input [19:0] address_0,
input [19:0] address_1,
input [19:0] address_2,
input [19:0] address_3,
input [19:0] address_4,
input [19:0] addr_host,

// auxilliary read command buses (input)
input [7:0] aux_read_0,
input [7:0] aux_read_1,
input [7:0] aux_read_2,
input [7:0] aux_read_3,
input [7:0] aux_read_4,

// address buses (pass-thru outputs)
output reg [19:0] addrPT_0,
output reg [19:0] addrPT_1,
output reg [19:0] addrPT_2,
output reg [19:0] addrPT_3,
output reg [19:0] addrPT_4,

// auxilliary read command buses (pass-thru output)
output reg [7:0] auxRdPT_0,
output reg [7:0] auxRdPT_1,
output reg [7:0] auxRdPT_2,
output reg [7:0] auxRdPT_3,
output reg [7:0] auxRdPT_4,

// data buses (output)
output reg [7:0] dataOUT_0,
output reg [7:0] dataOUT_1,
output reg [7:0] dataOUT_2,
output reg [7:0] dataOUT_3,
output reg [7:0] dataOUT_4,
output [7:0] data_host

);

// dual-port GPU RAM handler

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BIT = 20;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
// TBC
);

always @(posedge clk) begin

if (pc_ena[2:0] == 0) begin



end // pc_ena

end // always @clk

endmodule

addr_host and data_host are host Z80 buses.

Am I going along the right lines?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 12:35:46 pm
Yes, good work, except, for the first time, you will be working differently with the 'if (pc_ena[2:0] == 0) begin'

Next, make a reg 'address_mux[]' & 'aux_read_mux[]', (use you preferred name) and make those registers run at 125Mhz, serial sequencing through the 5 pc_ena[2:0] stages.

Now, there is one little annoying problem here, a 20+8 bits in total, mux 5:1 may run too slow for 125Mhz, if so, later on as we add new inputs to the ports, you may need to make that muxing algorithm take 3 clocks instead of 1 clock.  Basically 3 parallel 2:1 muxers, those outputs feed another 2 parallel 2:1 muxers, than that last one will feed a final 2:1 muxer.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 12:44:04 pm
Here's the skeleton of the 5:1 mux:

Code: [Select]
always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b011 : ;
3'b100 : ;
3'b101 : ;
3'b110 : ;
3'b111 : ;

end // always @clk

Just trying to work out what to put into the case statements based on your comment about making the data available on the next p_ena[2:0] phase 0...  :o

Yes, good work, except, for the first time, you will be working differently with the 'if (pc_ena[2:0] == 0) begin'

Next, make a reg 'address_mux[]' & 'aux_read_mux[]', (use you preferred name) and make those registers run at 125Mhz, serial sequencing through the 5 pc_ena[2:0] stages.

Now, there is one little annoying problem here, a 20+8 bits in total, mux 5:1 may run too slow for 125Mhz, if so, later on as we add new inputs to the ports, you may need to make that muxing algorithm take 3 clocks instead of 1 clock.  Basically 3 parallel 2:1 muxers, those outputs feed another 2 parallel 2:1 muxers, than that last one will feed a final 2:1 muxer.

Ookay, I think that's kind of what I've started to do (running the case statement at 125 MHz).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 12:50:20 pm
Remember, the case for pc_ena[2:0] goes 0,1,2,3,4,0...  Remember, I'm adding in the sync generator and resetting back to 0 after 4, the case of b111 for pc_ena[2:0] will never be reached.

This is not like the 8 bit font where at the left most coordinate of the screen xpos=0 the first pixel in the font's byte is the 7th bit, then 6th bit, then ect...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 12:55:38 pm
Remember, the case for pc_ena[2:0] goes 0,1,2,3,4,0...  Remember, I'm adding in the sync generator and resetting back to 0 after 4, the case of b111 for pc_ena[2:0] will never be reached.

This is not like the 8 bit font where at the left most coordinate of the screen xpos=0 the first pixel in the font's byte is the 7th bit, then 6th bit, then ect...

Ah yes,  I'd forgotten about the reset after the 5th count, hence the confusion over the bit count in the case statement.

Code: [Select]
reg address_mux[19:0], aux_read_mux[7:0];

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
// TBC
);

always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
address_mux <= address_0;
aux_read_mux <= aux_read_0;
addrPT_0 <= address_0;
end
3'b001 : begin
address_mux <= address_1;
aux_read_mux <= aux_read_1;
addrPT_1 <= address_1;
end
3'b011 : begin
address_mux <= address_2;
aux_read_mux <= aux_read_2;
addrPT_2 <= address_2;
end
3'b100 : begin
address_mux <= address_3;
aux_read_mux <= aux_read_3;
addrPT_3 <= address_3;
end
3'b101 : begin
address_mux <= address_4;
aux_read_mux <= aux_read_4;
addrPT_4 <= address_4;
end
endcase

end // always @clk
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 01:11:26 pm
Ok, next, we will start our  ''gpu_dual_port_ram_INTEL.v'' module.

In that module, you should have an input wire read port with address in , aux in, and pc_ena_in[2:0], data out, address out, aux out, pc_ena out[]  and host port wires and bidir.

Now, the altsyncram is obsolete, so, what you should do is within quartus, block diagram editor, double click on a blank area and insert a megafunction from the LPM_Ram_dp section.  Make sure launch wizard is selected on.

Next configure the memory for 1 read/write port and 1 read only port.  Clock/register the addresses going in and register the data coming out.  Before completing the function, sen me a snapshot of you screen example block diagram.

If it looks good, when finishing the wizard, select 'generate verilog source code/source files'.  Quartus will generate an example verilog.v file where you will copy and paste the LPM_Ram_dp/altsyncram into your ''gpu_dual_port_ram_INTEL.v'' source file where you will wire through the memories ports.
In that ''gpu_dual_port_ram_INTEL.v'', you will also pipe through the read address and aux input to the address output as well as pipe through the pc_ena_in[2:0] to an output pc_ena_out[2:0].

Don't forget about also having a MAX_RAM_ADDRESS parameter in this sub module as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 01:21:41 pm
Ok, next, we will start our  ''gpu_dual_port_ram_INTEL.v'' module.

In that module, you should have an input wire read port with address in , aux in, and pc_ena_in[2:0], data out, address out, aux out, pc_ena out[]  and host port wires and bidir.

Now, the altsyncram is obsolete, so, what you should do is within quartus, block diagram editor, double click on a blank area and insert a megafunction from the LPM_Ram_dp section.  Make sure launch wizard is selected on.

I don't have an LPM_Ram_dp section?

[attachimg=1]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 01:23:39 pm
The post today was interesting, however.  Have received the Cyclone IV EasyFPGA board - has an EP4CE6 on board, with SDRAM and VGA connector (as well as PS2, which will be handy later).

Is it worth me updating to the latest Quartus software to support this chip?  I was using Quartus II 13.0sp1 as it was the last version to support the Cyclone II I was using...

Will mean a delay in proceedings whilst I get it all set up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 01:27:49 pm
Ok, next, we will start our  ''gpu_dual_port_ram_INTEL.v'' module.

In that module, you should have an input wire read port with address in , aux in, and pc_ena_in[2:0], data out, address out, aux out, pc_ena out[]  and host port wires and bidir.

Now, the altsyncram is obsolete, so, what you should do is within quartus, block diagram editor, double click on a blank area and insert a megafunction from the LPM_Ram_dp section.  Make sure launch wizard is selected on.

I don't have an LPM_Ram_dp section?

[attachimg=1]

Strange, it should be in the memory compiler section.  Scroll down and expand/shrink the list.  Don't type LPM in the query box, it may just be called ram_dp, dual_port_ram...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 01:30:25 pm
Strange, it should be in the memory compiler section.  Scroll down and expand/shrink the list.  Don't type LPM in the query box, it may just be called ram_dp, dual_port_ram...

Is it because it's an older Quartus II version?  It may not have the module you're looking for?

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 01:35:59 pm
The post today was interesting, however.  Have received the Cyclone IV EasyFPGA board - has an EP4CE6 on board, with SDRAM and VGA connector (as well as PS2, which will be handy later).

Is it worth me updating to the latest Quartus software to support this chip?  I was using Quartus II 13.0sp1 as it was the last version to support the Cyclone II I was using...

Will mean a delay in proceedings whilst I get it all set up.
For now, while I'm available, let's work with what you have in hand.  You will need to transfer your project on your own time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 01:36:35 pm
Strange, it should be in the memory compiler section.  Scroll down and expand/shrink the list.  Don't type LPM in the query box, it may just be called ram_dp, dual_port_ram...

Is it because it's an older Quartus II version?  It may not have the module you're looking for?

(Attachment Link)
Try the ram-2port.  It's not the quartus version, I think its that you are using a CycloneII.  It shouldn't matter as the newer FPGA will support all the memory features of the earlier ones.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 01:46:47 pm
Okay, this is where I am currently...

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 01:51:31 pm
You got it.  Now, remember the specs.

2 different clocks.
1 port read only.
other port read & write.
8 bits
13 addressees, or, 8192 words.

and clock the input controls as well as the output data.  As you change your options, the illustration will update showing you what you are creating.  send me the final image + the verilog.v example text...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 01:55:02 pm
You got it.  Now, remember the specs.

2 different clocks.
1 port read only.
other port read & write.
8 bits
13 addressees, or, 8192 words.

and clock the input controls as well as the output data.  As you change your options, the illustration will update showing you what you are creating.  send me the final image + the verilog.v example text...

Okay, using dual-clock (separate clocks for A and B ports as opposed to input and output clocks).  Will disable write on port 1 in the code when it produces it (there's no option for that in the wizard), 8-bit data is configured and I've gone for 14 addresses (16384 words), as I'm now using the EP4CE6 (still with Quartus II 13.0sp1) and have ~30KB of RAM to play with.

EDIT:

Do I need rd_en signals for either port?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 01:58:04 pm
You got it.  Now, remember the specs.

2 different clocks.
1 port read only.
other port read & write.
8 bits
13 addressees, or, 8192 words.

and clock the input controls as well as the output data.  As you change your options, the illustration will update showing you what you are creating.  send me the final image + the verilog.v example text...

Okay, using dual-clock (separate clocks for A and B ports as opposed to input and output clocks).  Will disable write on port 1 in the code when it produces it (there's no option for that in the wizard), 8-bit data is configured and I've gone for 14 addresses (16384 words), as I'm now using the EP4CE6 (still with Quartus II 13.0sp1) and have ~30KB of RAM to play with.
Unless your EP4CE6 board is ready to run now, we can still get a lot done on the CycloneII board.
Show me the final illustration from the megawizard.
Memory size wont make a difference anyways as your MAX_MEM_ADDR will overwrite what the wizard has filled into the example.v file we will just be using as a guide.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 02:03:08 pm
Unless your EP4CE6 board is ready to run now, we can still get a lot done on the CycloneII board.

The EP4CE6 is set up and outputting the video RAM contents as good as anything.  The only downside is that it has 1-bit colour output on the VGA connector.

Show me the final illustration from the megawizard.
Memory size wont make a difference anyways as your MAX_MEM_ADDR will overwrite what the wizard has filled into the example.v file we will just be using as a guide.

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 02:06:00 pm
Perfect, paste the example into your  ''gpu_dual_port_ram_INTEL.v'' module and wire the ports to the modules IO declarations.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 02:10:00 pm
The EP4CE6 is set up and outputting the video RAM contents as good as anything.  The only downside is that it has 1-bit colour output on the VGA connector.

Now when you are saying 'outputting the video RAM contents', you mean the OSD generator we have written here, correct?

As for the color, you should eventually be able to do something about that.  Remember to choose output pins which are in the same IO bank as the current 1 bit RGB output pins.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 02:20:07 pm
The EP4CE6 is set up and outputting the video RAM contents as good as anything.  The only downside is that it has 1-bit colour output on the VGA connector.

Now when you are saying 'outputting the video RAM contents', you mean the OSD generator we have written here, correct?

Yes.  Without all these new modules we're working on at the moment.

As for the color, you should eventually be able to do something about that.  Remember to choose output pins which are in the same IO bank as the current 1 bit RGB output pins.

Yes, just means I'll have to use my breadboard resistor ladder and VGA breakout connector again.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 02:25:37 pm
Perfect, paste the example into your  ''gpu_dual_port_ram_INTEL.v'' module and wire the ports to the modules IO declarations.

Okay, I'm a little confused right now.  I've got a megafunction-generated file, gpu_ram.v, which isn't normally included in the project files as Quartus wants me to leave the source code alone and just use the diagram component.

I've included the gpu_ram.v file so I can get to the code, but do I need to change anything there?  Can't I just wire up the gpu_ram component in the diagram to the multiport_gpu_ram component?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 02:30:19 pm
The EP4CE6 is set up and outputting the video RAM contents as good as anything.  The only downside is that it has 1-bit colour output on the VGA connector.

Now when you are saying 'outputting the video RAM contents', you mean the OSD generator we have written here, correct?

Yes.  Without all these new modules we're working on at the moment.

As for the color, you should eventually be able to do something about that.  Remember to choose output pins which are in the same IO bank as the current 1 bit RGB output pins.

Yes, just means I'll have to use my breadboard resistor ladder and VGA breakout connector again.  ::)
Not, get the board's schematic as they have a series resistor feeding the analog RGB video, and add a 2x value in series of each resistor to a new IO pin each.  This will give you 2 bit color.  Add a 4x series resistor to the analog VGA on a third IO pin to get 3 bit color...

example:
currently:
Current Red IO --------220ohm-----VGAred

Cheap DAC without the R2R ladder.
Current Red IO --------220ohm--------|--- VGAred
New Red IO2 ----------440ohm--------|
New Red IO3 ----------880ohm--------|
New Red IO4 ---------1760ohm-------|

It should be simple enough to hand wire this addition...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 02:38:44 pm
I've included the gpu_ram.v file so I can get to the code, but do I need to change anything there?  Can't I just wire up the gpu_ram component in the diagram to the multiport_gpu_ram component?

Nope, just copy and paste it into your  ''gpu_dual_port_ram_INTEL.v'' module.  We will make some changes and pass some parameters.  Don't bother with the Quartus copyright text.  Take a look at how I did it with my altsyncram in my current OSD generator.  It was copied and pasted from the same megawizard as well.

Though you could have read intel's manual on the dual port memory types and all their controls, the wizard just helps give you the basic feature setup visually.  You can always add or remove files from your project at any time.

The ''gpu_dual_port_ram_INTEL.v'' has a few more things than just the ram and you don't want a wizard file which can edit the structure if you place the file or click on the block diagram file.


OH, BTW, obviously delete the memory symbol from your block diagram file.  Your obviously wont be using that one.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 02:42:35 pm
I've included the gpu_ram.v file so I can get to the code, but do I need to change anything there?  Can't I just wire up the gpu_ram component in the diagram to the multiport_gpu_ram component?

Nope, just copy and paste it into your  ''gpu_dual_port_ram_INTEL.v'' module.  We will make some changes and pass some parameters.  Don't bother with the Quartus copyright text.  Take a look at how I did it with my altsyncram in my current OSD generator.  It was copied and pasted from the same megawizard as well.

Though you could have read intel's manual on the dual port memory types and all their controls, the wizard just helps give you the basic feature setup visually.  You can always add or remove files from your project at any time.

The ''gpu_dual_port_ram_INTEL.v'' has a few more things than just the ram and you don't want a wizard file which can edit the structure if you place the file or click on the block diagram file.

So, this is my gpu_dual_port_ram_INTEL.v file now:

Code: [Select]
module gpu_dual_port_ram_INTEL (
input clk,
input [2:0] pc_ena_in,
input wr_en_a,
input clk_host,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_a,
input [7:0] data_b
);

// ****************************************************************************************************************************
// Multiport GPU RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clock_a),
.wren_a (wren_a),
.address_b (address_b),
.clock1 (clock_b),
.data_b (data_b),
.wren_b (wren_b),
.address_a (address_a),
.data_a (data_a),
.q_a (sub_wire0),
.q_b (sub_wire1),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 16384,
altsyncram_component.numwords_b = 16384,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 14,
altsyncram_component.widthad_b = 14,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

endmodule

I've just cut 'n' pasted like you said.  Seems to be a lot of clock enables for some reason?  Obviously I'm going to have to prune/sort out the IO assignments.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 02:55:19 pm
Fill and wire the IO ports.
Add the max address parameter, pass the parameters to the altsyncram's params.
When wiring the ram's address ports, limit the max ram adr inside the wiring there.

And, add a @(posedge clock), for the graphics, delay and pass through the read address, aux data and  pc_ena[3:0] with the same number of clock cycles as the memory's read pipe delay.

Try to think why I want you to do this.  What can these be used for.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 02:59:39 pm

Okay, this is where I am so far with multiport_gpu_ram.v:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena, // Pixel clock enable
input clk_host, // Host (Z80) clock input
input hc_ena, // Host (Z80) clock enable

// address buses (input)
input [19:0] address_0,
input [19:0] address_1,
input [19:0] address_2,
input [19:0] address_3,
input [19:0] address_4,
input [19:0] addr_host,

// auxilliary read command buses (input)
input [7:0] aux_read_0,
input [7:0] aux_read_1,
input [7:0] aux_read_2,
input [7:0] aux_read_3,
input [7:0] aux_read_4,

// address buses (pass-thru outputs)
output reg [19:0] addrPT_0,
output reg [19:0] addrPT_1,
output reg [19:0] addrPT_2,
output reg [19:0] addrPT_3,
output reg [19:0] addrPT_4,

// auxilliary read command buses (pass-thru output)
output reg [7:0] auxRdPT_0,
output reg [7:0] auxRdPT_1,
output reg [7:0] auxRdPT_2,
output reg [7:0] auxRdPT_3,
output reg [7:0] auxRdPT_4,

// data buses (output)
output reg [7:0] dataOUT_0,
output reg [7:0] dataOUT_1,
output reg [7:0] dataOUT_2,
output reg [7:0] dataOUT_3,
output reg [7:0] dataOUT_4,
output [7:0] data_host

);

// dual-port GPU RAM handler

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BIT = 20;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
// TBC
);

always @(posedge clk) begin

if (pc_ena[2:0] == 0) begin



end // pc_ena

end // always @clk

endmodule

addr_host and data_host are host Z80 buses.

Am I going along the right lines?
Change the 'hc_ena' to 'hc_write_ena'.  This is for writing data.  The host can read or write just like normal ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 03:03:21 pm

I've just cut 'n' pasted like you said.  Seems to be a lot of clock enables for some reason?  Obviously I'm going to have to prune/sort out the IO assignments.

(Attachment Link)

Those have been hardwired to stay always enabled.  Leave them like that.

As for your photo of the 'multiport_gpu_ram', LOL  :-DD  You didn't have to generate a symbol of it....
That's just absurd...
You will obviously just call an instance of it in the OSG graphics generator...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 03:19:37 pm
Time's up for me today - for a while at least.  Here's the latest where I've gotten to with gpu_dual_port_ram_INTEL.v:

Code: [Select]
module gpu_dual_port_ram_INTEL (
// inputs
input clk,
input [2:0] pc_ena_in,
input wr_en_a,
input clk_host,
input wr_en_host,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_a,
input [7:0] data_in_b,
// outputs
output [7:0] data_out_a,
output [7:0] data_out_b
);

// define delay pipe registers
reg [MAX_ADDR_BIT:0] rd_addr_pipe;
reg [7:0] aux_dat_pipe;
reg [3:0] pc_ena_pipe;

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BIT = 14;

// ****************************************************************************************************************************
// Multiport GPU RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (wr_en_a),
.address_b (addr_b[MAX_ADDR_BIT:0]),
.clock1 (clk_host),
.data_b (data_b),
.wren_b (wr_en_host),
.address_a (addr_a[MAX_ADDR_BIT:0]),
.data_a (data_a),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 16384,
altsyncram_component.numwords_b = 16384,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BIT,
altsyncram_component.widthad_b = MAX_ADDR_BIT,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

rd_addr_pipe  <= addr_a;

hde_pipe[7:1] <= hde_pipe[6:0];
hde_out       <= hde_pipe[PIPE_DELAY-2];

end

endmodule

Thanks for your help and patience so far!!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2019, 03:33:54 pm
Time's up for me today - for a while at least.  Here's the latest where I've gotten to with gpu_dual_port_ram_INTEL.v:

Code: [Select]
module gpu_dual_port_ram_INTEL (
// inputs
input clk,
input [2:0] pc_ena_in,
input wr_en_a,          *************** Unused
input clk_host,
input wr_en_host,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_a,   **************** Unused
input [7:0] data_in_b,
// outputs
output [7:0] data_out_a,
output [7:0] data_out_b
);

// define delay pipe registers  ********** dont forget that these will be output ports as well
reg [19:0] rd_addr_pipe;  ************************* even though the ram may be smaller, we should still pipe through all the 20 address bits.
reg [7:0] aux_dat_pipe;
reg [3:0] pc_ena_pipe;

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BITS = 14;   ********************** this is 32k, however, for less confusion, I've changed it to BITS

// ****************************************************************************************************************************
// Multiport GPU RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (wr_en_a),
.address_b (addr_b[MAX_ADDR_BITS-1:0]),           *****************   bits-1
.clock1 (clk_host),
.data_b (data_b),
.wren_b (wr_en_host),
.address_a (addr_a[MAX_ADDR_BITS-1:0]),               *********************
.data_a (data_a),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 16384,    ************** fix, needs calculation based on MAX_ADDR_BITS
altsyncram_component.numwords_b = 16384,  ***********    fix, needs calculation based on MAX_ADDR_BITS
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BITS,                           *************** bits-0
altsyncram_component.widthad_b = MAX_ADDR_BITS,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

rd_addr_pipe  <= addr_a;   *********** remember, there are 2 pipe steps before you should output the rd_addr out...

hde_pipe[7:1] <= hde_pipe[6:0];                  ******** unused
hde_out       <= hde_pipe[PIPE_DELAY-2];  ******* unused

end

endmodule


Thanks for your help and patience so far!!  ;D

Comments in code with the asterisk ****...
I'll check in later tonight...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 04:47:53 pm
And, add a @(posedge clock), for the graphics, delay and pass through the read address, aux data and  pc_ena[3:0] with the same number of clock cycles as the memory's read pipe delay.

Okay, latest code here:

Code: [Select]
module gpu_dual_port_ram_INTEL (
// inputs
input clk,
input [2:0] pc_ena_in,
input clk_host,
input wr_en_host,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,
// outputs
output [19:0] addr_out_a,
output [7:0] data_out_a,
output [7:0] data_out_b,
output [2:0] pc_ena_out
);

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BITS = 14;

// define delay pipe registers  ********** dont forget that these will be output ports as well
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;
reg [7:0] dat_out_a_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - MAX_ADDR_BITS wide (14 bits default)
// Memory word size - 2^MAX_ADDR_BITS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[MAX_ADDR_BITS - 1:0]),
.clock1 (clk_host),
.data_b (data_in_b),
.wren_b (wr_en_host),
.address_a (addr_a[MAX_ADDR_BITS - 1:0]),
.data_a (8'b00000000),
.q_a (data_out_a_pipe),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2 ** MAX_ADDR_BITS,
altsyncram_component.numwords_b = 2 ** MAX_ADDR_BITS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BITS - 1,
altsyncram_component.widthad_b = MAX_ADDR_BITS - 1,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe  <= addr_a;
addr_out_a <= rd_addr_pipe;

//dat_out_a_pipe <= data_out_a;
data_out_a <= dat_out_a_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule

Not sure I've got the delay pipes set up correctly.  data_out_a is coming straight out of the memory module, so only needs 1 (or actually probably 0?) delays.

Try to think why I want you to do this.  What can these be used for.

Well, the address pass-through and pc_ena signal will arrive at the next module at the same time as the data, so should all be valid at the same time and can thus be used to process the data?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2019, 07:37:53 pm
Code: [Select]
// define delay pipe registers  ********** dont forget that these will be output ports as well
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;
reg [7:0] aux_dat_pipe;
reg [3:0] pc_ena_pipe;

Why do they need to be output ports?  I've got them outputting their contents into outputs already...?

Code: [Select]
// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe  <= addr_a;
addr_out_a <= rd_addr_pipe;

//dat_out_a_pipe <= data_out_a;
data_out_a <= dat_out_a_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

addr_out_a, data_out_a and pc_ena_out are all outputs?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2019, 01:54:09 am
Ok, when defining a module IO, IE any signal/wires going in and out, all must be labeled as an input, or output, or bidir. (There are a few others, but not all compilers support it.)

Now, I know you have:
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;

However, if you want that reg to be exposed to you function's declared IO port, yes, it will also need to be declared as an output as well.  The one small exception is if when you declare 'INPUT', with nothing else written, it is also automatically considered a 'WIRE' even though you did not specifically write 'input wire'...

To make things easier on you, you should declare you function's IO pins like the way you have it in your first verilog program 'sync_generator.v'.  Writing out each passed wire/bus as an 'input wire', 'output wire', 'output reg', would really clean thing up for coding.  I know my 15 year old OSD code stuffed everything like a 'C' code declaration.

From now on, declare your verilog functions and update your current one like this:
Code: [Select]
module sync_generator(
// inputs
input wire clk, // base clock
input wire pix_enable, // pixel clock
input wire reset, // reset: restarts frame
// outputs
output reg hsync, // horizontal sync
output reg vsync, // vertical sync
output wire [9:0] x, // current pixel x position
output wire [9:0] y, // current pixel y position
output reg inDisplayArea // high when in display area (valid drawing area)
);


Now, for the memory data out.  That clocking and registering of that bus is something happening inside quartus' 'altsyncram' function.  From your point of view, that data signal is an 'OUTPUT' of the 'altsyncram' function which you are receiving, so, in your function, it is like you are receiving an input.   You do not want to pass the data out through another clocked register in you code.  It is already delayed 2 clocks behind the address input and putting it through a reg will now make that 3 clocks before the data bus exist your verilog function module.  In your function's declaration, just make a wire:

---------------------------------------------
output wire [7:0] data_out_a,
---------------------------------------------



However, if Quartus does not like this, you might need to declare an internal subwire. This means just above you 'altsyncram' function add this:
--------------------------------------------------
wire [7:0] sub_data_out_a;
wire [7:0] data_out_a = sub_data_out_a[7:0];
----------------------------------------------

And in the 'altsyncram' change:
         .q_a (data_out_a),
to:
         .q_a (sub_data_out_a),


In the body of your @(posedge clk), you do not need to touch the read data, it's just a wire right through from ram block to your outer function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2019, 04:20:22 am
OT: Thread read rankings:
In FPGA, we are #35 out of 285 since the inception of EEVblog forum.
In FPGA, in threads reads for a thread which existed for only the last 3 weeks, we are #1!

Ok, I realize that FPGA is a low read count on this forum...

Cant wait for the OP to get past this synchronous parallel access memory, the programmable memory pointing address generators is the last fancy thing, everything else is nothing more than 2 lookup palette table rams a few conditional A/B stencil switches, and the project will be finished.

Adding internal DVI serializer would be version 1.5 as it needs a routed PCB.
Adding a sophisticated pixel/line/box copy/drawing blitter would be considered next level version #2, though it is just added logic.  I ensured everything else which exists, how it is written in a way which will support the plugin.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 10, 2019, 12:49:36 pm
Ok, when defining a module IO, IE any signal/wires going in and out, all must be labeled as an input, or output, or bidir. (There are a few others, but not all compilers support it.)

Now, I know you have:
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;

However, if you want that reg to be exposed to you function's declared IO port, yes, it will also need to be declared as an output as well. 

That's my point though, it's just an internal register? The output from the altsyncram function goes into the pipe, which then goes into the output (addr_out_a, or pc_ena_out).  Do I still need to declare the pipe as an out as well then?

Now, for the memory data out.  That clocking and registering of that bus is something happening inside quartus' 'altsyncram' function.  From your point of view, that data signal is an 'OUTPUT' of the 'altsyncram' function which you are receiving, so, in your function, it is like you are receiving an input.   You do not want to pass the data out through another clocked register in you code.  It is already delayed 2 clocks behind the address input and putting it through a reg will now make that 3 clocks before the data bus exist your verilog function module.

Seems to compile with no errors as is - see latest gpu_dual_port_ram_INTEL.v code below.

Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [2:0] pc_ena_in,
input clk_host,
input wr_en_host,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,

// registered outputs
output reg [19:0] addr_out_a,
output reg [2:0] pc_ena_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BITS = 14;

// define delay pipe registers
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - MAX_ADDR_BITS wide (14 bits default)
// Memory word size - 2^MAX_ADDR_BITS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[MAX_ADDR_BITS - 1:0]),
.clock1 (clk_host),
.data_b (data_in_b),
.wren_b (wr_en_host),
.address_a (addr_a[MAX_ADDR_BITS - 1:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2 ** MAX_ADDR_BITS,
altsyncram_component.numwords_b = 2 ** MAX_ADDR_BITS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BITS - 1,
altsyncram_component.widthad_b = MAX_ADDR_BITS - 1,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe  <= addr_a;
addr_out_a <= rd_addr_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule


In the body of your @(posedge clk), you do not need to touch the read data, it's just a wire right through from ram block to your outer function.

Okay, the code above should be updated with the changes you've pointed out.  The only area I'm not sure about are the delay pipes - they're internal to the function and don't directly output, hence my reluctance to declare them as outputs.  Let me know if this is wrong and I've misunderstood something!   :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2019, 01:19:27 pm
Ok, when defining a module IO, IE any signal/wires going in and out, all must be labeled as an input, or output, or bidir. (There are a few others, but not all compilers support it.)

Now, I know you have:
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;

However, if you want that reg to be exposed to you function's declared IO port, yes, it will also need to be declared as an output as well. 


That's my point though, it's just an internal register? The output from the altsyncram function goes into the pipe, which then goes into the output (addr_out_a, or pc_ena_out).  Do I still need to declare the pipe as an out as well then?

Nope, we just want the final addr_out[] reg exposed.
Note that no matter the configured ram size, we still want to pass through all 20 address bits to the output, even if the ram is configured to only 16 or 17.
Quote

Now, for the memory data out.  That clocking and registering of that bus is something happening inside quartus' 'altsyncram' function.  From your point of view, that data signal is an 'OUTPUT' of the 'altsyncram' function which you are receiving, so, in your function, it is like you are receiving an input.   You do not want to pass the data out through another clocked register in you code.  It is already delayed 2 clocks behind the address input and putting it through a reg will now make that 3 clocks before the data bus exist your verilog function module.

Seems to compile with no errors as is - see latest gpu_dual_port_ram_INTEL.v code below.

Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [2:0] pc_ena_in,
input clk_host,
input wr_en_host,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,

// registered outputs
output reg [19:0] addr_out_a,
output reg [2:0] pc_ena_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BITS = 14;

// define delay pipe registers
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - MAX_ADDR_BITS wide (14 bits default)
// Memory word size - 2^MAX_ADDR_BITS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[MAX_ADDR_BITS - 1:0]),
.clock1 (clk_host),
.data_b (data_in_b),
.wren_b (wr_en_host),
.address_a (addr_a[MAX_ADDR_BITS - 1:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2 ** MAX_ADDR_BITS,
altsyncram_component.numwords_b = 2 ** MAX_ADDR_BITS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BITS - 1,
altsyncram_component.widthad_b = MAX_ADDR_BITS - 1,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe  <= addr_a;
addr_out_a <= rd_addr_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule

Ok, first little error:
altsyncram_component.widthad_a = MAX_ADDR_BITS - 1,
altsyncram_component.widthad_b = MAX_ADDR_BITS - 1,
Get rid of the '-1' here, Intel is asking for the 'Width' of the port, not what the maximum address wire number is.

Next,
---------------
   rd_addr_pipe  <= addr_a;
   addr_out_a <= rd_addr_pipe;
   
   pc_ena_pipe <= pc_ena_in;
   pc_ena_out <= pc_ena_pipe;
------------------
Correct.  You forgot, I asked for an additional auxiliary command to be piped through just like the addr_a in&out pipe.  Call it  'cmd_in' and 'cmd_out' and make it 16 bits ie. [15:0]...

The command is useful for example to direct the destination read to a specific register, or describe a specific pixel type, like bitplane, or 256 color, or, set how many pixels that read pixel should clock for, like a horizontal size/scale.  It can also be used to further expand one or more of our read ports into another 2 through 16 parallel read channels operating below the pixel 25MHz pixel clock speed.  (for example, maybe multichannel audio playback engine...)

Do not worry about all the extra wires, registers, and ports.  The compiler automatically simplifies out any un-wired logic.

Quote


In the body of your @(posedge clk), you do not need to touch the read data, it's just a wire right through from ram block to your outer function.

Okay, the code above should be updated with the changes you've pointed out.  The only area I'm not sure about are the delay pipes - they're internal to the function and don't directly output, hence my reluctance to declare them as outputs.  Let me know if this is wrong and I've misunderstood something!   :popcorn:

Wit the last addition of the cmd in&out pipe, it's time to wire this module into the multiport gpu ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2019, 01:25:47 pm
Also, you can optionally change:
--------------------------
input clk_host,
input wr_en_host,
-------------------------
to:
input clk_b
input wr_en_b

If you like....

Note that it is the job of the ''multiport_gpu_ram'' to wire the 2 port memory and wire  port b into the names clk_host, wr_en_host, data_in_host, data_out_host...


remember, you labeled port 2 addr_b, data in B, data out B....

And dont forget to change the:
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;
to:
reg [19:0] rd_addr_pipe;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 10, 2019, 02:20:42 pm
Nope, we just want the final addr_out[] reg exposed.
Not that no matter the configured ram size, we still want to pass through all 20 address bits to the output, even if the ram is configured to only 16 or 17.

Marvellous, was thinking along the right lines then. 

Correct.  You forgot, I asked for an additional auxiliary command to be piped through just like the addr_a in&out pipe.  Call it  'cmd_in' and 'cmd_out' and make it 16 bits ie. [15:0]...

Yes, my memory isn't my strong point.  ::)  Sorted now.

Wit the last addition of the cmd in&out pipe, it's time to wire this module into the multiport gpu ram.

I've made a start on the multiport_gpu_ram already - lots of things going off here though, so can't focus on this at the moment - will be back to it later tonight.

Current multiport_gpu_ram.v:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena, // Pixel clock enable
input clk_b, // Host (Z80) clock input
input write_ena_b, // Host (Z80) clock enable

// address buses (input)
input [19:0] address_0,
input [19:0] address_1,
input [19:0] address_2,
input [19:0] address_3,
input [19:0] address_4,
input [19:0] addr_host,

// auxilliary read command buses (input)
input [7:0] aux_read_0,
input [7:0] aux_read_1,
input [7:0] aux_read_2,
input [7:0] aux_read_3,
input [7:0] aux_read_4,

// address pass-thru bus (output)
output reg [19:0] addr_passthru,

// auxilliary read command buses (pass-thru output)
output reg [7:0] auxRdPT_0,
output reg [7:0] auxRdPT_1,
output reg [7:0] auxRdPT_2,
output reg [7:0] auxRdPT_3,
output reg [7:0] auxRdPT_4,

// data buses (output)
output reg [7:0] dataOUT_0,
output reg [7:0] dataOUT_1,
output reg [7:0] dataOUT_2,
output reg [7:0] dataOUT_3,
output reg [7:0] dataOUT_4,
output [7:0] data_host

);

// dual-port GPU RAM handler

// define the maximum address bits - effectively the RAM size
parameter MAX_ADDR_BITS = 20;

reg [MAX_ADDR_BITS - 1:0] address_mux;
reg [7:0] aux_read_mux;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(address_mux),
.addr_b(),
.data_in_b(),
.addr_out_a(addr_passthru),
.pc_ena_out(),
.data_out_a(aux_read_mux),
.data_out_b()
);

always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
address_mux <= address_0;
aux_read_mux <= aux_read_0;
addr_passthru <= address_0;
end
3'b001 : begin
address_mux <= address_1;
aux_read_mux <= aux_read_1;
addr_passthru <= address_1;
end
3'b011 : begin
address_mux <= address_2;
aux_read_mux <= aux_read_2;
addr_passthru <= address_2;
end
3'b100 : begin
address_mux <= address_3;
aux_read_mux <= aux_read_3;
addr_passthru <= address_3;
end
3'b101 : begin
address_mux <= address_4;
aux_read_mux <= aux_read_4;
addr_passthru <= address_4;
end
endcase

end // always @clk

endmodule

Have merged all the pass-through addresses into one bus - otherwise can't see the point of having them in the mux at all?  addr_passthru is the passed-through address, muxed from one of the five input addresses depending on pc_ena value.  Hopefully that's right.   ???

Also, you can optionally change:
--------------------------
input clk_host,
input wr_en_host,
-------------------------
to:
input clk_b
input wr_en_b

If you like....

Note that it is the job of the ''multiport_gpu_ram'' to wire the 2 port memory and wire  port b into the names clk_host, wr_en_host, data_in_host, data_out_host...


remember, you labeled port 2 addr_b, data in B, data out B....

And dont forget to change the:
reg [MAX_ADDR_BITS - 1:0] rd_addr_pipe;
to:
reg [19:0] rd_addr_pipe;

Think I've done all that - things have gotten busy here though and I've had to cut this short, so attaching files for perusal, but there may be incomplete bits errors.

gpu_dual_port_ram_INTEL:

Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [3:0] pc_ena_in,
input clk_b,
input wr_en_b,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,
input [15:0] cmd_in,

// registered outputs
output reg [19:0] addr_out_a,
output reg [2:0] pc_ena_out,
output reg [15:0] cmd_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit - effectively the RAM size
parameter MAX_ADDR_BITS = 14;

// define delay pipe registers
reg [19:0] rd_addr_pipe_a;
reg [15:0] cmd_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - MAX_ADDR_BITS wide (14 bits default)
// Memory word size - 2^MAX_ADDR_BITS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[MAX_ADDR_BITS:0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[MAX_ADDR_BITS:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 2 ** MAX_ADDR_BITS,
altsyncram_component.numwords_b = 2 ** MAX_ADDR_BITS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",they're
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BITS - 1,
altsyncram_component.widthad_b = MAX_ADDR_BITS - 1,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe <= addr_a;
addr_out_a <= rd_addr_pipe;

cmd_pipe <= cmd_in;
cmd_out <= cmd_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2019, 03:00:03 pm

I've made a start on the multiport_gpu_ram already - lots of things going off here though, so can't focus on this at the moment - will be back to it later tonight.

Current multiport_gpu_ram.v:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena, // Pixel clock enable
input clk_b, // Host (Z80) clock input
input write_ena_b, // Host (Z80) clock enable

// address buses (input)
input [19:0] address_0,
input [19:0] address_1,
input [19:0] address_2,
input [19:0] address_3,
input [19:0] address_4,
input [19:0] addr_host,

// auxilliary read command buses (input)
input [7:0] aux_read_0,
input [7:0] aux_read_1,
input [7:0] aux_read_2,
input [7:0] aux_read_3,
input [7:0] aux_read_4,

// address pass-thru bus (output)
output reg [19:0] addr_passthru,

// auxilliary read command buses (pass-thru output)
output reg [7:0] auxRdPT_0,
output reg [7:0] auxRdPT_1,
output reg [7:0] auxRdPT_2,
output reg [7:0] auxRdPT_3,
output reg [7:0] auxRdPT_4,

// data buses (output)
output reg [7:0] dataOUT_0,
output reg [7:0] dataOUT_1,
output reg [7:0] dataOUT_2,
output reg [7:0] dataOUT_3,
output reg [7:0] dataOUT_4,
output [7:0] data_host

);

// dual-port GPU RAM handler

// define the maximum address bits - effectively the RAM size
parameter MAX_ADDR_BITS = 20;

reg [MAX_ADDR_BITS - 1:0] address_mux;
reg [7:0] aux_read_mux;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(address_mux),
.addr_b(),
.data_in_b(),
.addr_out_a(addr_passthru),
.pc_ena_out(),
.data_out_a(aux_read_mux),
.data_out_b()
);

always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
address_mux <= address_0;
aux_read_mux <= aux_read_0;
addr_passthru <= address_0;
end
3'b001 : begin
address_mux <= address_1;
aux_read_mux <= aux_read_1;
addr_passthru <= address_1;
end
3'b011 : begin
address_mux <= address_2;
aux_read_mux <= aux_read_2;
addr_passthru <= address_2;
end
3'b100 : begin
address_mux <= address_3;
aux_read_mux <= aux_read_3;
addr_passthru <= address_3;
end
3'b101 : begin
address_mux <= address_4;
aux_read_mux <= aux_read_4;
addr_passthru <= address_4;
end
endcase

end // always @clk

endmodule

Have merged all the pass-through addresses into one bus - otherwise can't see the point of having them in the mux at all?  addr_passthru is the passed-through address, muxed from one of the five input addresses depending on pc_ena value.  Hopefully that's right.   ???

Ok, from what I can see so far:
After initiating the "gpu_dual_port_ram_INTEL gpu_RAM(.....);", you need the:
---------------------------
          defparam
                           gpu_RAM.MAX_ADDR_BITS = MAX_ADDR_BITS ;
---------------------------
     This will pass the module multiport_gpu_ram's MAX_ADDR_BITS parameter into the gpu_dual_port_ram_INTEL's MAX_ADDR_BITS parameter.  It may be useful to pass the 'altsyncram_component.numwords_a&b' since it may be possible to allocate 24kb in the FPGA since it has that much memory, yet not 32kb.

   .addr_out_a(addr_passthru), should change to (addr_passthru_mux) and don't forget to declare it as a wire.
   .data_out_a(aux_read_mux) is also a wire.
   .pc_ena_out(pc_ena_out), is also a wire and an output

   // address pass-thru bus (output)
   output reg [19:0] addr_out,   There are 5 of these to match the read address ins 0 through 5 in.

   // auxilliary read command buses (input)
   input [7:0] aux_read_0,
   input [7:0] aux_read_1,
   input [7:0] aux_read_2,
   input [7:0] aux_read_3,
   input [7:0] aux_read_4,
 change all these to cmd_in[15:0].  (global search and replace)

   // auxilliary read command buses (pass-thru output)
   output reg [7:0] auxRdPT_0,
   output reg [7:0] auxRdPT_1,
   output reg [7:0] auxRdPT_2,
   output reg [7:0] auxRdPT_3,
   output reg [7:0] auxRdPT_4,
change these to cmd_out[15:0]

reg [MAX_ADDR_BITS - 1:0] address_mux; 
change to reg [19:0] address_mux; 

reg [7:0] aux_read_mux;
change to reg [15:0] cmd_read_mux  (global search and replace)

Your missing a few of the new ports for 'gpu_dual_port_ram_INTEL gpu_RAM(...);'

Almost done, next you will resort the read ram contents, the piped through address & cmds into their output registers and sync those to your new delayed 'pc_ena_out[3:0]' coming out of the Intel ram module.

Note that we forgot to wire through the 'pc_ena_out[3:0]' coming out of the Intel ram module thought to the multiport_gpu_ram ( ...) ports, so that the rest of our graphics pipe heading to the output pins will incorporate the delay shift generated by the memory.  (Though we can work around this through sophisticated re-syncing all the ram outputs back to the next pc_ena_in==0 cycle, this ena signal in the FPGA is beginning to drive so much logic limiting our FMAX, this is an opportune point to D-clock pipe the signals for the second half of our graphics pipe.)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2019, 10:12:38 am
After initiating the "gpu_dual_port_ram_INTEL gpu_RAM(.....);", you need the:
---------------------------
          defparam
                           gpu_RAM.MAX_ADDR_BITS = MAX_ADDR_BITS ;
---------------------------
     This will pass the module multiport_gpu_ram's MAX_ADDR_BITS parameter into the gpu_dual_port_ram_INTEL's MAX_ADDR_BITS parameter.  It may be useful to pass the 'altsyncram_component.numwords_a&b' since it may be possible to allocate 24kb in the FPGA since it has that much memory, yet not 32kb.

Okay, stupid question - altsyncram specifies altsyncram_component.numwords_a (and b) - I had 2 ** MAXSIZE in there, but if they're the number of words, I'll need to divide that by word size (8), otherwise the RAM will (try to be) 8 times larger than what I think I'm specifying?

So, for example, this:

Code: [Select]
// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on MAX_ADDR_BITS if not otherwise specified
parameter WORDS = 2 ** MAX_ADDR_BITS;


..needs to be this:

Code: [Select]
// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on MAX_ADDR_BITS if not otherwise specified
parameter WORDS = (2 ** MAX_ADDR_BITS) / 8;


??

   // address pass-thru bus (output)
   output reg [19:0] addr_out,   There are 5 of these to match the read address ins 0 through 5 in.

   // auxilliary read command buses (input)
   input [7:0] aux_read_0,
   input [7:0] aux_read_1,
   input [7:0] aux_read_2,
   input [7:0] aux_read_3,
   input [7:0] aux_read_4,
 change all these to cmd_in[15:0].  (global search and replace)

   // auxilliary read command buses (pass-thru output)
   output reg [7:0] auxRdPT_0,
   output reg [7:0] auxRdPT_1,
   output reg [7:0] auxRdPT_2,
   output reg [7:0] auxRdPT_3,
   output reg [7:0] auxRdPT_4,
change these to cmd_out[15:0]

reg [MAX_ADDR_BITS - 1:0] address_mux; 
change to reg [19:0] address_mux; 

reg [7:0] aux_read_mux;
change to reg [15:0] cmd_read_mux  (global search and replace)

These should all be present and correct now... I think.  Got a little confused earlier with all the changes, so I'll be double-checking it all, but I think it would benefit from a close look.

Your missing a few of the new ports for 'gpu_dual_port_ram_INTEL gpu_RAM(...);'

They should all be present and correct now.  :D

Almost done, next you will resort the read ram contents, the piped through address & cmds into their output registers and sync those to your new delayed 'pc_ena_out[3:0]' coming out of the Intel ram module.

Have made a bit of a start on this - the 5:1 mux code is modified according to my present understanding.  The read address is passed through to the ram module, the pass-through address is passed out to the appropriate address bus according to the current mux step, as is the data read from memory.

I'm a little unsure about the command bus, though.  It's piped into the memory via cmd_read_mux, but that seems like an unnecessary step as I only have one cmd_in bus (and one cmd_out bus) - should these be increased to 5 as well?  It's possible I've misunderstood your instruction to 'change all these to cmd_in[15:0]'...  ???

Note that we forgot to wire through the 'pc_ena_out[3:0]' coming out of the Intel ram module thought to the multiport_gpu_ram ( ...) ports, so that the rest of our graphics pipe heading to the output pins will incorporate the delay shift generated by the memory.  (Though we can work around this through sophisticated re-syncing all the ram outputs back to the next pc_ena_in==0 cycle, this ena signal in the FPGA is beginning to drive so much logic limiting our FMAX, this is an opportune point to D-clock pipe the signals for the second half of our graphics pipe.)

Okay, I think I understand - but pc_ena passes through the gpu_dual_port_ram_INTEL module via a register pipe, which will fulfil the need to D-clock the signal, right?

gpu_dual_port_ram_INTEL.v:

Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [3:0] pc_ena_in,
input clk_b,
input wr_en_b,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,
input [15:0] cmd_in,

// registered outputs
output reg [19:0] addr_out_a,
output reg [3:0] pc_ena_out,
output reg [15:0] cmd_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit
parameter MAX_ADDR_BITS = 14;

// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on MAX_ADDR_BITS if not otherwise specified
parameter WORDS = 2 ** MAX_ADDR_BITS;

// define delay pipe registers
reg [19:0] rd_addr_pipe_a;
reg [15:0] cmd_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - MAX_ADDR_BITS wide (14 bits default)
// Memory word size - 2^MAX_ADDR_BITS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[MAX_ADDR_BITS:0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[MAX_ADDR_BITS:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = WORDS,
altsyncram_component.numwords_b = WORDS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",they're
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = MAX_ADDR_BITS - 1,
altsyncram_component.widthad_b = MAX_ADDR_BITS - 1,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe <= addr_a;
addr_out_a <= rd_addr_pipe;

cmd_pipe <= cmd_in;
cmd_out <= cmd_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule


multiport_gpu_ram.v:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena_in, // Pixel clock enable
input clk_b, // Host (Z80) clock input
input write_ena_b, // Host (Z80) clock enable

// address buses (input)
input [19:0] address_0,
input [19:0] address_1,
input [19:0] address_2,
input [19:0] address_3,
input [19:0] address_4,
input [19:0] addr_host,

// auxilliary read command buses (input)
input [15:0] cmd_in,

// outputs
output wire [3:0] pc_ena_out,

// address pass-thru bus (output)
output reg [19:0] addr_passthru_0,
output reg [19:0] addr_passthru_1,
output reg [19:0] addr_passthru_2,
output reg [19:0] addr_passthru_3,
output reg [19:0] addr_passthru_4,
output reg [19:0] addr_host_passthru,

// auxilliary read command bus (pass-thru output)
output reg [15:0] cmd_out,

// data buses (output)
output reg [7:0] dataOUT_0,
output reg [7:0] dataOUT_1,
output reg [7:0] dataOUT_2,
output reg [7:0] dataOUT_3,
output reg [7:0] dataOUT_4,
output [7:0] data_host

);

// dual-port GPU RAM handler

// define the maximum address bits - effectively the RAM size
parameter MAX_ADDR_BITS = 20;

reg [19:0] address_mux;
reg [15:0] cmd_read_mux;
wire [19:0] addr_passthru_mux;
wire [7:0] data_mux;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena_in),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(address_mux),
.addr_b(),
.data_in_b(),
.cmd_in(cmd_read_mux),
.addr_out_a(addr_passthru_mux),
.pc_ena_out(pc_ena_out),
.cmd_out(cmd_out),
.data_out_a(data_mux),
.data_out_b()
);

// pass MAX_ADDR_BITS into the gpu_RAM instance
defparam gpu_RAM.MAX_ADDR_BITS = MAX_ADDR_BITS;

// set none-default word size for the RAM (24 KB)
defparam gpu_RAM.WORDS = 24576;  // ************** should this be divided by 8?

always @(posedge clk) begin

// route non-muxed pass-throughs
cmd_read_mux <= cmd_in;

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
address_mux <= address_0;
addr_passthru_0 <= addr_passthru_mux;
dataOUT_0 <= data_mux;
end
3'b001 : begin
address_mux <= address_1;
addr_passthru_1 <= addr_passthru_mux;
dataOUT_1 <= data_mux;
end
3'b011 : begin
address_mux <= address_2;
addr_passthru_2 <= addr_passthru_mux;
dataOUT_2 <= data_mux;
end
3'b100 : begin
address_mux <= address_3;
addr_passthru_3 <= addr_passthru_mux;
dataOUT_3 <= data_mux;
end
3'b101 : begin
address_mux <= address_4;
addr_passthru_4 <= addr_passthru_mux;
dataOUT_4 <= data_mux;
end
endcase

end // always @clk

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 10:51:26 am
After initiating the "gpu_dual_port_ram_INTEL gpu_RAM(.....);", you need the:
---------------------------
          defparam
                           gpu_RAM.MAX_ADDR_BITS = MAX_ADDR_BITS ;
---------------------------
     This will pass the module multiport_gpu_ram's MAX_ADDR_BITS parameter into the gpu_dual_port_ram_INTEL's MAX_ADDR_BITS parameter.  It may be useful to pass the 'altsyncram_component.numwords_a&b' since it may be possible to allocate 24kb in the FPGA since it has that much memory, yet not 32kb.

Okay, stupid question - altsyncram specifies altsyncram_component.numwords_a (and b) - I had 2 ** MAXSIZE in there, but if they're the number of words, I'll need to divide that by word size (8), otherwise the RAM will (try to be) 8 times larger than what I think I'm specifying?

So, for example, this:

Code: [Select]
// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on MAX_ADDR_BITS if not otherwise specified
parameter WORDS = 2 ** MAX_ADDR_BITS;


..needs to be this:

Code: [Select]
// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on MAX_ADDR_BITS if not otherwise specified
parameter WORDS = (2 ** MAX_ADDR_BITS) / 8;


??
Nope, the first one not the divide by 8.
Quote

   // address pass-thru bus (output)
   output reg [19:0] addr_out,   There are 5 of these to match the read address ins 0 through 5 in.

   // auxilliary read command buses (input)
   input [7:0] aux_read_0,
   input [7:0] aux_read_1,
   input [7:0] aux_read_2,
   input [7:0] aux_read_3,
   input [7:0] aux_read_4,
 change all these to cmd_in[15:0].  (global search and replace)

   // auxilliary read command buses (pass-thru output)
   output reg [7:0] auxRdPT_0,
   output reg [7:0] auxRdPT_1,
   output reg [7:0] auxRdPT_2,
   output reg [7:0] auxRdPT_3,
   output reg [7:0] auxRdPT_4,
change these to cmd_out[15:0]

reg [MAX_ADDR_BITS - 1:0] address_mux; 
change to reg [19:0] address_mux; 

reg [7:0] aux_read_mux;
change to reg [15:0] cmd_read_mux  (global search and replace)

These should all be present and correct now... I think.  Got a little confused earlier with all the changes, so I'll be double-checking it all, but I think it would benefit from a close look.

Your missing a few of the new ports for 'gpu_dual_port_ram_INTEL gpu_RAM(...);'

They should all be present and correct now.  :D

Almost done, next you will resort the read ram contents, the piped through address & cmds into their output registers and sync those to your new delayed 'pc_ena_out[3:0]' coming out of the Intel ram module.

Have made a bit of a start on this - the 5:1 mux code is modified according to my present understanding.  The read address is passed through to the ram module, the pass-through address is passed out to the appropriate address bus according to the current mux step, as is the data read from memory.

I'm a little unsure about the command bus, though.  It's piped into the memory via cmd_read_mux, but that seems like an unnecessary step as I only have one cmd_in bus (and one cmd_out bus) - should these be increased to 5 as well?  It's possible I've misunderstood your instruction to 'change all these to cmd_in[15:0]'...  ???
The 1 command bus is inside the INTEL dual port ram module.  Just like the read addresses, it should be piped through in a single file fashion.
On the multiport GPU ram, there should be 5 groups going in, grouped with the 5 read addresses going in, and 5 grouped 16 bit cmd coming out, just like the 5 read datas, 5 read addresses, 5 cmd_outs, all in parallel...
 
Quote

Note that we forgot to wire through the 'pc_ena_out[3:0]' coming out of the Intel ram module thought to the multiport_gpu_ram ( ...) ports, so that the rest of our graphics pipe heading to the output pins will incorporate the delay shift generated by the memory.  (Though we can work around this through sophisticated re-syncing all the ram outputs back to the next pc_ena_in==0 cycle, this ena signal in the FPGA is beginning to drive so much logic limiting our FMAX, this is an opportune point to D-clock pipe the signals for the second half of our graphics pipe.)

Okay, I think I understand - but pc_ena passes through the gpu_dual_port_ram_INTEL module via a register pipe, which will fulfil the need to D-clock the signal, right?
Pipe it just like a read address and the auxiliary 16 bit cmd, delayed by two 125MHz clocks.  The difference is when it comes back through the GPU multiport ram module, there it is not muxed, it's just wired through without delay.
Quote


gpu_dual_port_ram_INTEL.v:

Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [3:0] pc_ena_in,
input clk_b,
input wr_en_b,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,
input [15:0] cmd_in,

// registered outputs
output reg [19:0] addr_out_a,
output reg [3:0] pc_ena_out,
output reg [15:0] cmd_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit
parameter ADDR_SIZE = 14;   **********************************************************

// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on ADDR_SIZE if not otherwise specified
parameter NUM_WORDS = 2 ** ADDR_SIZE;   **********************************************************

// define delay pipe registers
reg [19:0] rd_addr_pipe_a;
reg [15:0] cmd_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - MAX_ADDR_BITS wide (14 bits default)
// Memory word size - 2^MAX_ADDR_BITS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[ADDR_SIZE-1:0]),   ***************************************************************
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[ADDR_SIZE-1:0]),   ****************************************************************************
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = NUM_WORDS,
altsyncram_component.numwords_b = NUM_WORDS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",they're
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = ADDR_SIZE,  ********************************************************************
altsyncram_component.widthad_b = ADDR_SIZE,  *********************************************************************
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe <= addr_a;
addr_out_a <= rd_addr_pipe;

cmd_pipe <= cmd_in;
cmd_out <= cmd_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule


multiport_gpu_ram.v:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena_in, // Pixel clock enable
input clk_b, // Host (Z80) clock input
input write_ena_b, // Host (Z80) clock enable

// address buses (input)
input [19:0] address_0,
input [19:0] address_1,
input [19:0] address_2,
input [19:0] address_3,
input [19:0] address_4,
input [19:0] addr_host,

// auxilliary read command buses (input)
input [15:0] cmd_in,

// outputs
output wire [3:0] pc_ena_out,

// address pass-thru bus (output)
output reg [19:0] addr_passthru_0,
output reg [19:0] addr_passthru_1,
output reg [19:0] addr_passthru_2,
output reg [19:0] addr_passthru_3,
output reg [19:0] addr_passthru_4,
output reg [19:0] addr_host_passthru,

// auxilliary read command bus (pass-thru output)
output reg [15:0] cmd_out,  *************************************  NEED 5x cmd_out0/1/2/3/4 and we also need 5x cmd_in#

// data buses (output)
output reg [7:0] dataOUT_0,
output reg [7:0] dataOUT_1,
output reg [7:0] dataOUT_2,
output reg [7:0] dataOUT_3,
output reg [7:0] dataOUT_4,
output [7:0] data_host

);

// dual-port GPU RAM handler

// define the maximum address bits - effectively the RAM size
parameter ADDR_SIZE = 14;                 *******************************************
parameter NUM_WORDS = 2 ** ADDR_SIZE ;                 *******************************************

reg [19:0] address_mux;
reg [15:0] cmd_read_mux;
wire [19:0] addr_passthru_mux;
wire [7:0] data_mux;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena_in),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(address_mux),
.addr_b(),
.data_in_b(),
.cmd_in(cmd_read_mux),
.addr_out_a(addr_passthru_mux),
.pc_ena_out(pc_ena_out),
.cmd_out(cmd_out),
.data_out_a(data_mux),
.data_out_b()
);
// pass MAX_ADDR_BITS into the gpu_RAM instance
defparam gpu_RAM.ADDR_SIZE = ADDR_SIZE,    *************************************************************************
                 gpu_RAM.NUM_WORDS = NUM_WORDS ;  // **************  Actual word count

always @(posedge clk) begin

// route non-muxed pass-throughs
cmd_read_mux <= cmd_in;

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
address_mux <= address_0;
addr_passthru_0 <= addr_passthru_mux;
dataOUT_0 <= data_mux;
end
3'b001 : begin
address_mux <= address_1;
addr_passthru_1 <= addr_passthru_mux;
dataOUT_1 <= data_mux;
end
3'b011 : begin
address_mux <= address_2;
addr_passthru_2 <= addr_passthru_mux;
dataOUT_2 <= data_mux;
end
3'b100 : begin
address_mux <= address_3;
addr_passthru_3 <= addr_passthru_mux;
dataOUT_3 <= data_mux;
end
3'b101 : begin
address_mux <= address_4;
addr_passthru_4 <= addr_passthru_mux;
dataOUT_4 <= data_mux;
end
endcase

end // always @clk

endmodule


Read all my ********************************************** in the 2 codes above

To make 1 thing clear, I changes the 'MAX_ADDR_BIT' to 'ADDR_SIZE'.  So, 14 = 14 address lines = [13:0]...
Studying the settings you setup in the Megawizard, and analyzing the example dualp...v file it generated should confirm this.
Same for 'WORDS', I changed it to 'NUM_WORDS'.

Check all the new ***************************** as there were one of 2 other items...


Next, re-assemble all the outputs of the INTEL dualport ram into 5 addresses, 5 datas, 5 cmds.
Helpful hint:
Since we want all the 5 outputs to parallel appear, each with the write contents when the input (pc_ena[2:0] == 0), and you have a bunch of delays through this module where you can easily loose count of clocks cycles, especially if you need to make your mux take 2 or 3 clocks instead of 1 to help improve FMAX, make these local params and I'll leave it up to you to figure out how to implement them:

localparam   CLK_CYCLES_MUX  = 1;  // Adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed inputs
localparam   CLK_CYCLES_RAM  = 2;  // Adjust this figure to the number of clock cycles the DP_ram takes to retrieve a valid data from the read address in.

Im not sure of this one, we will need to send this parameter back to the OSD generator so it know how many pixels to delay the H&V ena, and OSD ena to align the picture.
localparam   CLK_CYCLES_PIXEL  ??? = ;  // Adjust this figure to the number of PIXEL clock cycles it takes the demuxed output data to be ready.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 11:17:02 am
You can only have 1 'defparam' after each module is initiated.  To set multiple parameters, you use the " , " at the end of each parameter and the ' ; ' at the end of the final setting.


When you pass multiple parameters to a sub module, you type it like this:
--------------------------------------------------------------------
// pass MAX_ADDR_BITS into the gpu_RAM instance
defparam gpu_RAM.ADDR_SIZE = ADDR_SIZE, 
                 gpu_RAM.NUM_WORDS = NUM_WORDS ; 
-------------------------------------------------------------------
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2019, 11:39:18 am
The 1 command bus is inside the INTEL dual port ram module.  Just like the read addresses, it should be piped through in a single file fashion.
On the multiport GPU ram, there should be 5 groups going in, grouped with the 5 read addresses going in, and 5 grouped 16 bit cmd coming out, just like the 5 read datas, 5 read addresses, 5 cmd_outs, all in parallel...

All done - I've renamed some of the buses as well to make it clearer what's going on with all the pass-throughs etc.


Pipe it just like a read address and the auxiliary 16 bit cmd, delayed by two 125MHz clocks.  The difference is when it comes back through the GPU multiport ram module, there it is not muxed, it's just wired through without delay.

Sorted.  pc_ena is treated the same way as the other delayed signals in the memory module, but passed straight to the output in multiport_gpu_ram.

Read all my ********************************************** in the 2 codes above

Thanks - have updated the code accordingly.

Next, re-assemble all the outputs of the INTEL dualport ram into 5 addresses, 5 datas, 5 cmds.
Helpful hint:
Since we want all the 5 outputs to parallel appear, each with the write contents when the input (pc_ena[2:0] == 0)...

Ooookay... so all five outputs should be valid when pc_ena[2:0] == 0?  At the moment, addr_out_0, cmd_out_0, data_out_0 will all be valid two or three clock cycles (at least) before addr_out_1, cmd_out_1 and data_out_1, etc. with the delays compounding up to the 5th set of outputs?  Not to mention pc_ena needing to be delayed as well until the 5th outputs of the mux are ready?

Would it work to just route the results of the first 4 mux cycles into registers and then assign all 5 sets of results to the outputs at the end of the 5th mux cycle?  Am I even understanding the issue?

Currently, the mux code is just putting the results onto the multiport outputs as soon as they come in.

...and you have a bunch of delays through this module where you can easily loose count of clocks cycles, especially if you need to make your mux take 2 or 3 clocks instead of 1 to help improve FMAX, make these local params and I'll leave it up to you to figure out how to implement them:

localparam   CLK_CYCLES_MUX  = 1;  // Adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed inputs
localparam   CLK_CYCLES_RAM  = 2;  // Adjust this figure to the number of clock cycles the DP_ram takes to retrieve a valid data from the read address in.

Im not sure of this one, we will need to send this parameter back to the OSD generator so it know how many pixels to delay the H&V ena, and OSD ena to align the picture.
localparam   CLK_CYCLES_PIXEL  ??? = ;  // Adjust this figure to the number of PIXEL clock cycles it takes the demuxed output data to be ready.

localparams added.  CLK_CYCLES_PIXEL (CLK_CYCLES_PIX in code) needs to be added to the OSD generator code then?

gpu_dual_port_ram_INTEL.v:
Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [3:0] pc_ena_in,
input clk_b,
input wr_en_b,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,
input [15:0] cmd_in,

// registered outputs
output reg [19:0] addr_out_a,
output reg [3:0] pc_ena_out,
output reg [15:0] cmd_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit
parameter ADDR_SIZE = 14;

// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on ADDR_SIZE if not otherwise specified
parameter NUM_WORDS = 2 ** ADDR_SIZE;

// define delay pipe registers
reg [19:0] rd_addr_pipe_a;
reg [15:0] cmd_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - ADDR_SIZE wide (14 bits default)
// Memory word size - NUM_WORDS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[ADDR_SIZE:0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[ADDR_SIZE:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../osd_mem.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = NUM_WORDS,
altsyncram_component.numwords_b = NUM_WORDS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",they're
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = ADDR_SIZE - 1,
altsyncram_component.widthad_b = ADDR_SIZE - 1,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe <= addr_a;
addr_out_a <= rd_addr_pipe;

cmd_pipe <= cmd_in;
cmd_out <= cmd_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule


multiport_gpu_ram.v:
Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena_in, // Pixel clock enable
input clk_b, // Host (Z80) clock input
input write_ena_b, // Host (Z80) clock enable

// address buses (input)
input [19:0] addr_in_0,
input [19:0] addr_in_1,
input [19:0] addr_in_2,
input [19:0] addr_in_3,
input [19:0] addr_in_4,
input [19:0] addr_host_in,

// auxilliary read command buses (input)
input [15:0] cmd_in_0,
input [15:0] cmd_in_1,
input [15:0] cmd_in_2,
input [15:0] cmd_in_3,
input [15:0] cmd_in_4,

// outputs
output wire [3:0] pc_ena_out,

// address pass-thru bus (output)
output reg [19:0] addr_out_0,
output reg [19:0] addr_out_1,
output reg [19:0] addr_out_2,
output reg [19:0] addr_out_3,
output reg [19:0] addr_out_4,
output reg [19:0] addr_host_out,

// auxilliary read command bus (pass-thru output)
output reg [15:0] cmd_out_0,
output reg [15:0] cmd_out_1,
output reg [15:0] cmd_out_2,
output reg [15:0] cmd_out_3,
output reg [15:0] cmd_out_4,

// data buses (output)
output reg [7:0] data_out_0,
output reg [7:0] data_out_1,
output reg [7:0] data_out_2,
output reg [7:0] data_out_3,
output reg [7:0] data_out_4,
output [7:0] data_host_out

);

// dual-port GPU RAM handler

// define the maximum address bits and number of words - effectively the RAM size
parameter ADDR_SIZE = 14;
parameter NUM_WORDS = 2 ** ADDR_SIZE;

localparam CLK_CYCLES_MUX = 1; // adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed outputs
localparam CLK_CYCLES_RAM = 2; // adjust this figure to the number of clock cycles the DP_ram takes to retrieve valid data from the read address in
localparam CLK_CYCLES_PIX = 5; // adjust this figure to the number of PIXEL clock cycles it takes the demuxed output data to be ready

reg [19:0] addr_in_mux;
reg [15:0] cmd_mux_in;
reg [15:0] cmd_mux_out;
wire [19:0] addr_out_mux;
wire [7:0] data_mux_out;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena_in),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(addr_in_mux),
.addr_b(),
.data_in_b(),
.cmd_in(cmd_mux_in),
.addr_out_a(addr_out_mux),
.pc_ena_out(pc_ena_out),
.cmd_out(cmd_mux_out),
.data_out_a(data_mux_out),
.data_out_b()
);

defparam gpu_RAM.ADDR_SIZE = ADDR_SIZE, // pass ADDR_SIZE into the gpu_RAM instance
gpu_RAM.NUM_WORDS = NUM_WORDS; // set non-default word size for the RAM (16 KB)

always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
addr_in_mux <= addr_in_0;
cmd_mux_in <= cmd_in_0;
addr_out_0 <= addr_out_mux;
cmd_out_0 <= cmd_mux_out;
data_out_0 <= data_mux_out;
end
3'b001 : begin
addr_in_mux <= addr_in_1;
cmd_mux_in <= cmd_in_1;
addr_out_1 <= addr_out_mux;
cmd_out_1 <= cmd_mux_out;
data_out_1 <= data_mux_out;
end
3'b011 : begin
addr_in_mux <= addr_in_2;
cmd_mux_in <= cmd_in_2;
addr_out_2 <= addr_out_mux;
cmd_out_2 <= cmd_mux_out;
data_out_2 <= data_mux_out;
end
3'b100 : begin
addr_in_mux <= addr_in_3;
cmd_mux_in <= cmd_in_3;
addr_out_3 <= addr_out_mux;
cmd_out_3 <= cmd_mux_out;
data_out_3 <= data_mux_out;
end
3'b101 : begin
addr_in_mux <= addr_in_4;
cmd_mux_in <= cmd_in_4;
addr_out_4 <= addr_out_mux;
cmd_out_4 <= cmd_mux_out;
data_out_4 <= data_mux_out;
end
endcase

end // always @clk

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 12:04:28 pm
Ooookay... so all five outputs should be valid when pc_ena[2:0] == 0?  At the moment, addr_out_0, cmd_out_0, data_out_0 will all be valid two or three clock cycles (at least) before addr_out_1, cmd_out_1 and data_out_1, etc. with the delays compounding up to the 5th set of outputs?  Not to mention pc_ena needing to be delayed as well until the 5th outputs of the mux are ready?

Would it work to just route the results of the first 4 mux cycles into registers and then assign all 5 sets of results to the outputs at the end of the 5th mux cycle?  Am I even understanding the issue?

Currently, the mux code is just putting the results onto the multiport outputs as soon as they come in.

Ok, here lies the trick/headache (at least until you figure out how to do it).
Yes, the way you have it written, the outputs are scrambled into the wrong demuxed ports.

Also, remember, I said I want all the demuxed outputs from the gpu_ram module to all become properly valid during the next valid pixel clock (pc_ena[3:0]==0) time slot, and, to hold their contents and all switch during the next valid pixel clock once again.

As an aid, I would move all the :

            addr_out_# <= addr_out_mux;
            cmd_out_# <= cmd_mux_out;
            data_out_# <= data_mux_out;

Outside the case statement.

Here is the hint#1 :
------------------------------------
localparam   CLK_CYCLES_MUX  = 1;  // Adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed inputs
localparam   CLK_CYCLES_RAM  = 2;  // Adjust this figure to the number of clock cycles the DP_ram takes to retrieve a valid data from the read address in.
-------------------------------------
With additional variable sized piped regs will be used to generate the desired output.


Here is hint #2:   (make a buss version of this single bit/wire example)
-----------------------
bla_pipe[0]   <= bla_in;
bla_pipe[7:1] <= bla_pipe[6:0];
out                  <= bla_pipe[PIPE_DELAY-2];
-----------------------------------


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2019, 12:27:23 pm
Ok, here lies the trick/headache (at least until you figure out how to do it).
Yes, the way you have it written, the outputs are scrambled into the wrong demuxed ports.

Also, remember, I said I want all the demuxed outputs from the gpu_ram module to all become properly valid during the next valid pixel clock (pc_ena[3:0]==0) time slot, and, to hold their contents and all switch during the next valid pixel clock once again.

Right, so I'm now assigning the data returned from the ram module into a register that will hold that data, for each section of the mux.  Outside of the case statement, I've got a check for pc_ena[3:0] == 0 - when that condition is satisfied, all five data paths from the ram module are passed to the multiport's output IOs:

Code: [Select]
// declare registers to hold data until pc_ena[3:0] == 0 and
// it can be passed to the output IOs
reg [19:0] addr_buf_out_0,
addr_buf_out_1,
addr_buf_out_2,
addr_buf_out_3,
addr_buf_out_4;

reg [15:0] cmd_buf_out_0,
cmd_buf_out_1,
cmd_buf_out_2,
cmd_buf_out_3,
cmd_buf_out_4;

reg [7:0] data_buf_out_0,
data_buf_out_1,
data_buf_out_2,
data_buf_out_3,
data_buf_out_4;

always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
addr_in_mux <= addr_in_0;
cmd_mux_in <= cmd_in_0;
addr_buf_out_0 <= addr_mux_out;
cmd_buf_out_0 <= cmd_mux_out;
data_buf_out_0 <= data_mux_out;
end
3'b001 : begin
addr_in_mux <= addr_in_1;
cmd_mux_in <= cmd_in_1;
addr_buf_out_1 <= addr_mux_out;
cmd_buf_out_1 <= cmd_mux_out;
data_buf_out_1 <= data_mux_out;
end
3'b011 : begin
addr_in_mux <= addr_in_2;
cmd_mux_in <= cmd_in_2;
addr_buf_out_2 <= addr_mux_out;
cmd_buf_out_2 <= cmd_mux_out;
data_buf_out_2 <= data_mux_out;
end
3'b100 : begin
addr_in_mux <= addr_in_3;
cmd_mux_in <= cmd_in_3;
addr_buf_out_3 <= addr_mux_out;
cmd_buf_out_3 <= cmd_mux_out;
data_buf_out_3 <= data_mux_out;
end
3'b101 : begin
addr_in_mux <= addr_in_4;
cmd_mux_in <= cmd_in_4;
addr_buf_out_4 <= addr_mux_out;
cmd_buf_out_4 <= cmd_mux_out;
data_buf_out_4 <= data_mux_out;
end
endcase

if (pc_ena[3:0] == 0)
begin
addr_out_0 <= addr_buf_out_0;
cmd_out_0 <= cmd_buf_out_0;
data_out_0 <= data_buf_out_0;

addr_out_1 <= addr_buf_out_1;
cmd_out_1 <= cmd_buf_out_1;
data_out_1 <= data_buf_out_1;

addr_out_2 <= addr_buf_out_2;
cmd_out_2 <= cmd_buf_out_2;
data_out_2 <= data_buf_out_2;

addr_out_3 <= addr_buf_out_3;
cmd_out_3 <= cmd_buf_out_3;
data_out_3 <= data_buf_out_3;

addr_out_4 <= addr_buf_out_4;
cmd_out_4 <= cmd_buf_out_4;
data_out_4 <= data_buf_out_4;
end

end // always @clk

Is that going down the right road?  Obviously I haven't given any consideration to pipe delays yet...

Here is the hint#1 :
------------------------------------
localparam   CLK_CYCLES_MUX  = 1;  // Adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed inputs
localparam   CLK_CYCLES_RAM  = 2;  // Adjust this figure to the number of clock cycles the DP_ram takes to retrieve a valid data from the read address in.
-------------------------------------
With additional variable sized piped regs will be used to generate the desired output.


Here is hint #2:   (make a buss version of this single bit/wire example)
-----------------------
bla_pipe[0]   <= bla_in;
bla_pipe[7:1] <= bla_pipe[6:0];
out                  <= bla_pipe[PIPE_DELAY-2];
-----------------------------------

Just run this part by me once more - why do I need more delays?  If what I've done above is correct, the results are held in registers until pc_ena[3:0] == 0, where they all get passed out to the output IOs.  What are the additional delay pipes for?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 01:11:55 pm
Ok, not quite.  Your outputs would still be scrambled, not only that, but, now, some of your outputs will be ahead by 1 pixel and the rest will have the correct pixel.

What you have setup has no configuration/adjustment capabilities.

Currently, at pc_ena 0, you may be switching to addr0, but the memory is seeing the previous addr4, while what is coming out of the ram is the previous addr2. but, you are currently snapping that into addr_buf0/data_buf0, and then feeding the previous  holdings of every addr_buf#/data_buf# into addr_out#/data_out#.

At pc_ena 1, you may be switching to addr1, but the memory is seeing the previous addr0, while what is coming out of the ram is the previous addr3. and are currently snapping that into addr_buf1/data_buf1, though the addr_out#/data_out# all hold their new state from when pc_ena0 phase has updated them.

Now, you can see the headache here.  Say you weed out everything as set the delays fixed and you code appears to work good.  What happens after adding some features, you might need to expand your mux for speed by making it collapse in 3 clocks stages instead of the current 1 clock.  What will sorting out the mess look like?

Step 1: Get rid of any and all demuxing in the case statement.
Step 2: Make a easily variable clock delay pipe tap coming out of the gpu_ram.

Example:
reg [9*8+7:0]  data_pipe;   // make a large enough register to store 10 words (words 0 through 9).  In the case of ram data, the width of each word is 8 bits.

Now, inside the always @(posedge clk) place

data_pipe[7:0]                <= data_mux_out[7:0];         // fill the first 8 bit word in the register pipe
data_pipe[9*8+7:1*8]  <= data_pipe[8*8+7:0*8];    // shift over the next 9 words in this 10 word 8 bit wide pipe


if (pc_ena[3:0] == 0)
   begin
   data_out_0 <= data_pipe[MUX_0_POS*8+7:MUX_0_POS*8];
   data_out_1 <= data_pipe[MUX_1_POS*8+7:MUX_1_POS*8];
   data_out_2 <= data_pipe[MUX_2_POS*8+7:MUX_2_POS*8];
   data_out_3 <= data_pipe[MUX_3_POS*8+7:MUX_3_POS*8];
   data_out_4 <= data_pipe[MUX_4_POS*8+7:MUX_4_POS*8];

....
end

Now, the key is to workout the values for the 5 'MUX_#_POS' which are a fixed value based of the delays incurred by both   the  CLK_CYCLES_MUX  = 1 and CLK_CYCLES_RAM  = 2, and the tricky one, where each piece of data is in the pipe when the next  pc_ena==0 comes around so that all 5 output regs take the correct pipe position.

Resolve MUX_#_POS using the 2 CLK_CYCLES parameters with the knowledge that pc_ena[] counts from 0-4, and in the future if you may any changes which add additional clocks in the preparation for the memory data, or different clock cycles in the FPGA memory core, or if you wire external static memory, just adjusting the 'CLK_CYCLES' parameters will allow your design to continue to function without re-doing all the individual written hardwired logic.

When calculating the MUX_#_POS may also mean adding a full additional pixel delay if one or more pixels comes in earlier than the rest, or if 1 pixel comes in later than the rest.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2019, 01:57:37 pm
Ok, not quite.  Your outputs would still be scrambled, not only that, but, now, some of your outputs will be ahead by 1 pixel and the rest will have the correct pixel.

What you have setup has no configuration/adjustment capabilities.

Currently, at pc_ena 0, you may be switching to addr0, but the memory is seeing the previous addr4, while what is coming out of the ram is the previous addr2. but, you are currently snapping that into addr_buf0/data_buf0, and then feeding the previous  holdings of every addr_buf#/data_buf# into addr_out#/data_out#.

At pc_ena 1, you may be switching to addr1, but the memory is seeing the previous addr0, while what is coming out of the ram is the previous addr3. and are currently snapping that into addr_buf1/data_buf1, though the addr_out#/data_out# all hold their new state from when pc_ena0 phase has updated them.

Now, you can see the headache here.  Say you weed out everything as set the delays fixed and you code appears to work good.  What happens after adding some features, you might need to expand your mux for speed by making it collapse in 3 clocks stages instead of the current 1 clock.  What will sorting out the mess look like?

My mind has just melted...  :scared:

Step 1: Get rid of any and all demuxing in the case statement.

Like so?

Code: [Select]
always @(posedge clk) begin

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
addr_in_mux <= addr_in_0;
cmd_mux_in <= cmd_in_0;
end
3'b001 : begin
addr_in_mux <= addr_in_1;
cmd_mux_in <= cmd_in_1;
end
3'b011 : begin
addr_in_mux <= addr_in_2;
cmd_mux_in <= cmd_in_2;
end
3'b100 : begin
addr_in_mux <= addr_in_3;
cmd_mux_in <= cmd_in_3;
end
3'b101 : begin
addr_in_mux <= addr_in_4;
cmd_mux_in <= cmd_in_4;
end
endcase

end // always @clk

Step 2: Make a easily variable clock delay pipe tap coming out of the gpu_ram.

Example:
reg [9*8+7:0]  data_pipe;   // make a large enough register to store 10 words (words 0 through 9).  In the case of ram data, the width of each word is 8 bits.

Now, inside the always @(posedge clk) place

data_pipe[7:0]                <= data_mux_out[7:0];         // fill the first 8 bit word in the register pipe
data_pipe[9*8+7:1*8]  <= data_pipe[8*8+7:0*8];    // shift over the next 9 words in this 10 word 8 bit wide pipe


if (pc_ena[3:0] == 0)
   begin
   data_out_0 <= data_pipe[MUX_0_POS*8+7:MUX_0_POS*8];
   data_out_1 <= data_pipe[MUX_1_POS*8+7:MUX_1_POS*8];
   data_out_2 <= data_pipe[MUX_2_POS*8+7:MUX_2_POS*8];
   data_out_3 <= data_pipe[MUX_3_POS*8+7:MUX_3_POS*8];
   data_out_4 <= data_pipe[MUX_4_POS*8+7:MUX_4_POS*8];

....
end

Okay, so we're feeding the data from the RAM into a pipeline which, at the start when pc_ena=0, is passed out to the data outputs and is bit-shifted up the pipe by 8 places on each clk count?

Now, the key is to workout the values for the 5 'MUX_#_POS' which are a fixed value based of the delays incurred by both   the  CLK_CYCLES_MUX  = 1 and CLK_CYCLES_RAM  = 2, and the tricky one, where each piece of data is in the pipe when the next  pc_ena==0 comes around so that all 5 output regs take the correct pipe position.

Errrrrr..... I've just had to cold-reset my brain twice.  I have literally lost myself in all this and am almost throwing code at the wall to see what sticks...:

Code: [Select]
localparam MUX_0_POS = (CLK_CYCLES_RAM + CLK_CYCLES_MUX) * 1;
localparam MUX_1_POS = (CLK_CYCLES_RAM + CLK_CYCLES_MUX) * 2;
localparam MUX_2_POS = (CLK_CYCLES_RAM + CLK_CYCLES_MUX) * 3;
localparam MUX_3_POS = (CLK_CYCLES_RAM + CLK_CYCLES_MUX) * 4;
localparam MUX_4_POS = (CLK_CYCLES_RAM + CLK_CYCLES_MUX) * 5;

always @(posedge clk) begin

data_pipe[7:0] <= data_mux_out[7:0]; // fill the first 8-bit word in the register pipe with data from RAM
data_pipe[9*8+7:1*8] <= data_pipe[8*8+7:0*8]; // shift over the next 9 words in this 10 word, 8-bit wide pipe

if (pc_ena[3:0] == 0)
begin
data_out_0 <= data_pipe[MUX_0_POS*8+7:MUX_0_POS*8];
data_out_1 <= data_pipe[MUX_1_POS*8+7:MUX_1_POS*8];
data_out_2 <= data_pipe[MUX_2_POS*8+7:MUX_2_POS*8];
data_out_3 <= data_pipe[MUX_3_POS*8+7:MUX_3_POS*8];
data_out_4 <= data_pipe[MUX_4_POS*8+7:MUX_4_POS*8];
end

Resolve MUX_#_POS using the 2 CLK_CYCLES parameters with the knowledge that pc_ena[] counts from 0-4, and in the future if you may any changes which add additional clocks in the preparation for the memory data, or different clock cycles in the FPGA memory core, or if you wire external static memory, just adjusting the 'CLK_CYCLES' parameters will allow your design to continue to function without re-doing all the individual written hardwired logic.

When calculating the MUX_#_POS may also mean adding a full additional pixel delay if one or more pixels comes in earlier that the rest, or if 1 pixel comes in later that the rest.

Yeah, I'm going to have to walk away and come back to this later in the hope that I can get my head around it from a different angle, because this just isn't going in.   :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 02:25:57 pm
Yes, the first part you got right.  Yes, the data_pipe connected to the output of the ram module clocks at 125MHz nonstop, just like the memory itself, and the 5 cycled address going into the ram.

Yeah, I'm going to have to walk away and come back to this later in the hope that I can get my head around it from a different angle, because this just isn't going in.   :-\

Ok, this should really help, however, you will still need to concentrate a little and print out my little 2 tables on some paper to make what's happening clear.

Lay out these 2 tables on 2 sheets of paper, one side list each reg in the pipe in order, and on the second is a list of how the muxed addresses and screen pixel number is being fed through:

On paper page #1
-------------------------------------------
into data_pipe[8*8+7:8*8]
into data_pipe[7*8+7:7*8]
into data_pipe[6*8+7:6*8]
into data_pipe[5*8+7:5*8]
into data_pipe[4*8+7:4*8]
into data_pipe[3*8+7:3*8]
into data_pipe[2*8+7:2*8]
into data_pipe[1*8+7:1*8]
into data_pipe[0*8+7:0*8]
inside ram 2
inside ram 1
addr to addr-mux
PC_ENA pos0
-------------------------------------------

On paper #2

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

pc_ena 0 pixel 0
pc_ena 1 pixel 0
pc_ena 2 pixel 0
pc_ena 3 pixel 0
pc_ena 4 pixel 0
pc_ena 0 pixel 1
pc_ena 1 pixel 1
pc_ena 2 pixel 1
pc_ena 3 pixel 1
pc_ena 4 pixel 1
pc_ena 0 pixel 2
pc_ena 1 pixel 2
pc_ena 2 pixel 2
pc_ena 3 pixel 2
pc_ena 4 pixel 2
pc_ena 0 pixel 3
pc_ena 1 pixel 3
pc_ena 2 pixel 3
pc_ena 3 pixel 3
pc_ena 4 pixel 3

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

Slide paper #2 vertically across paper #1, 5 steps at a time, (paper 2 starts at the bottom, then you slide it vertically upwards) to see where each data is in your output pipe.  Remember, the numbers in red which all have the same pixel number in green are your 5 correct functional MUX_#_POS.  (Use the smallest possible valid pipe).  And every time your shift the paper vertically 5 steps, the next 5 pixels should line up to the same 5 MUX_#_POS.

Subtracting the pixel number at the reg output from the bottom line on page 1, plus 1 gives you to total number of 25MHz screen pixels it takes from address# in on your gpu multiport ram, to data out#.

I hope this helps.  Note that this is the most difficult part of your project.  There may be a few simpler tricks to do this, but, this offers maximum flexibility and upgrade paths as the 5 ports can address anything and all results are given in parallel.


Remember, the 5 'MUX_#_POS' are 5 localparams you will set.
The 5 localparams are identical for the addr_out# & cmd_out# pip selection.  It's only the *8 which will change to *20 for the address_pipe reg and *16 for the cmd_pipe reg.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 03:03:42 pm
To the more advance users out there, yes, all the 5 channel memory buses and shift pipes could be compacted down to a single reg in a single line with just the right expression within two brackets[], latching and shifting muxing, demuxing the entire results.  For example for the 5 data bytes output register, all 40 bits of the grouped buss may be latched on 1 line time with the right 8 bit (1 word) offset from the source pipe.  This could make the multi-port-ram module nothing more than a 3 lines of code for the 3 muxed buss inputs, and another 3 for the 3 bus outputs.  same for the 5x20bit address meaning a 100bit address input and 100 bits out with the right 20bit offset when latching the entire demux pipe.

However, this GPU project is an exercise for beginners and having me just dictate all these compact tricks to tap memory in a sequence pipe, aligning it to a multiphase system clock would not explain:

What I have done.
How it works.
Why it works.
Why I did it that way.
How can I design my own version?
What can I use it for?
Where should I use it?

Well, you should get the idea.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2019, 05:29:01 pm
Ok, this should really help, however, you will still need to concentrate a little and print out my little 2 tables on some paper to make what's happening clear.

One empty printer cartridge and sore wrist later...  ;D

Slide paper #2 vertically across paper #1, 5 steps at a time, (paper 2 starts at the bottom, then you slide it vertically upwards) to see where each data is in your output pipe.

Okay, so I'm starting with paper #2 below #1, so the first step brings pc_ena 0 pixel 0 into pc_ena pos 0.

Remember, the numbers in red which all have the same pixel number in green are your 5 correct functional MUX_#_POS.  (Use the smallest possible valid pipe).  And every time your shift the paper vertically 5 steps, the next 5 pixels should line up to the same 5 MUX_#_POS.

So after 10 steps, I get this:

into data_pipe [5*8+7:5*8] <= pc_ena 0 pixel 0
into data_pipe [4*8+7:4*8] <= pc_ena 1 pixel 0
into data_pipe [3*8+7:3*8] <= pc_ena 2 pixel 0
into data_pipe [2*8+7:2*8] <= pc_ena 3 pixel 0
into data_pipe [1*8+7:1*8] <= pc_ena 4 pixel 0
into data_pipe [0*8+7:0*8] <= pc_ena 0 pixel 1
inside ram 2                        <= pc_ena 1 pixel 1
inside ram 1                        <= pc_ena 2 pixel 1
addr to addr_mux                <= pc_ena 3 pixel 1
pc_ena pos 0                       <= pc_ena 4 pixel 1

So the five correct functional values are:
5,
4,
3,
2,
1??

Subtracting the pixel number at the reg output from the bottom line on page 1, plus 1 gives you to total number of 25MHz screen pixels it takes from address# in on your gpu multiport ram, to data out#.

2 pixels then?  ???

I hope this helps.  Note that this is the most difficult part of your project.  There may be a few simpler tricks to do this, but, this offers maximum flexibility and upgrade paths as the 5 ports can address anything and all results are given in parallel.

That makes me feel so much better knowing this is the most difficult part.   :o ;D

Remember, the 5 'MUX_#_POS' are 5 localparams you will set.
The 5 localparams are identical for the addr_out# & cmd_out# pip selection.  It's only the *8 which will change to *20 for the address_pipe reg and *16 for the cmd_pipe reg.

So my code looks like this:

Code: [Select]
module multiport_gpu_ram (

input clk, // Primary clk input (125 MHz)
input [3:0] pc_ena_in, // Pixel clock enable
input clk_b, // Host (Z80) clock input
input write_ena_b, // Host (Z80) clock enable

// address buses (input)
input [19:0] addr_in_0,
input [19:0] addr_in_1,
input [19:0] addr_in_2,
input [19:0] addr_in_3,
input [19:0] addr_in_4,
input [19:0] addr_host_in,

// auxilliary read command buses (input)
input [15:0] cmd_in_0,
input [15:0] cmd_in_1,
input [15:0] cmd_in_2,
input [15:0] cmd_in_3,
input [15:0] cmd_in_4,

// outputs
output wire [3:0] pc_ena_out,

// address pass-thru bus (output)
output reg [19:0] addr_out_0,
output reg [19:0] addr_out_1,
output reg [19:0] addr_out_2,
output reg [19:0] addr_out_3,
output reg [19:0] addr_out_4,
output reg [19:0] addr_host_out,

// auxilliary read command bus (pass-thru output)
output reg [15:0] cmd_out_0,
output reg [15:0] cmd_out_1,
output reg [15:0] cmd_out_2,
output reg [15:0] cmd_out_3,
output reg [15:0] cmd_out_4,

// data buses (output)
output reg [7:0] data_out_0,
output reg [7:0] data_out_1,
output reg [7:0] data_out_2,
output reg [7:0] data_out_3,
output reg [7:0] data_out_4,
output [7:0] data_host_out

);

// dual-port GPU RAM handler

// define the maximum address bits and number of words - effectively the RAM size
parameter ADDR_SIZE = 14;
parameter NUM_WORDS = 2 ** ADDR_SIZE;

localparam CLK_CYCLES_MUX = 1; // adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed outputs
localparam CLK_CYCLES_RAM = 2; // adjust this figure to the number of clock cycles the DP_ram takes to retrieve valid data from the read address in
localparam CLK_CYCLES_PIX = 5; // adjust this figure to the number of PIXEL clock cycles it takes the demuxed output data to be ready

reg [19:0] addr_in_mux;
reg [15:0] cmd_mux_in;
reg [15:0] cmd_mux_out;
wire [19:0] addr_mux_out;
wire [7:0] data_mux_out;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena_in),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(addr_in_mux),
.addr_b(),
.data_in_b(),
.cmd_in(cmd_mux_in),
.addr_out_a(addr_mux_out),
.pc_ena_out(pc_ena_out),
.cmd_out(cmd_mux_out),
.data_out_a(data_mux_out),
.data_out_b()
);

defparam gpu_RAM.ADDR_SIZE = ADDR_SIZE, // pass ADDR_SIZE into the gpu_RAM instance
gpu_RAM.NUM_WORDS = NUM_WORDS; // set non-default word size for the RAM (16 KB)

reg [9*8+7:0] data_pipe;
reg [9*20+19:0] addr_pipe;
reg [9*16+15:0] cmd_pipe;

localparam MUX_0_POS = 5;
localparam MUX_1_POS = 4;
localparam MUX_2_POS = 3;
localparam MUX_3_POS = 2;
localparam MUX_4_POS = 1;

always @(posedge clk) begin

data_pipe[7:0] <= data_mux_out[7:0]; // fill the first 8-bit word in the register pipe with data from RAM
data_pipe[9*8+7:1*8] <= data_pipe[8*8+7:0*8]; // shift over the next 9 words in this 10 word, 8-bit wide pipe
// this moves the data up one word at a time, dropping the top most 8 bits
addr_pipe[19:0] <= addr_mux_out;
addr_pipe[9*20+19:1*20] <= addr_pipe[8*20+19:0*20];

cmd_pipe[15:0] <= cmd_mux_out[15:0];
cmd_pipe[9*16+15:1*16] <= cmd_pipe[8*16+15:0*16];

if (pc_ena[3:0] == 0)
begin
addr_out_0 <= addr_pipe[MUX_0_POS*20+19:MUX_0_POS*20];
addr_out_1 <= addr_pipe[MUX_1_POS*20+19:MUX_1_POS*20];
addr_out_2 <= addr_pipe[MUX_2_POS*20+19:MUX_2_POS*20];
addr_out_3 <= addr_pipe[MUX_3_POS*20+19:MUX_3_POS*20];
addr_out_4 <= addr_pipe[MUX_4_POS*20+19:MUX_4_POS*20];

cmd_out_0 <= cmd_pipe[MUX_0_POS*16+15:MUX_0_POS*16];
cmd_out_1 <= cmd_pipe[MUX_1_POS*16+15:MUX_1_POS*16];
cmd_out_2 <= cmd_pipe[MUX_2_POS*16+15:MUX_2_POS*16];
cmd_out_3 <= cmd_pipe[MUX_3_POS*16+15:MUX_3_POS*16];
cmd_out_4 <= cmd_pipe[MUX_4_POS*16+15:MUX_4_POS*16];

data_out_0 <= data_pipe[MUX_0_POS*8+7:MUX_0_POS*8];
data_out_1 <= data_pipe[MUX_1_POS*8+7:MUX_1_POS*8];
data_out_2 <= data_pipe[MUX_2_POS*8+7:MUX_2_POS*8];
data_out_3 <= data_pipe[MUX_3_POS*8+7:MUX_3_POS*8];
data_out_4 <= data_pipe[MUX_4_POS*8+7:MUX_4_POS*8];
end

// perform 5:1 mux for all inputs to the dual-port RAM
case (pc_ena[2:0])
3'b000 : begin
addr_in_mux <= addr_in_0;
cmd_mux_in <= cmd_in_0;
end
3'b001 : begin
addr_in_mux <= addr_in_1;
cmd_mux_in <= cmd_in_1;
end
3'b011 : begin
addr_in_mux <= addr_in_2;
cmd_mux_in <= cmd_in_2;
end
3'b100 : begin
addr_in_mux <= addr_in_3;
cmd_mux_in <= cmd_in_3;
end
3'b101 : begin
addr_in_mux <= addr_in_4;
cmd_mux_in <= cmd_in_4;
end
endcase

end // always @clk

endmodule


CLK_CYCLES_MUX, RAM and PIX aren't used yet?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2019, 11:57:57 pm
Don't threat, I am deliberately pushing to to take big steps, and you are doing fine for such a complex 1st project.
You are doing great.  :-+

Your bulk of code is perfect, though 2 little mistakes:  (I hope Im not making one....  ;) )
----------------------------------------
into data_pipe [5*8+7:5*8] <= pc_ena 0 pixel 0
into data_pipe [4*8+7:4*8] <= pc_ena 1 pixel 0
into data_pipe [3*8+7:3*8] <= pc_ena 2 pixel 0
into data_pipe [2*8+7:2*8] <= pc_ena 3 pixel 0
into data_pipe [1*8+7:1*8] <= pc_ena 4 pixel 0
into data_pipe [0*8+7:0*8] <= pc_ena 0 pixel 1
inside ram 2                        <= pc_ena 1 pixel 1
inside ram 1                        <= pc_ena 2 pixel 1
addr to addr_mux                <= pc_ena 3 pixel 1
pc_ena pos 0                       <= pc_ena 4 pixel 1
------------------------------------------------------

You need to push all the pixels on the right up by 1 more since the 'pc_ena pos 0' is the time in 'IF (pc_ena pos == 0)' statement and not a register.  At the beginning of 'pc_ena pos == 0', 'addr to addr_mux's output  should holding the last 'pc_ena 4 pixel 1' and  'pc_ena pos == 0' should be ready to take the next pixel 'pc_ena 0 pixel 2'... This also adds 1 whole pixel to the pixel pipe delay.

Next: (I corrected your offset figures)
localparam MUX_0_POS = 6;
localparam MUX_1_POS = 5;
localparam MUX_2_POS = 4;
localparam MUX_3_POS = 3;
localparam MUX_4_POS = 2;

Is functional, however, there is a smarter way to fill these out and it includes my earlier hint:
Here is the hint#1 :
------------------------------------
localparam   CLK_CYCLES_MUX  = 1;  // Adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed inputs
localparam   CLK_CYCLES_RAM  = 2;  // Adjust this figure to the number of clock cycles the DP_ram takes to retrieve a valid data from the read address in.
localparam   CLK_CYCLES_PCENA  = 5;  // Adjust this figure to the number of clock cycles per pixel.
-------------------------------------

Currently, in your code, your first mux takes 1 clock and the INTEL altsyncram megafunction takes 2 clocks:
----------------------------
into data_pipe[0*8+7:0*8]
inside ram 2                               2 clock cycles here for INTEL's altsyncram function.
inside ram 1
addr to addr-mux                       1 clock cycle here for you current MUX code.
PC_ENA pos0
-------------------------------
Now, also knowing that PC_ENA has 5 positions per pixel, and using those 3 reference 'CLK_CYCLES_xxxx' which describes the # of clocks as each step in your delay pipe, write a formula which fills in all 5 'localparam MUX_#_POS's numbers.

Next, test you formula against a slower addr-mux algorithm which takes 2 clocks instead of 1 clock.

Step 1:Example, fill in 'localparam   CLK_CYCLES_MUX  = 2'
Step 2, change table on page 1 so addr-mux has 2 clock steps:
-----------------------------
nto data_pipe[2*8+7:2*8]
into data_pipe[1*8+7:1*8]
into data_pipe[0*8+7:0*8]
inside ram 2
inside ram 1
addr to addr-mux        step #2
addr to addr-mux        step #1
PC_ENA pos0
-------------------------------------------

Now verify that you formula generating the 5  'localparam MUX_#_POS's have valid pipe positions.
Do this a few more times with 'CLK_CYCLES_MUX  = 3', 'CLK_CYCLES_MUX  = 4', CLK_CYCLES_RAM  = 3'.

Everything else you wrote looks correct.  :-+

Also, you should realize trying to properly unmux the data stream coming out of the ram could never be done properly any other way without pure luck.  And with luck, if you ever had to increase a number of clock steps in for example the addr-mux stage, or, the FPGA's altsyncram dual port ram function, everything would fall apart and luck again would be needed to hope you get the right output all in parallel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 05:28:48 am
Ok, next....

You will need to create a 16 kilobyte "gpu_ram_init.mif" file.  This file should contain my Atari font beginning at byte 4'h0800 & the test memory text file beginning at byte 4'h1000.

Next, remove my old 2 alt synccrams from the OSG generator and wire in your new "multiport_gpu_ram.v".
You will need to appropriately cross wire in my old addresses into the 20 bit address, hard wiring the upper addresses to the 2 bases 4h'0800 & 4h'1000.

Also, in my old code, each read took 2 pixel clocks, now each new ram read takes 3 pixel clocks.  (even I might have counted wrong here, but I'm pretty sure it's 3...)
This means touching up inside the OSD:

Code: [Select]
parameter   PIPE_DELAY =  4;   // This parameter selects the number of pixel clocks which the output VDE and syncs are delayed



//  The disp_x is the X coordinate counter.  It runs from 0 to 512 and stops there
//  The disp_y is the Y coordinate sounter.  It runs from 0 to 256 and stops there

assign disp_pos[4:0]  = disp_x[8:4] ;  // The disp_pos[4:0] is the lower address for the 32 characters wide display ascii text.
assign disp_pos[8:5]  = disp_y[7:4] ;  // the disp_pos[8:5] is the upper address for the 16 lines of text


//  The result from the ascii memory component 'altsyncram_component_osd_mem'  is called letter[7:0]
//  Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.

//  Now, font_pos[12:0] is the read address for the memory block containing the font memory

assign font_pos[12:6] = letter[6:0] ;       //  Selec the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0]  = dly2_disp_x[3:1] ;  //  select the font X coordinate with a 2 pixel clock DELAYES disp_x address.  [3:1] is used so that every 2 x pixels are repeats
assign font_pos[5:3]  = dly2_disp_y[3:1] ;  //  select the font y coordinate with a 2 pixel clock DELAYES disp_y address.  [3:1] is used so that every 2 y lines are repeats


//  The resulting font image, 2 bits since I made a 2 bit color atari font is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii test memory, I use that as a third OSD output color bit.

assign osd_image[1:0] = osd_img[1:0];
assign osd_image[2]   = dly2_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]


// **********************************************************************************************
// AND
// **********************************************************************************************
osd_ena_out  <= dly2_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
                           // It needs to be delayed by the number of pixel clocks required for the above memories


You should be able to recreate your last OSD image perfectly.  If so, congratulations, you passed the 50% mark of completing version 1.0!.

If you have time, you should now think about getting 12bit color working as this is coming up next.
Then comes proper dynamic display of any memory as text or graphics at any resolution.

This is the fun part is coming...  You will soon need to think about videos, not just pictures, but, you will need to fill the memory_init file with data for things to happen and you will need to get a Z80 connected with software to achieve anything interesting.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 09:05:28 am
Currently, in your code, your first mux takes 1 clock and the INTEL altsyncram megafunction takes 2 clocks:
----------------------------
into data_pipe[0*8+7:0*8]
inside ram 2                               2 clock cycles here for INTEL's altsyncram function.
inside ram 1
addr to addr-mux                       1 clock cycle here for you current MUX code.
PC_ENA pos0
-------------------------------
Now, also knowing that PC_ENA has 5 positions per pixel, and using those 3 reference 'CLK_CYCLES_xxxx' which describes the # of clocks as each step in your delay pipe, write a formula which fills in all 5 'localparam MUX_#_POS's numbers.

Code: [Select]
localparam CLK_CYCLES_MUX = 1; // adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed outputs
localparam CLK_CYCLES_RAM = 2; // adjust this figure to the number of clock cycles the DP_ram takes to retrieve valid data from the read address in
localparam CLK_CYCLES_PIX = 5; // adjust this figure to the number of PIXEL clock cycles it takes the demuxed output data to be ready

localparam MUX_0_POS = 6; // pixel offset positions in their respective synchronisation
localparam MUX_1_POS = 5; // pipelines (where the pixels will be found in the pipeline
localparam MUX_2_POS = 4; // when pc_ena[3:0]==0).
localparam MUX_3_POS = 3; //
localparam MUX_4_POS = 2; //

To get the MUX_x_POS values from those parameters, I've come up with this:

Code: [Select]
MUX_POS = 2*CLK_CYCLES_MUX + 2*CLK_CYCLES_RAM + 2*CLK_CYCLES_PIX - (POS + 10);
It's not elegant, but seems to do the job and works with parameter changes as far as I can tell.  I've had to add another parameter - POS - which replaces the _x_ in MUX_x_POS...  And I'm not 100% happy with the constant '10' being in there... so I guess what I'm trying to say is that I'm not 100% happy with the formula...  ::)

I know Verilog isn't a programming language, but is there any chance we can replace all those MUX_x_POS parameters with a single array of values and access them using POS as the index?

Also, you should realize trying to properly unmux the data stream coming out of the ram could never be done properly any other way without pure luck.  And with luck, if you ever had to increase a number of clock steps in for example the addr-mux stage, or, the FPGA's altsyncram dual port ram function, everything would fall apart and luck again would be needed to hope you get the right output all in parallel.

Yeah, with my luck it'd blow up or something.  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 11:47:15 am
Ok, next....

You will need to create a 16 kilobyte "gpu_ram_init.mif" file.  This file should contain my Atari font beginning at byte 4'h0800 & the test memory text file beginning at byte 4'h1000.

That's done.  File attached (gpu_16K_RAM.mif).

Next, remove my old 2 alt synccrams from the OSG generator and wire in your new "multiport_gpu_ram.v".
You will need to appropriately cross wire in my old addresses into the 20 bit address, hard wiring the upper addresses to the 2 bases 4h'0800 & 4h'1000.

You make it sound so easy... :o

I'm a little confused about how to wire up the 5 batches of address, data and command buses.  Well, actually, completely clueless.   :scared:

So disp_pos is a 9-bit address that needs to go into the new multiport_gpu_ram module, and needs to be shifted to address the display RAM portion of memory starting at 0x1000 in gpu_16K_RAM.mif.  This needs to be put into a 13-bit address value - disp_addr for example:

Code: [Select]
wire disp_addr[12:0];
disp_addr[12] = 1'b1;    // set 13th bit to 1 to start address at 0x1000
disp_addr[8:0] = disp_pos[8:0];    // map display position address into new memory address

And to get the font data, which uses a 10-bit address, I'll need to map its address into a new 11-bit address for the new memory like so:

Code: [Select]
wire font_addr[11:0];
font_addr[11] = 1'b1;    // set 12th bit to 1 to start address at 0x800
disp_addr[9:0] = font_pos[9:0];    // map display position address into new memory address

Above is pseudo-Verilog code... I'm writing this from the top of my head at the moment (not a great place to start from!)  ::)

But, in any case, I'm not sure where these values should be going into the multiport_gpu_ram instance and what I should be doing with the masses of unassigned inputs?

Code: [Select]
// ****************************************************************************************************************************
// create a multiport GPU RAM handler instance
// ****************************************************************************************************************************
multiport_gpu_ram gpu_RAM(

.clk(clk),
.pc_ena_in(pc_ena),
.clk_b(),
.write_ena_b(),

.addr_in_0(),
.addr_in_1(),
.addr_in_2(),
.addr_in_3(),
.addr_in_4(),
.addr_host_in(),

.cmd_in_0(),
.cmd_in_1(),
.cmd_in_2(),
.cmd_in_3(),
.cmd_in_4(),

.pc_ena_out(),

.addr_out_0(),
.addr_out_1(),
.addr_out_2(),
.addr_out_3(),
.addr_out_4(),
.addr_host_out(),

.cmd_out_0(),
.cmd_out_1(),
.cmd_out_2(),
.cmd_out_3(),
.cmd_out_4(),

.data_out_0(),
.data_out_1(),
.data_out_2(),
.data_out_3(),
.data_out_4(),
.data_host_out()

);

Also, in my old code, each read took 2 pixel clocks, now each new ram read takes 3 pixel clocks.  (even I might have counted wrong here, but I'm pretty sure it's 3...)
This means touching up inside the OSD:

Code: [Select]
assign osd_image[1:0] = osd_img[1:0];
assign osd_image[2]   = dly2_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]

Is that second-to-last line of code correct?  Assigning osd_image[1:0] to itself?  (Assuming osd_img is a typo)

// **********************************************************************************************
// AND
// **********************************************************************************************
osd_ena_out  <= dly2_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
                           // It needs to be delayed by the number of pixel clocks required for the above memories

[/code]

You should be able to recreate your last OSD image perfectly.  If so, congratulations, you passed the 50% mark of completing version 1.0!.

Yeah, not quite there yet with the code.  ;)

If you have time, you should now think about getting 12bit color working as this is coming up next.[/code]

Ah okay - will see what I can do.

This is the fun part is coming...  You will soon need to think about videos, not just pictures, but, you will need to fill the memory_init file with data for things to happen and you will need to get a Z80 connected with software to achieve anything interesting.

 ;D

Looking forward to getting the host connected and getting a working video console.  That'll be a big win for me.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 11:51:42 am
Currently, in your code, your first mux takes 1 clock and the INTEL altsyncram megafunction takes 2 clocks:
----------------------------
into data_pipe[0*8+7:0*8]
inside ram 2                               2 clock cycles here for INTEL's altsyncram function.
inside ram 1
addr to addr-mux                       1 clock cycle here for you current MUX code.
PC_ENA pos0
-------------------------------
Now, also knowing that PC_ENA has 5 positions per pixel, and using those 3 reference 'CLK_CYCLES_xxxx' which describes the # of clocks as each step in your delay pipe, write a formula which fills in all 5 'localparam MUX_#_POS's numbers.

Code: [Select]
localparam CLK_CYCLES_MUX = 1; // adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed outputs
localparam CLK_CYCLES_RAM = 2; // adjust this figure to the number of clock cycles the DP_ram takes to retrieve valid data from the read address in
localparam CLK_CYCLES_PIX = 5; // adjust this figure to the number of PIXEL clock cycles it takes the demuxed output data to be ready

localparam MUX_0_POS = 6; // pixel offset positions in their respective synchronisation
localparam MUX_1_POS = 5; // pipelines (where the pixels will be found in the pipeline
localparam MUX_2_POS = 4; // when pc_ena[3:0]==0).
localparam MUX_3_POS = 3; //
localparam MUX_4_POS = 2; //

To get the MUX_x_POS values from those parameters, I've come up with this:

Code: [Select]
MUX_POS = 2*CLK_CYCLES_MUX + 2*CLK_CYCLES_RAM + 2*CLK_CYCLES_PIX - (POS + 10);
It's not elegant, but seems to do the job and works with parameter changes as far as I can tell.  I've had to add another parameter - POS - which replaces the _x_ in MUX_x_POS...  And I'm not 100% happy with the constant '10' being in there... so I guess what I'm trying to say is that I'm not 100% happy with the formula...  ::)

I know Verilog isn't a programming language, but is there any chance we can replace all those MUX_x_POS parameters with a single array of values and access them using POS as the index?


Ok, I'll give this one to you in a simpler way, but, to do so in a simple way, I've added 1 parameter, PIXEL_PIPE.  PIXEL_PIPE needs to be large enough so that the 'MUX_4_POS' doesn't become a negative number, otherwise, you will get a compile error and need to increase the new 'PIXEL_PIPE' parameter until 'MUX_4_POS' is a positive integer.

Code: [Select]
parameter   PIXEL_PIPE = 3;  // This externally set parameter defines the number of 25MHz pixels it takes to receive a new pixel from a presented address

localparam CLK_CYCLES_MUX = 1; // adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed outputs
localparam CLK_CYCLES_RAM = 2; // adjust this figure to the number of clock cycles the DP_ram takes to retrieve valid data from the read address in
localparam CLK_CYCLES_PIX = 5; // adjust this figure to the number of 125MHz clocks there are for each pixel, IE number of muxed inputs for each pixel

//  This parameter begins with the wanted top number of 125Mhz pixel clock headroom for the pixel pipe, then subtracts the additional 125MHz clocks used by the _MUX and _RAM cycles used to arrive at the first pixel out, DEMUX_PIPE_TOP position.
localparam  DEMUX_PIPE_TOP    =  (( (PIXEL_PIPE - 1) * CLK_CYCLES_PIX ) - 1) - CLK_CYCLES_MUX - CLK_CYCLES_RAM;

localparam MUX_0_POS = DEMUX_PIPE_TOP - 0;  // pixel offset positions in their respective synchronisation
localparam MUX_1_POS = DEMUX_PIPE_TOP - 1;   // pipelines (where the pixels will be found in the pipeline
localparam MUX_2_POS = DEMUX_PIPE_TOP - 2;   // when pc_ena[3:0]==0).
localparam MUX_3_POS = DEMUX_PIPE_TOP - 3;   //
localparam MUX_4_POS = DEMUX_PIPE_TOP - 4; //

Code: [Select]
// Now that we know the DEMUX_PIPE_TOP, we can assign the top size of the 3 pipe regs

reg [DEMUX_PIPE_TOP*8+7:0] data_pipe;
reg [DEMUX_PIPE_TOP*20+19:0] addr_pipe;
reg [DEMUX_PIPE_TOP*16+15:0] cmd_pipe;

Code: [Select]
// We also need to limit the pipe in the 3 ' <= '

data_pipe[7:0]                     <= data_mux_out[7:0]; // fill the first 8-bit word in the register pipe with data from RAM
data_pipe[DEMUX_PIPE_TOP*8+7:1*8] <= data_pipe[ (DEMUX_PIPE_TOP-1) *8+7:0*8]; // shift over the next 9 words in this 10 word, 8-bit wide pipe
// this moves the data up one word at a time, dropping the top most 8 bits
addr_pipe[19:0]                   <= addr_mux_out;
addr_pipe[DEMUX_PIPE_TOP*20+19:1*20] <= addr_pipe[ (DEMUX_PIPE_TOP-1) *20+19:0*20];

cmd_pipe[15:0]                         <= cmd_mux_out[15:0];
cmd_pipe[DEMUX_PIPE_TOP*16+15:1*16] <= cmd_pipe[ (DEMUX_PIPE_TOP-1) *16+15:0*16];

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 12:09:24 pm
First, only mistakes in gpu_dual_port_ram_INTEL.v:

Code: [Select]
.address_b (addr_b[ (ADDR_SIZE-1) :0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[ (ADDR_SIZE-1) :0]),
Changed the 'ADDR_SIZE)' to '(ADDR_SIZE-1)'.

Code: [Select]
altsyncram_component.widthad_a = ADDR_SIZE,
altsyncram_component.widthad_b = ADDR_SIZE,
Changed the 'ADDR_SIZE - 1' to 'ADDR_SIZE'.

Next comes the 'vid_osd_generator.v'.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 12:39:28 pm
Ok, I know we are 'Jerry' rigging my old disp_x/y addresses into this new algorithm, so temporarily, we will use wires to make this happen and temporarily touch up my OSD code.  The next step will make all of this obsolete, however, for now let's do it like this:

Insert the following into the OSD code:

wire [19:0] read_text_adr;
wire [19:0] read_font_adr;

assign read_text_adr[8:0]   = disp_pos[8:0];
assign read_text_adr[9]      =  1b'0;
assign read_text_adr[19:10] = 1'h4;

assign read_font_adr[9:0]   = font_pos[9:0];
assign read_font_adr[19:10] = 1'h2;


Now, pass  read_font_adr &  read_text_adr into 2 memory address 'addr_in_#()' ports of your liking.
And in the appropriate 'data_out_#()' ports, place the 'letter[7:0]' and 'char_line[7:0]'.

Without any other changes, this should generate a messed up text display as my old pipe delays were designed for 2 pixel clocks on each read, not the new current 3.  To fix this, you need to make the changes I listed in red:

parameter   PIPE_DELAY =  6;   // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.


assign font_pos[12:6]= letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0]   = dly3_disp_y[3:1] ;  // select the font x coordinate with a 2 pixel clock DELAYED disp_x address.  [3:1] is used so that every 2 x lines are repeats
assign font_pos[5:3]   = dly3_disp_y[3:1] ;  // select the font y coordinate with a 2 pixel clock DELAYED disp_y address.  [3:1] is used so that every 2 y lines are repeats

assign osd_image[1:0] = osd_image[1:0];  You are working with the wrong version of OSD generator. You already changed this line to convert a 8bit font line into 8 individual pixels, 1 bit color B&W font, remember?

assign osd_image[2] = dly3_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]



      osd_ena_out  <= dly4_dena;   // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 12:53:12 pm
 :palm: There is a bug in your mux (partially my bad...) in the 'multiport_gpu_ram.v', however, we will fix it after you get your garbled text with the current version.  It's one of those 'gotcha' things which would leave many helpless without running a simulator, even so, it would take days to fix depending on the rest of the design.  Don't threat, the real solution is easy if you know what you are doing, we will fix it next.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 01:30:12 pm
Insert the following into the OSD code:

wire [19:0] read_text_adr;
wire [19:0] read_font_adr;

assign read_text_adr[8:0]   = disp_pos[8:0];
assign read_text_adr[9]      =  1b'0;
assign read_text_adr[19:10] = 1'h4;

assign read_font_adr[9:0]   = font_pos[9:0];
assign read_font_adr[19:10] = 1'h2;

Righto - I've pasted that in before the multiport_gpu_ram declaration.

Now, pass  read_font_adr &  read_text_adr into 2 memory address 'addr_in_#()' ports of your liking.
And in the appropriate 'data_out_#()' ports, place the 'letter[7:0]' and 'char_line[7:0]'.

Code: [Select]
parameter   PIPE_DELAY =  6;   // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

wire [9:0] font_pos;
wire [8:0] disp_pos;
wire [2:0] osd_image;
wire [19:0] read_text_adr;
wire [19:0] read_font_adr;

assign read_text_adr[8:0] = disp_pos[8:0];
assign read_text_adr[9] =  1b'0;
assign read_text_adr[19:10] = 1'h4;

assign read_font_adr[9:0] = font_pos[9:0];
assign read_font_adr[19:10] = 1'h2;

// ****************************************************************************************************************************
// create a multiport GPU RAM handler instance
// ****************************************************************************************************************************
multiport_gpu_ram gpu_RAM(

.clk(clk),
.pc_ena_in(pc_ena),
.clk_b(),
.write_ena_b(),

.addr_in_0(read_font_adr),
.addr_in_1(read_text_adr),
.addr_in_2(),
.addr_in_3(),
.addr_in_4(),
.addr_host_in(),

.cmd_in_0(),
.cmd_in_1(),
.cmd_in_2(),
.cmd_in_3(),
.cmd_in_4(),

.pc_ena_out(),

.addr_out_0(),
.addr_out_1(),
.addr_out_2(),
.addr_out_3(),
.addr_out_4(),
.addr_host_out(),

.cmd_out_0(),
.cmd_out_1(),
.cmd_out_2(),
.cmd_out_3(),
.cmd_out_4(),

.data_out_0(letter[7:0]),
.data_out_1(char_line[7:0]),
.data_out_2(),
.data_out_3(),
.data_out_4(),
.data_host_out()

);


Without any other changes, this should generate a messed up text display as my old pipe delays were designed for 2 pixel clocks on each read, not the new current 3.  To fix this, you need to make the changes I listed in red:

parameter   PIPE_DELAY =  6;   // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.


assign font_pos[12:6]= letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0]   = dly3_disp_y[3:1] ;  // select the font x coordinate with a 2 pixel clock DELAYED disp_x address.  [3:1] is used so that every 2 x lines are repeats
assign font_pos[5:3]   = dly3_disp_y[3:1] ;  // select the font y coordinate with a 2 pixel clock DELAYED disp_y address.  [3:1] is used so that every 2 y lines are repeats

All done.

assign osd_image[1:0] = osd_image[1:0];  You are working with the wrong version of OSD generator. You already changed this line to convert a 8bit font line into 8 individual pixels, 1 bit color B&W font, remember?

Yeah, I'd commented the line out where I'd changed it as you specified 'assign osd_image[1:0] = osd_image[1:0];' in place of 'assign osd_image[1:0] = char_line[(~dly4_disp_x[3:1])];'.  Which should I be using?

assign osd_image[2] = dly3_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]



      osd_ena_out  <= dly4_dena;   // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown[/code]

Done.  I've also added the extra dly lines.

Code: [Select]
module vid_osd_generator ( clk, pc_ena, hde_in, vde_in, hs_in, vs_in, osd_ena_out, osd_image, hde_out, vde_out, hs_out, vs_out,
wren_disp, wren_font, wr_addr, wr_data );

// To write contents into the display and font memories, the wr_addr[15:0] selects the address
// the wr_data[7:0] contains a byte which will be written
// the wren_disp is the write enable for the ascii text ram.  Only the wr_addr[8:0] are used as the character display is 32x16.
// the wren_font is the write enable for the font memory.  Only 2 bits are used of the wr_data[1:0] and wr_addr[12:0] are used.
// tie these ports to GND for now disabling them

input clk;
input [3:0] pc_ena;
input hde_in, vde_in, hs_in, vs_in;

output osd_ena_out;
reg    osd_ena_out;
output [2:0] osd_image;
output hde_out, vde_out, hs_out, vs_out;
reg hde_out, vde_out, hs_out, vs_out;

input wren_disp, wren_font;
input [15:0] wr_addr;
input [7:0] wr_data;

reg  [9:0] disp_x,dly1_disp_x,dly2_disp_x,dly3_disp_x,dly4_disp_x;
reg  [8:0] disp_y,dly1_disp_y,dly2_disp_y;

reg  dena,dly1_dena,dly2_dena,dly3_dena,dly4_dena;
reg  [7:0] dly1_letter, dly2_letter;

reg  [7:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe;

parameter   PIPE_DELAY =  6;   // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

wire [9:0] font_pos;
wire [8:0] disp_pos;
wire [2:0] osd_image;
wire [19:0] read_text_adr;
wire [19:0] read_font_adr;

assign read_text_adr[8:0] = disp_pos[8:0];
assign read_text_adr[9] =  1b'0;
assign read_text_adr[19:10] = 1'h4;

assign read_font_adr[9:0] = font_pos[9:0];
assign read_font_adr[19:10] = 1'h2;

// ****************************************************************************************************************************
// create a multiport GPU RAM handler instance
// ****************************************************************************************************************************
multiport_gpu_ram gpu_RAM(

.clk(clk),
.pc_ena_in(pc_ena),
.clk_b(),
.write_ena_b(),

.addr_in_0(read_font_adr),
.addr_in_1(read_text_adr),
.addr_in_2(),
.addr_in_3(),
.addr_in_4(),
.addr_host_in(),

.cmd_in_0(),
.cmd_in_1(),
.cmd_in_2(),
.cmd_in_3(),
.cmd_in_4(),

.pc_ena_out(),

.addr_out_0(),
.addr_out_1(),
.addr_out_2(),
.addr_out_3(),
.addr_out_4(),
.addr_host_out(),

.cmd_out_0(),
.cmd_out_1(),
.cmd_out_2(),
.cmd_out_3(),
.cmd_out_4(),

.data_out_0(letter[7:0]),
.data_out_1(char_line[7:0]),
.data_out_2(),
.data_out_3(),
.data_out_4(),
.data_host_out()

);

//  The disp_x is the X coordinate counter.  It runs from 0 to 512 and stops there
//  The disp_y is the Y coordinate counter.  It runs from 0 to 256 and stops there

// Get the character at the current x, y position
assign disp_pos[4:0]  = disp_x[8:4] ;  // The disp_pos[4:0] is the lower address for the 32 characters for the ascii text.
assign disp_pos[8:5]  = disp_y[7:4] ;  // the disp_pos[8:5] is the upper address for the 16 lines of text

//  The result from the ascii memory component 'altsyncram_component_osd_mem'  is called letter[7:0]
//  Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.

//  Now, font_pos[12:0] is the read address for the memory block containing the character specified in letter[]

assign font_pos[12:6]= letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0] = dly3_disp_y[3:1] ;  // select the font x coordinate with a 2 pixel clock DELAYED disp_x address.  [3:1] is used so that every 2 x lines are repeats
assign font_pos[5:3] = dly3_disp_y[3:1] ;  // select the font y coordinate with a 2 pixel clock DELAYED disp_y address.  [3:1] is used so that every 2 y lines are repeats

//  The resulting 2-bit font image at x is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image[1:0] = char_line[(~dly4_disp_x[3:1])];
assign osd_image[2] = dly3_letter[7];  // Remember, it takes 2 pixel clocks for osd_img[1:0] data to be valid from read address letter[6:0]

always @ ( posedge clk ) begin

if (pc_ena[2:0] == 0) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

hde_pipe[0]   <= hde_in;
hde_pipe[7:1] <= hde_pipe[6:0];
hde_out       <= hde_pipe[PIPE_DELAY-2];

vde_pipe[0]   <= vde_in;
vde_pipe[7:1] <= vde_pipe[6:0];
vde_out       <= vde_pipe[PIPE_DELAY-2];

hs_pipe[0]    <= hs_in;
hs_pipe[7:1]  <= hs_pipe[6:0];
hs_out        <= hs_pipe[PIPE_DELAY-2];

vs_pipe[0]    <= vs_in;
vs_pipe[7:1]  <= vs_pipe[6:0];
vs_out        <= vs_pipe[PIPE_DELAY-2];

// **********************************************************************************************
// This OSD generator's window is only 512 pixels by 256 lines.
// Since the disp_X&Y counters are the screens X&Y coordinates, I'm using an extra most
// significant bit in the counters to determine if the OSD ena flag should be on or off.

if (disp_x[9] || disp_y[8])
dena <= 0; // When disp_x > 511 or disp_y > 255, then turn off the OSD's output enable flag
else
dena <= 1; // otherwise, turn on the OSD output enable flag

if (~vde_in)
disp_y[8:0] <= 9'b111111111; // preset the disp_y counter to max while the vertical display is disabled

else if (hde_in && ~hde_pipe[0])
begin // isolate a single event at the begining of the active display area

disp_x[9:0] <= 10'b0000000000; // clear the disp_x counter
if (!disp_y[8] | (disp_y[8:7] == 2'b11))
disp_y <= disp_y + 1; // only increment the disp_y counter if it hasn't reached it's end

end
else if (!disp_x[9])
disp_x <= disp_x + 1;  // keep on addind to the disp_x counter until it reaches it's end.

// **********************************************************************************************
// *** These delay pipes registers are explained in the 'assign's above
// **********************************************************************************************
dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;
dly3_disp_x <= dly2_disp_x;
dly4_disp_x <= dly3_disp_x;

dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;
dly3_disp_y <= dly2_disp_y;

dly1_letter <= letter;
dly2_letter <= dly1_letter;
dly3_letter <= dly2_letter;

dly1_dena   <= dena;
dly2_dena   <= dly1_dena;
dly3_dena   <= dly2_dena;
dly4_dena   <= dly3_dena;

// **********************************************************************************************
osd_ena_out  <= dly4_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
// It needs to be delayed by the number of pixel clocks required for the above memories

end // ena

end // always@clk

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 01:36:02 pm
'assign osd_image[1:0] = char_line[(~dly4_disp_x[3:1])];' is the right line as your 8bit font ram needs yo be turned into 8 individual pixels.

Since I don't know how quartus deals with a missing clock on a dual port ram, for now, feed a clock here:
-----------------
      .clk_b(clk),
-----------------

For all other unused inputs, set them to '0', so at least you are sure they are doing nothing...

Hopefully you can compile the thing and get a first picture.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 01:45:23 pm
Yeah, getting it to compile was problematic - there were a few errors, but nothing insurmountable.

I'm not sure about the fix for this one, though:

Error (10663): Verilog HDL Port Connection error at multiport_gpu_ram.v(75): output or inout port "cmd_out" must be connected to a structural net expression

The lines in question is this one:

Code: [Select]
reg [15:0] cmd_mux_out;              **** I APPLIED FIX HERE - CHANGED TO 'WIRE'
wire [19:0] addr_mux_out;
wire [7:0] data_mux_out;

// create a GPU RAM instance
gpu_dual_port_ram_INTEL gpu_RAM(
.clk(clk),
.pc_ena_in(pc_ena_in),
.clk_b(clk_b),
.wr_en_b(wr_en_b),
.addr_a(addr_in_mux),
.addr_b(),
.data_in_b(),
.cmd_in(cmd_mux_in),
.addr_out_a(addr_mux_out),
.pc_ena_out(pc_ena_out),
.cmd_out(cmd_mux_out),    *********** THIS LINE IS WHERE THE ERROR POINTS TO
.data_out_a(data_mux_out),
.data_out_b()
);

As stated in the code sample above, I changed the cmd_mux_out from a REG to a WIRE and it compiles now... Not sure that later breaks something else, though?

Off to see what the output is like on my screen....   :-BROKE

EDIT:

Just getting a black screen...

Here's the data I'm passing to the multiport_gpu_ram module:

Code: [Select]
multiport_gpu_ram gpu_RAM(

.clk(clk),
.pc_ena_in(pc_ena),
.clk_b(clk),
.write_ena_b(1'b1),

.addr_in_0(read_font_adr),
.addr_in_1(read_text_adr),
.addr_in_2(20'b0),
.addr_in_3(20'b0),
.addr_in_4(20'b0),
.addr_host_in(20'b0),

.cmd_in_0(16'b0),
.cmd_in_1(16'b0),
.cmd_in_2(16'b0),
.cmd_in_3(16'b0),
.cmd_in_4(16'b0),

.pc_ena_out(),

.addr_out_0(),
.addr_out_1(),
.addr_out_2(),
.addr_out_3(),
.addr_out_4(),
.addr_host_out(),

.cmd_out_0(),
.cmd_out_1(),
.cmd_out_2(),
.cmd_out_3(),
.cmd_out_4(),

.data_out_0(letter[7:0]),
.data_out_1(char_line[7:0]),
.data_out_2(),
.data_out_3(),
.data_out_4(),
.data_host_out()

);
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 01:50:07 pm
Does your altsyncram memory have anything in it?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 01:57:59 pm
Yeah, getting it to compile was problematic - there were a few errors, but nothing insurmountable.

I'm not sure about the fix for this one, though:

Error (10663): Verilog HDL Port Connection error at multiport_gpu_ram.v(75): output or inout port "cmd_out" must be connected to a structural net expression

Something else is off, otherwise the "addr_out" would have a similar error.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 02:25:04 pm
Does your altsyncram memory have anything in it?

Nope.  :palm:  Was just testing.  ;)

Still getting a black screen, though.  Latest files attached.

Error (10663): Verilog HDL Port Connection error at multiport_gpu_ram.v(75): output or inout port "cmd_out" must be connected to a structural net expression

Something else is off, otherwise the "addr_out" would have a similar error.

That's what I thought, but I can't see any differences that would cause the error for cmd_out and nothing else...

There is another error message after it - this is both together in the compilation report:

Error (10663): Verilog HDL Port Connection error at multiport_gpu_ram.v(75): output or inout port "cmd_out" must be connected to a structural net expression
Error (12152): Can't elaborate user hierarchy "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM"
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 02:38:57 pm
Don't outputs from modules have to be wires?  So cmd_mux_out should be a wire that is assigned to a reg somewhere else?

Have tried this, with cmd_tmp_out being a wire on the cmd_out output of the module, and with the cmd_mux_out <= cmd_tmp_out in the always block, but still getting a black screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 02:41:09 pm
Your .mif file is still wrong and it should be in the main file path.
here is what you have now:
      altsyncram_component.init_file = "../osd_mem.mif",

Code: [Select]
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
************************ altsyncram_component.init_file = "../osd_mem.mif",   *************************************
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = NUM_WORDS,
altsyncram_component.numwords_b = NUM_WORDS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = ADDR_SIZE,
altsyncram_component.widthad_b = ADDR_SIZE,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1",
altsyncram_component.init_file = "gpu_16K_RAM.mif";

also, make:
   .write_ena_b(1'b1),

into a
   .write_ena_b(1'b0),

Your not writing anything to ram....

The only difference I could find is this: (See red)
      // this moves the data up one word at a time, dropping the top most 8 bits
   addr_pipe[19:0]                          <= addr_mux_out;
   addr_pipe[DEMUX_PIPE_TOP*20+19:1*20]   <= addr_pipe[(DEMUX_PIPE_TOP-1)*20+19:0*20];
   
   cmd_pipe[15:0]                             <= cmd_mux_out[15:0];
   cmd_pipe[DEMUX_PIPE_TOP*16+15:1*16]      <= cmd_pipe[(DEMUX_PIPE_TOP-1)*16+15:0*16];


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 02:42:35 pm
Don't outputs from modules have to be wires?  So cmd_mux_out should be a wire that is assigned to a reg somewhere else?

Have tried this, with cmd_tmp_out being a wire on the cmd_out output of the module, and with the cmd_mux_out <= cmd_tmp_out in the always block, but still getting a black screen.
cmd_out is currently not being use, so I'm not worried about that.

Check your compiler reports and see how much 'ram' is being used...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 03:21:47 pm
Your .mif file is still wrong and it should be in the main file path.
here is what you have now:
      altsyncram_component.init_file = "../osd_mem.mif",

Code: [Select]
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
************************ altsyncram_component.init_file = "../osd_mem.mif",   *************************************
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = NUM_WORDS,
altsyncram_component.numwords_b = NUM_WORDS,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = ADDR_SIZE,
altsyncram_component.widthad_b = ADDR_SIZE,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1",
altsyncram_component.init_file = "gpu_16K_RAM.mif";

Darn it - missed the component.init setting near the top - added another at the bottom.  Beginner's mistake.   :palm:

also, make:
   .write_ena_b(1'b1),

into a
   .write_ena_b(1'b0),

Your not writing anything to ram....

Chalk that one up to confusion over active high/low signals.

The only difference I could find is this: (See red)
      // this moves the data up one word at a time, dropping the top most 8 bits
   addr_pipe[19:0]                          <= addr_mux_out;
   addr_pipe[DEMUX_PIPE_TOP*20+19:1*20]   <= addr_pipe[(DEMUX_PIPE_TOP-1)*20+19:0*20];
   
   cmd_pipe[15:0]                             <= cmd_mux_out[15:0];
   cmd_pipe[DEMUX_PIPE_TOP*16+15:1*16]      <= cmd_pipe[(DEMUX_PIPE_TOP-1)*16+15:0*16];

Okay, have removed the bit in red, but it's the same for the data_pipe as well (that specifies [7:0] and doesn't generate an error).  Still getting the same error after compilation - must be to do with outputs from the module needing to be wires.

Check your compiler reports and see how much 'ram' is being used...

According to the compilation report:

Code: [Select]
Flow Status                 Successful - Tue Nov 12 15:16:18 2019
Quartus Prime Version       18.1.0 Build 625 09/12/2018 SJ Lite Edition
Family                     Cyclone IV E
Device                     EP4CE6E22C8
Timing Models             Final
Total logic elements     168 / 6,272 ( 3 % )
Total registers             127
Total pins             10 / 92 ( 11 % )
Total virtual pins     0
Total memory bits     8,224 / 276,480 ( 3 % )
Embedded Multiplier 9-bit elements 0 / 30 ( 0 % )
Total PLLs             1 / 2 ( 50 % )

Still just a black screen...  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 03:34:11 pm
Code: [Select]
Flow Status                 Successful - Tue Nov 12 15:16:18 2019
Quartus Prime Version       18.1.0 Build 625 09/12/2018 SJ Lite Edition
Family                     Cyclone IV E
Device                     EP4CE6E22C8
Timing Models             Final
Total logic elements     168 / 6,272 ( 3 % )
Total registers             127
Total pins             10 / 92 ( 11 % )
Total virtual pins     0
Total memory bits     8,224 / 276,480 ( 3 % )
Embedded Multiplier 9-bit elements 0 / 30 ( 0 % )
Total PLLs             1 / 2 ( 50 % )

Still just a black screen...  :(
Total memory bits       8,224 / 276,480 ( 3 % ) OOOPSSSS this should be at least 131072....
The memory isn't being allocated...
Try this, all the parameters where you have NUM_WORDS = 2**ADDR_SIZE, change that to NUM_WORDS=16384.

There is another thing to try if this doesn't work.
Inside the 'altsyncram_component', hard wire the ADDR_SIZE to 14 and NUM_WORDS to 16384.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 03:43:30 pm
Okay, nothing happening still.  I've hardwired the values into the ALTSYNCRAM component, still no joy.

Here's my gpu_dual_port_ram_INTEL code:

Code: [Select]
module gpu_dual_port_ram_INTEL (

// inputs
input clk,
input [3:0] pc_ena_in,
input clk_b,
input wr_en_b,
input [19:0] addr_a,
input [19:0] addr_b,
input [7:0] data_in_b,
input [15:0] cmd_in,

// registered outputs
output reg [19:0] addr_out_a,
output reg [3:0] pc_ena_out,
output reg [15:0] cmd_out,

// direct outputs
output wire [7:0] data_out_a,
output wire [7:0] data_out_b

);

// define the maximum address bit
parameter ADDR_SIZE = 14;

// define the memory size (number of words) - this allows RAM sizes other than multiples of 2
// but defaults to power-of-two sizing based on ADDR_SIZE if not otherwise specified
parameter NUM_WORDS = 16384;

// define delay pipe registers
reg [19:0] rd_addr_pipe_a;
reg [15:0] cmd_pipe;
reg [3:0] pc_ena_pipe;

// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - ADDR_SIZE wide (14 bits default)
// Memory word size - NUM_WORDS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b0),
.address_b (addr_b[13:0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[13:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_a = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "../gpu_16K_RAM.mif",
altsyncram_component.intended_device_family = "Cyclone IV E",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 16384,
altsyncram_component.numwords_b = 16384,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 14,
altsyncram_component.widthad_b = 14,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clk) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************
rd_addr_pipe_a <= addr_a;
addr_out_a <= rd_addr_pipe_a;

cmd_pipe <= cmd_in;
cmd_out <= cmd_pipe;

pc_ena_pipe <= pc_ena_in;
pc_ena_out <= pc_ena_pipe;
// **************************************************************************************************************************

end

endmodule


Reported memory usage is still 8,224 / 276,480 (3%)  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 03:47:21 pm
way too few logic elements too:
Total logic elements       168 / 6,272 ( 3 % )
This is enough just for the sync generator and IO.

What was the logic element count when the project used to display text?


It's time to learn how to read the compiler reports, and see what is being left out.  I have a feeling it may be connected to the odd error where you placed a 'REG' to fix the bug.

Can you zip it and send a copy.  I believe it's a .html file.

Worst case, I may have to install Quartus on one of my PCs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 03:58:59 pm
Not sure what's going on here in the compilation report:

Code: [Select]
Warning (14284): Synthesized away the following node(s):
Warning (14285): Synthesized away the following RAM node(s):
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a8"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a9"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a10"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a11"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a12"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a13"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a14"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a15"

Quartus isn't saving the compilaton report as a file - there's probably a setting somewhere for it - although there is an export option in the r/click menu that doesn't seem to work.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 04:19:24 pm
Not sure what's going on here in the compilation report:

Code: [Select]
Warning (14284): Synthesized away the following node(s):
Warning (14285): Synthesized away the following RAM node(s):
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a8"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a9"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a10"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a11"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a12"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a13"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a14"
Warning (14320): Synthesized away node "vid_osd_generator:inst10|multiport_gpu_ram:gpu_RAM|gpu_dual_port_ram_INTEL:gpu_RAM|altsyncram:altsyncram_component|altsyncram_tnf2:auto_generated|ram_block1a15"

Quartus isn't saving the compilaton report as a file - there's probably a setting somewhere for it - although there is an export option in the r/click menu...
That part is just the rough overview.  You should be able to enter a complete breakdown usage report where the compiler tells you everything it has done with every file in your project.

No memory should have been simplified away.  Something fishy is happening.

Ok, try this one weird thing I used to have to do:

Inside "gpu_dual_port_ram_INTEL.v":
Code: [Select]
wire [7:0] sub_data_out_a;        // ***NEW***
wire [7:0] data_out_a = sub_data_out_a[7:0];      // ***NEW***
wire [7:0] sub_data_out_b;      // ***NEW***
wire [7:0] data_out_b = sub_data_out_b[7:0];      // ***NEW***

altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),
.address_b (addr_b[ADDR_SIZE - 1:0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[ADDR_SIZE - 1:0]),
.data_a (8'b00000000),
.q_a (sub_data_out_a),      // ***NEW******NEW******NEW******NEW***
.q_b (sub_data_out_b),      // ***NEW******NEW******NEW******NEW***
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));



ALSO:  you have not set the ".defparam" for the multiport_gpu_ram gpu_RAM() in the osd generator, though, the sub_modules should have ended up using their default values.

I'm downloading QuartusPrime 18.1 now.  How big is you project in .zip?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 05:11:44 pm
Ok, try this one weird thing I used to have to do:

Inside "gpu_dual_port_ram_INTEL.v":
Code: [Select]
wire [7:0] sub_data_out_a;        // ***NEW***
wire [7:0] data_out_a = sub_data_out_a[7:0];      // ***NEW***
wire [7:0] sub_data_out_b;      // ***NEW***
wire [7:0] data_out_b = sub_data_out_b[7:0];      // ***NEW***

Quartus freaks with those declarations - I've had to change:

Code: [Select]
wire [7:0] data_out_a = sub_data_out_a[7:0];      // ***NEW***
wire [7:0] data_out_b = sub_data_out_b[7:0];      // ***NEW***

as they're already declared as outputs.  Changed them to:

Code: [Select]
assign data_out_a = sub_data_out_a[7:0];      // ***NEW***
assign data_out_b = sub_data_out_b[7:0];      // ***NEW***

... which compiles, but still to a black screen.

ALSO:  you have not set the ".defparam" for the multiport_gpu_ram gpu_RAM() in the osd generator, though, the sub_modules should have ended up using their default values.

Yes, spotted that earlier but didn't think it'd matter as the sub-modules should use their default values.

I'm downloading QuartusPrime 18.1 now.  How big is you project in .zip?

Just over 7 MB - too big for the forum, unless I just archive the main files and ignore the sub-folders (db, greybox_tmp, incremental_db, output_files)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 06:13:31 pm
I've confirmed that the 'gpu_dual_port_ram_INTEL.v' compiles fine as it's own project.  See here:

[attach=4]
[attach=3]

As you can see, Quartus Prime reports 45% of your FPGA ram being used.

Next, I made a stand alone project with 'multiport_gpu_ram.v' as the top in it's own project, with the ''gpu_dual_port_ram_INTEL.v'' being accessed within.  See here:

[attach=2]
[attach=1]

As you can see, Quartus Prime still reports 45% of your FPGA ram being used.  So, there is nothing wrong with the 5 channel multiport module.  Next, I'll try the OSD code.

And this is with the cmd_mux_out as a 'WIRE':
Code: [Select]
wire [15:0] cmd_mux_out;

Next, I'll try the OSD module.  Things like this usually lie down with a typo, or, you forgot to 'ADD SOURCE FILES' to your project and make the top hierarchy you top .bdf file.

YUP: The error is in the OSD module.  Give me a few minutes...
[attach=5]
[attach=6]

See, we dropped to 3% ram usage.  Now, why?  Something is amiss.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 07:25:02 pm
Clearly something up with the osd module...

I have the project zipped and in a shared dropbox folder - if you pm me your email, I'll add you to it so you can download the entire project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2019, 07:27:14 pm
Found it!

In the OSD generator, I had:
Code: [Select]
assign read_text_adr[19:10] = 1'h4;
....
assign read_font_adr[19:10] = 1'h2;

When it should have been:
Code: [Select]
assign read_text_adr[19:10] = 10'h4;        // my mistake, I has 1bit instead of 10bits
......
assign read_font_adr[19:10] = 10'h2;        // my mistake, I has 1bit instead of 10bits

The compiler was shorting all the higher addresses to GND.  This means only the first [9:0] of x&y counters made it to the memory and Quartus said, hey, all other addresses are shorted to GND, so, I only need 8192 bits of ram...

There were a few other little mistakes like:
   //output reg [19:0] addr_host_out,     I never specified this port to be made...

   .wr_en_b(write_ena_b),   // **** error, you wrote (wr_en_b), it should be (write_ena_b)

   .data_out_b(data_host_out)   // ****** error, you had this field empty.

and all this wasn't updated from my earlier post:
Code: [Select]
parameter   PIXEL_PIPE = 3;  // This externally set parameter defines the number of 25MHz pixels it takes to receive a new pixel from a presented address

localparam CLK_CYCLES_MUX = 1; // adjust this parameter to the number of 'clk' cycles it takes to select 1 of 5 muxed outputs
localparam CLK_CYCLES_RAM = 2; // adjust this figure to the number of clock cycles the DP_ram takes to retrieve valid data from the read address in
localparam CLK_CYCLES_PIX = 5; // adjust this figure to the number of 125MHz clocks there are for each pixel, IE number of muxed inputs for each pixel

//  This parameter begins with the wanted top number of 125Mhz pixel clock headroom for the pixel pipe, then subtracts the additional 125MHz clocks used by the _MUX and _RAM cycles used to arrive at the first pixel out, DEMUX_PIPE_TOP position.
localparam  DEMUX_PIPE_TOP    =  (( (PIXEL_PIPE - 1) * CLK_CYCLES_PIX ) - 1) - CLK_CYCLES_MUX - CLK_CYCLES_RAM;

localparam MUX_0_POS = DEMUX_PIPE_TOP - 0;  // pixel offset positions in their respective synchronisation
localparam MUX_1_POS = DEMUX_PIPE_TOP - 1;   // pipelines (where the pixels will be found in the pipeline
localparam MUX_2_POS = DEMUX_PIPE_TOP - 2;   // when pc_ena[3:0]==0).
localparam MUX_3_POS = DEMUX_PIPE_TOP - 3;   //
localparam MUX_4_POS = DEMUX_PIPE_TOP - 4; //

// Now that we know the DEMUX_PIPE_TOP, we can assign the top size of the 3 pipe regs

reg [DEMUX_PIPE_TOP*8+7:0] data_pipe;
reg [DEMUX_PIPE_TOP*20+19:0] addr_pipe;
reg [DEMUX_PIPE_TOP*16+15:0] cmd_pipe;

always @(posedge clk) begin

// We also need to limit the pipe in the 3 ' <= '

data_pipe[7:0]                     <= data_mux_out[7:0]; // fill the first 8-bit word in the register pipe with data from RAM
data_pipe[DEMUX_PIPE_TOP*8+7:1*8]    <= data_pipe[ (DEMUX_PIPE_TOP-1) *8+7:0*8]; // shift over the next 9 words in this 10 word, 8-bit wide pipe
// this moves the data up one word at a time, dropping the top most 8 bits
addr_pipe[19:0]                   <= addr_mux_out;
addr_pipe[DEMUX_PIPE_TOP*20+19:1*20] <= addr_pipe[ (DEMUX_PIPE_TOP-1) *20+19:0*20];

cmd_pipe[15:0]                       <= cmd_mux_out[15:0];
cmd_pipe[DEMUX_PIPE_TOP*16+15:1*16]    <= cmd_pipe[ (DEMUX_PIPE_TOP-1) *16+15:0*16];

I've attached the latest verilog files for you to use.  Also don't forget to update our top block diagram file with the OSD generator's new pipeline delay as it may still be 4.  It might be best to re-generate symbol files and clear & re-insert the OSD generator in you block diagram to clear out any old junk.

There is only the matter of patching your 'mux' in the multiport ram module, however, you should now be getting a picture.  If so, I'll explain the patch and everything should work.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2019, 08:30:30 pm
Found it!

Well done!  :clap:

...I've attached the latest verilog files for you to use.  Also don't forget to update our top block diagram file with the OSD generator's new pipeline delay as it may still be 4.  It might be best to re-generate symbol files and clear & re-insert the OSD generator in you block diagram to clear out any old junk.

No worries, all done.  Was so excited I rushed to see it working and got the black screen again...

There is only the matter of patching your 'mux' in the multiport ram module, however, you should now be getting a picture.  If so, I'll explain the patch and everything should work.

Nope - no picture - still just a black screen.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 07:42:29 am
@nockieboy,  :scared: I'M GONNA MURDER YOU!!!!!!!  |O  :horse:  :rant:  :box:

Ok, you are god damn lucky I still have a Quartus 9.1 full install, with it's built in high speed logic simulator.

Let's begin.
Step 1. Simulate the 'gpu_dual_port_ram_INTEL.v'.
I made a project with only the ram with the .mif file like so:
[attach=1]
I setup a simulation feeding the above inputs to see what the outputs would look like when beginning the read address just before the ASCII text begins where you have stored 0,1,2,3,4,5,...:
[attach=2]
So far, the read of the data looks fine.

Step 2. Simulate the 'multiport_gpu_ram.v'.
I made the project feed the clock, ena, all 4 addresses, all 4 cmds, even the 'host' address & it's read results.  (I used a 484 pin Cyclone III to get the IOs)
See in green the 'host' address wiring is taken from the second addr_in.
[attach=3]
This is what the simulator gave me.
[attach=4]
WTF?  Addr ports 1 and 2 seem read to data out properly, yet, the reading of port addr4' data out has all 0s.  Also, a weird thing, the 'HOST' data out, which is also fed the addr2 reads the right data, BUT, it suddenly goes 'UU' (undefined), then goes back to 0.

Without that 'HOST' data out, seeing the data being erased, I would have never found the bug.
In you code, you have:
Code: [Select]
// ****************************************************************************************************************************
// Dual-port GPU RAM
//
// Port A - read only by GPU
// Port B - read/writeable by host system
// Data buses - 8 bits / 1 byte wide
// Address buses - ADDR_SIZE wide (14 bits default)
// Memory word size - NUM_WORDS (16384 bytes default)
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clock0 (clk),
.wren_a (1'b1),  ************************F--K******************
.address_b (addr_b[ADDR_SIZE - 1:0]),
.clock1 (clk_b),
.data_b (data_in_b),
.wren_b (wr_en_b),
.address_a (addr_a[ADDR_SIZE - 1:0]),
.data_a (8'b00000000),
.q_a (data_out_a),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));

defparam
            .wren_a (1'b1),  **********F--K***********

You made the Write Enable for the read address forced on!!!!!!!!
Every address we sent to be read was instead written clear to all 0's.

It gets worse, in you mux algorithm in the 'multiport_gpu_ram.v' module, you did this:
Quote
   // perform 5:1 mux for all inputs to the dual-port RAM
   case (pc_ena_in[2:0])
      3'b000 : begin  //******** Excellent, this is state 0 and you made the case 3'b000 which equals 0.
                  addr_in_mux <= addr_in_0;
                  cmd_mux_in <= cmd_in_0;
               end
      3'b001 : begin  //******** Excellent, this is state 1 and you made the case 3'b001 which equals 1.
                  addr_in_mux <= addr_in_1;
                  cmd_mux_in <= cmd_in_1;
               end
      3'b011 : begin  //******** Hun? What? This is state 2 and you made the case 3'b011 which equals 3?
                  addr_in_mux <= addr_in_2;
                  cmd_mux_in <= cmd_in_2;
               end
      3'b100 : begin  //******** Hun? What? This is state 3 and you made the case 3'b100 which equals 4?
                  addr_in_mux <= addr_in_3;
                  cmd_mux_in <= cmd_in_3;
               end
      3'b101 : begin  //******** Hun? What? This is state 4 and you made the case 3'b101 which equals 5?
                  addr_in_mux <= addr_in_4;
                  cmd_mux_in <= cmd_in_4;
               end
   endcase

After these 2 fixes, the simulation looks like this:
[attach=5]
This is a zoom out of the simulation.  As you can see, I'm reading 5 different ports at 5 different addresses simultaneously, with all the outputs coming in parallel.
[attach=6]

Now, for the last little bit.  When performing the 'mux' the only addition I wanted to do was 'snap' all the address_# and cmd_# inputs at (pc_ena_in==0), then feed those latched results to the ram.  To do this, here is the simple addition I made to your 'case' statement in the 'mux'.
Code: [Select]
case (pc_ena_in[2:0])
3'b000 : begin
addr_in_mux <= addr_in_0;  // Send the first, #0 addr & cmd to the memory module.
cmd_mux_in <= cmd_in_0;

addr_lat_1 <= addr_in_1;  // latch all addr_in_# in parallel
addr_lat_2 <= addr_in_2;
addr_lat_3 <= addr_in_3;
addr_lat_4 <= addr_in_4;

cmd_lat_1  <= cmd_in_1;  // latch all cmd_in_# in parallel
cmd_lat_2  <= cmd_in_2;
cmd_lat_3  <= cmd_in_3;
cmd_lat_4  <= cmd_in_4;

end
3'b001 : begin
addr_in_mux <= addr_lat_1; //  Send the latched, #1 addr & cmd to the memory module.
cmd_mux_in  <= cmd_lat_1;
end
3'b010 : begin   
addr_in_mux <= addr_lat_2; //  Send the latched, #2 addr & cmd to the memory module.
cmd_mux_in  <= cmd_lat_2;
end
3'b011 : begin   
addr_in_mux <= addr_lat_3; //  Send the latched, #3 addr & cmd to the memory module.
cmd_mux_in  <= cmd_lat_3;
end
3'b100 : begin   
addr_in_mux <= addr_lat_4; //  Send the latched, #4 addr & cmd to the memory module.
cmd_mux_in  <= cmd_lat_4;
end
endcase

I've attached the latest source verilog files.  Setting up 2 different Quartus' and preparing the simulation stimulus, plus finding that "Write Enable = 1" was a good 5 hours out of my day.

If you don't get a picture now, I will have no choice but to simulate your entire OSD project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 08:03:33 am
@nockieboy, go here:

Code: [Select]
https://www.intel.com/content/www/us/en/programmable/downloads/software/quartus-ii-we/91sp2.html
And download QuartusII V9, sp2 and install it.  Don't worry, you can have 2 different Quartuses in your system at 1 time.

We'll use it's built in 'Quick' simulator tool to create the graphics address generator as we do not want to create the same hidden problem as above.

Note that you'll just use that Quartus to edit and simulate your verilog.v file, selecting a huge IO pincount Cyclone III, while you may use Quartus Prime to build your chip, or, that Quartus as it does support Cyclone IV, just not with simulation support.

I don't have time to teach you how to use the new Modelsim and the old abandoned forgotten built in Quartus simulator is just too fast and easy to setup/manipulate inputs and compile instantly when in 'Functional' logic mode.  Yes, the timing mode is still very quick for a small project like yours.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 08:37:38 am
Ooops, 1 typo: In 'vid_osd_generator.v', fix this one line #99:
------------------------------------------------
         gpu_RAM.PIXEL_PIPE = 2;    // set the length of the pixel pipe to offset multi-read port sequencing
------------------------------------------------
It said gpr_RAM instead of gpu_RAM.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2019, 09:26:43 am
@nockieboy,  :scared: I'M GONNA MURDER YOU!!!!!!!  |O  :horse:  :rant:  :box:

 :-[

Let's begin...

...You made the Write Enable for the read address forced on!!!!!!!!
Every address we sent to be read was instead written clear to all 0's.

:palm: So sorry about the write enable setting.  That's because I'm used to LOWs being the active state with all the Z80 work I've been doing recently - I have to stop and check every time I look at a 1'b0 or 1'b1 now.  ::)   |O

Thank you for persevering and finding the issues.

It gets worse, in you mux algorithm in the 'multiport_gpu_ram.v' module, you did this:
Quote
   // perform 5:1 mux for all inputs to the dual-port RAM
   case (pc_ena_in[2:0])
      3'b000 : begin  //******** Excellent, this is state 0 and you made the case 3'b000 which equals 0.
                  addr_in_mux <= addr_in_0;
                  cmd_mux_in <= cmd_in_0;
               end
      3'b001 : begin  //******** Excellent, this is state 1 and you made the case 3'b001 which equals 1.
                  addr_in_mux <= addr_in_1;
                  cmd_mux_in <= cmd_in_1;
               end
      3'b011 : begin  //******** Hun? What? This is state 2 and you made the case 3'b011 which equals 3?
                  addr_in_mux <= addr_in_2;
                  cmd_mux_in <= cmd_in_2;
               end
      3'b100 : begin  //******** Hun? What? This is state 3 and you made the case 3'b100 which equals 4?
                  addr_in_mux <= addr_in_3;
                  cmd_mux_in <= cmd_in_3;
               end
      3'b101 : begin  //******** Hun? What? This is state 4 and you made the case 3'b101 which equals 5?
                  addr_in_mux <= addr_in_4;
                  cmd_mux_in <= cmd_in_4;
               end
   endcase

:palm:  I can count in binary, honest!  :-[

It's really difficult for me to maintain a good focus on this when I'm working around it, doing bits here and there, then coming back to it later.  I can only mark this mistake up to some earlier code I'd written when I made case statements for all 8 combinations of the 3-bit pc_ena value, before you reminded me that it resets at 4, and not checking the conditions when I deleted the extra states.

Okay, I've made the additions to the code, fixed the stupid errors, and almost got it to compile.  :o

In vid_osd_generator.v:

Code: [Select]
defparam gpu_RAM.ADDR_SIZE = 14, // pass ADDR_SIZE into the gpu_RAM instance
         gpu_RAM.PIXEL_PIPE = 2; // set the length of the pixel pipe to offset multi-read port sequencing

I was getting negative indexes in the demux pipe in multiport_gpu_ram.v.  The pipeline wasn't deep enough, so I upped gpu_RAM.PIXEL_PIPE value to 3 and it compiles now.

This is what I'm getting on the screen now...

[attach=1]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2019, 10:25:38 am
Here's my workspace:

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 10:52:11 am
Don't threat too bad, FPGAs are a new experience for those who buy CPU and wire and software program them.
- get used to wiring everything as POSITIVE logic.
- if you want a negative input or output, place an 'EXP' by the final pin.
- if you can't count binary eg " 4'b1010 ", instead use hex " 4'h0A " or decimal " 4'd10' ".


There were numerous other errors.  Today has turned into a non-stop 10 hour debug fest.  Nothing wrong with the architecture, it's just when I correcting what you have written, I have no experience on how you typed everything in.

Here is why your text is scrambled:
------------------------------------------------------------
   .addr_in_0(read_font_adr[19:0]),
   .addr_in_1(read_text_adr[19:0]),
-------------------------------------------------------------
The text and font was backwards.


This is what my full simulation setup looks like (Yes, full OSD output now.)
[attach=1]
[attach=2]

There were a few other little patches.  Please don't change any of the pixel pipe settings until we get clean text.  A pipe error would just shave a pixel on one side of the letters.


Now, I've attached my Quartus project to see if it opens in Prime.
To make it work on you PCB, all you need to do is change the FPGA to your FPGA IC#, enter the pin numbers. (Delete my test unused IOs), and add a PLL.  You can always install QuartusIIv9sp2 since it supports Cyclone IV, and, it's a lot faster.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 11:08:29 am
I just opened my 'GPU_OSD_Sim_q2v9.zip ' project in Quartus Prime 18.1.
[attach=1]
During the open, it asks you to switch to a Cyclone IV or Max10 FPGA chip.
On the top hierarchy, only the parameter boxes need to be adjusted in size to show all the variables due to the system font being different.

Lets work with this version as it is a clean virgin with no old crap lingering around.
(You can tell by the .zip file size.)

Don't forget to set your IO pins and add a PLL to get 125MHz.

LOL, QuartusIIv9sp2 = 15 seconds for compile.
        Quartus Prime  = 40 seconds for compile.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 12:02:38 pm
Ive added the PLL and changed the project to a Cyclone IV IC, I believe it's the one on your dev board.
You still need to assign the IO pins.
I also setup the timing analyzer so it give you valid results.

Do not worry that I set the clock to 54Mhz, technically, you are just slightly under-clocking the design for now, but the PLL has been setup so that our builds are capable of driving DDR-IOs to transmit a home built HDMI serdes directly.

LOL, my architecture is so well laid out, even though we asked for 135MHz, quartus says it can achieve 238MHz, and this is on a -c8, the slowest version of the FPGA.

LOL, the C6 with my code will run at 315MHz....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2019, 12:06:11 pm
Ookay... switched to the clean project now, added a PLL and just had to change a timing error in the sync generator on line 67:

Code: [Select]
if (pc_ena[3:2] == 0) // once per pixel

... was too slow for the monitor - changed it to pc_ena[2:0] and I'm getting this picture now:

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 12:27:16 pm
Ookay... switched to the clean project now, added a PLL and just had to change a timing error in the sync generator on line 67:

Code: [Select]
if (pc_ena[3:2] == 0) // once per pixel

... was too slow for the monitor - changed it to pc_ena[2:0] and I'm getting this picture now:

(Attachment Link)

Arrrrgggg this:
   if (pc_ena[3:2] == 0)   // once per pixel
Everywhere????
How????

Ok, patching everything...
Here is the patched project.
When uploading you latest xxxx.v files on the forum, please make sure they are actually the latest versions.
I feel as if I'm revisiting errors patched long ago...

Now, I hope the text come out correct.  The simulation on my side has the right horizontal size for the text box.  Only an addressing error on the font address would mean garbled up letters (since I only get an oscilloscope waveform), or, the conversion from the 8bit wide font into a 1 bit pixel.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 12:33:31 pm
Ookay... switched to the clean project now, added a PLL and just had to change a timing error in the sync generator on line 67:

Code: [Select]
if (pc_ena[3:2] == 0) // once per pixel

... was too slow for the monitor - changed it to pc_ena[2:0] and I'm getting this picture now:

(Attachment Link)
Look carefully, your Microcom text is there, it's just the FONT which isn't being rendered properly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2019, 04:32:52 pm
Again, half old code, half new code error.....

This code was hald the original Atari 2 bit font and half the 8bit atari font code squished together.
Code: [Select]
assign font_pos[12:6]   = letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0] = dly3_disp_y[3:1] ;  // select the font x coordinate with a 2 pixel clock DELAYED disp_x address.  [3:1] is used so that every 2 x lines are repeats
assign font_pos[5:3] = dly3_disp_y[3:1] ;  // select the font y coordinate with a 2 pixel clock DELAYED disp_y address.  [3:1] is used so that every 2 y lines are repeats
It should be this way, and you had it this way since you were able to display the red text:
Code: [Select]
assign font_pos[9:3]   = letter[6:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2:0] = dly3_disp_y[3:1] ;  // select the font x coordinate with a 2 pixel clock DELAYED disp_x address.  [3:1] is used so that every 2 x lines are repeats

Please, Please, Please, when doing corrections, please post you latest updates.  It's taking hours to find something I though was already working just to find that the last xxxxx.v source code you posted has bugs in it, yet you had a fine picture back with the 8bit Atari font in red...

Please be more careful in the future.  I should not be fixing these problems as I feel like I'm giving you wrong directions, yet my layout is fine.

From now on, lets star using revision numbers and dates for each verilog module.  The next stuff coming up isn't as huge, but a single mistake to our existing code will lead to hours of debugging not knowing where the problem originates.

(This took hours to proof by simulation....)
Make this attachment your new project and if it works and you are ready, we will tackle the universal pixel pointing read address generator.

(If everything works and you are waiting for me, think about getting the 4 bit RGB dac working...)
Also, install:
Code: [Select]
https://www.intel.com/content/www/us/en/programmable/downloads/software/quartus-ii-we/91sp2.htmlYour going to need it for engineering the address generator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2019, 07:03:50 pm
Okay, got the new project working, code is up on github (https://github.com/nockieboy/gpu) - but I'll only update that repo with working commits.

I'm with you on the versioning - it will clear up confusion with all these updates and corrections.

(This took hours to proof by simulation....)

:palm:

Make this attachment your new project and if it works and you are ready, we will tackle the universal pixel pointing read address generator.

 :phew: It works...

[attach=1]

(If everything works and you are waiting for me, think about getting the 4 bit RGB dac working...)

This might have to wait a day or so, depending on how much free time I have tomorrow.

Also, install:
Code: [Select]
https://www.intel.com/content/www/us/en/programmable/downloads/software/quartus-ii-we/91sp2.htmlYour going to need it for engineering the address generator.

I'm having real trouble downloading that package - seems the download link is broken?  :palm:  I'll keep working at it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 13, 2019, 07:16:19 pm
Wow, BrianHG has been really helpful and really patient...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2019, 07:21:05 pm
Wow, BrianHG has been really helpful and really patient...

I feel bad enough as it is.  :'(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 01:59:14 am
Here nockieboy, and to anyone else who wants a copy of '91sp2_quartus_free.exe' install.
91sp2_quartus_free.rar (https://wetransfer.com/downloads/41dd4f099fc3c6d56349c140da21297420191114010918/8874200f4f97784caa401b21626d967620191114010918/a83338)
(The file will be at this link for only 7 days.)

It's the official Windows download version, just after the point when Altera removed the licensing features.
Note that you should still use the new Quartus Prime USB Blaster Drivers especially with Windows 10.
Both Quartus can be installed in one system and they can both run at the same time.
When simulating your verilog code, in QuartusIIv9, you need to select a CycloneIII or earlier FPGA.  Cyclone IV will compile for the chip, but will not simulate.
Making small dedicated projects to test out each xxxx.v core before adding them to your main project is the norm.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 02:10:24 am
Wow, BrianHG has been really helpful and really patient...

I feel bad enough as it is.  :'(
For the new year, I'm leaving electronic engineering and heading into management.  I'll never have time left to do electronic ever again.  Since I'm currently at the last of my free time, I figured, I'm going to do 1 last special thing, and 'nockieboy' hit the jackpot.  I don't know who he's going to sell of push this little core to, but, It will be capable of doing more than a SuperNintendo and quite a bit towards a full VGA card, up to 720x480 modes, memory dependent.  I hope he is ready for documenting all the function controls which are coming up next, making a board with HDMI (DVI) out, and perhaps we might have time for stereo 16 channel sound too.  All by January....

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 04:35:05 am
Just found a source code for a HDMI serializer with audio support!.
https://www.realdigital.org/doc/189f72e0ee822643d7946fb639754841 (https://www.realdigital.org/doc/189f72e0ee822643d7946fb639754841)

It's good as a guide, but we don't want realdigital.org copyright (We are allowed to use it if we give credit & ask permission), and the final verilog output module uses Xilinx specific serdes function.  It's enough to work with to create a 480p version which uses non-dedicated serdes hardware and will compile on all FPGA vendor suites.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 05:08:03 am
Lattice FPGA part numbers price VS ram:

4 megabit / 512kb for 30$ usd, 26.60$ for 25.  (actual 400 kilobytes realistically.)
LFE5U-85F-6MG285C (https://www.mouser.com/ProductDetail/Lattice/LFE5U-85F-6MG285C?utm_term=LFE5U-85F&qs=Rp3RbKSfAt3i%252b4nmoAgpiw==&utm_campaign=LFE5U-85F-6MG285C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice)
(LOL, with an added flash card reader port added to the FPGA, your GPU could playback full motion 360x480 video with 65k colors...)

2 megabit / 256kb for 16$ usd.    (actual 200 kilobytes realistically.)
Unfortunately, not pin-pin compatible with the 4mbit version.
LFE5U-45F-6BG256C (https://www.mouser.com/ProductDetail/Lattice/LFE5U-45F-6BG256C?utm_term=LFE5U-45F-6&qs=w%2Fv1CP2dgqpblS%252b2xYE99A%3D%3D&utm_campaign=LFE5U-45F-6BG256C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice)
(360x240 65k color full motion video possible with an accelerated flash card reader.)

Strangely enough, these are the faster -6 grade, not the slowest -8 grade versions of the chips.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 08:54:41 am
For the new year, I'm leaving electronic engineering and heading into management.  I'll never have time left to do electronic ever again.  Since I'm currently at the last of my free time, I figured, I'm going to do 1 last special thing, and 'nockieboy' hit the jackpot.  I don't know who he's going to sell of push this little core to, but, It will be capable of doing more than a SuperNintendo and quite a bit towards a full VGA card, up to 720x480 modes, memory dependent.  I hope he is ready for documenting all the function controls which are coming up next, making a board with HDMI (DVI) out, and perhaps we might have time for stereo 16 channel sound too.  All by January....

Well, first of all, thank you.  :-+  Secondly, it's a hobby project that started out as an attempt to learn about electronics and broaden my programming skills - it has clearly ballooned into something much bigger than anything I could have wished for at the start.  :o  I'm not intending to sell anything - I seriously doubt I could make a living (or even some pocket money) from what I've developed, but I do want to get my act together and create a website that will document my journey and help anyone else out wanting to try the same thing.

My original end goal, simple as it was (on the face of it  :o ), was to create a little 8-bit system I can plug into my TV and play some games I've written for it, like Pong or a Rogue-like - with better specs than my first computer I had as a kid.  The GPU (and sound, I guess) is the last part of the puzzle, really.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 09:08:31 am
Lattice FPGA part numbers price VS ram:

4 megabit / 512kb for 30$ usd, 26.60$ for 25.  (actual 400 kilobytes realistically.)
LFE5U-85F-6MG285C (https://www.mouser.com/ProductDetail/Lattice/LFE5U-85F-6MG285C?utm_term=LFE5U-85F&qs=Rp3RbKSfAt3i%252b4nmoAgpiw==&utm_campaign=LFE5U-85F-6MG285C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice)
...
2 megabit / 256kb for 16$ usd.    (actual 200 kilobytes realistically.)
Unfortunately, not pin-pin compatible with the 4mbit version.
LFE5U-45F-6BG256C (https://www.mouser.com/ProductDetail/Lattice/LFE5U-45F-6BG256C?utm_term=LFE5U-45F-6&qs=w%2Fv1CP2dgqpblS%252b2xYE99A%3D%3D&utm_campaign=LFE5U-45F-6BG256C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice)
(360x240 65k color full motion video possible with an accelerated flash card reader.)

Strangely enough, these are the faster -6 grade, not the slowest -8 grade versions of the chips.

Those Lattice chips are quite tempting. So it looks like I need to start getting my head around designing for and soldering BGA packages, as that's the way the GPU card is going, it seems.  Whilst the MAX10 is very desirable in terms of features and simplicity, the cost is prohibitive.

(LOL, with an added flash card reader port added to the FPGA, your GPU could playback full motion 360x480 video with 65k colors...)

Sheesh, you're kidding, right?  I knew using an FPGA for the graphics was going to be overkill, but that takes the biscuit!  :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 09:15:00 am
Ok, next step, not only will you want to simulate test, but, you will want to actually modify memory while running the GPU.  Do you have any means of doing this?

Which CycloneIV dev board are you using?  Do you have schematics of it?  Is there a way to interface with it?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 09:22:04 am
Ok, next step, not only will you want to simulate test, but, you will want to actually modify memory while running the GPU.  Do you have any means of doing this?

Which CycloneIV dev board are you using?  Do you have schematics of it?  Is there a way to interface with it?

I'm using one of these:

[attachimg=1]

Have found some good resources here for it: http://fpga.redliquid.pl (http://fpga.redliquid.pl)

Have attached a file called VGA Schematic.pdf.  It seems to show extra connections for more VGA colour resolution?  Hmm.. seems that's an add-on module, perhaps.  There's certainly no resistor networks on the board...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 10:02:52 am
Next is the address generator/graphics instruction engine.

Here are the targeted controls/capable features:  (We want to make 1 identical algorithm which will be used 4 times.)

1) Enable/disable.  Requires 1 bit.

2) The base/beginning of a memory address which contains either the screen text data, font data, graphics data and sprite data.  (This eats 20 bits since we can address 1 megabyte for this address)

3) Vertical memory increment size.  When beginning a new line, this is the amount added every time to the base address.  (16 bits is fair, maximum 64kb wide picture.)

4) Pixel type.  1bit=8 pixels wide per byte 2 colors per pixel,
                       2bit=4 pixels per byte 4 colors per pixel,
                       4bit=2 pixels per byte 16 colors,
                       8bit=1 pixel per byte, 256 colors,
                      16bit=2 bytes per pixel, 65k true-color
          = 5 settings possible meaning requires 3 bits for this setting.

5)  X scale.  Counts the number of pixels wide each bitmap image pixel will occupy.  1 through 16 (4 bits)

6)  Y scale.  Counts the number of lines each bitmap image line  will occupy.  1 through 16 (4 bits)

7) Sub-pixel starting X&Y coordinates.  This setting vertically & horizontally shifts the image up and to the left by single pixels in text mode and 4/2/1 bit color modes.  IE, smooth scrolling of text horizontally by up to 7/8th of 1 character, then you can change the base memory address by 1 character and reset this setting back to 0 allowing you to move the text pixel by pixel horizontally and vertically. The shift 16 pixels x by 16 pixels y , or 8 bits total.

8 )  Special control for font size.  8x8 pixel bitmap to 16x16 bitmap.  4 bit control.

9)  Total number of video lines to render before loading a new set of the above controls.  This will allow you to switch video modes mid screen, EG: have a window of 40 column text for half the screen, then switch to 80 column text for the bottom half.

Have I missed anything.  The total here is around 14 control bytes, or, we will reserve 16 bytes per address generator and call it safe.

Extra Note: The horizontal and vertical windows and enables for the 16 sprites will be stored separately.  10bit X 10 bit Y.
Palettes also have a dedicated separate set of registers.  A programmable interrupt generator based on a selected line of video will also be added for smooth animation apps.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 10:08:53 am
Ok, next step, not only will you want to simulate test, but, you will want to actually modify memory while running the GPU.  Do you have any means of doing this?

Okay, so this is the Z80<->GPU interface.  I'll need a block of logic in the GPU that responds to memory reads in the desired address range and passes the data from the GPU RAM to the host, and accepts writes to the desired address range and updates the GPU RAM with the written data.  This may take a little time and trial-and-error to build, but I'll get right on it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 10:10:39 am
Oh, I see you have RS232.  Good.  Do you have terminal software on you PC?

I can stuff together an ultra stupid bridge to your HOST_ram port so you may set memory contents.
Can you create a dumb utility on your PC to read and write binary to the com port in a format I will describe?

Let's face it, once the stuff I listed above begins to function, immediately, you will want to test and play beyond just seeing a simulation and static tests once every Quartus compile and you can work on a PC making test scripts.

Note if you do not hace any programming language on your PC, if you can program Basic, I have a free 64bit basic compiler which can access the com port.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 10:24:29 am
Next is the address generator/graphics instruction engine.

Here are the targeted controls/capable features:  (We want to make 1 identical algorithm which will be used 4 time.)

1) Enable/disable.  Requires 1 bit.

2) The base/beginning of a memory address which contains either the screen text data, font data, graphics data and sprite data.  (This eats 20 bits since we can address 20mbytes for this address)

3) Vertical memory increment size.  When beginning a new line, this is the amount added every time to the base address.  (16 bits is fair, maximum 64kb wide picture.)

4) Pixel type.  1bit=8 pixels wide per byte 2 colors per pixel,
                       2bit=4 pixels per byte 4 colors per pixel,
                       4bit=2 pixels per byte 16 colors,
                       8bit=1 pixel per byte, 256 colors,
                      16bit=2 bytes per pixel, 65k true-color
          = 5 settings possible meaning requires 3 bits for this setting.

5)  X scale.  Counts the number of pixels wide each bitmap image pixel will occupy.  1 through 16 (4 bits)

6)  Y scale.  Counts the number of lines each bitmap image line  will occupy.  1 through 16 (4 bits)

7) Sub-pixel starting X&Y coordinates.  This setting vertically & horizontally shifts the image up and to the left by single pixels in text mode and 4/2/1 bit color modes.  IE, smooth scrolling of text horizontally by up to 7/8th of 1 character, then you can change the base memory address by 1 character and reset this setting back to 0 allowing you to move the text pixel by pixel horizontally and vertically. The shift 16 pixels x by 16 pixels y , or 8 bits total.

8 )  Special control for font size.  8x8 pixel bitmap to 16x16 bitmap.  4 bit control.

9)  Total number of video lines to render before loading a new set of the above controls.  This will allow you to switch video modes mid screen, EG: have a window of 40 column text for half the screen, then switch to 80 column text for the bottom half.

Have I missed anything.  The total here is around 14 control bytes, or, we will reserve 16 bytes per address generator and call it safe.

No, it sounds like you've covered everything and more besides.  :o

This (multiple) address generator/graphics instruction engine (let's follow in the footsteps of the Amiga architects and call it MAGGIE - jhpadjustable will be proud  ;D ) - if this is going to handle graphics as well as (tiled) text modes, would this be where we'd want to consider adding hardware-accelerated drawing commands?  i.e. the host could pass a command, say 'FILL', 'LINE', 'BOX' or 'CIRCLE', and a parameter or two and MAGGIE would fill the GPU RAM according to that command and parameters?  If so, is 16 control bytes enough?  Am I getting ahead of myself?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 14, 2019, 10:33:00 am
There is a "JTAG to Avalon MM bus" block provided by Quartus for doing exactly this.

You instantiate the block inside the FPGA and then use TCL scripting in Quartus to issue read and write commands to it. I used it a few times to exercise some peripherals on a bus, but my bus was Avalon based to begin with so it worked out of the box. If you have a different bus type (Like a Z80) you need to build a adapter for it. Also TCL is not that great of a language in my opinion.

Tho building your own UART and a simple protocol parser for it is a pretty good exercise in HDL. It also lets you easily write PC software in any language you like since serial ports are easy to use under Windows or Linux in all the common programing languages. Just make sure that the UART protocol is really simple so that the FPGA can parse it without much work. It will also probably also  come in very useful once you have your Z80 running since you can use it as a debug interface into your GPU, Especially if you write a nice tool that displays the state of memory registers and a hex editor to roam around video RAM.

In principle it could also have the debug interface tell the FPGA to single step the Z80 trough gating its clock or holding the wait line. But if you wanted to live debug the Z80 a better solution is getting some Z80 ICE system to put a "Emulated Z80" into the socket and get all of the real time debugging functionality like seeing all the CPU registers
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 10:35:02 am
Oh, I see you have RS232.  Good.  Do you have terminal software on you PC?

I use PuTTY to access my Microcom at the moment via a USB-TTL interface (FT232) on the Microcom itself - but I don't have a RS232<->USB adapter, so the RS232 port is a little useless on the FPGA board as I have no way of using it.

I can stuff together an ultra stupid bridge to your HOST_ram port so you may set memory contents.

I was going to wire up the Microcom to the FPGA and get access to the RAM that way, as it would mostly just require the electrical connection between the two systems and some logic in the FPGA to read the memory accesses from the Microcom.  I could POKE data into the FPGA with no software development necessary, or even get it sending console output to the FPGA with a little tweaking of the BIOS/monitor software.

The FPGA board has a USB connector on it that I use to power the board - not sure that would be a viable alternative route?

Can you create a dumb utility on your PC to read and write binary to the com port in a format I will describe?

Yes - might take a little trial and error, but that's how I program, it seems.  ::)

Note if you do not hace any programming language on your PC, if you can program Basic, I have a free 64bit basic compiler which can access the com port.

I use C# in Visual Studio 2017 on the (rare) occasions  I need to do something in a language other than Z80 assembly, PHP or Javascript.

EDIT:  re: the Z80<->GPU interface, the one complicating factor I keep forgetting about is the level conversion.  Going to need a breadboard with a few chips on it to convert between 5v and 3.3v...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 10:49:53 am

No, it sounds like you've covered everything and more besides.  :o

This (multiple) address generator/graphics instruction engine (let's follow in the footsteps of the Amiga architects and call it MAGGIE - jhpadjustable will be proud  ;D ) - if this is going to handle graphics as well as (tiled) text modes, would this be where we'd want to consider adding hardware-accelerated drawing commands?  i.e. the host could pass a command, say 'FILL', 'LINE', 'BOX' or 'CIRCLE', and a parameter or two and MAGGIE would fill the GPU RAM according to that command and parameters?  If so, is 16 control bytes enough?  Am I getting ahead of myself?
     Nope, lateron you might make a graphics co-processor which will share the HOST memory interface.  It should be able to fill or draw 130 million 8 bit pixels a second, or, copy 65 million pixels a second, with a transparent color.  (IE Software sprites)  This one would roast anything the Amiga AGA chipset can do when in 256 color mode, or, any color mode.  Expect the Lattice FPGA to double this speed.  This wont be register control based, rather it would be a script of instructions gathered from system memory.  I would engineer it to operate this way so you may have a compiled script screen elements to render in multiple tight strings of bytes which your CPU can request it to run.
     Realtime scaling of images during the copy is possible, but, you wont get there using simple QuartusIIv9.1 as a simple simulation tool.  You will need to learn how to use Modelsim and deal with M.N floating point math in verilog.  I've done it on my video scaler and you are talking about a serious commitment, like a month or 2 just learning how to use Modelsim effectively, (this will be the most boring month of your life, I avoided it) at your beginner level.   Especially when trying to maintain that high FMAX which is needed to fill pixels as fast as possible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 11:05:02 am
Oh, I see you have RS232.  Good.  Do you have terminal software on you PC?

I use PuTTY to access my Microcom at the moment via a USB-TTL interface (FT232) on the Microcom itself - but I don't have a RS232<->USB adapter, so the RS232 port is a little useless on the FPGA board as I have no way of using it.
Ok, so yes, you do have a serial interface.  Yes?  Doesn't matter, as long as you can make your PC talk to the board, right?

If so, let's see what I come up with.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 11:14:31 am
Erm... I thought Quartus II had some way of updating FPGA memory while it was on...?  Found this - not sure if this is of any use at all?

In-System Updating of Memory and Constants (http://ridl.cfd.rit.edu/products/manuals/Altera/In-System%20Memory%20Content%20Editor/qts_qii53012.pdf)

Perhaps it only works with single-port memory, but for the purposes of testing we could scrub the host port to the RAM and give Quartus II access to the RAM that way?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 14, 2019, 11:28:43 am
Erm... I thought Quartus II had some way of updating FPGA memory while it was on...?  Found this - not sure if this is of any use at all?

In-System Updating of Memory and Constants (http://ridl.cfd.rit.edu/products/manuals/Altera/In-System%20Memory%20Content%20Editor/qts_qii53012.pdf)

Perhaps it only works with single-port memory, but for the purposes of testing we could scrub the host port to the RAM and give Quartus II access to the RAM that way?

Yeah you can also do those for editing things that are memory blocks. It looks like its fully TCL scriptable too. Tho it will likely eat up one port on a dual port RAM block, so if you still need them being dual port in your design that might be an issue.

Also you will most likely keep hardware configuration registers as normal register rather than block RAM. Those won't show up in the memory editor. So the best universal way that works for everything is injecting read and write commands just like the Z80 would. It also inherently tests tests things are accessible at the right addresses since its accessing them in the same way the Z80 would.

Or if you want to be really authentically oldschool with this project you can wire up the address bus to switches and have LEDs show bits like it did on the Altair computer. ;D Just joking, some things are best left in the past.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 11:34:32 am
Ok, next step, not only will you want to simulate test, but, you will want to actually modify memory while running the GPU.  Do you have any means of doing this?

Which CycloneIV dev board are you using?  Do you have schematics of it?  Is there a way to interface with it?

I'm using one of these:

(Attachment Link)

Have found some good resources here for it: http://fpga.redliquid.pl (http://fpga.redliquid.pl)

Have attached a file called VGA Schematic.pdf.  It seems to show extra connections for more VGA colour resolution?  Hmm.. seems that's an add-on module, perhaps.  There's certainly no resistor networks on the board...
Copy their DAC design, only the top 4 bits of each color, wired to a header where the 12 wires all come from 1 bank if possible.  Take a look at the SEG and DIG resistors R46 to R57, that's 12 bits there (Remove those resistors).  Copy the resistor dac schematic you sent me, the upper 4 bits of each color, and wire in place of R14,R15,R16. by the VGA connector.  Key the current H&V sync wires attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 11:40:56 am
Erm... I thought Quartus II had some way of updating FPGA memory while it was on...?  Found this - not sure if this is of any use at all?

In-System Updating of Memory and Constants (http://ridl.cfd.rit.edu/products/manuals/Altera/In-System%20Memory%20Content%20Editor/qts_qii53012.pdf)

Perhaps it only works with single-port memory, but for the purposes of testing we could scrub the host port to the RAM and give Quartus II access to the RAM that way?

Yeah you can also do those for editing things that are memory blocks. It looks like its fully TCL scriptable too. Tho it will likely eat up one port on a dual port RAM block, so if you still need them being dual port in your design that might be an issue.

Yes, it looks like it uses one of the ports as it says in the document I linked that it only supports single-port RAM, so that's most likely why.

Also you will most likely keep hardware configuration registers as normal register rather than block RAM. Those won't show up in the memory editor.

Really?  The only way the Z80 will be able to access the GPU is via a window in its physical memory space where the GPU exposes its own RAM - so a section of the GPU RAM will need to be reserved for configuration, the rest for the GPU RAM itself, and the Z80 will be writing to RAM whether it's setting or reading hardware configuration or screen memory.  What the GPU does with the configuration bits is another matter, but they'll be set in RAM initially.

So the best universal way that works for everything is injecting read and write commands just like the Z80 would. It also inherently tests tests things are accessible at the right addresses since its accessing them in the same way the Z80 would.

Yes, and I hope to get some sort of interface with the Z80 up and running as soon as possible for just that reason - maybe at the weekend, if I'm lucky.  I suspect it will require fair bit of debugging to get working - probably another thread's worth, knowing me - but I could just be being pessimistic.  ???

Or if you want to be really authentically oldschool with this project you can wire up the address bus to switches and have LEDs show bits like it did on the Altair computer. ;D Just joking, some things are best left in the past.

Hahaha - you're a funny guy.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 11:41:28 am

Also you will most likely keep hardware configuration registers as normal register rather than block RAM. Those won't show up in the memory editor. So the best universal way that works for everything is injecting read and write commands just like the Z80 would. It also inherently tests tests things are accessible at the right addresses since its accessing them in the same way the Z80 would.

Or if you want to be really authentically oldschool with this project you can wire up the address bus to switches and have LEDs show bits like it did on the Altair computer. ;D Just joking, some things are best left in the past.
It's a combination of ram and addressable registers.
I already have a dumb verilog UART to parallel ram read/write debug port.
The interface is a really dumb 1 byte command, 1 response, but, It's idiot proof. (I hope)
I'll fetch it tonight.

It's also good for forcing memory read and writes while the Z80 is wired in.  With 125Mhz dedicated ram port for the HOST, I dont think the speed of the Z80 will ever eat any significant access time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 14, 2019, 12:31:24 pm
Yeah these dumb, zero configuration, "it just does one thing" kind of peripherals are what i like in FPGAs.

And yes the Z80 will be using it trough a memory window, but its not practical for this memory window to be all block RAM. Its only possible to access one word at a time in block RAM trough one port. This is great for buffers, character maps, lookup tables where you only need to look at one (or a few) locations in memory at a time.

Hardware configuration registers are different. Because these register need to affect the operation of your circuitry means that the bits in those registers are wired out to individually so that there state can affect the input of some logic gate inside the logic circuitry. To make this possible you can build your own RAM with flip flops in the logic fabric. This is usualy what "reg something; something <= 1" ends up being. Since they are individual flip flops means they can be wired up in any way you like. To make these memory mapped you need a tiny local address decoder that selects the correct register when its address is fed in. So perhaps the first 1KB of the Z80 visible memory map might be reserved for hardware registers and the rest is passed trough as a window into block RAM.

These registers are more expensive in terms of FPGA resources so you generally only use them when you need it. They would store things like config bits, status bits, adjustable video timings, pointers to memory... etc that only take a single word to store, not store big things like image data in these.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 12:53:04 pm
Okay, 12-bit DAC is up and running.  Well, aside from the additional outputs from the FPGA - there's no signals to put out yet, but it's ready to go when needed.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 03:09:23 pm
Okay, 12-bit DAC is up and running.  Well, aside from the additional outputs from the FPGA - there's no signals to put out yet, but it's ready to go when needed.  :-+

Ok, I've attached a 12bit color version + with a test RS232 debugger.

Select 2 IOs and use your FTDI TTL RS232 transceiver.
Use 115200 baud, 8N1.  No handshaking, no xon/xoff.  Full duplex.

Go into a terminal software and type.  Your typing should appear on the OSD, plus, it should also be echoed back to your terminal software.  Hitting the reset button will reset the invisible cursor to the home position.

If this works, I'll add the control commands and send you a small basic program with windows compiler which will allow you to read and write any memory addresses.  You can setup the Basic software read or dump files as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 14, 2019, 03:27:23 pm
For the new year, I'm leaving electronic engineering and heading into management.

Congrats!
Get ready for a complete change in your daily activities, and learn to say "no", which is one of the hardest parts of management. (Another one is sometimes being "compressed" between the doers and the deciders. ;D )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2019, 05:55:18 pm
For the new year, I'm leaving electronic engineering and heading into management.  I'll never have time left to do electronic ever again.
It's going to be the complete opposite. Sitting your pants off in endless stupid meetings talking about stuff nobody cares about is what's the average manager's work day looks like in a large company. And pretending to be super-busy to his/her boss by sending insane amount of emails that few people read or even care about. So yeah - you'll probably have all the time in the world to think about (and maybe even read about) electronics during those meetings because a lot of them won't even be designed to be useful or productive. I know I had. And you will also have higher-quality spare time because if something in your systems breaks down during off-work time, you won't be the one rushing into the office/firing up your laptop and connecting to your office network and sitting there long past midnight trying to get things to work again.
Just remember one thing - talking about stuff never gets anything done, only doing does. So don't bring your engineers into meetings unless you're absolutely sure this is going to be that unicorn of a meeting where something relevant is going to be discussed and decided (the last part is super-important!).
I used to be a manager, but returned into engineering after I realized what that job was all about, and was bored to death in those meetings, which I now hate with passion and always demand a crystal-clear agenda before I even consider attending one. This does not apply to engineers-only meetings - they tend to be useful, but you won't be participating in them anymore.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 06:27:47 pm
Okay, have downloaded the latest project, put it in a new folder, compiled it, assigned pins to the 12-bit RGB output, clock, reset, hsync and vsync, and connected my USB-TTL lead to the board, connecting Tx and Rx and setting up the serial port in PuTTY according to your instructions.  Have not changed anything else.

Am getting this:

[attach=1]

As you can see, what I'm typing in PuTTY is getting echoed back to the terminal (have tried it with Tx/Rx reversed on the board to make sure it's wired up correctly - obviously nothing comes back at all), but nothing is appearing on the screen.

I'm just hunting through the code to see if there's any obvious reason it's not working for me, but it's going to be something I've done wrong...

EDIT:  Also, just a thought, but isn't the output of the USB-TTL a 5v signal?  If that's the case, isn't there a chance I could be damaging the IO on the board?  (Note: I have only got the Rx/Tx and GND connected to the board - RTS and CTS are 'connected' to inactive (tri-stated) IO pins, as I don't want to pull the connector apart to isolate just Tx, Rx and GND, if that makes sense.

gpu_16K_RAM.mif wasn't included in the list of project files, but since I've added that it hasn't made any difference either.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 14, 2019, 08:31:24 pm
EDIT:  Also, just a thought, but isn't the output of the USB-TTL a 5v signal?  If that's the case, isn't there a chance I could be damaging the IO on the board?
It's possible. It depends on the USB-to-serial adapter in your hand. Some might be switchable. Some might default to 3.3V. Some might be designed by someone for easy money who just doesn't care. The only way to know for sure is to check it with a meter.

(MAGGIE. I like that. Very Simpsons.  ;D )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2019, 10:24:06 pm
EDIT:  Also, just a thought, but isn't the output of the USB-TTL a 5v signal?  If that's the case, isn't there a chance I could be damaging the IO on the board?
It's possible. It depends on the USB-to-serial adapter in your hand. Some might be switchable. Some might default to 3.3V. Some might be designed by someone for easy money who just doesn't care. The only way to know for sure is to check it with a meter.

Yeah, it was more of a rhetorical question I guess; I knew the answer before I even wrote it.  I've stopped using the TTL-USB cable, will dig out a TTL-USB board from my box of bits - I know they have a jumper on them to set the voltage to 5v or 3v3.  Will look at trying that tomorrow.  Also, must stop 'writing out loud'...  :-DD

(MAGGIE. I like that. Very Simpsons.  ;D )

Thought you would.  ;)  And getting the Simpsons reference as well.  ;D ;D

Now if we can name another module 'BART', we're on to something. Blitter And Raster Timer? If we integrate audio into the FPGA, that module will definitely be 'LISA'.  Linear Integrated Stereo Audio?

I'm open to better suggestions.  :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2019, 11:37:43 pm
Okay, have downloaded the latest project, put it in a new folder, compiled it, assigned pins to the 12-bit RGB output, clock, reset, hsync and vsync, and connected my USB-TTL lead to the board, connecting Tx and Rx and setting up the serial port in PuTTY according to your instructions.  Have not changed anything else.

Am getting this:

(Attachment Link)

As you can see, what I'm typing in PuTTY is getting echoed back to the terminal (have tried it with Tx/Rx reversed on the board to make sure it's wired up correctly - obviously nothing comes back at all), but nothing is appearing on the screen.

I'm just hunting through the code to see if there's any obvious reason it's not working for me, but it's going to be something I've done wrong...

EDIT:  Also, just a thought, but isn't the output of the USB-TTL a 5v signal?  If that's the case, isn't there a chance I could be damaging the IO on the board?  (Note: I have only got the Rx/Tx and GND connected to the board - RTS and CTS are 'connected' to inactive (tri-stated) IO pins, as I don't want to pull the connector apart to isolate just Tx, Rx and GND, if that makes sense.

Funny, with no rs232 text into the board, you should still have the original test text.  Your typing should overwrite the test text as you type.
If your echo is coming from the FPGA you didn't kill your FPGA since the echo of the text I made goes through IP code.
If you see your text still and your terminal software doesn't have local echo enabled, or half duplex enabled, this means my RS232 baud rate is correct and the UART, fifos, status flags are all 100% functional as all these need to work correctly to pass a character through.  It's just for some reason, at least 16k worth of writes somehow made it through the com port erasing your font and everything else.

Test #1, disconnect the 'host_wr_ena' like so:
[attach=1]
This will stop the write and show the original text font test pattern.  Otherwise, something else went wrong.
Your color palette looks wrong.  Could be you need a pull-down resistors on the RGB, or decoupling caps as well, or the RGB ports are wired wrong.  Remember, R(3:0), not R(1:0).  Check your pin assignments as these may be assigned to the wrong pins.
Quote
gpu_16K_RAM.mif wasn't included in the list of project files, but since I've added that it hasn't made any difference either.
Yes, i just downloaded the 'GPU_12bitcolor_rs232debugger_test.zip' and checked.  The 'gpu_16K_RAM.mif' is in there.

Test #2, put back the 'host_wr_ena' and change this 1 line in my source code: (Line 56, rs232_DEBUGGER.v')
Code: [Select]
if (ena_rxd_dly) host_addr_reg   <= <= DEBUG_RST_ADR ; //host_addr_reg + 1;
This should stick any writes to cursor position 1, so, every key you hit should only show the new letter pressed at that 1 top left cursor position.  The letter should stay, not blink.  If this works, don't worry, my actual writes will be protected by a setup string preventing + a write enable lock which will be on by default during powerup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 15, 2019, 12:22:19 am
Thought you would.  ;)  And getting the Simpsons reference as well.  ;D ;D

Now if we can name another module 'BART', we're on to something. Blitter And Raster Timer?
Block Area/Alpha Renderer/Rotator and Translator, depending on how far you want to push it.

Quote
If we integrate audio into the FPGA, that module will definitely be 'LISA'.  Linear Integrated Stereo Audio?
Paula and other simple sample engines transition instantly between one frame of the sample and the next. The decimation in the time domain and the loop ticks are audible, and may be undesirable (or not). We'll build NCOs (https://en.wikipedia.org/wiki/Numerically-controlled_oscillator), use phase accumulators to set playback rate (like SID), and use the fractional part to Linearly Interpolate between the previous and current value over the sample period. But that's for later. BrianHG appears to be on a deadline and I don't want to get in his way. :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2019, 12:55:53 am
I've attached 2 dumb terminal programs.  Termite and Hexcom.
Note that in termite, I switched off local echo and append CL/LF in the transmit setting.
Try these guys.  I think Putty may be flushing the com port with junk and as my test software checks nothing at all, all it doe is dump incoming characters to adjacent memory addresses, Putty might have been a bad choice.


Hexcom, written by my friend, allows you to receive view and transmit both ascii and hexadecimal to RS-232 and a UDP port.

Termite is a third party software.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2019, 03:48:49 am
For the new year, I'm leaving electronic engineering and heading into management.  I'll never have time left to do electronic ever again.
It's going to be the complete opposite. Sitting your pants off in endless stupid meetings talking about stuff nobody cares about is what's the average manager's work day looks like in a large company. And pretending to be super-busy to his/her boss by sending insane amount of emails that few people read or even care about. So yeah - you'll probably have all the time in the world to think about (and maybe even read about) electronics during those meetings because a lot of them won't even be designed to be useful or productive. I know I had. And you will also have higher-quality spare time because if something in your system ;Ds breaks down during off-work time, you won't be the one rushing into the office/firing up your laptop and connecting to your office network and sitting there long past midnight trying to get things to work again.
Just remember one thing - talking about stuff never gets anything done, only doing does. So don't bring your engineers into meetings unless you're absolutely sure this is going to be that unicorn of a meeting where something relevant is going to be discussed and decided (the last part is super-important!).
I used to be a manager, but returned into engineering after I realized what that job was all about, and was bored to death in those meetings, which I now hate with passion and always demand a crystal-clear agenda before I even consider attending one. This does not apply to engineers-only meetings - they tend to be useful, but you won't be participating in them anymore.
I'm going to be at the top, with absolute authority & part owner of the new corp.  No one above me except my responsibilities to the investors.   ;D  I'm creating the 'agenda'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2019, 10:05:48 am
Funny, with no rs232 text into the board, you should still have the original test text.  Your typing should overwrite the test text as you type.
If your echo is coming from the FPGA you didn't kill your FPGA since the echo of the text I made goes through IP code.
If you see your text still and your terminal software doesn't have local echo enabled, or half duplex enabled, this means my RS232 baud rate is correct and the UART, fifos, status flags are all 100% functional as all these need to work correctly to pass a character through.  It's just for some reason, at least 16k worth of writes somehow made it through the com port erasing your font and everything else.

Local echo is 'forced off' in the PuTTY settings.  There's definitely no text appearing on the screen, although it's being echoed back to the terminal.

Test #1, disconnect the 'host_wr_ena' like so:

This will stop the write and show the original text font test pattern.  Otherwise, something else went wrong.

.... no change.  I've been testing different USB-TTL adapters, trying it without one plugged in at all, checked all the connections to VGA 'ladder',

I've even loaded up the previous version of the GPU project and upped it to 4-bit RGB output, and it appears to be working fine:

[attach=1]

... yes, the colours are out, but I can still see the text so something should be visible on the screen with the new project, especially if the serial port isn't connected.

Your color palette looks wrong.  Could be you need a pull-down resistors on the RGB, or decoupling caps as well, or the RGB ports are wired wrong.  Remember, R(3:0), not R(1:0).  Check your pin assignments as these may be assigned to the wrong pins.

Yes, they do.  I had arbitrarily wired up the resistor ladder and wasn't expecting perfect colours... I'm using something like 470R, 1.1K, 1.9K, 4K7 values - they were old resistors that I'd tested on my meter years ago and written the values on the sticker strips they were attached to (including the error margin on a couple of them by the looks of it!), but I'm not after colour perfection right now, just a visible output.  As I can see the text on the previous version of the GPU project, I'm more concerned about getting this new version working first.

If I'm going to be using this test bench for an extended length of time, I'll get a PCB made up with some 0802 resistors with proper values (or as close as) and make a proper VGA breakout board - for the moment, trusty breadboard is the medium of choice.  ::)

Test #2, put back the 'host_wr_ena' and change this 1 line in my source code: (Line 56, rs232_DEBUGGER.v')
Code: [Select]
if (ena_rxd_dly) host_addr_reg   <= <= DEBUG_RST_ADR ; //host_addr_reg + 1;
This should stick any writes to cursor position 1, so, every key you hit should only show the new letter pressed at that 1 top left cursor position.  The letter should stay, not blink.  If this works, don't worry, my actual writes will be protected by a setup string preventing + a write enable lock which will be on by default during powerup.

Haven't tried this one yet as I've stalled on the first test.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2019, 10:15:11 am
For dac, all you need is 1 Kohm and 2Kohm resistors, good quality 1% or better.

For the MSB 3, tie 2x 1k in parallel, the equals 500Ohm.
For the bit    2, it's just a 1k.
For the bit    1, it's just a 2k.
For the LSB  0, it's 2 of the 2k in series, making 4k.

This makes an exact 0.5k, 1k, 2k, 4k resistor dac.

Make sure you removed tho old 1k resistors.  You cannot use different outputs across different IO banks as each bank has different clock delay and even different current ratings for the IO pins.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2019, 10:33:03 am
Here, test this one.  you should see the original debug text plus some echoing characters on PUTTY.

type this exactly, match my case (or copy and paste):

Code: [Select]
WRI!These 34 letters should displayed.
If that worked then send this:

Code: [Select]
REA!
Your terminal should receive the next 34 characters which are already on the display after my text message.

If it works, I'll sen you the 4 different arguments and how they work, or let me know, I'll find/remake my old basic development utility which handles the com.

Setting the read/write address requires binary numbers, I just made these commands ascii compatible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2019, 03:23:34 pm
I'm going to be at the top, with absolute authority & part owner of the new corp.  No one above me except my responsibilities to the investors.   ;D  I'm creating the 'agenda'.
Ah, startup, I see. Good luck!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 15, 2019, 03:59:49 pm
I'm going to be at the top, with absolute authority & part owner of the new corp.  No one above me except my responsibilities to the investors.   ;D  I'm creating the 'agenda'.

Oh, you won't be plagued with the problems common for middle-managers then.
Just keep in mind that the investors may/will be deciders at some point (it's always rosy at the beginning). But enjoy the ride and good luck! :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2019, 04:07:09 pm
I've reversed the RGB connection order and, with the new project, am now getting the text display as previously:

[attach=1]

Here, test this one.  you should see the original debug text plus some echoing characters on PUTTY.

type this exactly, match my case (or copy and paste):

Code: [Select]
WRI!These 34 letters should displayed.

Okay, here's the result of pasting
Code: [Select]
WRI!These 34 letters should displayed. into the terminal:

In the terminal, I get:

Code: [Select]
WRI!▒▒e 34@▒ett▒▒s should ▒▒splayed.
On the screen, I get:

[attach=2]

It's trying to work - seems like a timing problem?  I've just double-checked PuTTY's settings:

115200, 8N1, Flow control: None

If that worked then send this:

Code: [Select]
REA!
Your terminal should receive the next 34 characters which are already on the display after my text message.

That's more or less what happens, but the text is slightly corrupted.  I received one string with no errors out of about 5 attempts.

If it works, I'll sen you the 4 different arguments and how they work, or let me know, I'll find/remake my old basic development utility which handles the com.

Setting the read/write address requires binary numbers, I just made these commands ascii compatible.

Ah!  ;D  Looks like you've made a mistake on altpll0 in the project - you've got a clock source of 54 MHz??  My board is 50 MHz, so that'll throw the baud rate out enough to cause the glitches I'm seeing. Not sure how the display is okay - probably just within tolerances, I guess?

EDIT:

Yep, it's the baud rate that's the problem - I've upped UART_BAUD to 1088 (how does this relate to the clock speed?) in rs232_debugger, and am now getting almost 100% integrity on the Tx/Rx console contents:

[attach=3]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2019, 05:08:13 pm
Further to my last - have gone back to the GPU_test project and changed the PLL settings for a 50 MHz source clock, updated UART_BAUD to 1090 (serial seems 100% stable now) and have re-ordered the RGB outputs.  Am now able to write to the GPU RAM:

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2019, 06:18:51 pm
Quote
I've reversed the RGB connection order and, with the new project, am now getting the text display as previously:
So, blank text had nothing to do with my code....

Ok, the clk54 shouldn't be a problem as Altera allows huge play on the PLL.  I know you have a 50Mhz clock source and I said 54 in the PLL settings.  All that the FPGA is concerned is that what is coming in will be multiplied by 5 then divided by 2.  And it will do it with a clock anywhere between something like 40 and 65 Mhz with the settings I have made.  The '54' mhz is just so when you compile, Quartus will make sure the project is fast enough for 480p HDMI with audio which would have a 54MHz clock source.

However, yes, the 'baud' might need to be slowed down.  It's a period number.  IE:
Frequency / baudrate.  So, (125000000 / 115200)-1 = 1084. 

What number did I have?  Raising the baud number actually slightly slows down the baud rate.
-----------------------
Just checked, there was a bit of it which was hard wired for 27Mhz, and Im running it at 125Mhz in this project....  I'll patch it in the next release.
-------------------------

Note that the UART I used was a home-made 15 year old thing.  In the next update I'm giving you, I'm running the UART debugger section at 50Mhz instead of the 125MHz graphics clock, it was originally designed and used at 27Mhz.


I'm almost finished the PC software, an onscreen - keyboard & mouse point and click memory viewer/editor for the GPU.  It has hex view with ascii, binary, 8 & 16 bit decimal view and entry.  Load/Save memory blocks to binary files.  However, without a GPU, I cant test locally.  Will you be around tomorrow for testing?

With this out of the way, working on the raster memory pointer generator & with this tool, manipulating and testing both display controls and image data in real time will be easy.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2019, 07:35:16 pm
Quote
I've reversed the RGB connection order and, with the new project, am now getting the text display as previously:
So, blank text had nothing to do with my code....

Well I didn't think the RGB order was an issue, as I tested the previous version of the project and it was showing the text just fine (albeit a little off-colour!)  :-//

Ok, the clk54 shouldn't be a problem as Altera allows huge play on the PLL.  I know you have a 50Mhz clock source and I said 54 in the PLL settings.  All that the FPGA is concerned is that what is coming in will be multiplied by 5 then divided by 2.  And it will do it with a clock anywhere between something like 40 and 65 Mhz with the settings I have made.  The '54' mhz is just so when you compile, Quartus will make sure the project is fast enough for 480p HDMI with audio which would have a 54MHz clock source.

Ah, fair enough - well, remember I don't have years of experience with this stuff.  I was just pleased that I'd managed to fix the issue.  ::)

However, yes, the 'baud' might need to be slowed down.  It's a period number.  IE:
Frequency / baudrate.  So, (125000000 / 115200)-1 = 1084.

What number did I have?  Raising the baud number actually slightly slows down the baud rate.

You had 1084 - I had to up it to 1090 to get a stable interface.

-----------------------
Just checked, there was a bit of it which was hard wired for 27Mhz, and Im running it at 125Mhz in this project....  I'll patch it in the next release.
-------------------------

No worries, I'll know what to do if we have the same problem again.

I'm almost finished the PC software, an onscreen - keyboard & mouse point and click memory viewer/editor for the GPU.  It has hex view with ascii, binary, 8 & 16 bit decimal view and entry.  Load/Save memory blocks to binary files.  However, without a GPU, I cant test locally.  Will you be around tomorrow for testing?

Jeez BrianHG, you've been busy!!  :o :o :o  Yes, I'll try to be around as much as possible.  Will get up early and see what we can get done - though I've got Christmas shopping duties with the missus at some point, I'll try to keep the morning as clear as possible.  ;)  Out of interest, what are you using to write the PC software?

With this out of the way, working on the raster memory pointer generator & with this tool, manipulating and testing both display controls and image data in real time will be easy.

The serial interface is a pretty big thing for me - but I'm really excited about the next steps as well.  I'm going to keep thanking you constantly for all this help and support - seems Christmas has come early!  ^-^
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2019, 07:42:12 pm
Ok, I patched the UART's true baud problem.  I'm also now running the RS232 debugger at 50Mhz instead of 125Mhz.  This means the baud setting is (50000000/115200)-1 = 433.

I turned off the local echo of commands, so you wont see anything in putty unless you copy&paste the
Code: [Select]
REA!
Or, to print text on the screen, use the:
Code: [Select]
WRIaThis should work without issue.  I know it's taken much time and hassle, but, we will get there...
What time will you be available tomorrow?
Because the Basic software will need testing, we may need to use 'teamviewer' to debug it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2019, 12:01:48 am
Preview of GPUtalk.exe.
It's a Win64 application.
Just hit enter when it asks for a com number.
It will work without any GPU connected.
It's a work in progress.

Just need entry, com, and load/save and it will be ready.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2019, 07:58:23 am
Preview of GPUtalk.exe.
It's a Win64 application.
Just hit enter when it asks for a com number.
It will work without any GPU connected.
It's a work in progress.

Just need entry, com, and load/save and it will be ready.

It seems to be reading memory, or at least the sample data?

[attach=1]

[attach=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2019, 01:19:04 pm
Here we go with the text version.  I've attached the QuartusProject with a version which is compatible with the GPUtalk utility.

The GPUtalk utility for now only copies, displays and edits memory realtime from the GPU.  If it works ok, I'll add the bulk copy routines and fix up the load and save as they currently self erase.

@nockieboy, we will probably need to TeamView for me to certify the GPUtalk and program fixes.
Let me know when you want to hookup.

To make thing as fast as possible, I would recommend installing 'Freebasic' from here:
https://www.freebasic.net/ (https://www.freebasic.net/)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2019, 02:22:27 pm
Ooops,a typo in the GUPtalk, I wasn't setting the read/write address correctly.

Here you go:
I've included a 115200 version in the zip just in case.  Well sort it out when we teamview.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2019, 06:31:42 pm
Ooops,a typo in the GUPtalk, I wasn't setting the read/write address correctly.

Here you go:
I've included a 115200 version in the zip just in case.  Well sort it out when we teamview.

Hmmm... now it doesn't seem to be reading the GPU memory - has it gone back to reading the demo files?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2019, 04:20:55 pm
Ok @nockieboy, now that the GPU_talk RS232 memory sniffer/debugger is perfectly functional, your work on the controls and features for the GPU begins now.  I'm sending an enhanced version of the GPU_talk with some added smart features for later tonight.

These are the following simple additions are required for your project before we make the address generator:

1.  Modify the core of your sync_gen.v so that the position of the active video image is shifted 16 pixels to the right by 16 lines down.  Remember, you will also need to move the sync signals as well so that the picture still remains centered with reference to the syncs timings.  Make this 2 new parameters called "IMAGE_X_OFFSET" and "IMAGE_Y_OFFSET".

2. To vid_osd_generator.v, add and pass through these parameters:
     A) 'GPU_powerup.mif' file
     B) Memory Address Bits  (take care as we want total bits here.  This means when defining the top bit in a register, it would be this value -1)
     C) Memory Words           (If this field is left empty, it's value should be calculated from (B)'s parameter )

3.  Make a new verilog module called 'GPU_HW_Control_Regs.v'.  This module should be a mass of registers which which are all available in parallel to any other part of the GPU, with an 8 bit data & address[19:0] input write port, a reset input and reset parameters for the first 32 bytes.  This one huge output register should be called GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0].  Module specs:

     a)  All inputs, 8 bit data in, write data enable, 20 bit write address, and reset should be all register latched (yes, latch the reset input, then use that register's output as the module's reset).  This latching offers better FMAX timing fitting if we need to run this module on the alternate slower clock frequency. (IE, 50 Mhz clock).
     b)  A parameter, HW_REGS_SIZE , for the quantity/size bulk of 8 bit registers.  (Note, for your top hierarchy, block diagram design entry, you will place a 'param' which this module will use as it's setting, see attached image as an example.)
     c)  Base write address for the write input.  The module will always take in all 20 address bits, but when writing data to the 8 bit data input port, the upper address wires [19:8] should equal this number for the write to be successful.  If parameter (b) is >256, then the bottom of the upper base write address [8] will be ignored as you will be opening a 512 byte window, and so on.  (Set this default to the base of the last 256 bytes in your system memory.  Yes, it will occupy the same last 256 bytes as your system GPU ram.)
     d)  Reset parameters.  Have 32 8 bit parameter settings which will be forced into the first 32 bytes if the reset signal is sent.  Make the rest of the registers reset to 0.

4.  Place an input for the 'bulk GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0] registers' into the following verilog modules: sync_generator.v, vid_osd_generator.v, vid_out_stencil.v.  Remember, you will need to receive the block diagram parameter into each module to get the right number of wires for the inputs.

5.  Add a new 48 register output to the 'sync_gen.v' called 'raster_HV_trigger[47:0]'.  Make the even 'raster_HV_trigger[47:0]' wires pulse at a horizontal pixel position and the odd wires pulse on a vertical line according to the new 'GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0]' onput wire, organized as 16 bit words, using the first 10 of 16 bits of each 2x2 bytes coming from the new input "GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0]".  You should add a new parameter input to the sync_gen.v which will allow you to shift the beginning byte base (beginning) address of GPU_HW_Controls where the 'raster_HV_trigger' get their 48 settings from.  IE 48x2 bytes = 96 bytes total.  Once done, out on your top block diagram, 'or' these 48 HV triggers outputs together and 'or' tie them to to the upper ro[],go[],bo[] bits of the OSD_img output.  Test with the GPUtalk app.  You should be able to move 24 vertical lines and 24 horizontal lines around the screen, with the first 0-15 coordinates being non-visible as those coordinates are too far to the left and above the top of the picture since we moved the picture window by 16 pixels to the right and down in step (1).  (Once working, mix and combine / change around the 'or' driven ro[]&go[]&bo[] colors VS raster_HV_trigger[47:0] even and odd pairs so each set of coordinate generated lines may generate a different color on the display.)

     Show us your progress.  Do one item at a time.  For the new modules and functions, perform a functional simulation of each one to make sure their controls work before inserting it into your design, otherwise, you are guessing to what functions and what doesn't.  Even show us the simulations as proof of functionality.  (Do this step, and you will have a full GPU working in not time at all.)

     This work is the preparation required for the image raster address generators as they require parallel hardware control registers and and some adjustable trigger events at adjustable locations during the display, including a setup time just before the active display begins.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2019, 05:22:54 pm
Simulation tips:

Make you main GPU folder with a complete final project sub-folder + alternate projects for each verilog.v simulation.

  In each of those alternate folders for the simulation project, make a quartus 9 project with with a cyclone 3 FPGA and make a block diagram entry with clk and reset inputs as well as any other input pins to drive your verilog module.  Add outputs pins you wan to see from the verilog module.

  Add the verilog module by 'Adding' it's file to your quartus 9 project in quartus 9's 'Project/Add remove files in project' from your master Quartus Prime project's folder and add any other required verilog dependencies.  This way you are not copying xxx.v files back and forth.  Quartus 9's simulation will use only the verilog code in you master Quartus Prime's project folder.

  Open the xxx.v file and generate the symbol in Quartus 9, insert and wire the symbol into your simulation design.  Compile.  Create a new .vwf  (vector waveform file) and add the input and output pins, buses and regs you want to see in the simulation.  Go into simulator settings and select 'Simulation mode' "Functional" and Simulator Input "xxxx.vwf". and simulate away.

I can walk you through simulating your 'sync_gen.v' if you are having trouble.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2019, 09:37:13 am
1.  Modify the core of your sync_gen.v so that the position of the active video image is shifted 16 pixels to the right by 16 lines down.  Remember, you will also need to move the sync signals as well so that the picture still remains centered with reference to the syncs timings.  Make this 2 new parameters called "IMAGE_X_OFFSET" and "IMAGE_Y_OFFSET".

Is this really as simple as this?

Code: [Select]
// image offset parameters
parameter IMAGE_OFFSET_X = 16;    <----- added parameter
parameter IMAGE_OFFSET_Y = 16;    <----- added parameter

// no-draw area definitions
// defined as parameters so you can edit these on Quartus' block diagram editor
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH   = 96;
parameter H_BACK_PORCH  = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH  = 33;
parameter PIX_CLK_DIVIED = 4;

// re-calculate back porch values, taking image offset into account
localparam H_ADJ_B_PORCH = H_BACK_PORCH - IMAGE_OFFSET_X;    <----- reduce back porch accordingly
localparam V_ADJ_B_PORCH = V_BACK_PORCH - IMAGE_OFFSET_Y;    <----- reduce back porch accordingly

// total screen resolution
localparam LINE = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_ADJ_B_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_ADJ_B_PORCH; // total scan lines (inc. vertical blanking area)

// useful trigger points
localparam HS_STA = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1; // horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2019, 09:57:46 am
2. To vid_osd_generator.v, add and pass through these parameters:
     A) 'GPU_powerup.mif' file
     B) Memory Address Bits  (take care as we want total bits here.  This means when defining the top bit in a register, it would be this value -1)
     C) Memory Words           (If this field is left empty, it's value should be calculated from (B)'s parameter )

Okay, just need some clarification here for A).  You want me to pass a reference to the init file that gpu_RAM uses so the filename can easily be changed in the design view, or you me to pass a new file?

Code including changes for B) and C) is attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2019, 10:57:22 am
3.  Make a new verilog module called 'GPU_HW_Control_Regs.v'.  This module should be a mass of registers which which are all available in parallel to any other part of the GPU, with an 8 bit data & address[19:0] input write port, a reset input and reset parameters for the first 32 bytes.  This one huge output register should be called GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0].  Module specs:

     a)  All inputs, 8 bit data in, write data enable, 20 bit write address, and reset should be all register latched (yes, latch the reset input, then use that register's output as the module's reset).  This latching offers better FMAX timing fitting if we need to run this module on the alternate slower clock frequency. (IE, 50 Mhz clock).
     b)  A parameter, HW_REGS_SIZE , for the quantity/size bulk of 8 bit registers.  (Note, for your top hierarchy, block diagram design entry, you will place a 'param' which this module will use as it's setting, see attached image as an example.)
     c)  Base write address for the write input.  The module will always take in all 20 address bits, but when writing data to the 8 bit data input port, the upper address wires [19:8] should equal this number for the write to be successful...

Okay, still with you so far...  ???

...If parameter (b) is >256, then the bottom of the upper base write address [8] will be ignored as you will be opening a 512 byte window, and so on.  (Set this default to the base of the last 256 bytes in your system memory.  Yes, it will occupy the same last 256 bytes as your system GPU ram.)

Nope - lost me now. :o

So I'm supposed to set the 9th bit [8] to zero if [19:8] is greater than 256?  The bit in parenthesis is totally lost on me.

So we've got 32 hardware control registers that can be written to and are all output from the module.  These write addresses we're discussing here are to address the individual bits of the registers, but something else is going on which I don't understand if the upper 12 bits are above 256?  These registers are separate from the GPU RAM, so I guess the reference to the base address in GPU RAM is to set the HW registers from the values in a 32-byte block in GPU RAM that the host can write to?  Going to need a little more guidance on this one.  Wouldn't it make sense to have the 32 HW registers' shadow the first 32 bytes in GPU RAM?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2019, 02:30:49 pm
I'll get to your 2 last comments in the next response.

Ok, 2 items:

1) The latest GPUtalk.

-I've added Load and Save dialogs, where you can now choose file names and start memory address and length of memory.  Entering nothing for the start and length automatically uses all the ram buffer.
-I've added 'm' which generates and saves a Quartus .mif Memory Initialization File.
-You can now click on the binary bits to toggle them when editing the data.
-You can now also click on the data and 16bit decimal data to enter a number.
-Using the + and - keys to increment and decrement the selected memory data does it for 2 bytes as a 16 bit word.  Using the wheel mouse to inc and dec the data value is still only 8 bit.
-When not in writing data mode, you can now click on the address to enter an address to directly jump to.
-Now, if you do not enter anything when prompted for the 'COM' number, the program bypasses all RS232 routines making it just as fast as if you were connected.  Pretty much makes it just a hex editor and .mif file generator.

2) 256 character, high res version of the GPU Quartus project.
-It will now has a 256 character font and should be in high res 64x32 characters.
-The font graphics now begin at address 0.
-There is also a Parameter in the OSD to switch to a 8x16 font.
-The .mif still has the Atari 128 character font (in case the attached VGA rom .bin fonts aren't compatible), so you will need to use the GPUtalk to load in the right font, 8x8, or 8x16 depending on the parameter setting into address 0.  Then you can now generate a new .mif file with the best looking font for you.  (Send photos.)

I've included 2 VGA fonts I got from this site:
https://github.com/spacerace/romfont/tree/master/font-bin (https://github.com/spacerace/romfont/tree/master/font-bin) -> Binary files
https://github.com/spacerace/romfont/tree/master/font-images (https://github.com/spacerace/romfont/tree/master/font-images) -> Photos of the fonts
If they work, the others should work too.

See attachments:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2019, 02:59:26 pm
1.  Modify the core of your sync_gen.v so that the position of the active video image is shifted 16 pixels to the right by 16 lines down.  Remember, you will also need to move the sync signals as well so that the picture still remains centered with reference to the syncs timings.  Make this 2 new parameters called "IMAGE_X_OFFSET" and "IMAGE_Y_OFFSET".

Is this really as simple as this?

Code: [Select]
// image offset parameters
parameter IMAGE_OFFSET_X = 16;    <----- added parameter
parameter IMAGE_OFFSET_Y = 16;    <----- added parameter

// no-draw area definitions
// defined as parameters so you can edit these on Quartus' block diagram editor
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH   = 96;
parameter H_BACK_PORCH  = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH  = 33;
parameter PIX_CLK_DIVIED = 4;

// re-calculate back porch values, taking image offset into account
localparam H_ADJ_B_PORCH = H_BACK_PORCH - IMAGE_OFFSET_X;    <----- reduce back porch accordingly
localparam V_ADJ_B_PORCH = V_BACK_PORCH - IMAGE_OFFSET_Y;    <----- reduce back porch accordingly

// total screen resolution
localparam LINE = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_ADJ_B_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_ADJ_B_PORCH; // total scan lines (inc. vertical blanking area)

// useful trigger points
localparam HS_STA = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1; // horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF
Oh, ok, here is how I would have done it:

Code: [Select]
// image offset parameters
parameter IMAGE_OFFSET_X = 16;    <----- added parameter
parameter IMAGE_OFFSET_Y = 16;    <----- added parameter

// no-draw area definitions
// defined as parameters so you can edit these on Quartus' block diagram editor
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH   = 96;
parameter H_BACK_PORCH  = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH  = 33;
parameter PIX_CLK_DIVIED = 4;

// total screen resolution
localparam LINE = H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_BACK_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_BACK_PORCH; // total scan lines (inc. vertical blanking area)

// useful trigger points
localparam HS_STA = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1; // horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = IMAGE_OFFSET_X + V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = IMAGE_OFFSET_X + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF


and don't forget, you need to push the HDE and VDE screen coordinates in the middle of the code.

If you do not move the image, with your 8bit cpu, if you wan to position an action off the left edge of the screen, you would have to know about the raster width and place that controlled action on the right side of the image X&Y counter.  If you rather do things this way, then, you do not need to change the sync_gen at all.  However, any code for you MCU which uses sprites which can be scrolled off the left side of the screen will require you to place the sprite off the right side of the screen and subtract value.

Basically, though usually fixed, there are a number of settings which will need changing if you change the horizontal and vertical screen resolution where as if the screen was shifted down and to the right according to the reference H&V counter, these settings will always stay the same.

You have a judgement call to make here.  I decided to make the numbers parameters so you may turn the feature off and on lateron depending on the complexity of the horizontal line address generator features.

I'm also forcing you to setup a simulation of the sync_gen.v so you may check if the feature works correctly.

Your going to need this step.  Compile and check will no longer suffice when you need to see if each signal happens on the right pixel exactly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2019, 03:16:59 pm
3.  Make a new verilog module called 'GPU_HW_Control_Regs.v'.  This module should be a mass of registers which which are all available in parallel to any other part of the GPU, with an 8 bit data & address[19:0] input write port, a reset input and reset parameters for the first 32 bytes.  This one huge output register should be called GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0].  Module specs:

     a)  All inputs, 8 bit data in, write data enable, 20 bit write address, and reset should be all register latched (yes, latch the reset input, then use that register's output as the module's reset).  This latching offers better FMAX timing fitting if we need to run this module on the alternate slower clock frequency. (IE, 50 Mhz clock).
     b)  A parameter, HW_REGS_SIZE , for the quantity/size bulk of 8 bit registers.  (Note, for your top hierarchy, block diagram design entry, you will place a 'param' which this module will use as it's setting, see attached image as an example.)
     c)  Base write address for the write input.  The module will always take in all 20 address bits, but when writing data to the 8 bit data input port, the upper address wires [19:8] should equal this number for the write to be successful...

Okay, still with you so far...  ???

...If parameter (b) is >256, then the bottom of the upper base write address [8] will be ignored as you will be opening a 512 byte window, and so on.  (Set this default to the base of the last 256 bytes in your system memory.  Yes, it will occupy the same last 256 bytes as your system GPU ram.)

Nope - lost me now. :o

So I'm supposed to set the 9th bit [8] to zero if [19:8] is greater than 256?  The bit in parenthesis is totally lost on me.

So we've got 32 hardware control registers that can be written to and are all output from the module.  These write addresses we're discussing here are to address the individual bits of the registers, but something else is going on which I don't understand if the upper 12 bits are above 256?  These registers are separate from the GPU RAM, so I guess the reference to the base address in GPU RAM is to set the HW registers from the values in a 32-byte block in GPU RAM that the host can write to?  Going to need a little more guidance on this one.  Wouldn't it make sense to have the 32 HW registers' shadow the first 32 bytes in GPU RAM?

Note, the HW_REGS_SIZE should be at least be 256.  Now, you need a parameter 'WRITE_BASE_ADDRESS'.
Now, for example, if we set the base address to $003F00 (16128), when the input address[19:0] = $003F00 through $003FFF, and a write enable comes in, the correct 8 bits will be filled into the right 1 of 256 GPU_HW_Control_regs.  It's basically a ram, but in regs.  Now if you have the HW_REGS_SIZE set to 512 and the 'WRITE_BASE_ADDRESS' set to $003E00 then writes from input address[19:0] = $003E00 through $003FFF would access the 512 x 8bit GPU_HW_Control_regs.  the 'WRITE_BASE_ADDRESS' can be set to anything within the 20 bit address range.  (Don't think about addr > or addr <, think about just the number of address wires in the 'WRITE_BASE_ADDRESS' and the input address[19:0] just need to be equal while the least significant address wires are are not used if addressA==AddressB test.  These low address bits are only used to point to the correct GPU_HW_Control_regs for writing the 8 bit data coming in.

Begin with this much and simulate.

As for the reset, is just like any of the other resets you have already done.  No separate handle needed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2019, 04:36:34 pm
1) The latest GPUtalk.

Marvellous - works really well, thanks!

-The .mif still has the Atari 128 character font (in case the attached VGA rom .bin fonts aren't compatible), so you will need to use the GPUtalk to load in the right font, 8x8, or 8x16 depending on the parameter setting into address 0.  Then you can now generate a new .mif file with the best looking font for you.  (Send photos.)

Okay, so I've changed the 8x8 font using GPUtalk without any issues:

Before:

[attach=1]

After changing to 8x8 font:

[attach=2]

But there's a problem - if I recompile the project with the parameter FONT_8x16 set to 1 in vid_osd_generator.v, I get a slightly corrupted display - which is expected as initially the GPU is powering up with the default 8x8 .mif in memory, but when I start up GPUtalk, it is constantly listing errors and takes a good 10-15 seconds to list the first page of data:

[attach=3]

This only happens when FONT_8x16 is set to 1 in vid_osd_generator...  :-//

If they work, the others should work too.

Well, it looked like it might be working, but the errors in GPUtalk are preventing a clean bin transfer to the GPU.  I can't imagine what the problem could be, but you might have an idea?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2019, 07:30:09 pm
...and don't forget, you need to push the HDE and VDE screen coordinates in the middle of the code.

Not really sure what you mean here - like this?

Code: [Select]
// handle signal generation
always @(posedge pclk)
begin
if (reset) // reset to start of frame
begin
h_count <= (H_RES - 2);
v_count <= (SCANLINES - 2);
//z_count <= 1'b0;
hsync   <= 1'b0;
vsync   <= 1'b0;
vde     <= 1'b0;
hde     <= 1'b0;
end
else
begin
if (pc_ena[3:0] == 0) // once per pixel
begin

// Horizontal blanking area - set HDE LOW
if (h_count == IMAGE_OFFSET_X + H_RES - 1)    *******  Added IMAGE_OFFSET_X in here
begin
hde <= 1'b0;
end

// check for generation of HSYNC pulse
if (h_count == HS_STA)
begin
hsync <= 1'b1; // turn on HSYNC pulse
end
else if (h_count == HS_END)
hsync <= 1'b0; // turn off HSYNC pulse

// check for generation of VSYNC pulse
if (v_count == VS_STA)
begin
vsync <= 1'b1; // turn on VSYNC pulse
end
else if (v_count == VS_END)
vsync <= 1'b0; // turn off VSYNC pulse

// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin
h_count <= 1'b0;
hde <= 1'b1;  // Turn on horizontal video data enable

// Now h_count has been zeroed, check if the V-count should be cleared at end of SCANLINES
if (v_count == SCANLINES - 1)
begin
v_count <= 1'b0;
vde <= 1'b1; // Turn on vertical video data enable
end
else
begin // If v_count isn't being cleared, increment v_count
v_count <= v_count + 1'b1; // increment v_count to next scanline
if (v_count == V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area
end
end
else // not at end of scanline, so just increment horizontal counter
h_count <= h_count + 1'b1;
if (h_count == H_RES - 1)
hde <= 1'b0 ;  // Turn off vertical video data enable

end // if (pc_ena)

end // else !reset

end // always @clk

...but not sure about pushing vde - it seems to be fine as it uses triggers that incorporate IMAGE_OFFSET_Y?

I'm also forcing you to setup a simulation of the sync_gen.v so you may check if the feature works correctly.

Your going to need this step.  Compile and check will no longer suffice when you need to see if each signal happens on the right pixel exactly.

This is going to take me a little time to set up and interpret correctly, but I understand that it's an important step.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2019, 09:26:50 pm
Now, for example, if we set the base address to $003F00 (16128), when the input address[19:0] = $003F00 through $003FFF, and a write enable comes in, the correct 8 bits will be filled into the right 1 of 256 GPU_HW_Control_regs.

Right, I'm with you.  So I can set WRITE_BASE_ADDRESS based off of HW_REGS_SIZE:

Code: [Select]
parameter HW_REGS_SIZE = 256;
parameter [HW_REGS_SIZE - 1:0] RESET_BYTES;
parameter WRITE_BASE_ADDRESS = 16384 - HW_REGS_SIZE;

Assuming I'm not out by 1 in those calculations - I seem to have real difficulty with when and where I should be subtracting 1 from the figures.  :o  But the above figures will give a WRITE_BASE_ADDRESS of $3F00, according to my trusty Windows calculator..  :-DMM

I guess the above calculation for WRITE_BASE_ADDRESS is fine as long as we always want it at the end of the GPU's RAM space.

Don't think about addr > or addr <, think about just the number of address wires in the 'WRITE_BASE_ADDRESS' and the input address[19:0] just need to be equal while the least significant address wires are are not used if addressA==AddressB test.  These low address bits are only used to point to the correct GPU_HW_Control_regs for writing the 8 bit data coming in.

So we're not comparing the write address against a range of suitable addresses, but instead checking for WRITE_ADDRESS[19:8] == WRITE_BASE_ADDRESS[19:8]?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2019, 09:42:18 pm

This only happens when FONT_8x16 is set to 1 in vid_osd_generator...  :-//

If they work, the others should work too.

Well, it looked like it might be working, but the errors in GPUtalk are preventing a clean bin transfer to the GPU.  I can't imagine what the problem could be, but you might have an idea?
There shouldn't be a problem with the GPUtalk and the 8x16 setting as it has nothing to do with the com at all.
GPU talk says 'received 0 bytes of a read expecting 256 bytes.'.  Now, GPU talk doesn't check if the com port it opened is actually working.  So it may be transmitting data into a 'NULL' port.  This could happen if another app or GPUtalk is open in the background, or, if you remember how Quartus' USB BlasterII wouldn't work when GPUtalk was left running, since USB Blaster also uses a FTDI chip like your USB-TTL RS232 cable, maybe you just need to close the USB Blaster control window, or close and re-open GPUtalk.   It might be useful to check if you USB-RS232 cable has a RXD-TXD LED.  Or, I can add a TXD/RXD Led output signal to my RS232debugger.v and you can tie those to 2 LEDs on you dev board.  Then you can see com activity regardless of the data coming in and out.  (I'm prepping a new .v file with 2 led outputs, RXD and TXD led signals.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2019, 10:38:40 pm
I've added a LED_txd and LED_rxd to the "rs232_DEBUGGER.v".  These outputs are positive logic, so, if you dev board uses active low leds, then just add the 'exp' gate between the module outputs and the IO pins.

(Note I found a bug with the low baud rate in the rs232_debugger.v, so 1 last fix will be coming after I get a days rest.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 19, 2019, 02:49:12 pm
There shouldn't be a problem with the GPUtalk and the 8x16 setting as it has nothing to do with the com at all.

I know - I don't think the issue is with GPUtalk, though.  :o  Nothing changes with GPUtalk, whether it's talking to the 8x8-build GPU or 8x16-build version.  Is something getting changed somehow in the RS232 module in the 8x16 build?  I know it's just a single parameter that's changing, and it's not even in the RS232 module, but I don't see how GPUtalk can work fine with the 8x8 build but not the 8x16 one.  :-//

GPU talk says 'received 0 bytes of a read expecting 256 bytes.'.  Now, GPU talk doesn't check if the com port it opened is actually working.  So it may be transmitting data into a 'NULL' port.

But some data is getting through, because after 10 seconds or so the screen updates with data, and I'm able to write to the GPU, albeit not very predictably.  I happen to share the Tx/Rx lines with two of the LEDs on the dev board, so I can see activity on the serial connection at the GPU - I can also see the Tx/Rx LEDs flickering on the USB-TTL converter.

Also, immediately after testing the 8x16 build, I compile and upload the 8x8 version to the GPU and restart GPUtalk and everything works fine.  I'm careful to make sure the programmer isn't still open when I run GPUtalk, and vice-versa.

Though to me, it can't be an issue with GPUtalk as it works fine with the GPU in 8x8 mode - it must be something going wrong with the GPU build somehow?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 20, 2019, 01:20:05 pm
I've re-vamped to com and GPUtalk into a generic debugging utility.  Update coming later today.
Meanwhile, create a simulation project for just the sync_gen.v module.  You gotta learn, cause the next steps will get deep...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 20, 2019, 03:38:03 pm
Meanwhile, create a simulation project for just the sync_gen.v module.

Installing 9.1sp2 as I write this.

You gotta learn, cause the next steps will get deep...

Were you just trying to keep me motivated earlier when you said we'd hit the hardest part of the project then?  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 20, 2019, 08:43:25 pm
Meanwhile, create a simulation project for just the sync_gen.v module.

Installing 9.1sp2 as I write this.

You gotta learn, cause the next steps will get deep...

Were you just trying to keep me motivated earlier when you said we'd hit the hardest part of the project then?  ;)

It's not that it's hard, it's that you will not succeed without simulation.  You need to see what you code and internal registers are doing when you write code.  You need to test thing which you cannot generate in the real world feeding into your FPGA.  You need to test each verilog module feeding it specific controled inputs to see how it behaves.

    I've renamed to GPU_talk to RS232_Debugger.  I've cleaned up the verilog code and going to soon clean up the HEX Editor / Debugger and post it on a separate thread as it has now become/becoming a viable product all on it's own.  I've removed all the Altera dependencies in the RS232_Debugger.v so it now may work with any FPGA Vendor /  verilog compiler.

     I've also added an additional 8 real-time parallel debug ports.  4x8bit input ports and 4x8bit output ports.  In the new RS232_Debugger.exe, the 4 green ports displayed at the bottom left are real-time always updated refreshed display.  I currently connected the in0[7:0] & in1[7:0] to a new 16bit frame counter in the sync_gen.v module which you can see counting while the RS232_Debugger is running.  As for the output ports,   I tied ports out1[7:0] through out3[7:0] as a color palette selection for you OSD font.  (The foreground text color is set negative values while the background is set positive.)  You can manipulate the colors by clicking on the out1,2,3 bits in the debugger, or, hover the mouse over the out's binary bits and use the mouse wheel to increment/decrement the number.

See attached image for illustration, +, get the new GPU project and RS232_Debugger hex editor.
And if you cant get the 8x16 font working, there is something wrong with your setup, compiler install, corrupt files, or, something else.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 21, 2019, 10:19:12 am
I've renamed to GPU_talk to RS232_Debugger.  I've cleaned up the verilog code and going to soon clean up the HEX Editor / Debugger and post it on a separate thread as it has now become/becoming a viable product all on it's own.  I've removed all the Altera dependencies in the RS232_Debugger.v so it now may work with any FPGA Vendor /  verilog compiler.

[attach=1]

It certainly is a viable product.  It's working perfectly now - not sure what's changed between this project and the last, or this version of GPU_talk/RS232_Debugger and the last, but I'm not getting any problems communicating with the GPU while it's running in 8x16 mode now:

[attach=2]

Sorry about the picture quality in that second one - the sun decided to come out whilst I was trying to take the picture, but you get the idea.  ;D

     I've also added an additional 8 real-time parallel debug ports.  4x8bit input ports and 4x8bit output ports.  In the new RS232_Debugger.exe, the 4 green ports displayed at the bottom left are real-time always updated refreshed display.  I currently connected the in0[7:0] & in1[7:0] to a new 16bit frame counter in the sync_gen.v module which you can see counting while the RS232_Debugger is running.  As for the output ports,   I tied ports out1[7:0] through out3[7:0] as a color palette selection for you OSD font.  (The foreground text color is set negative values while the background is set positive.)  You can manipulate the colors by clicking on the out1,2,3 bits in the debugger, or, hover the mouse over the out's binary bits and use the mouse wheel to increment/decrement the number.

Yes, I've had some fun playing with the colours before realising I had work to do!  :-\

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 21, 2019, 12:00:43 pm
See what you can learn of setting up a simulation in QIIv9.1.  I can make myself available on the weekend to walk you through a complete simulation from scratch.  You'll probably need this as existing documentation sucks.

:( Sadly, when Altera decided to ditch their inbuilt simulator, and re-wrote their user interface to the new slower one, we lost a quick code diagnostic tool which helped one didn't want to bother with ModelSim where you could just drop and draw IO pins and registers from your project and see immediate results.

It's funny, even if you wanted to use third party simulators like ModelSim, Quartus' original Vector Waveform editor did allow the generation of vector stimulus files to be used by ModelSim and other third party simulators.  However, in the new QuartusPrime, it's vector file viewer/editor just sucks royal shit in speed and performance and editing/entering/generation waveform features compared to the old QIIv9.1 version which functions like a combined word-processor and Photoshop paint software.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: avogadro on November 21, 2019, 12:10:34 pm
I dont know if anyone mentioned but you can use wayback machine to access the site you're looking for.

https://web.archive.org/web/20190414023118/http://searle.hostei.com/grant/z80/ (https://web.archive.org/web/20190414023118/http://searle.hostei.com/grant/z80/)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 21, 2019, 12:53:49 pm
I dont know if anyone mentioned but you can use wayback machine to access the site you're looking for.

https://web.archive.org/web/20190414023118/http://searle.hostei.com/grant/z80/ (https://web.archive.org/web/20190414023118/http://searle.hostei.com/grant/z80/)

Thanks avogadro, that's all sorted now - there's a few mirror sites, as well as the wayback machine, but Grant Searle has opened another website at http://searle.wales (http://searle.wales) as well.

See what you can learn of setting up a simulation in QIIv9.1.  I can make myself available on the weekend to walk you through a complete simulation from scratch.  You'll probably need this as existing documentation sucks.

Absolutely - I'll see what I can do with the limited spare time I have before the weekend, but a walkthrough would be much appreciated.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 21, 2019, 03:15:49 pm
Okay, so while I'm waiting for the weekend to learn about simulation, I thought I'd have a go at writing a host handler to monitor the Z80's address, data and control buses and accept anything written to the 'GPU window' in memory and pass it to the GPU RAM.

I thought I'd pop my code up to be torn apart as I don't really know if I'm going down the right lines with this and would appreciate the feedback.  ;)

Basically, it should monitor the Z80's address bus and memory signals to see if a byte is being written to the window in RAM that the GPU will sit within - this should be the third 512 KB, so 0x180000 to 0x1FFFFF.  When it sees the Z80's MREQ and WR lines go low (I haven't bothered with inverting signals yet, this is purely a code exercise at the moment) and M1 is high (i.e. the Z80 is writing to memory), it checks to see if the Z80 is addressing a byte within its 512 KB window - by checking if host_addr[21:19] == 3'b011.  If it does, then it passes host_addr[18:0] to the vid_osd_generator, along with the data being written and setting h_wr_ena high so that vid_osd_generator will write the data to memory.

I've just thrown this code together really, but the more I think about it the more I worry that there could be timing problems etc.  Should I run the code off of the Z80's 8 MHz clock or the much faster GPU clock?  Are there issues with how I'm setting/resetting h_wr_ena? etc..  :-//

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0] host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM

// output
output wire [7:0] h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
output reg          h_rd_req, //
output reg          h_wr_ena, // flag HIGH when writing to GPU RAM
output wire [19:0] h_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg  [7:0]  h_wdata // 8-bit data bus to GPU RAM in vid_osd_generator

);

always @ (posedge host_CLK)
begin

// is a WR memory cycle being executed?
if (!host_M1 && host_MREQ && host_WR) begin

// is the GPU being addressed?
if (host_addr[21:19] == 3'b011) begin // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

h_wdata <= host_wr_data;
h_addr <= host_addr[18:0];
h_wr_ena <= 1;

end // gpu addressed
else begin
h_wr_ena <= 0;
end // gpu not addressed

end // memory cycle
else begin

h_wr_ena <= 0;

end

end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 21, 2019, 04:33:44 pm
Your doing ok, and for now, maybe you should keep working like this.
But, you are going to need to begin to eventually think along operating in 2 different clock domains.

1) You have a Z80 operating at 8Mhz.  It is sending you impossibly slow read and write requests.
2) Your static ram in an FPGA can operating at 125 Mhz.
3) How can I keep it running that fast and still run the Z80's 8Mhz requests?


This is not difficult.  Working/thinking like this will allow you to keep running the ram's host port at 125MHz.

If you are not sure what you are writing is functional, it is time to simulate...

Your other choice is to not change anything, but, create a separate xxxx.v module bridge to take these slow 8mhz requests and strobe them out at the system 125mhz speed.  This would be wasteful and may introduce additional clock delays.  Remember, if you clock the intel FPGA ram at 8mhz, though the writes may be taken immediately, if you do a read request, you get a response 2 clocks later unless you change the setting on the dual port ram which may kill your FMAX to a point where the GPU cant work.  Also, what happens if you do a write on one clock and a read of that same address on the next clock?  In the FPGA running at 8MHz, an additional clock cycle is required to get the new value.  Same goes for 125Mhz, however, since at 125MHz the write would go through and complete before the next Z80 read, I don't think this could be a problem unless the Z80 ran above 75MHz.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 21, 2019, 04:40:08 pm
This is the final RS232_Debugger update before I make it's own dedicated thread.  I've added page read bursts into the communications protocol.  The read and write the the GPU now operate at full speed unhinged.  This means with 128 kilobytes in the GPU, reading or writing the full memory contents should take under 2 seconds.

Let me know if it loads and sends the full 16k any faster...

I've also made the VGA 8x16 font default.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 21, 2019, 04:41:36 pm

I've just thrown this code together really, but the more I think about it the more I worry that there could be timing problems etc.  Should I run the code off of the Z80's 8 MHz clock or the much faster GPU clock?  Are there issues with how I'm setting/resetting h_wr_ena? etc..  :-//

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0] host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM

// output
output wire [7:0] h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
output reg          h_rd_req, //
output reg          h_wr_ena, // flag HIGH when writing to GPU RAM
output wire [19:0] h_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg  [7:0]  h_wdata // 8-bit data bus to GPU RAM in vid_osd_generator

);

always @ (posedge host_CLK)
begin

// is a WR memory cycle being executed?
if (!host_M1 && host_MREQ && host_WR) begin

// is the GPU being addressed?
if (host_addr[21:19] == 3'b011) begin // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

h_wdata <= host_wr_data;
h_addr <= host_addr[18:0];
h_wr_ena <= 1;

end // gpu addressed
else begin
h_wr_ena <= 0;
end // gpu not addressed

end // memory cycle
else begin

h_wr_ena <= 0;

end

end

Show me a Z80 data sheet write and read cycle waveform example.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 21, 2019, 05:10:57 pm
LOL, here you go:

[attach=1]

[attach=2]

I shoved your GPU project into my 10 year old 15K$  video scaler:

[attach=3]

Your GPU is driving a 30bit color HDMI output, with HDCP encryption... LOL, talk about overkill.  It's using around 2% of the onboard FPGA + -110% of the 2 x 1GB DDR2 sodim modules mounted under the PCB.  My project went from this:

[attach=4]

To now this:

[attach=5]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: lawrence11 on November 21, 2019, 07:14:10 pm
NOTE: This message has been deleted by the forum moderator Simon for being against the forum rules and/or at the discretion of the moderator as being in the best interests of the forum community and the nature of the thread.
If you believe this to be in error, please contact the moderator involved.
An optional additional explanation is:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on November 21, 2019, 09:36:47 pm
Shoved? Shouldn't that be more like thrown? :)

Show me a Z80 data sheet write and read cycle waveform example.

Aloow me to play librarian for a sec...

[attachimg=1]

~M1 (not shown) is an active low instruction fetch cycle type identifier signal. It is asserted during an instruction fetch and negated otherwise.

nockieboy's logic looks alright, without even looking at timing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 21, 2019, 11:26:09 pm
Shoved? Shouldn't that be more like thrown? :)

Show me a Z80 data sheet write and read cycle waveform example.

Aloow me to play librarian for a sec...

(Attachment Link)

~M1 (not shown) is an active low instruction fetch cycle type identifier signal. It is asserted during an instruction fetch and negated otherwise.

nockieboy's logic looks alright, without even looking at timing.
Oh boy, that's a joke easy.  What I was getting at looking at that illustration, create a synchronous 125mhz core clocked interface which looks like a static ram access to the host Z80 cpu, but, only eats a single 125mhz cycle from the FPGA 125mhz ram.  Hint, it pretty much looks like my 5 port design, but without the 5 cycle pixel phase.  Since the Z80 only cycles once every 3 8Mhz clock cycles, there is no need to eat up the FPGA at all.


Write Example:
Code: [Select]
-------------------------------------------------------------------------
output regs fpga_mem_addr/data/write_ena... ect

Always @ (posedge 125MHz clock ...) begin

     last_Z80wr <= Z80wr;  // This is part 1 of the secret sauce

//           *** This is part 2 of the secret sauce ***
          if (   (~Z80nwr && last_Z80nwr)    &&  ~Z80mreq  && (good page address)  ) begin    // trap the high to low transition of the Z80wr, for a single 125MHz clock event as soon as the Z80wr input falls

               fpga_mem_addr       <= Z80addr;    // register latch the z80 address and
               fpga_write_data     <= Z80data;    // data only on that falling edge of the Z80wr
               fpga_write_ena      <= 1;           // turn on the ram write request

          end else fpga_write_ena <= 0;      // at the next 125mhz clock cycle, turn off the FPGA memory write request, IE the write pulse is only a 1 clock pulsed cycle

end
-------------------------------------------------------------
(Now, this code works good since 125Mhz runs at least 4 fold faster than the Z80 8MHz buss clock.)

No Z80 clock.  FPGA ram and interface module runs at 125Mhz.  This also leaves the FPGA ram empty for around 45 additional reads or writes in between each Z80 access which will be put to use by my RS232 Debugger and the graphics accelerated drawing hardware lateron.

Now, just like I trapped the falling edge of the Z80we, you can also trap the rising or falling edge of the Z80clk inside the 'IF' as well, or, you can double register ALL the Z80 inputs.  The first set using the Z80 clock, then trigger from those registered inputs at the 125mhz clock with the single pulse transition detection trick.

The read would be a second 'IF()begin' after the write, except you would pulse out a read request to the FPGA ram, latch the data coming back from the FPGA ram.  Only the MREQ and RD, plus valid address range would switch the Z80 data port on the FPGA IO's output enable.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 22, 2019, 09:39:59 am
This is the final RS232_Debugger update before I make it's own dedicated thread.  I've added page read bursts into the communications protocol.  The read and write the the GPU now operate at full speed unhinged.  This means with 128 kilobytes in the GPU, reading or writing the full memory contents should take under 2 seconds.

Let me know if it loads and sends the full 16k any faster...

I've also made the VGA 8x16 font default.

Works fine - yes, seems to load faster than previous version and is pretty darn quick in any case.  :-+

Your doing ok, and for now, maybe you should keep working like this.
But, you are going to need to begin to eventually think along operating in 2 different clock domains.

1) You have a Z80 operating at 8Mhz.  It is sending you impossibly slow read and write requests.
2) Your static ram in an FPGA can operating at 125 Mhz.
3) How can I keep it running that fast and still run the Z80's 8Mhz requests?


This is not difficult.  Working/thinking like this will allow you to keep running the ram's host port at 125MHz.

Well, I was thinking of acting on the Z80 write as soon as it came in, setting a flag so as not to act on the write more than once, and writing the data to the GPU RAM, resetting the flag when the Z80's write action completes.  That way, the GPU and its internals would all still run at full speed.

I shoved your GPU project into my 10 year old 15K$  video scaler:
...
Your GPU is driving a 30bit color HDMI output, with HDCP encryption... LOL, talk about overkill.  It's using around 2% of the onboard FPGA + -110% of the 2 x 1GB DDR2 sodim modules mounted under the PCB.

 :wtf:   Aye carumba... :o


Shoved? Shouldn't that be more like thrown? :)

Yeah, I can't imagine Brian broke out much of a sweat trying to squeeze my project in there..!  :-DD

(Attachment Link)

~M1 (not shown) is an active low instruction fetch cycle type identifier signal. It is asserted during an instruction fetch and negated otherwise.

nockieboy's logic looks alright, without even looking at timing.

Yep - I have to check for the state of ~M1 as I don't want the GPU responding to an instruction fetch cycle - the Z80 won't be running code from the GPU RAM.  Although that's an interesting point.  Maybe I should get the GPU to return NOPs (8'b00000000) in the edge-case that the Z80 does try to read instructions from the GPU memory space?

Oh boy, that's a joke easy.  What I was getting at looking at that illustration, create a synchronous 125mhz core clocked interface which looks like a static ram access to the host Z80 cpu, but, only eats a single 125mhz cycle from the FPGA 125mhz ram.  Hint, it pretty much looks like my 5 port design, but without the 5 cycle pixel phase.  Since the Z80 only cycles once every 3 8Mhz clock cycles, there is no need to eat up the FPGA at all.

I guess the only consideration I have to make is that it needs to share the access to the RAM with the RS232 debugger module?

Write Example:
Code: [Select]
-------------------------------------------------------------------------
output regs fpga_mem_addr/data/write_ena... ect

Always @ (posedge 125MHz clock ...) begin

     last_Z80wr <= Z80wr;  // This is part 1 of the secret sauce

//           *** This is part 2 of the secret sauce ***
          if (   (~Z80nwr && last_Z80nwr)    &&  ~Z80mreq  && (good page address)  ) begin    // trap the high to low transition of the Z80wr, for a single 125MHz clock event as soon as the Z80wr input falls

               fpga_mem_addr       <= Z80addr;    // register latch the z80 address and
               fpga_write_data     <= Z80data;    // data only on that falling edge of the Z80wr
               fpga_write_ena      <= 1;           // turn on the ram write request

          end else fpga_write_ena <= 0;      // at the next 125mhz clock cycle, turn off the FPGA memory write request, IE the write pulse is only a 1 clock pulsed cycle

end
-------------------------------------------------------------
(Now, this code works good since 125Mhz runs at least 4 fold faster than the Z80 8MHz buss clock.)

Yes - that's kinda what I was planning to do, but yours is a bit more straightforward.  ;)

No Z80 clock.  FPGA ram and interface module runs at 125Mhz.  This also leaves the FPGA ram empty for around 45 additional reads or writes in between each Z80 access which will be put to use by my RS232 Debugger and the graphics accelerated drawing hardware lateron.

So I'll just need to create a bus mux for the two write inputs to the host port in the vid_osd_generator, like the multiport_gpu_ram module we have currently, to gate the writes to the second port of the GPU RAM?

Now, just like I trapped the falling edge of the Z80we, you can also trap the rising or falling edge of the Z80clk inside the 'IF' as well, or, you can double register ALL the Z80 inputs.  The first set using the Z80 clock, then trigger from those registered inputs at the 125mhz clock with the single pulse transition detection trick.

That might be necessary to return data to the Z80 for a read request, but I'm liking the simplicity of your example above for the writes.

The read would be a second 'IF()begin' after the write, except you would pulse out a read request to the FPGA ram, latch the data coming back from the FPGA ram.  Only the MREQ and RD, plus valid address range would switch the Z80 data port on the FPGA IO's output enable.

The Z80 data port on the FPGA is going to need to be bidirectional - bearing in mind my extremely limited experience with FPGAs, will that be a problem or require any special considerations?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 22, 2019, 10:45:33 am
Okay, latest update to host_handler below:

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0] host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg          h_rd_req, //
output reg          gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg [19:0] gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg  [7:0]  gpu_wdata // 8-bit data bus to GPU RAM in vid_osd_generator

);

reg last_Z80_WR = 1'b1;

always @ (posedge GPU_CLK)
begin

// is this the start of a WR memory cycle being executed within the GPU's memory window?
// host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF
if ((~host_WR && last_Z80_WR) && host_M1 && ~host_MREQ && (host_addr[21:19] == 3'b011))
begin
// yes - pass the address (limited to 512 KB) and data through
gpu_wdata <= host_wr_data;
gpu_addr <= host_addr[18:0];
gpu_wr_ena <= 1'b1;

end // memory cycle
else begin

gpu_wr_ena <= 1'b0;

end

last_Z80_WR <= host_WR;

end

endmodule

I think this is looking quite usable - I moved the last_Z80_WR assignment to the end, otherwise the GPU would always be comparing the current Z80_WR signal with itself (or a few nanoseconds old).  Hope that's right and I haven't misunderstood something.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 22, 2019, 12:06:09 pm
Got it right.

     As for the bidirectional port, there is the 'bidir' pin and 'tri' block diagram symbols in Quartus block diagram entry.  Just make add a 'bidir' pin on you block diagram.  Label it 'host_data[7..0]'.  Then add a 'tri' and tie it to the 'bidir' pin.  On the 'bidir' pin side, label that wire 'host_data_in[7..0].  On the other side of the 'tri' symbol, add a buss wire and label it 'host_data_out[7..0]'.  On the top of the 'tri' symbol, just add a single wire and label it 'host_data_oe'.  The rest should be self explanatory.

     I would also make an output pin or 2 from your GPU host interface to control the direction and output enables of the TTL 3.3v to 5v level shifters if you are using them.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 22, 2019, 12:15:07 pm
I think this is looking quite usable - I moved the last_Z80_WR assignment to the end, otherwise the GPU would always be comparing the current Z80_WR signal with itself (or a few nanoseconds old).  Hope that's right and I haven't misunderstood something.  ???
     This is wrong, all the compares inside the 'IF()' are only finalized at the next 'always @ (posedge GPU_CLK)'.  So, as long as the GPU clock isn't faster than the combination of logic in the FPGA, which is spelled out to you by the compiler's FMAX in the compilation report, it doesn't matter where you place the 'last_Z80_WR <= host_WR;' line.  Remember, the compiler is wiring a breadboard with your description.  You aren't telling it where to place the wires and IC logic on that breadboard, being the FPGA fabric.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 22, 2019, 01:33:55 pm
Some code cleaning tips:

Quote from: nockieboy on Today at 05:45:33 am

 
Code: [Select]
  module host_handler (

    // input
    input wire reset, // GPU reset signal
    input wire GPU_CLK, // GPU clock (125 MHz)
    input wire host_CLK, // Microcom clock signal (8 MHz)
    input wire host_M1, // Z80 M1 - active LOW
    input wire host_MREQ, // Z80 MREQ - active LOW
    input wire host_WR, // Z80 WR - active LOW
    input wire host_RD, // Z80 RD - active LOW
    input wire [21:0] host_addr, // Microcom 22-bit address bus
    input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
   
    // output
    //output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
    //output reg          h_rd_req, //
    output reg          gpu_wr_ena, // flag HIGH when writing to GPU RAM
    output reg [19:0] gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
    output reg  [7:0]  gpu_wdata // 8-bit data bus to GPU RAM in vid_osd_generator

    );

    parameter MEMORY_RANGE = 3'b011;  // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

    reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered.
    reg last_Z80_RD = 1'b0;

    assign mem_window = (host_addr[21:19] == MEMORY_RANGE) ; // Define an active memory range
    assign Z80_mreq = ~host_MREQ && host_M1 ; // Define a bus memory access state
    assign Z80_write = ~host_WR && last_Z80_WR ; // Isolate a single write transaction
    assign Z80_read = ~host_RD && last_Z80_RD ; // Isolate a single read transaction

    assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write ; // Define a GPU Write action
    assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read ; // Define a GPU Read action
    assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD ; // Define the time the GPU ouputs data onto the Z80 data bus.

    always @ (posedge GPU_CLK)
    begin

    // is this the start of a WR memory cycle being executed within the GPU's memory window?
   
    if ( Write_GPU_RAM )
    begin
    // yes - pass the address (limited to 512 KB) and data through
    gpu_wdata <= host_wr_data;
    gpu_addr <= host_addr[18:0];
    gpu_wr_ena <= 1'b1;

    end // memory cycle
    else begin
   
    gpu_wr_ena <= 1'b0;
   
    end
   
    last_Z80_WR <= host_WR;

    end

    endmodule

You should be able to workout the rest.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 22, 2019, 04:48:37 pm
Ooops, to prevent compiler warnings, add this 1 line of code to the above code:

Code: [Select]
wire  mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe ;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 22, 2019, 05:12:05 pm
Some code cleaning tips:

Quote from: nockieboy on Today at 05:45:33 am

 
Code: [Select]
  module host_handler (

    // input
    input wire reset, // GPU reset signal
    input wire GPU_CLK, // GPU clock (125 MHz)
    input wire host_CLK, // Microcom clock signal (8 MHz)
    input wire host_M1, // Z80 M1 - active LOW
    input wire host_MREQ, // Z80 MREQ - active LOW
    input wire host_WR, // Z80 WR - active LOW
    input wire host_RD, // Z80 RD - active LOW
    input wire [21:0] host_addr, // Microcom 22-bit address bus
    input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
   
    // output
    //output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
    //output reg          h_rd_req, //
    output reg          gpu_wr_ena, // flag HIGH when writing to GPU RAM
    output reg [19:0] gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
    output reg  [7:0]  gpu_wdata // 8-bit data bus to GPU RAM in vid_osd_generator

    );

    parameter MEMORY_RANGE = 3'b011;  // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

    reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered.
    reg last_Z80_RD = 1'b0;

    assign mem_window = (host_addr[21:19] == MEMORY_RANGE) ; // Define an active memory range
    assign Z80_mreq = ~host_MREQ && host_M1 ; // Define a bus memory access state
    assign Z80_write = ~host_WR && last_Z80_WR ; // Isolate a single write transaction
    assign Z80_read = ~host_RD && last_Z80_RD ; // Isolate a single read transaction

    assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write ; // Define a GPU Write action
    assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read ; // Define a GPU Read action
    assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD ; // Define the time the GPU ouputs data onto the Z80 data bus.

    always @ (posedge GPU_CLK)
    begin

    // is this the start of a WR memory cycle being executed within the GPU's memory window?
   
    if ( Write_GPU_RAM )
    begin
    // yes - pass the address (limited to 512 KB) and data through
    gpu_wdata <= host_wr_data;
    gpu_addr <= host_addr[18:0];
    gpu_wr_ena <= 1'b1;

    end // memory cycle
    else begin
   
    gpu_wr_ena <= 1'b0;
   
    end
   
    last_Z80_WR <= host_WR;

    end

    endmodule

You should be able to workout the rest.

Awesome, thank you.   ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 22, 2019, 07:47:18 pm
As for the bidirectional port, there is the 'bidir' pin and 'tri' block diagram symbols in Quartus block diagram entry.  Just make add a 'bidir' pin on you block diagram.  Label it 'host_data[7..0]'.  Then add a 'tri' and tie it to the 'bidir' pin.  On the 'bidir' pin side, label that wire 'host_data_in[7..0].  On the other side of the 'tri' symbol, add a buss wire and label it 'host_data_out[7..0]'.  On the top of the 'tri' symbol, just add a single wire and label it 'host_data_oe'.

So, something like this?

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 22, 2019, 08:49:16 pm
As for the bidirectional port, there is the 'bidir' pin and 'tri' block diagram symbols in Quartus block diagram entry.  Just make add a 'bidir' pin on you block diagram.  Label it 'host_data[7..0]'.  Then add a 'tri' and tie it to the 'bidir' pin.  On the 'bidir' pin side, label that wire 'host_data_in[7..0].  On the other side of the 'tri' symbol, add a buss wire and label it 'host_data_out[7..0]'.  On the top of the 'tri' symbol, just add a single wire and label it 'host_data_oe'.

So, something like this?

(Attachment Link)
LOL..., that's backwards, like this: (Hint, take a look ad the direction of the 'tri' buffer.)
[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 22, 2019, 10:20:20 pm
LOL..., that's backwards, like this: (Hint, take a look ad the direction of the 'tri' buffer.)
(Attachment Link)

 :palm:

Attempt 2:

[attachimg=1]

h_data_oe should be HIGH to output data, right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 06:34:00 am
Yes, always positive logic.

Also, when naming you Z80 ports, or host ports, use caps for the signal control  names an add a lowercase 'n' in front so you know those are deliberate negative logic.  EG:

h_nWR
h_nRD
h_nMREQ

Keep the 'n' wherever the logic is negative, so, inside the verilog module, you may make wires:
input h_nWR...

wire h_wr;
assign h_wr = ~h_nWR;
....
If a verilog/hdl friendly way of having the '!' or '/' in front of the signal, or having the bar on top of the signal name.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 10:13:48 am
Okay, this is wrong as I'm not sure about delaying the output of data back to the Z80 whilst waiting for the read data to come from the GPU, but this is my first attempt at a 'read' function:

Code: [Select]
if (Read_GPU_RAM)
begin

gpu_addr <= host_addr[18:0]; // pass address to GPU RAM

// wait a clock cycle?

data_dir <= 1'b1; // switch level converter to -> Z80
host_data_ena <= 1'b1; // drive data outputs
host_data[7:0] <= gpu_r_data[7:0]; // set data to output

end
else begin

data_dir <= 1'b0; // ensure data pins aren't driven when not reading

end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 10:32:33 am
Okay, this is wrong as I'm not sure about delaying the output of data back to the Z80 whilst waiting for the read data to come from the GPU, but this is my first attempt at a 'read' function:

Code: [Select]
if (Read_GPU_RAM)
begin

gpu_addr <= host_addr[18:0]; // pass address to GPU RAM

// wait a clock cycle?

data_dir <= 1'b1; // switch level converter to -> Z80
host_data_ena <= 1'b1; // drive data outputs
host_data[7:0] <= gpu_r_data[7:0]; // set data to output

end
else begin

data_dir <= 1'b0; // ensure data pins aren't driven when not reading

end

Missing too much stuff.  Let's see the whole program...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 12:30:45 pm
I've attached the GPU project with the final RS232_Debugger setup.  This version passes the 'ADDR_SIZE' parameter to the RS232_Debugger client on the PC.  I've also attached the updated client as it expects this reading within one of the commands it uses.  Let me know if they work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 04:19:14 pm
Missing too much stuff.  Let's see the whole program...

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0] host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_r_data,

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg          h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg data_dir, // control level converter direction for data flow
output reg [19:0] gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg [7:0] gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0] host_data,
output reg host_data_ena // flag HIGH to write data back to Z80

);

parameter MEMORY_RANGE = 3'b011; // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;

assign mem_window = (host_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~host_MREQ && host_M1 ; // Define a bus memory access state
assign Z80_write = ~host_WR && last_Z80_WR ; // Isolate a single write transaction
assign Z80_read = ~host_RD && last_Z80_RD ; // Isolate a single read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read ; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD ; // Define the time the GPU ouputs data onto the Z80 data bus

always @ (posedge GPU_CLK)
begin

// is this the start of a WR memory cycle being executed within the GPU's memory window?
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin
// yes - pass the address (limited to 512 KB) and data through
gpu_wdata <= host_wr_data;
gpu_addr <= host_addr[18:0];
gpu_wr_ena <= 1'b1;

end // memory cycle
else begin

gpu_wr_ena <= 1'b0;

end

if (Read_GPU_RAM)
begin

gpu_addr <= host_addr[18:0]; // pass address to GPU RAM

// wait a clock cycle?

data_dir <= 1'b1; // switch level converter to -> Z80
host_data_ena <= 1'b1; // drive data outputs
host_data[7:0] <= gpu_r_data[7:0]; // set data to output


end
else begin

data_dir <= 1'b0; // ensure data pins aren't driven when not reading

end

last_Z80_WR <= host_WR;

end

endmodule

There ya go.  :-+

Oh - apologies for the tabs - I've no idea what's going on with my editors and pasting code into other areas, but my tabs are all messed up.  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 04:47:31 pm
Now, you need to explain to me why I made these changes and where the pitfalls are:

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0]   host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_r_data,

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   host_data,
output reg host_data_ena // flag HIGH to write data back to Z80

);

parameter MEMORY_RANGE = 3'b011; // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;

assign mem_window = (host_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~host_MREQ && host_M1 ; // Define a bus memory access state
assign Z80_write = ~host_WR && last_Z80_WR ; // Isolate a single write transaction
assign Z80_read = ~host_RD && last_Z80_RD ; // Isolate a single read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read ; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD ; // Define the time the GPU ouputs data onto the Z80 data bus

always @ (posedge GPU_CLK)
begin

// is this the start of a WR memory cycle being executed within the GPU's memory window?
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin
// yes - pass the address (limited to 512 KB) and data through
gpu_wdata <= host_wr_data;
gpu_addr <= host_addr[18:0];
gpu_wr_ena <= 1'b1;

end // memory cycle
else begin

gpu_wr_ena <= 1'b0;

end

if (Read_GPU_RAM)

begin
gpu_addr <= host_addr[18:0] ; // pass address to GPU RAM
gpu_rd_req <= 1'b1 ;               // Send a read request to GPU.

end else if (gpu_rd_rdy)

begin
gpu_rd_req <= 1'b0;                // End the read request once the read is ready
host_data[7:0]  <= gpu_r_data[7:0]; // Latch the GPU ram read into the output register for the Z80
end

data_dir      <= GPU_data_oe ;
host_data_ena <= GPU_data_oe ;

last_Z80_WR <= host_WR;
last_Z80_RD <= host_RD;

end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 05:16:43 pm
Now, you need to explain to me why I made these changes and where the pitfalls are:

Code: [Select]
if (Read_GPU_RAM)

begin
gpu_addr <= host_addr[18:0] ; // pass address to GPU RAM
gpu_rd_req <= 1'b1 ;               // Send a read request to GPU.

Okay, so this piece of code is triggered on the falling edge of the Z80 RD signal and is effectively executed once per Z80 read cycle.  It passes the requested address through to the GPU RAM and sets gpu_rd_req HIGH to signal a read.  There's no corresponding input in multiport_gpu_ram.v for this 'gpu_rd_req' signal, so I'm guessing this is for some sort of mux with the RS232 input to the GPU RAM?

Code: [Select]
end else if (gpu_rd_rdy)

begin
gpu_rd_req <= 1'b0;                // End the read request once the read is ready
host_data[7:0]  <= gpu_r_data[7:0]; // Latch the GPU ram read into the output register for the Z80
end

This bit of code above is executed when 'gpu_rd_rdy' is high - again, this isn't defined in the module but must be an input (reg?) from the bus mux which I've yet to create which will gate GPU RAM access between the RS232 module and the Z80 module here.  The gpu_rd_req signal is released (pulled LOW) so the (yet-to-be-created) bus mux can allow the RS232 module access to the GPU RAM again and prevent repeated memory accesses by the Z80 module.  The returned data held in the gpu_r_data registers is passed through to the data output to the Z80.

Code: [Select]
data_dir      <= GPU_data_oe ;
host_data_ena <= GPU_data_oe ;

last_Z80_WR <= host_WR;
last_Z80_RD <= host_RD;

Finally, at the end of every GPU clock cycle, data_dir and host_data_ena are set high depending on whether a valid memory read access is detected, and the edge-detecting last_Z80_WR and last_Z80_RD flags are updated with the current status of the WR and RD lines from the Z80.

As for pitfalls....  :-\  Erm... gpu_rd_rdy isn't reset in the host_handler - so it must be a wire input from the mux module which would go HIGH when it receives data from the multiport_GPU_RAM module, and be reset by mux module when it detects gpu_rd_req going LOW?  Not really a pitfall, more of an observation.

Hmm.. not sure I know enough about the workings of the system to identify pitfalls?  Is there a chance it will still be driving the data outputs a clock or two after the end of the RD cycle?  That's not really a pitfall either though - at 125 MHz, there should be plenty of time for the data_dir signal to update the buffer on the Z80 data bus and get it to reverse direction before the next memory cycle...

Can I phone a friend or ask the audience?  ;)

EDIT:

Shouldn't gpu_rd_req be assigned LOW at the start?

Code: [Select]
assign gpu_rd_req = 1'b0;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 06:00:41 pm
You pretty much got it.

The only pitfall to mention is that the new added output reg, gpu_re_req stays high until the incoming confirmation signal gpu_rd_rdy.  Externally, when muxing, or what will be 'priority' selecting access to the gpu's host memory port will need to understand that when the req goes high, it only needs a single read, and it should only make the rdy pulse high after the right address made it through the ram and the ram's output contents are correct, not before.

In the case of having the host ram just tied to this one module alone, you would tie the rdy to 1 (vcc) and ignore the req signal as the ram would always feed the data out correctly within 2 clock cycles of the read address change.

Now, is there any change you can make to ensure no output enable collision between your external bidirectional data buffer and the FPGA tristated IO pins.  There should be a control for outputting data from the IO level translator to the FPGA.  Show me what IC you will be using...


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 06:13:07 pm
Now, is there any change you can make to ensure no output enable collision between your external bidirectional data buffer and the FPGA tristated IO pins.  There should be a control for outputting data from the IO level translator to the FPGA.  Show me what IC you will be using...

I'm using a 74LVC245 - datasheet here (http://www.ti.com/lit/ds/symlink/sn74lvc245a.pdf).  It has DIRection and OE pins.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 06:16:42 pm
Remember, all you need is an OE to the FPGA side, or in this case, you just need the 2 control signals setup properly, 'DIR' and 'OE'.  So, I recommend changing your Z80 module's code to just drive those 2 wires.

You will also want to configure the data buss IOs on your FPGA to weak-pullup.  This is for when the buss is in high impedance, your IO's wont float in noise.

BTY, did you like my additions to you gpu core?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 06:19:26 pm
The only pitfall to mention is that the new added output reg, gpu_re_req stays high until the incoming confirmation signal gpu_rd_rdy.  Externally, when muxing, or what will be 'priority' selecting access to the gpu's host memory port will need to understand that when the req goes high, it only needs a single read, and it should only make the rdy pulse high after the right address made it through the ram and the ram's output contents are correct, not before.

Okay, so that'll just need some similar if...end conditionals like the host_handler module has, that's simple enough.

In the case of having the host ram just tied to this one module alone, you would tie the rdy to 1 (vcc) and ignore the req signal as the ram would always feed the data out correctly within 2 clock cycles of the read address change.

Well, this is probably how I'll test it initially - I'll disconnect the RS232 interface and just have the host_interface module connected, then add the RS232 back in later when I'm confident the bus muxer is working for the host_interface and RS232 modules.

If the RAM is feeding back data in 2 clock cycles, don't I need to worry about what's on the data bus in the first two cycles then?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 07:07:29 pm
This is what the simulator is for if you wish to visualize what's going on, however, look at this image:
[attachimg=1]

Running you core at 48Mhz would probably do it all the time, never mind your current 125Mhz core.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 07:47:24 pm
Remember, all you need is an OE to the FPGA side, or in this case, you just need the 2 control signals setup properly, 'DIR' and 'OE'.  So, I recommend changing your Z80 module's code to just drive those 2 wires.

If I add a 'data_oe', that can drive the OE pin of the 245 along with data_dir.  Hmm.. going to have to think about how to implement that as it takes a non-trivial amount of time for the 245 to switch direction and enable/disable its outputs, i.e. 4-8ns to enable, 4-7ns to disable outputs under typical conditions. 

You will also want to configure the data buss IOs on your FPGA to weak-pullup.  This is for when the buss is in high impedance, your IO's wont float in noise.

Fair point, well made.  :-+

BTY, did you like my additions to you gpu core?

 ??? :-\ Erm... rushes off to check the code.  :o  What changes again?  ^-^

This is what the simulator is for if you wish to visualize what's going on, however, look at this image:
(Attachment Link)

Running you core at 48Mhz would probably do it all the time, never mind your current 125Mhz core.

Yeah, it's pretty clear to me that timings aren't really an issue when I'm running the FPGA at 125 MHz.  ;)  Looks to me like I have nearly 125ns from MREQ going HIGH (and the FPGA shutting off the data bus output) before the next use of the Z80's data bus.

I just need to work out what I'm doing with the OE and DIR pins of the 245.  data_dir (and the h_data_dir pin) control the direction of the 245.  I need a new data_oe output and pin for the 245 OE and some gubbins in the host_handler for them...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 07:48:25 pm
So I've added a 245_OE pin, from data_oe internally to the host_handler.  It runs an inverted signal (see the design image above), so the Verilog remains active positive whilst the output is active LOW, which matches the chip's logic.  data_oe is set LOW from the outset (see code attached)... but I don't think (as usual) it's 100% right.

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0]   host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_r_data,
input wire gpu_rd_rdy,

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   host_data,
output reg host_data_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg data_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;

assign mem_window = (host_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~host_MREQ && host_M1; // Define a bus memory access state
assign Z80_write = ~host_WR && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~host_RD && last_Z80_RD; // Isolate a single read transaction
assign Z80_nread = host_RD && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0;
assign data_oe = 1'b0;

always @ (posedge GPU_CLK)
begin

// is this the start of a WR memory cycle being executed within the GPU's memory window?
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin
// yes - pass the address (limited to 512 KB) and data through
data_dir <= GPU_data_oe; // set 245 direction
data_oe <= 1'b1; // enable 245 to allow data through

// ***** I'll need to delay this next bit at least 5ns to allow the 245 to enable its outputs ???

gpu_wdata <= host_wr_data;
gpu_addr <= host_addr[18:0];A
gpu_wr_ena <= 1'b1;

end // memory cycle
else begin

gpu_wr_ena <= 1'b0;

end

if (Read_GPU_RAM)
begin

gpu_addr <= host_addr[18:0]; // pass address to GPU RAM
gpu_rd_req <= 1'b1; // Send a read request to GPU.
data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
data_oe <= 1'b1; // enable 245 data output

end else if (gpu_rd_rdy)
begin

gpu_rd_req <= 1'b0;                // End the read request once the read is ready
host_data[7:0] <= gpu_r_data[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (gpu_rd_rdy && Z80_nread)
begin

// end of read transaction
data_oe <= 1'b0; // disable 245 data output

end

data_dir      <= GPU_data_oe;
host_data_ena <= GPU_data_oe;

last_Z80_WR <= host_WR;
last_Z80_RD <= host_RD;

end

endmodule

Oh, and apologies for the ridiculous tabs again - it looks fine on my editor, honest!  ::)

I'm thinking of moving the end of 'read request' signal to the // end of read transaction part of the if block.  That way, the mux can turn off gpu_rd_rdy as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 23, 2019, 09:50:20 pm
Ok, I see your point about the switch and output enable.  This is not hard to solve, however, first lets see how and when we want the '245 to be engaged.  Including the FPGA output enable.

Look here:
[attachimg=1]

Legend:
White and green areas, the 245 is disabled.
Green = This is where your 1 shot triggers take place.
Red = Your GPU FPGA output enable's data & the 245 is switched on with direction towards the Z80.
Blue = Switch off all output enables & 245.

Purple,  turn on 245 and make it's direction to feed data to the GPU.
Yellow, at least 8ns later, plus say another 20ns for good measure (this is where defining the input tsu/th values in the compiler becomes important to verify proper timing functionality during fitting, but for now, 20ns is extravagant to a point where you can ignore this.), read the FPGA input port data and write it to memory, and you may also then turn off the 245.  Optionally, you can wait another few ns before turning off the 245.

Remember, during the purple, you do not want the 245 to send any output on the Z80 by accident at all, even for a ns.
Same during the red period, you do not want the 245 to accidentally pulse any output on the FPGA data bus at all.

Let's see what you can code to make the second half (memory write cycle) work properly no matter what.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 23, 2019, 11:30:07 pm
Let's see what you can code to make the second half (memory write cycle) work properly no matter what.

Okay... here's some code:

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0]   host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_r_data,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   host_data,
output reg host_data_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg data_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal

assign mem_window = (host_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~host_MREQ && host_M1; // Define a bus memory access state
assign Z80_write = ~host_WR && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~host_RD && last_Z80_RD; // Isolate a single read transaction
assign Z80_nread = host_RD && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0;
assign data_oe = 1'b0;

always @ (posedge GPU_CLK)
begin

// is this the start of a WR memory cycle being executed within the GPU's memory window?
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin
// yes - pass the address (limited to 512 KB) and data through
data_dir <= GPU_data_oe; // set 245 direction
data_oe <= 1'b1; // 'turn on' 245

// ***** I'll need to delay this next bit at least 5ns to allow the 245 to enable its outputs ???

gpu_wdata <= host_wr_data;
gpu_addr <= host_addr[18:0];A
gpu_wr_ena <= 1'b1;

end // memory cycle
else begin

gpu_wr_ena <= 1'b0;

end

if (Read_GPU_RAM)
begin

gpu_addr <= host_addr[18:0]; // pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
data_oe <= 1'b1; // 'turn on' 245

end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= gpu_rd_rdy; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
host_data_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0;                // End the read request once the read is ready
host_data[7:0] <= gpu_r_data[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (data_hold && Z80_nread)
begin

// data is being output to Z80, which has signalled end of read transaction
data_oe <= 1'b0; // turn off 245
data_hold <= 1'b0; // reset the latch
host_data_ena <= 1'b0; // set bidir pins to input

end

data_dir      <= GPU_data_oe;
host_data_ena <= GPU_data_oe;

last_Z80_WR <= host_WR;
last_Z80_RD <= host_RD;

end

endmodule


Haven't touched the WRITE conditional, so not sure if it's compatible with the 245 controls in the READ conditional (it's probably not).

Okay, brief explanation of what I was hoping to do with the above code.  If Read_GPU_RAM is HIGH, a read transaction from the Z80 has been detected:
Then nothing should happen for a couple of cycles, until gpu_rd_rdy is asserted HIGH for one clock cycle by the mux:
This state is held until the Z80 has read the data and ends the read cycle by setting RD HIGH.  This triggers the last part of the conditional structure:
I think that might work...  ???  But as I said, not sure about the write conditional now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 24, 2019, 09:00:55 am
Small tip you probably want to distinguish any active low signals with something in the name. Like for example calling "host_RD" instead "host_RDn" or "host_RD_N" or "host_nRD" or whatever. There is no standard convention for it, my personal preference is adding a extra n on the end (I use this on my cirucit schematics too).

As for the bus coming out of there into memory you could consider using one of the FPGA bus standards so that naming of the signals is firmly defined and the documentation for that bus is already written. The bus specification has well thought out rules for how to use the bus in a way that makes it compatible with a wide range of situations and the documentation PDF will have lots of timing diagrams (I find these very useful when programing HDL as i can see exactly what needs to happen on what clock edge).

The standard "open source" FPGA bus is called Wishbone: https://en.wikipedia.org/wiki/Wishbone_(computer_bus) (https://en.wikipedia.org/wiki/Wishbone_(computer_bus))
Altera has its own proprietary spec called the Avalon bus: https://www.intel.com/content/www/us/en/programmable/documentation/nik1412467993397.html (https://www.intel.com/content/www/us/en/programmable/documentation/nik1412467993397.html)
There are plenty of other buses like the AXI AHB...etc that are used in ARM processors and lots more but they are complex due to all the features they have.

Technically there is no clear performance advantage of one bus over another, for basic functionality they all do the same thing. When you are developing for Intel/Altera there is however some advantage to be had in using the Avalon bus. Since its a bus they have developed means that all IP modules (Such as a SDRAM controller) you get from Altera will have this same bus interface and so will be easy to connect to other Avalon buses. Also if you want to use the Quartus Qsys (formerly SOPC Builder) to auto-magicaly generate the memory bus switching fabric, then you need to have Avalon buses on all your blocks. For simple systems Qsys is not that useful, but when you start having many devices connected by a memory bus and multiple masters and all that it can be an amazing help. You just hook up your devices to the bus with a single line and Qsys will figure out how to make that happen under the hood. It works even if the buses are different such as 32bit bus going into a 8bit one, two buses running on different clocks, different latency... etc as it will insert the appropriate bus adapter to convert it. If there are multiple masters on a bus it will automatically insert arbitration logic to make all the masters play nice with each other without the master even knowing about it (bus just looks busy for a unusually long time if another master is using it). It also takes care of all address decoding for you so you simply edit your address map in a table for where in memory each device is supposed to appear.

Making use of Qsys does require a bit of extra work tho. In addition it giving it the .v file of your module you also have to explain to it what pins do what. It needs to know where every pin of the Avalon bus is, how many buses there are (You can have 10 memory buses into one block if you like) and for each bus it needs to know the timing specifications such as what latency the read and write cycles happen on, if it supports burst transfers etc.. For example i did this when i had a board with a OMAP 138L microprocessor(450MHz ARM+DSP) and a FPGA. The processor had a SRAM style bus going out of it that my FPGA sat on as a peripheral much like you are doing here with the Z80. So i wrote a module that converts a SRAM style bus into Avalon and turned it into a Qsys block. Then i could just throw a DDR2 memory controller, some GPIO for LEDs and other peripherals into the bus and so with only a few clicks they would magically appear accessible to the ARM processor in that SRAM memory window.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 10:27:33 am
Small tip you probably want to distinguish any active low signals with something in the name. Like for example calling "host_RD" instead "host_RDn" or "host_RD_N" or "host_nRD" or whatever. There is no standard convention for it, my personal preference is adding a extra n on the end (I use this on my cirucit schematics too).

As for the bus coming out of there into memory you could consider using one of the FPGA bus standards so that naming of the signals is firmly defined and the documentation for that bus is already written. The bus specification has well thought out rules for how to use the bus in a way that makes it compatible with a wide range of situations and the documentation PDF will have lots of timing diagrams (I find these very useful when programing HDL as i can see exactly what needs to happen on what clock edge).

The standard "open source" FPGA bus is called Wishbone: https://en.wikipedia.org/wiki/Wishbone_(computer_bus) (https://en.wikipedia.org/wiki/Wishbone_(computer_bus))
Altera has its own proprietary spec called the Avalon bus: https://www.intel.com/content/www/us/en/programmable/documentation/nik1412467993397.html (https://www.intel.com/content/www/us/en/programmable/documentation/nik1412467993397.html)
There are plenty of other buses like the AXI AHB...etc that are used in ARM processors and lots more but they are complex due to all the features they have.


     I recommended using the 'n' for negative signals as well.  The wishbone is actually a nice choice.  The problem with Avalon is that it's Intel proprietary.  In actually, the Z80 is the project's only interface with an outside third party device and the rest is a register memory bank mentioned in point #3 here : Unified HW-Control Register Bank (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698) and a programmable horizontal and vertical counter mentioned here: Video RAM pointer address Generator & Pixel Size Features (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2783948/#msg2783948) .  Other than 2 small palette rams taking the feed from the core memory output fed by the address generators, this would create a very powerful GPU for an 8 bit Z80.

    This thread is part work, part Verilog learning, part how to sequence, and I trying to get nockieboy and anyone else reading this thread to begin using a simulation tool, if any but a quick one at minimum just to see how important such a tool is, then maybe he will advance to full code style simulators which are well documented like Modelsim.

    In helping nockieboy, I let him begin his idea, suggest some code cleaning techniques & recommendations, then just as thing look to finish, I post a question on how not necessarily make the most useful code, but show how simple it may be to gets as a solution using thing he already learned but in a different way as you will see in my next post.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 10:51:42 am
Let's see what you can code to make the second half (memory write cycle) work properly no matter what.

Okay... here's some code:

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire host_M1, // Z80 M1 - active LOW
input wire host_MREQ, // Z80 MREQ - active LOW
input wire host_WR, // Z80 WR - active LOW
input wire host_RD, // Z80 RD - active LOW
input wire [21:0]   host_addr, // Microcom 22-bit address bus
input wire [7:0] host_wr_data, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_r_data,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to host_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   host_data,
output reg host_data_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg data_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // host_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal

assign mem_window = (host_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~host_MREQ && host_M1; // Define a bus memory access state
assign Z80_write = ~host_WR && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~host_RD && last_Z80_RD; // Isolate a single read transaction
assign Z80_nread = host_RD && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~host_RD; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0;
assign data_oe = 1'b0;

always @ (posedge GPU_CLK)
begin

// is this the start of a WR memory cycle being executed within the GPU's memory window?
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin
// yes - pass the address (limited to 512 KB) and data through
data_dir <= GPU_data_oe; // set 245 direction
data_oe <= 1'b1; // 'turn on' 245

// ***** I'll need to delay this next bit at least 5ns to allow the 245 to enable its outputs ???

gpu_wdata <= host_wr_data;
gpu_addr <= host_addr[18:0];A
gpu_wr_ena <= 1'b1;

end // memory cycle
else begin

gpu_wr_ena <= 1'b0;

end

if (Read_GPU_RAM)
begin

gpu_addr <= host_addr[18:0]; // pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
data_oe <= 1'b1; // 'turn on' 245

end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= gpu_rd_rdy; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
host_data_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0;                // End the read request once the read is ready
host_data[7:0] <= gpu_r_data[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (data_hold && Z80_nread)
begin

// data is being output to Z80, which has signalled end of read transaction
data_oe <= 1'b0; // turn off 245
data_hold <= 1'b0; // reset the latch
host_data_ena <= 1'b0; // set bidir pins to input

end

data_dir      <= GPU_data_oe;
host_data_ena <= GPU_data_oe;

last_Z80_WR <= host_WR;
last_Z80_RD <= host_RD;

end

endmodule


Haven't touched the WRITE conditional, so not sure if it's compatible with the 245 controls in the READ conditional (it's probably not).

Okay, brief explanation of what I was hoping to do with the above code.  If Read_GPU_RAM is HIGH, a read transaction from the Z80 has been detected:
  • First, we grab the address and pass it through (to the mux when it's completed)
  • Then, we assert gpu_rd_req to tell the mux we want to get data from the GPU RAM
  • The 245's direction is switched by setting data_dir to GPU_data_oe
  • Finally, data_oe is asserted HIGH, causing the 245's OE to go LOW and enable its output (the output is inverted in the design)
Then nothing should happen for a couple of cycles, until gpu_rd_rdy is asserted HIGH for one clock cycle by the mux:
  • data_hold is asserted HIGH to latch the data output to the Z80 for a time
  • gpu_rd_req is cleared LOW to stop any further read requests to the mux (which will ignore them as it's a one-shot signal)
  • host_data_ena is asserted to make the data bidir pins outputs
  • the data from the mux is passed-through to the data output for the Z80 to read
This state is held until the Z80 has read the data and ends the read cycle by setting RD HIGH.  This triggers the last part of the conditional structure:
  • data_oe is set LOW, making the 245's data pins tri-state
  • data_hold is set LOW, ready for the next read transaction
  • host_data_ena is set LOW to reset bidir pins to input
I think that might work...  ???  But as I said, not sure about the write conditional now.


Ok, now that you see it may need to sequence a set of events after a detection of a write, let's start by changing your:
Code: [Select]
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin ....
        ....end


To something like this:
Code: [Select]
reg [9:0] Z80_write_sequencer;
......
always
.......

Z80_write_sequencer[0] <= Write_GPU_RAM ;
Z80_write_sequencer[9:1] <= Z80_write_sequencer[8:0] ;

//Next... the new IF()'s

if ( Z80_write_sequencer[#] )    'perform a function, say, select 245 dir
if ( Z80_write_sequencer[#] )    'perform a function, say, make sure FPGA IO is in input mode.
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on 245 OE
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 Write address
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 data bus
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off 245 OE

.........



     Remember, the 'Write_GPU_RAM' only pulses high for 1 clock exactly right at the detection of a valid write state.  That pulse will now shift down the 'Z80_write_sequencer[9:0] ' pipe.  Now, if you choose the right #, you can keep everything clean and functional, even if the Z80 is running at a synchronous 1/2 clock speed to you GPU clock.  To make you code really nice, make a parameter something like 'BIDIR_245_Delay_clock_cycles', or, with a little math, instead use 'GPU_CLK_Frequency' and 'BIDIR_245_Delay_ns' to shift those those sequencer[#'s] so your code may auto generate the positions if you wish to run the project at any other frequency like 135MHz, or 250MHz, or 270MHz.

Bonus hint (but not necessary at your clock speed): There is a way to push this entire sequence chain up by one clock cycle sooner, let's see if you can figure this out...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 24, 2019, 11:54:09 am
]
     I recommended using the 'n' for negative signals as well.  The wishbone is actually a nice choice.  The problem with Avalon is that it's Intel proprietary.  In actually, the Z80 is the project's only interface with an outside third party device and the rest is a register memory bank mentioned in point #3 here : Unified HW-Control Register Bank (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698) and a programmable horizontal and vertical counter mentioned here: Video RAM pointer address Generator & Pixel Size Features (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2783948/#msg2783948) .  Other than 2 small palette rams taking the feed from the core memory output fed by the address generators, this would create a very powerful GPU for an 8 bit Z80.

    This thread is part work, part Verilog learning, part how to sequence, and I trying to get nockieboy and anyone else reading this thread to begin using a simulation tool, if any but a quick one at minimum just to see how important such a tool is, then maybe he will advance to full code style simulators which are well documented like Modelsim.

    In helping nockieboy, I let him begin his idea, suggest some code cleaning techniques & recommendations, then just as thing look to finish, I post a question on how not necessarily make the most useful code, but show how simple it may be to gets as a solution using thing he already learned but in a different way as you will see in my next post.

Well these standard buses (even if proprietary to a FPGA vendor) don't really lock you in to exclusively using that bus. Nobody stopping you in using a Avalon bus in a Xilinx or Lattice FPGA and no special vendor specific IP is needed to make them work. Its mostly just a common convention to make things easily work together. Much like the convention of water taps having hot left and cold right, no reason why it can't be the other way around, but sticking to a standard saves effort by not having to check where is what, it just works.

A pair of similar Wishbone and Avalon buses can sometimes be adapted to each other by simply connecting the right pins together, no logic gates at all. Sometimes it might need a few NOT and AND gates to flip and merge some signals that work differently but that's it. Its only more complex if the buses are very different (mismatched number of bits, incompatible timings, missing byte selects etc..) but for those even connecting two standard Wishbone buses needs an adapter with lots of logic, but so as long as the buses are similar its all mostly directly connected. Even the Z80 bus looks quite similar to one of the possible Wishbone bus configurations (if you rename the signals a bit and split out the bidirectional data bus). What makes adapting the Z80 bus to the internal bus more complex is mostly due to the Z80 bus running at a different clock than the internal bus. So everything needs to be buffered between them, but still not all that hard. Its mostly about using a bus with a offical name so that you can google the bus name and get documentation on how it should work with diagrams and everything. If i make my own bus i know id do a terrible job at documenting it for the future me 5 years later looking at the code and not understanding it.

On Lattice FPGAs i have indeed been sticking to the Wishbone bus because its the most popular non proprietary bus spec. Sticking to the bus spec also helps with simulation, once you have built testbenches for a wishbone master and slave you find that you can reuse those testbenches with little to no modification, exercising most other wishbone enabled modules you write yourself.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 12:44:19 pm
Ok, yes, I do think that 'nockieboy's following bridge interface naming convention could be amended:
[attach=1]

We know it is a Z80 interface specifically with Z80 names and IO symbols on one side which can be confused since his uses 'h_xxx', and the '_xxx' may be confused with the his other 'h_xxx' inside the FPGA.  What belongs where?  And how to use?

The 'h_' connections for the GPU ram should have been just been a GPU_RAM... port.  And his Z80 Verilog bridge should have had Z80_xxx names for each Z80_ signal.  And maybe the 245 buffer controls could have been labeled 'Z80_245buffer_xx'.  OMG, this would end the difficult time I have reading his code & understanding what's being wired where and how it works without needing the block diagram illustrations.

Yes, using the Avalon bus is nice for many.   

This project will eventually need read and write simultaneously to the GPU ram with 0 wait states, as this project will have a hardware draw / copy function which shares the Z80's GPU memory port.  And we want to fill/draw/copy as close to the 125Mhz in million pixels per second as possible, minus the 2.7 million possible Z80 transactions a second.  So, for this project, Yes on adopting the Avalon naming scheme if you want, but, we will need to hard wire each specific unidirectional address/data read path, write path channels into a priority encoder/selector, and take the return data into the right registers with acknowledge will be nothing more than a address & read req, or write req on each dedicated address line to the ram.  Coming out will be the read rdy which is just the read_req piped through with the right clk delay of the FPGA memory core.  That's 2 or 3 wires in and 2 or 3 wires out.  (Counting the data and address as 1 wire + the req signal).  There won't be time for any bus arbitration except on this tiny Z80 interface bridge.

     Now, here is the big + for Avalon.  Instead of this Z80 to GPU ram module which is currently being designed, but, if a GPU to Avalon module was being designed instead, and, in the public domain, a Z80 to Avalon bridge exists, as well as 6502 to Avalon, as well as 68000 to Avalon, ect, this may be the perfect spot to use Avalon.  However, once again, on the other side of this Avalon bridge where the GPU ram port resides, we just want those 3 wire interface ports since we want 3 to 5 new high speed parallel channels to access the GPU ram directly as static ram.  The other big + if if someone else want to port this GPU into their project, the Avalon bridge link would help if they are familiar, however, since the 'host' GPU ram interface is only supposed to be and address, data in and data out with a write enable, just using the Avalon correct 4 labels would be enough to function.

     Note that inside the current project, the 5 existing 5 port parallel access to the GPU ram already exists with only 1 address input and 1 data output, and currently unused, a request auxiliary flag input and output as well as passing the address through.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 24, 2019, 01:28:20 pm
Avalon does have the ability to work in a zero wait state configuration that functions a lot like SRAM.

I also tend to write my Wishbone peripherals to be zero wait state for registers since that lets me ignore most of the signals (Its just a MUX controlled by the address bus that puts the correct register out on the bus regardless if its being read or not). If this big pure combinatorial read path ends up being too slow i can always just make it raise its wait line for the first cycle and this turns it into 1 wait state latency.

There are also specs for read-modify-write operations on the bus that could be used to transfer data in both directions simultaneously. As for multiple data on single address can be implemented by concatenating the data buses into one wide data bus. can be 1024 bits wide if needed. If multiple address and multiple data are needed the entire bus could be duplicated as many times as needed.

But yes i agree that RAM will rarely have a zero wait state bus coming out of it. It is possible to do for internal block RAM, but running any sort of external RAM (even just SRAM) will tend to have at least 1 wait state, DRAMs will tend to have even longer wait states. So in order to get full speed out of those pipelined burst transfers must be used and these are supposed by both Wishbone and Avalon. But yeah i would stick with the fast internal block ram for as long as possible because writing pipelined Verilog code that milks every last clock cycle for performance still hurts my brain. Sometimes special requirements do require a special bus, but you can still stick to the naming conventions so that you can know what a signal is for at a glance.

I do agree the usual memory bus arbitration is a poor fit for the critical real time buses inside the GPU where guaranteed bandwidth is required. Using a normal memory bus with multi-master arbitration is better suited on the bus before the GPU where you might have other hardware sitting on it such as the sound card, IO controller, DMA etc.. that all might want to talk to each other in some way and all make use of a single large external memory of a few Megabytes in size.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 02:29:15 pm
There are also specs for read-modify-write operations on the bus that could be used to transfer data in both directions simultaneously. As for multiple data on single address can be implemented by concatenating the data buses into one wide data bus. can be 1024 bits wide if needed. If multiple address and multiple data are needed the entire bus could be duplicated as many times as needed.
This really legitimizes Avalon capabilities...
So many getting into 16/32/64 bit designs always ignore whenever we want to write bytes in the middle only, but our memory necessarily doesn't have byte mask features.  Ir in the case of a GPU, maybe we are using 2 pixels per byte in 16 color mode and you want to hardware accelerate drawing on only one of the 2 pixels.  Read-modify-write, as well as any simple logic done to a pixel like a transparency stencil when copying blocks of memory becomes ever so useful.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2019, 03:28:30 pm
Ok, now that you see it may need to sequence a set of events after a detection of a write, let's start by changing your:
Code: [Select]
if (Write_GPU_RAM) // these compares are finalised on the next GPU_CLK
begin ....
        ....end


To something like this:
Code: [Select]
reg [9:0] Z80_write_sequencer;
......
always
.......

Z80_write_sequencer[0] <= Write_GPU_RAM ;
Z80_write_sequencer[9:1] <= Z80_write_sequencer[8:0] ;

//Next... the new IF()'s

if ( Z80_write_sequencer[#] )    'perform a function, say, select 245 dir
if ( Z80_write_sequencer[#] )    'perform a function, say, make sure FPGA IO is in input mode.
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on 245 OE
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 Write address
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 data bus
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off 245 OE

.........



     Remember, the 'Write_GPU_RAM' only pulses high for 1 clock exactly right at the detection of a valid write state.  That pulse will now shift down the 'Z80_write_sequencer[9:0] ' pipe.  Now, if you choose the right #, you can keep everything clean and functional, even if the Z80 is running at a synchronous 1/2 clock speed to you GPU clock.  To make you code really nice, make a parameter something like 'BIDIR_245_Delay_clock_cycles', or, with a little math, instead use 'GPU_CLK_Frequency' and 'BIDIR_245_Delay_ns' to shift those those sequencer[#'s] so your code may auto generate the positions if you wish to run the project at any other frequency like 135MHz, or 250MHz, or 270MHz.

Bonus hint (but not necessary at your clock speed): There is a way to push this entire sequence chain up by one clock cycle sooner, let's see if you can figure this out...

Okay, so I really should be getting used to using pipes by now, but I keep coming at these problems from a programming point of view and this isn't programming.  ;)

So at 125 MHz, one clock cycle takes 8ns - I guess that should be enough for the 245 to enable its outputs and/or change direction, so for the moment I'm using position [1] in the Z80_write_sequencer to get the data from the data bus and pass it to the GPU RAM.  Can always up it to 2 if there's data instability.

Here's the code:

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   Z80_rData,
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg data_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // Z80_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF
parameter DELAY_CYCLES = 1; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Z80_nRead, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal
reg [9:0] Z80_write_sequencer;

assign mem_window = (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_nRead = Z80_RDn && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~Z80_RDn; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0; // default gpu_rd_req to LOW
assign data_oe = 1'b0; // disable 245 output
assign Z80_rData_ena = 1'b0; // set Z80 data pins to input on the FPGA

always @ (posedge GPU_CLK)
begin

Z80_write_sequencer[0] <= Write_GPU_RAM;
Z80_write_sequencer[9:1] <= Z80_write_sequencer[8:0];

if (Z80_write_sequencer[0])
begin

// start of Z80 WRite detected
data_dir <= GPU_data_oe; // set 245 direction
Z80_rData_ena <= 1'b0; // set FPGA pins to input (should be by default)
data_oe <= 1'b1; // enable 245 output

end
else if (Z80_write_sequencer[DELAY_CYCLES]) // at 125 MHz, 1 cycle = 8ns - just enough time for the 245 to change direction & enable outputs
begin

// pass address (limited to 512 KB) and data through to mux
gpu_wdata <= Z80_wData;
gpu_addr <= Z80_addr[18:0];
gpu_wr_ena <= 1'b1;

end
else if (Z80_write_sequencer[DELAY_CYCLES + 1])
begin

// end of write to GPU RAM
gpu_wr_ena <= 1'b0;
data_oe <= 1'b0; // disable 245 output

end

if (Read_GPU_RAM)
begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
data_oe <= 1'b1; // 'turn on' 245

end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= gpu_rd_rdy; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
Z80_rData_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0; // End the read request once the read is ready
Z80_rData[7:0] <= gpu_rData[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (data_hold && Z80_nRead)
begin

// data is being output to Z80, which has signalled end of read transaction
data_oe <= 1'b0; // disable 245 output
data_hold <= 1'b0; // reset the latch
Z80_rData_ena <= 1'b0; // set bidir pins to input

end

data_dir      <= GPU_data_oe;
Z80_rData_ena <= GPU_data_oe;

last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;

end

endmodule


I've had a go making the naming convention a little more consistent, but as always I'm open to advice, recommendations and (constructive!) criticism!  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 04:29:28 pm

I've had a go making the naming convention a little more consistent, but as always I'm open to advice, recommendations and (constructive!) criticism!  ;)
Yes, you got the idea, however, please change the naming convention to what I said 2 posts ago.  All of it.

2: I know you love squishing everything into 1 'IF' within it's 'begin' and 'end', for this case, write it out my way without the begin & end like so:
Code: [Select]
if ( Z80_write_sequencer[#] )    'perform a function, say, select 245 dir
if ( Z80_write_sequencer[#] )    'perform a function, say, make sure FPGA IO is in input mode.
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on 245 OE
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 Write address
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 data bus
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off 245 OE
And I'm about to show you why once you pasted the changes back here....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2019, 05:24:19 pm
Yes, you got the idea, however, please change the naming convention to what I said 2 posts ago.  All of it.

Err okay, I thought I had?  I've just changed the 245 signal names, but other than that, I'm not sure what else you want changed?  :-//

The inputs from the Z80 all start with 'Z80_', all have an 'n' at the end where they're active low...  :scared:

2: I know you love squishing everything into 1 'IF' within it's 'begin' and 'end', for this case, write it out my way without the begin & end like so:
Code: [Select]
if ( Z80_write_sequencer[#] )    'perform a function, say, select 245 dir
if ( Z80_write_sequencer[#] )    'perform a function, say, make sure FPGA IO is in input mode.
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on 245 OE
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 Write address
if ( Z80_write_sequencer[#] )    'perform a function, say, latch Z80 data bus
if ( Z80_write_sequencer[#] )    'perform a function, say, turn on FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off FPGA ram we
if ( Z80_write_sequencer[#] )    'perform a function, say, turn off 245 OE

And I'm about to show you why once you pasted the changes back here....

Okay, have done the above - updated code below.

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg Z80_245data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   Z80_rData,
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg Z80_245_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // Z80_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF
parameter DELAY_CYCLES = 1; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Z80_nRead, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal
reg [9:0] Z80_write_sequencer;

assign mem_window = (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_nRead = Z80_RDn && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~Z80_RDn; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0; // default gpu_rd_req to LOW
assign Z80_245_oe = 1'b0; // disable 245 output
assign Z80_rData_ena = 1'b0; // set Z80 data pins to input on the FPGA

always @ (posedge GPU_CLK)
begin

Z80_write_sequencer[0] <= Write_GPU_RAM;
Z80_write_sequencer[9:1] <= Z80_write_sequencer[8:0];

if ( Z80_write_sequencer[0] )
Z80_245data_dir <= GPU_data_oe; // set 245 dir

if ( Z80_write_sequencer[0] )
Z80_rData_ena <= 1'b0; // set FPGA pins to input (should be by default)

if ( Z80_write_sequencer[0] )
Z80_245_oe <= 1'b1; // enable 245 output

if ( Z80_write_sequencer[DELAY_CYCLES] )
gpu_addr <= Z80_addr[18:0]; // latch address bus onto GPU address bus

if ( Z80_write_sequencer[DELAY_CYCLES] )
gpu_wdata <= Z80_wData; // latch data bus onto GPU data bus

if ( Z80_write_sequencer[DELAY_CYCLES] )
gpu_wr_ena <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )
gpu_wr_ena <= 1'b0; // turn off FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )
Z80_245_oe <= 1'b0; // disable 245 output


if (Read_GPU_RAM)
begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b1; // 'turn on' 245

end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= gpu_rd_rdy; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
Z80_rData_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0; // End the read request once the read is ready
Z80_rData[7:0] <= gpu_rData[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (data_hold && Z80_nRead)
begin

// data is being output to Z80, which has signalled end of read transaction
Z80_245_oe <= 1'b0; // disable 245 output
data_hold <= 1'b0; // reset the latch
Z80_rData_ena <= 1'b0; // set bidir pins to input

end

Z80_245data_dir      <= GPU_data_oe;
Z80_rData_ena <= GPU_data_oe;

last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;

end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Berni on November 24, 2019, 06:03:10 pm
There are also specs for read-modify-write operations on the bus that could be used to transfer data in both directions simultaneously. As for multiple data on single address can be implemented by concatenating the data buses into one wide data bus. can be 1024 bits wide if needed. If multiple address and multiple data are needed the entire bus could be duplicated as many times as needed.
This really legitimizes Avalon capabilities...
So many getting into 16/32/64 bit designs always ignore whenever we want to write bytes in the middle only, but our memory necessarily doesn't have byte mask features.  Ir in the case of a GPU, maybe we are using 2 pixels per byte in 16 color mode and you want to hardware accelerate drawing on only one of the 2 pixels.  Read-modify-write, as well as any simple logic done to a pixel like a transparency stencil when copying blocks of memory becomes ever so useful.

Actually sorry i looked at the Avalon and Wishbone spec again and the read-modify-write operation is not simultaneous in both directions.

I never used it before as i didn't tend to need it. It turns out that the whole point of the read-modify-write cycle is to lock down any bus arbiters along the path so that you are guaranteed to get the last write part of the operation trough without someone else modifying that location and causing a glitch. This is not all that useful functionality in my opinion.

In theory you could set both write and read signals high on Avalon, but this is probably illegal in the spec?... somehow?...I dunno I haven't seen it specifically mentioned its not legal to do this, but i also haven't seen any timing diagrams that show doing this. Using common sense id say you are probably not supposed to do that. That being said tho most Avalon peripherals that only use internal memory usually have completely separate write logic and separate read logic. So it should work just fine to both read and write to one address, since the two separate sets of logic would simply do there thing as usual. But if you tried to pull this stunt on a memory controller for external memory it would probably refuse to do anything, or do just one of the two, since the data bus is bidirectional so it can't read and write at the same time. I suppose you could pretend this simultaneous read and write functionality is your own custom extension to the Avalon standard and so write your Avalon bus modules in a way where this is guaranteed to always work.

In any case even when using Wishbone or Avalon its good to have some idea what will be connected on the other end of the bus so that you can chose the port configuration that best fits the use. For just setting hardware registers the most basic configuration is good enugh. You want the bit depth of the bus to match up to avoid bus width adapters, if you have a 16 or 32bit bus you might want to support byte enable signals, if the device has a lot of latency you might want to support burst transfers...etc

Avalon also has a specification for streaming interfaces too. This is just a data bus with control signals and no address, usually used for point to point real time streaming of data like perhaps between a ADC controller and a DSP block. Useful for signal processing chains and all of Alteras IP blocks for filters and such use it. Again nothing special about it as there is no single one best way to design a streaming bus, but you can use the naming conventions and timings so that anyone who looks at it understands how the bus works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 06:13:46 pm

Okay, have done the above - updated code below.

Code: [Select]
module host_handler (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg Z80_245data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   Z80_rData,
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg Z80_245_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // Z80_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF
parameter DELAY_CYCLES = 1; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Z80_nRead, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal
reg [9:0] Z80_write_sequencer;

assign mem_window = (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_nRead = Z80_RDn && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~Z80_RDn; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0; // default gpu_rd_req to LOW
assign Z80_245_oe = 1'b0; // disable 245 output
assign Z80_rData_ena = 1'b0; // set Z80 data pins to input on the FPGA

always @ (posedge GPU_CLK)
begin

Z80_write_sequencer[0] <= Write_GPU_RAM;
Z80_write_sequencer[9:1] <= Z80_write_sequencer[8:0];

if ( Z80_write_sequencer[0] )
Z80_245data_dir <= GPU_data_oe; // set 245 dir

if ( Z80_write_sequencer[0] )
Z80_rData_ena <= 1'b0; // set FPGA pins to input (should be by default)

if ( Z80_write_sequencer[0] )
Z80_245_oe <= 1'b1; // enable 245 output

if ( Z80_write_sequencer[DELAY_CYCLES] )
gpu_addr <= Z80_addr[18:0]; // latch address bus onto GPU address bus

if ( Z80_write_sequencer[DELAY_CYCLES] )
gpu_wdata <= Z80_wData; // latch data bus onto GPU data bus

if ( Z80_write_sequencer[DELAY_CYCLES] )
gpu_wr_ena <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )
gpu_wr_ena <= 1'b0; // turn off FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )
Z80_245_oe <= 1'b0; // disable 245 output


if (Read_GPU_RAM)
begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b1; // 'turn on' 245

end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= gpu_rd_rdy; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
Z80_rData_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0; // End the read request once the read is ready
Z80_rData[7:0] <= gpu_rData[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (data_hold && Z80_nRead)
begin

// data is being output to Z80, which has signalled end of read transaction
Z80_245_oe <= 1'b0; // disable 245 output
data_hold <= 1'b0; // reset the latch
Z80_rData_ena <= 1'b0; // set bidir pins to input

end

Z80_245data_dir      <= GPU_data_oe;
Z80_rData_ena <= GPU_data_oe;

last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;

end

endmodule


Ok, much better.  Now, looking at it this way:
Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
//input wire host_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg Z80_245data_dir, // control level converter direction for data flow
output reg [19:0]  gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   Z80_rData,
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg Z80_245_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // Z80_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF
parameter DELAY_CYCLES = 2; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Z80_nRead, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal
reg [9:0] Z80_write_sequencer;

assign mem_window = (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_nRead = Z80_RDn && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign GPU_data_oe = mem_window && Z80_mreq && ~Z80_RDn; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0; // default gpu_rd_req to LOW
assign Z80_245_oe = 1'b0; // disable 245 output
assign Z80_rData_ena = 1'b0; // set Z80 data pins to input on the FPGA

always @ (posedge GPU_CLK)
begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0] , Write_GPU_RAM };


if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= GPU_data_oe;   // set 245 dir
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0;           // set FPGA pins to input (should be by default)

if ( Z80_write_sequencer[1] )                 Z80_245_oe       <= 1'b1;           // enable 245 output

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_addr         <= Z80_addr[18:0]; // latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wdata        <= Z80_wData;      // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b1;           // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0;           // turn off FPGA RAM we
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe       <= 1'b0;           // disable 245 output



if (Read_GPU_RAM)
begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= GPU_data_oe; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b1; // 'turn on' 245

end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= gpu_rd_rdy; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
Z80_rData_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0; // End the read request once the read is ready
Z80_rData[7:0] <= gpu_rData[7:0]; // Latch the GPU ram read into the output register for the Z80

end else if (data_hold && Z80_nRead)
begin

// data is being output to Z80, which has signalled end of read transaction
Z80_245_oe <= 1'b0; // disable 245 output
data_hold <= 1'b0; // reset the latch
Z80_rData_ena <= 1'b0; // set bidir pins to input

end

Z80_245data_dir      <= GPU_data_oe;
Z80_rData_ena <= GPU_data_oe;

last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;

end

endmodule


See how much easier it is for me, or even you to move around the timing / or sequence.  Plus, you need to add an additional clock cycle on top of the delay generated by the 245's OE control.  Remember, there is also a 'tsu' and 'th' (Time setup, and time hold for data inputs with relation to external and internal FPGA clock) figure inside the FPGA which must be met, and, if you are not defining these for your inputs in the compiler and relying on the compiler's 'FMAX' alone, you need to assume the the inputs take 1 entire clock cycle before they get from the input pins to the internal registers.  Operating the FPGA IO's at break-neck speed would require you to set these figure up correctly so the compiler will tell you if your design will receive the correct data, however, with this design, you can easily get away with that cheap 1 additional clock cycle delay as you are running more than 10 clock cycles within a single Z80 clock cycle.  And even then, the Z80 is even holding that data for even longer than 1 clock cycle...

Basically, your time is the switch on delay of the 245, under worst case conditions, not optimum, plus capacitance and trace leads, plus the delay from input pin in the FPGA to it's gpu_wdata[7:0] register.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 06:36:56 pm
Error:
------------------------------------------------------------------------------------------------
   if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= GPU_data_oe;     // set 245 dir
------------------------------------------------------------------------------------------------
and this:
------------------------------------------------------------------------------------------------
if (Read_GPU_RAM)
   begin
      
      gpu_addr      <= Z80_addr[18:0];// pass address to GPU RAM
      gpu_rd_req   <= 1'b1;            // flag a read request to the mux which is one-shotted in the mux
      Z80_245data_dir      <= GPU_data_oe;   // set 245 direction (TO Z80)
------------------------------------------------------------------------------------------------

Should be set to exclusively 1's or 0's, or defined by a parameter if you haven't decided the direction of the IC on your PCB.

The read section could use a little cleaning.  I cant follow it clearly.  It's going to be time to simulate this one to double check things out...


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2019, 06:56:55 pm
See how much easier it is for me, or even you to move around the timing / or sequence.

Yeah, I suppose so - I guess it would be possible to re-write the read if...endif conditional in the same way, but the read flow depends on a couple of different triggers which, I guess, would make the pipeline method undesirable?

Plus, you need to add an additional clock cycle on top of the delay generated by the 245's OE control.  Remember, there is also a 'tsu' and 'th' (Time setup, and time hold for data inputs with relation to external and internal FPGA clock) figure inside the FPGA which must be met, and, if you are not defining these for your inputs in the compiler and relying on the compiler's 'FMAX' alone, you need to assume the the inputs take 1 entire clock cycle before they get from the input pins to the internal registers.  Operating the FPGA IO's at break-neck speed would require you to set these figure up correctly so the compiler will tell you if your design will receive the correct data, however, with this design, you can easily get away with that cheap 1 additional clock cycle delay as you are running more than 10 clock cycles within a single Z80 clock cycle.  And even then, the Z80 is even holding that data for even longer than 1 clock cycle...

Basically, your time is the switch on delay of the 245, under worst case conditions, not optimum, plus capacitance and trace leads, plus the delay from input pin in the FPGA to it's gpu_wdata[7:0] register.

Okay, fair enough - so it's looking like the Z80_bridge module is pretty much complete now?  Time to start simulating...?  :-BROKE

Error:
------------------------------------------------------------------------------------------------
   if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= GPU_data_oe;     // set 245 dir
------------------------------------------------------------------------------------------------
and this:
------------------------------------------------------------------------------------------------
if (Read_GPU_RAM)
   begin
      
      gpu_addr      <= Z80_addr[18:0];// pass address to GPU RAM
      gpu_rd_req   <= 1'b1;            // flag a read request to the mux which is one-shotted in the mux
      Z80_245data_dir      <= GPU_data_oe;   // set 245 direction (TO Z80)
------------------------------------------------------------------------------------------------

Should be set to exclusively 1's or 0's, or defined by a parameter if you haven't decided the direction of the IC on your PCB.

Sorted.  I've also removed these two lines:
------------------------------------------------------------------------------------------------
   Z80_245data_dir   <= GPU_data_oe;
   Z80_rData_ena      <= GPU_data_oe;
------------------------------------------------------------------------------------------------
Both those outputs are fully catered for in the write and read code, so I've commented them out.

The read section could use a little cleaning.  I cant follow it clearly.  It's going to be time to simulate this one to double check things out...

Code: [Select]
if (Read_GPU_RAM)
begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b1; // 'turn on' 245

So when a Z80 read is detected, we grab the bottom 19 bits of the address and pass that to the mux, along with the gpu_rd_req.  The 245's direction is set TO Z80 and its output is enabled as the Z80 won't be driving the data bus at all during the read operation, and will only sample the data bus at the end of the read op.

Code: [Select]
end else if (gpu_rd_rdy) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

data_hold <= 1'b0; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
Z80_rData_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0; // End the read request once the read is ready
Z80_rData[7:0] <= gpu_rData[7:0]; // Latch the GPU ram read into the output register for the Z80

So the mux will signal via gpu_rd_rdy for one clock cycle that the GPU RAM data is ready.  When this is detected, data_hold goes HIGH to keep the data output from the FPGA to the Z80, Z80_rData_ena goes HIGH to set bidir pins to output, gpu_rd_req is reset and the data is latched onto the Z80_rData bus.

Code: [Select]
end else if (data_hold && Z80_nRead)
begin

// data is being output to Z80, which has signalled end of read transaction
Z80_245_oe <= 1'b0; // disable 245 output
data_hold <= 1'b0; // reset the latch
Z80_rData_ena <= 1'b0; // set bidir pins to input

end

Finally, when the end of the Z80 read cycle is detected by RD going high, the 245's output is disabled, the data_hold latch is reset and the bidir pins are set to input.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 08:31:40 pm
Arrrg, that ' 1 shot ' on the read is nasty looking at the timing chart.  If seem you will need to qualify it on the rising edge of the CPU clock unlike the Z80 write data where we can cheat and trigger on the fall of the Z80 WE exclusively.

Here is how we will need to assign and trigger the read:


assign Read_GPU_RAM_BEGIN   = mem_window && Z80_mreq && ~Z80_RDn && Z80_clk && ~Z80_clk_delay  ;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END   = Z80_RDn && ~last_Z80_RD;  // Define the time to end a GPU ram read

........
Z80_clk_delay <= Z80_clk;  // add this to find the rising clock edge.


you only need 2 IF()', 1 for Read_GPU_RAM_BEGIN, and 1 for Read_GPU_RAM_END.

This change must be made since we cannot guarantee which signal will fall first, the Z80_MREQn, or the Z80_RDn.  In the original code, if the 'Z80_RDn' falls before the 'Z80_MREQn', we will not see that cycle as a read & we will ignore the transaction.  We only know that both signals are valid by the time the next rising edge of the CPU clk.  To be constant, you may also qualify the write signal strobe the same way as well.


As for the 'Z80_rData', make 1 if outside everything else an just say:
if (gpu_rd_rdy)  Z80_rData[7:0]   <= gpu_rData[7:0];   // Latch the GPU ram read into the output register for the Z80

And your done...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2019, 10:47:22 pm
Arrrg, that ' 1 shot ' on the read is nasty looking at the timing chart.  If seem you will need to qualify it on the rising edge of the CPU clock unlike the Z80 write data where we can cheat and trigger on the fall of the Z80 WE exclusively.

Here is how we will need to assign and trigger the read:


assign Read_GPU_RAM_BEGIN   = mem_window && Z80_mreq && ~Z80_RDn && Z80_clk && ~Z80_clk_delay  ;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END   = Z80_RDn && ~last_Z80_RD;  // Define the time to end a GPU ram read

........
Z80_clk_delay <= Z80_clk;  // add this to find the rising clock edge.


you only need 2 IF()', 1 for Read_GPU_RAM_BEGIN, and 1 for Read_GPU_RAM_END.

This change must be made since we cannot guarantee which signal will fall first, the Z80_MREQn, or the Z80_RDn.  In the original code, if the 'Z80_RDn' falls before the 'Z80_MREQn', we will not see that cycle as a read & we will ignore the transaction.  We only know that both signals are valid by the time the next rising edge of the CPU clk.  To be constant, you may also qualify the write signal strobe the same way as well.


As for the 'Z80_rData', make 1 if outside everything else an just say:
if (gpu_rd_rdy)  Z80_rData[7:0]   <= gpu_rData[7:0];   // Latch the GPU ram read into the output register for the Z80

And your done...

Okay, I think I've made the changes required above.  I've commented-out changes to data_hold as it appears it's no longer necessary.

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
//output wire [7:0]  h_rd_data, // Z80 DATA bus to return data from GPU RAM to Z80
//output reg            h_rd_req, //
output reg gpu_wr_ena, // flag HIGH when writing to GPU RAM
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [19:0]  gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]   gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg [7:0]   Z80_rData,
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg gpu_rd_req,
output reg Z80_245_oe // OE for 245 level translator (active LOW)

);

parameter MEMORY_RANGE = 3'b011; // Z80_addr[21:19] == 3'b011 targets the 512KB 'window' at 0x180000-0x1FFFFF
parameter DELAY_CYCLES = 2; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Z80_nRead, Write_GPU_RAM, Read_GPU_RAM, GPU_data_oe, Z80_clk_delay;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;

reg last_Z80_WR = 1'b0;  // keep these low on power-up, otherwise a read or write pulse may be triggered
reg last_Z80_RD = 1'b0;
//reg data_hold = 1'b0; // used to latch the gpu_rd_rdy signal
reg [9:0] Z80_write_sequencer;

assign mem_window = (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_nRead = Z80_RDn && ~last_Z80_RD; // Isolate end of a read transaction

assign Write_GPU_RAM = mem_window && Z80_mreq && Z80_write; // Define a GPU Write action
//assign Read_GPU_RAM = mem_window && Z80_mreq && Z80_read; // Define a GPU Read action
assign Read_GPU_RAM_BEGIN = mem_window && Z80_mreq && ~Z80_RDn && Z80_CLK && ~Z80_clk_delay;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END = Z80_RDn && ~last_Z80_RD;  // Define the time to end a GPU ram read
assign GPU_data_oe = mem_window && Z80_mreq && ~Z80_RDn; // Define the time the GPU ouputs data onto the Z80 data bus

assign gpu_rd_req = 1'b0; // default gpu_rd_req to LOW
assign Z80_245_oe = 1'b0; // disable 245 output
assign Z80_rData_ena = 1'b0; // set Z80 data pins to input on the FPGA

always @ (posedge GPU_CLK)
begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)

if ( Z80_write_sequencer[1] )                 Z80_245_oe       <= 1'b1; // enable 245 output

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_addr         <= Z80_addr[18:0]; // latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe       <= 1'b0; // disable 245 output

if ( Read_GPU_RAM_BEGIN )
begin
gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b1; // enable 245 output
end

if ( gpu_rd_rdy ) // gpu_rd_rdy is a one-shot from the mux, reset after one clock
begin

//data_hold <= 1'b1; // latch the gpu_rd_rdy signal to keep outputting data until Z80 is done with it
Z80_rData_ena <= 1'b1; // set bidir pins to output
gpu_rd_req <= 1'b0; // End the read request once the read is ready
Z80_rData[7:0] <= gpu_rData[7:0]; // Latch the GPU RAM read into the output register for the Z80

end

if ( Read_GPU_RAM_END )
begin
// data is being output to Z80, which has signalled end of read transaction
Z80_245_oe <= 1'b0; // disable 245 output
//data_hold <= 1'b0; // reset the latch
Z80_rData_ena <= 1'b0; // set bidir pins to input
end

//Z80_245data_dir <= GPU_data_oe;
//Z80_rData_ena <= GPU_data_oe;

last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK;  // find the rising clock edge

end

endmodule


If that's all looking good, I'll get started on setting up a simulation for it tomorrow if I get the time.  What sort of complexity will the mux bring?  Will this be a cut-down version of the multiport_GPU_RAM module?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 24, 2019, 11:27:32 pm
Looks Good.
The mux is a 2:1, or 3:1 lateron with the cpu on top and RS232 debugger on bottom.

Other than making that Z80 module's read req into a single pulse instead of always on, the mux will cycle to any available triggered input.  Just a J-K flipflop equivalent selecting 2 address and data sourced, with a 2 clock cycle delayed rd_ready output matching the altsynccram megafunction's 2 clock cycle read delay.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 12:49:16 am
Ok, @nockieboy, now that I know you can simulate code in Quartus, let's take a look at point #3 here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)

Now I said I would like to a Verilog guide about initiating memory : https://www.chipverify.com/verilog/verilog-single-port-ram (https://www.chipverify.com/verilog/verilog-single-port-ram) , but I don't like their example.  We only need a block of registers to write to and have continuous parallel access with some instantaneous reset values.  So, take a look at this I threw together:

Code: [Select]
module r_bank (
input wire rst,
input wire clk,
input wire we,
input wire [7:0] addr_in,
input wire [7:0] data_in,

output reg  [7:0] mem[256]  );


 
  integer i;
 
  always @ (posedge clk) begin
 
  if (rst) begin

mem[0] <= 8'hAA;
mem[1] <= 8'hBB;
mem[2] <= 8'hCC;
mem[3] <= 8'hDD;

    for (i = 4; i < 256; i = i + 1) begin
mem[i] <= 8'h0;
    end

end else begin
 
if (we)
mem[addr_in] <= data_in;
end

end

endmodule

Now, you will need to re-work it to the specs and controls I laid out for your GPU.  One thing is in Quartus, to use Verilog addressable memory arrays, please set the 'Verilog' language style/version to 'System Verilog'.  Also, to make the block diagram symbol for this example verilog code, you will need to use Quartus Prime as old QuartusIIv9.1 doesn't know how to do it.  Then you can bring that .bsf file back into the older Quartus and simulate it.

Here is an example of what it should look like.

[attachimg=1]

You can see how Altera/Intel labels the ' register memory bank ' differently outside the Verilog module where I fed some of the individual register bytes to a few output pins.
This bank of registers is what will hold and feed all you graphics control settings.  As you can see, you write to them just like ram, but, you have individual access to all their contents at all times.

It's also much reads much easier this way than mem[255*8+7:0*0], and selecting the right sub wires, though, it works out to the same thing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 02:17:43 am
The RS232_Debugger I created for nockieboy's VGA Controller has become a thread upon it's own here as it has proven functional and has also become a viable product all on it's own:
https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/msg2801388/#msg2801388 (https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/msg2801388/#msg2801388)

The latest RS232_Debugger.exe HEX editor/filed editor is now located here:
https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/?action=dlattach;attach=878982 (https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/?action=dlattach;attach=878982)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2019, 10:02:17 am
Ok, @nockieboy, now that I know you can simulate code in Quartus, let's take a look at point #3 here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)
...
Now, you will need to re-work it to the specs and controls I laid out for your GPU....

Okay, have done that (thanks for the example - makes my life much easier and assists my understanding no end!) - code below:

Code: [Select]
module GPU_HW_Control_Regs (

input reg rst,
input reg clk,
input reg we,
input reg [19:0] addr_in,
input reg [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = HW_REGS;

parameter [7:0] RST_VALUES [32] = {
8'h01,
8'h02,
8'h03,
8'h04,
8'h05,
8'h06,
8'h07,
8'h08,
8'h09,
8'h0A,
8'h0B,
8'h0C,
8'h0D,
8'h0E,
8'h0F,
8'h10,
8'h11,
8'h12,
8'h13,
8'h14,
8'h15,
8'h16,
8'h17,
8'h18,
8'h19,
8'h1A,
8'h1B,
8'h1C,
8'h1D,
8'h1E,
8'h1F,
8'h20
};

wire valid_wr;

assign valid_wr = we && ( addr_in[19:8] == data_in ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
for (i = 0; i < 32; i = i + 1) begin
GPU_HW_Control_regs[i] <= RST_VALUES[i];
end

// reset remaining registers to zero
for (i = 33; i < HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[i] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[7:0]] <= data_in;

end

end
end

endmodule

So I've been wading through the specifications you provided in the earlier post for the GPU_HW_Control_Regs, but I'm struggling with this bit:

Quote
c)  Base write address for the write input.  The module will always take in all 20 address bits, but when writing data to the 8 bit data input port, the upper address wires [19:8] should equal this number for the write to be successful.  If parameter (b) is >256, then the bottom of the upper base write address [8] will be ignored as you will be opening a 512 byte window, and so on.  (Set this default to the base of the last 256 bytes in your system memory.  Yes, it will occupy the same last 256 bytes as your system GPU ram.)

I've got the check to make sure the data value is the same as the upper 8-bits of the address value, but the bit in bold is making my brain ache.  Can you rephrase those three sentences, or reduce them to single-syllable words with crayon sketches?  :o

You can see how Altera/Intel labels the ' register memory bank ' differently outside the Verilog module where I fed some of the individual register bytes to a few output pins.
This bank of registers is what will hold and feed all you graphics control settings.  As you can see, you write to them just like ram, but, you have individual access to all their contents at all times.

So I'll need 32 output pins - one for each of the 'main' registers?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 11:18:01 am
Ok, @nockieboy, now that I know you can simulate code in Quartus, let's take a look at point #3 here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)
...
Now, you will need to re-work it to the specs and controls I laid out for your GPU....

Okay, have done that (thanks for the example - makes my life much easier and assists my understanding no end!) - code below:

Code: [Select]
module GPU_HW_Control_Regs (

input reg rst,
input reg clk,
input reg we,
input reg [19:0] addr_in,
input reg [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = HW_REGS;

parameter [7:0] RST_VALUES [32] = {
8'h01,
8'h02,
8'h03,
8'h04,
8'h05,
8'h06,
8'h07,
8'h08,
8'h09,
8'h0A,
8'h0B,
8'h0C,
8'h0D,
8'h0E,
8'h0F,
8'h10,
8'h11,
8'h12,
8'h13,
8'h14,
8'h15,
8'h16,
8'h17,
8'h18,
8'h19,
8'h1A,
8'h1B,
8'h1C,
8'h1D,
8'h1E,
8'h1F,
8'h20
};

wire valid_wr;

assign valid_wr = we && ( addr_in[19:8] == data_in ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
for (i = 0; i < 32; i = i + 1) begin
GPU_HW_Control_regs[ i ] <= RST_VALUES[ i ];
end

// reset remaining registers to zero
for (i = 4; i < HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[ i ] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[7:0]] <= data_in;

end

end
end

endmodule

So I've been wading through the specifications you provided in the earlier post for the GPU_HW_Control_Regs, but I'm struggling with this bit:

Quote
c)  Base write address for the write input.  The module will always take in all 20 address bits, but when writing data to the 8 bit data input port, the upper address wires [19:8] should equal this number for the write to be successful.  If parameter (b) is >256, then the bottom of the upper base write address [8] will be ignored as you will be opening a 512 byte window, and so on.  (Set this default to the base of the last 256 bytes in your system memory.  Yes, it will occupy the same last 256 bytes as your system GPU ram.)

I've got the check to make sure the data value is the same as the upper 8-bits of the address value, but the bit in bold is making my brain ache.  Can you rephrase those three sentences, or reduce them to single-syllable words with crayon sketches?  :o

You can see how Altera/Intel labels the ' register memory bank ' differently outside the Verilog module where I fed some of the individual register bytes to a few output pins.
This bank of registers is what will hold and feed all you graphics control settings.  As you can see, you write to them just like ram, but, you have individual access to all their contents at all times.

So I'll need 32 output pins - one for each of the 'main' registers?
You just about got it... #1, see error in 'RED'
         // reset key registers to initial values      
         for (i = 0; i < 32; i = i + 1) begin
            GPU_HW_Control_regs[ i ] <= RST_VALUES[ i ];
         end
         
         // reset remaining registers to zero
         for (i = 4; i < HW_REGS_SIZE; i = i + 1) begin
            GPU_HW_Control_regs[ i ] <= 8'h0;
         end

A simulation which had a reset somewhere and at least 8 output regs on display and some random parameters would have shown you this bug.

Quote
I've got the check to make sure the data value is the same as the upper 8-bits of the address value, but the bit in bold is making my brain ache.  Can you rephrase those three sentences, or reduce them to single-syllable words with crayon sketches?  :o

Ok, you need another Parameter.  Call it 'BASE_WRITE_ADDRESS'.  Now, change to your current valid write enable condition:


   assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] );      // upper addr_in should equal to the same specified upper base address.  This will allow us to map the register bank anywhere inside the 20bit address range.

 
So, if we have a HW_REG_SIZE of 8, space for 256 registers, only addr_in address wires [19:8] need to be equal with the value in 'BASE_WRITE_ADDRESS[19:8]' and 'we' needs to be high to engage the write enable.  Remember, even though you may think of parameters as numbers, to a Verilog compiler, it is nothing more than a bundle of single wires with set specific high and low values.  So writing my above line make all too much easy sense.  (HINT: In specifying a Z80 window address location..... not in binary or 3 arbitrary bit located who knows where.... Give it a legitimate understandable figure which matches what you code in the Z80 + what you see when you enter an address in your simulator setup.)


And, don't forget this:

      if (valid_wr) begin
            
            // apply written value to addressed register
            GPU_HW_Control_regs[addr_in[HW_REG_SIZE-1:0]] <= data_in;
            
         end

Let's see a test bench of this for setting a few regs, then doing a reset showing all the defaults set in 1 shot.

Quote
So I'll need 32 output pins - one for each of the 'main' registers?
Only if you want to send 32 registers to 32x8bit output pins.  All I'm saying is that when Quartus wires a addressable register ram on it's block diagrams, it calls them "mem[0..255][7..0]" instead of Veriog's  ' reg [7:0] mem [256]; '.  Quartus does this to allow you to take sub-groups of 'mem', like [15..20] and sen those to 1 module while wiring [200..210] to another in the block diagram.  Don't worry, we will be piping all 256, [0..255] into each verilog module and a parameter there will select which memory contents in that bundle will control it's features.  My example screenshot shows you how to select and wire a bundle of the mem register bank in the block diagram editor to anywhere you like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2019, 12:18:36 pm
You just about got it... #1, see error in 'RED'
         // reset key registers to initial values      
         for (i = 0; i < 32; i = i + 1) begin
            GPU_HW_Control_regs[ i ] <= RST_VALUES[ i ];
         end
         
         // reset remaining registers to zero
         for (i = 4; i < HW_REGS_SIZE; i = i + 1) begin
            GPU_HW_Control_regs[ i ] <= 8'h0;
         end

Yeah, I spotted and corrected that bug in my post above, but not in time before you read it.  :)

Ok, you need another Parameter.  Call it 'BASE_WRITE_ADDRESS'.  Now, change to your current valid write enable condition:


   assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] );      // upper addr_in should equal to the same specified upper base address.  This will allow us to map the register bank anywhere inside the 20bit address range.

Couple of issues here - HW_REGS_SIZE originally was intended to be a literal number of registers... i.e. 32 for 32 registers.  So I've had to make some changes to the code to treat HW_REGS_SIZE as the square root of the desired number of registers, so it can be dropped into address ranges directly as the number of address lines needed to make the required number of regs.  So now it would have a value of 5 for 32 registers, instead of 32 before.

The other thing is this:

Quote
assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] );

BASE_WRITE_ADDRESS:  Can I just declare it as a hex or binary value?

Code: [Select]
BASE_ADDRESS = 19'b0000011111100000000;
That should be the address of the top 256 bytes of the GPU's 16K RAM?

Code: [Select]
module GPU_HW_Control_Regs (

input reg rst,
input reg clk,
input reg we,
input reg [19:0] addr_in,
input reg [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[2**HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = HW_REGS;
parameter BASE_WRITE_ADDRESS = 0;

parameter [7:0] RST_VALUES [32] = {
8'h01,
8'h02,
8'h03,
8'h04,
8'h05,
8'h06,
8'h07,
8'h08,
8'h09,
8'h0A,
8'h0B,
8'h0C,
8'h0D,
8'h0E,
8'h0F,
8'h10,
8'h11,
8'h12,
8'h13,
8'h14,
8'h15,
8'h16,
8'h17,
8'h18,
8'h19,
8'h1A,
8'h1B,
8'h1C,
8'h1D,
8'h1E,
8'h1F,
8'h20
};

wire valid_wr;

assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
for (i = 0; i < 32; i = i + 1) begin
GPU_HW_Control_regs[i] <= RST_VALUES[i];
end

// reset remaining registers to zero
for (i = 4; i < 2**HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[i] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[HW_REG_SIZE-1:0]] <= data_in;

end

end
end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2019, 12:35:13 pm
 :palm:

Now I'm hitting error after error trying to create symbol files for GPU_HW_Control_Regs.  I've saved it as a .sv file to try to enforce the System Verilog language, but it's really not happy with the RST_VALUES parameter array.

This is where I am currently - this error message:


Error (10016): Can't create symbol/include/instantiation/component file for module "GPU_HW_Control_Regs" because port "GPU_HW_Control_regs" has an unsupported type

Code: [Select]
module GPU_HW_Control_Regs (

input rst,
input clk,
input we,
input [19:0] addr_in,
input [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[2**HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = 5;
parameter BASE_WRITE_ADDRESS = 0;

parameter bit [7:0] RST_VALUES [32] = '{
8'h01,
8'h02,
8'h03,
8'h04,
8'h05,
8'h06,
8'h07,
8'h08,
8'h09,
8'h0A,
8'h0B,
8'h0C,
8'h0D,
8'h0E,
8'h0F,
8'h10,
8'h11,
8'h12,
8'h13,
8'h14,
8'h15,
8'h16,
8'h17,
8'h18,
8'h19,
8'h1A,
8'h1B,
8'h1C,
8'h1D,
8'h1E,
8'h1F,
8'h20
};

wire valid_wr;

assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
for (i = 0; i < 32; i = i + 1) begin
GPU_HW_Control_regs[i] <= RST_VALUES[i];
end

// reset remaining registers to zero
for (i = 4; i < 2**HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[i] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[HW_REGS_SIZE-1:0]] <= data_in;

end

end
end

endmodule

I've made changes to how RST_VALUES is declared, including specifying a type which I think is causing this error, but I get other errors if I don't specify a type.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 12:37:12 pm

BASE_WRITE_ADDRESS:  Can I just declare it as a hex or binary value?

Code: [Select]
BASE_ADDRESS = 19'b0000011111100000000;
That should be the address of the top 256 bytes of the GPU's 16K RAM?

Yup, that's fine, just note that [19:0] is 20'bxxxx not 19'bxxxx.  0 in 19:0 counts as a bit as well.

As for hardware regs, just fix up the parameter nae to what you like.  A parameter of HW_REG_ADDR_SIZE would be fine and using the 2**HW_REG_ADDR_SIZE would do it for you  [7:0]reg[xxxxx], and don't forget your reset loop...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 12:42:04 pm
:palm:

Now I'm hitting error after error trying to create symbol files for GPU_HW_Control_Regs.  I've saved it as a .sv file to try to enforce the System Verilog language, but it's really not happy with the RST_VALUES parameter array.

This is where I am currently - this error message:


Error (10016): Can't create symbol/include/instantiation/component file for module "GPU_HW_Control_Regs" because port "GPU_HW_Control_regs" has an unsupported type

Code: [Select]
module GPU_HW_Control_Regs (

input rst,
input clk,
input we,
input [19:0] addr_in,
input [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[2**HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = 5;
parameter BASE_WRITE_ADDRESS = 0;

parameter bit [7:0] RST_VALUES [32] = '{
8'h01,
8'h02,
8'h03,
8'h04,
8'h05,
8'h06,
8'h07,
8'h08,
8'h09,
8'h0A,
8'h0B,
8'h0C,
8'h0D,
8'h0E,
8'h0F,
8'h10,
8'h11,
8'h12,
8'h13,
8'h14,
8'h15,
8'h16,
8'h17,
8'h18,
8'h19,
8'h1A,
8'h1B,
8'h1C,
8'h1D,
8'h1E,
8'h1F,
8'h20
};

wire valid_wr;

assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
for (i = 0; i < 32; i = i + 1) begin
GPU_HW_Control_regs[i] <= RST_VALUES[i];
end

// reset remaining registers to zero
for (i = 4; i < 2**HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[i] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[HW_REGS_SIZE-1:0]] <= data_in;

end

end
end

endmodule

I've made changes to how RST_VALUES is declared, including specifying a type which I think is causing this error, but I get other errors if I don't specify a type.

It's in part a limitation of QuartusIIv9's 'generate sheet symbol' function, you just need to generate the sheet symbol in Quartus Prime, then it will still load in QuartusIIv9 once generated.  Once you have the symbol, everything else is still functional in both versions of Quartus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 12:59:20 pm
If you cant solve the reset parameter array, just make 8 16 bit parameter inputs and assign the 8 to the first 16 regs.  We will most likely only use 4 of these, filled with 16 or even 24 bit quantities as they will point to the power up display address pointer settings to generate a valid picture.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2019, 01:36:38 pm
It's in part a limitation of QuartusIIv9's 'generate sheet symbol' function, you just need to generate the sheet symbol in Quartus Prime, then it will still load in QuartusIIv9 once generated.  Once you have the symbol, everything else is still functional in both versions of Quartus.

It's Quartus Prime I'm getting the errors in.  :-\

If you cant solve the reset parameter array, just make 8 16 bit parameter inputs and assign the 8 to the first 16 regs.  We will most likely only use 4 of these, filled with 16 or even 24 bit quantities as they will point to the power up display address pointer settings to generate a valid picture.

I'll go for this solution, I think. Here's the updated code:

Code: [Select]
module GPU_HW_Control_Regs (

input rst,
input clk,
input we,
input [19:0] addr_in,
input [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[2**HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = 5;
parameter BASE_WRITE_ADDRESS = 0;
parameter RST_VALUE_0 = 16'b0000000000000000;
parameter RST_VALUE_1 = 16'b0000000000000001;
parameter RST_VALUE_2 = 16'b0000000000000010;
parameter RST_VALUE_3 = 16'b0000000000000011;
parameter RST_VALUE_4 = 16'b0000000000000100;
parameter RST_VALUE_5 = 16'b0000000000000101;
parameter RST_VALUE_6 = 16'b0000000000000110;
parameter RST_VALUE_7 = 16'b0000000000000111;

wire valid_wr;

assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
GPU_HW_Control_regs[0] <= RST_VALUE_0[7:0];
GPU_HW_Control_regs[1] <= RST_VALUE_0[15:8];
GPU_HW_Control_regs[2] <= RST_VALUE_1[7:0];
GPU_HW_Control_regs[3] <= RST_VALUE_1[15:8];
GPU_HW_Control_regs[4] <= RST_VALUE_2[7:0];
GPU_HW_Control_regs[5] <= RST_VALUE_2[15:8];
GPU_HW_Control_regs[6] <= RST_VALUE_3[7:0];
GPU_HW_Control_regs[7] <= RST_VALUE_3[15:8];
GPU_HW_Control_regs[8] <= RST_VALUE_4[7:0];
GPU_HW_Control_regs[9] <= RST_VALUE_4[15:8];
GPU_HW_Control_regs[10] <= RST_VALUE_5[7:0];
GPU_HW_Control_regs[11] <= RST_VALUE_5[15:8];
GPU_HW_Control_regs[12] <= RST_VALUE_6[7:0];
GPU_HW_Control_regs[13] <= RST_VALUE_6[15:8];
GPU_HW_Control_regs[14] <= RST_VALUE_7[7:0];
GPU_HW_Control_regs[15] <= RST_VALUE_7[15:8];

// reset remaining registers to zero
for (i = 16; i < 2**HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[i] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[HW_REGS_SIZE-1:0]] <= data_in;

end

end
end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 05:07:25 pm
It's in part a limitation of QuartusIIv9's 'generate sheet symbol' function, you just need to generate the sheet symbol in Quartus Prime, then it will still load in QuartusIIv9 once generated.  Once you have the symbol, everything else is still functional in both versions of Quartus.

It's Quartus Prime I'm getting the errors in.  :-\

If you cant solve the reset parameter array, just make 8 16 bit parameter inputs and assign the 8 to the first 16 regs.  We will most likely only use 4 of these, filled with 16 or even 24 bit quantities as they will point to the power up display address pointer settings to generate a valid picture.

I'll go for this solution, I think. Here's the updated code:

Code: [Select]
module GPU_HW_Control_Regs (

input rst,
input clk,
input we,
input [19:0] addr_in,
input [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[2**HW_REGS_SIZE]

);
 
parameter HW_REGS_SIZE = 8;
parameter BASE_WRITE_ADDRESS = 20'h003F00;
parameter RST_VALUE_0 = 16'h0000;
parameter RST_VALUE_1 = 16'h0011;
parameter RST_VALUE_2 = 16'h0022;
parameter RST_VALUE_3 = 16'h0033;
parameter RST_VALUE_4 = 16'h0044;
parameter RST_VALUE_5 = 16'h0055;
parameter RST_VALUE_6 = 16'h0066;
parameter RST_VALUE_7 = 16'h0077;

This should be more functional, closer to my spec, and easier to see on the simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2019, 06:19:35 pm
This should be more functional, closer to my spec, and easier to see on the simulation.

Okay, I've updated the code with those changes - still can't compile it in Quartus Prime.  :-\  Getting this error still:

Error (10016): Can't create symbol/include/instantiation/component file for module "GPU_HW_Control_Regs" because port "GPU_HW_Control_regs" has an unsupported type


This is where the problem is:

Code: [Select]
output reg  [7:0] GPU_HW_Control_regs[2**HW_REGS_SIZE]

If I remove [2**HW_REGS_SIZE] it compiles.  Is it not happy with the parameter size or the maths going on there? Or both?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 06:29:28 pm
Arrrrrrrgggg  :rant: Damn Quartus prime and QuartusIIv9.1 with their 'SPECIFIC' syntax which must be met just for the block diagram entry.  This version works, generates the block diagram, compiles without warnings, still System Verilog compliant, and simulates properly too:

Do not loose this example.  It works, and is totally parameter configurable, including the 'Arrayed' parameter feature.

Not only that, but, the 'Generate Sheet Symbol' function now also works in Quartus II v9.1!!!
(Not to mention compiling and simulating in 2 seconds instead of 50 seconds!)


Code: [Select]
module GPU_HW_Control_Regs (

input rst,
input clk,
input we,
input [19:0] addr_in,
input [7:0] data_in,

output reg  [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)]

);
 
parameter HW_REGS_SIZE = 8;
parameter int BASE_WRITE_ADDRESS = 20'h0;

parameter int RST_VALUES [32] = '{
8'h01, 8'h02, 8'h03, 8'h04, 8'h05, 8'h06, 8'h07, 8'h08,
8'h09, 8'h0A, 8'h0B, 8'h0C, 8'h0D, 8'h0E, 8'h0F, 8'h10,
8'h11, 8'h12, 8'h13, 8'h14, 8'h15, 8'h16, 8'h17, 8'h18,
8'h19, 8'h1A, 8'h1B, 8'h1C, 8'h1D, 8'h1E, 8'h1F, 8'h20 };

wire valid_wr;

assign valid_wr = we && ( addr_in[19:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[19:HW_REGS_SIZE] ); // upper 8-bits of addr_in should equal data_in for a successful write

integer i;
 
always @ (posedge clk) begin

if (rst) begin

// reset key registers to initial values
for (i = 0; i < 32; i = i + 1) begin
GPU_HW_Control_regs[i] <= RST_VALUES[i][7:0];
end

// reset remaining registers to zero
for (i = 32; i < 2**HW_REGS_SIZE; i = i + 1) begin
GPU_HW_Control_regs[i] <= 8'h0;
end

end
else
begin

if (valid_wr) begin

// apply written value to addressed register
GPU_HW_Control_regs[addr_in[HW_REGS_SIZE-1:0]] <= data_in;

end

end
end

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 06:33:52 pm
I've attached a simulation test bench Quartus project of the above code testing a few writes, then a sudden reset.  As you can see, the simulation proves the module is doing exactly what we want it to do...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 06:43:44 pm
Ok, it's time to get onto points #4 and #5 here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)

Note: place the register bank in the last 256 bytes of the 16kb addressable memory and tie it's data/address/we inputs to the RS232 debugger outputs in parallel with system 'host_' memory.

I'm assuming you will be updating points #2.  And, we will wait on point #1 so you will see what happens and why point #1 needs to be taken care of after you finish point #5.

using the 'for' loop trick, point #5 is easily doable for all those cursors.  Mix the outputs in the new temporary 'color_sel' color mixing block.  Mix the lines with simple 'OR' gates right at the 'out[11:0]', prior to the modules output pins.  Show us your results...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2019, 07:55:08 pm
Damn, we would be nowhere if I didn't re-install Quartus myself...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2019, 07:59:11 pm
I've attached a simulation test bench Quartus project of the above code testing a few writes, then a sudden reset.  As you can see, the simulation proves the module is doing exactly what we want it to do...

Works just fine in 9.1.  :-+

Ok, it's time to get onto points #4 and #5 here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)

Note: place the register bank in the last 256 bytes of the 16kb addressable memory and tie it's data/address/we inputs to the RS232 debugger outputs in parallel with system 'host_' memory.

I'm assuming you will be updating points #2.  And, we will wait on point #1 so you will see what happens and why point #1 needs to be taken care of after you finish point #5.

using the 'for' loop trick, point #5 is easily doable for all those cursors.  Mix the outputs in the new temporary 'color_sel' color mixing block.  Mix the lines with simple 'OR' gates right at the 'out[11:0]', prior to the modules output pins.  Show us your results...

Okay, will have a go at this tomorrow now as I doubt I'll have any time tonight the way things are going.   ::)

Damn, we would be nowhere if I didn't re-install Quartus myself...

Some things are just too complicated to give direction by proxy, I guess.  Quartus is certainly one of those things.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 10:56:23 am
Ok, it's time to get onto points #4 and #5 here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)

Note: place the register bank in the last 256 bytes of the 16kb addressable memory and tie it's data/address/we inputs to the RS232 debugger outputs in parallel with system 'host_' memory.

Okay, point #4 is nearly done.  I've attached the project below - that's the LATEST version, with all the changes so far including point #4 changes and some tweaks I made to the format of the vid_osd_generator code at the very start to make the I/O declarations easier to read.  I've also made the connections on the design sheet to the outputs of the RS232 module, so should all be present and correct.

Here's a screenshot of the design sheet now - it's getting hard to fit into one screen:

[attach=2]

(I'm aware I've set a hex value when it should be INT for the BASE_WRITE_ADDRESS in the design sheet - that's corrected).  However, it won't compile due to bus width errors - it seems Quartus isn't happy with me connecting a 14-lane bus from host_addr in the RS232 debugger module to a 20-lane input bus for addr_in in the GPU_HW_Control_Regs module.  It's also complaining about bus width errors elsewhere where the GPU_HW_REGS_BUS connects to other modules.

Is there an easy way to interface buses of different sizes without changing parameters in the modules themselves?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 12:45:53 pm
In danger of diluting the focus of our current efforts (#4 & #5 in the current task list), here's my latest on #1.  I've updated the sync_generator to include the 16 pixel X and Y offset.  Not 100% convinced you'll be happy with how I've done it, but it seems to work according to how I'm interpreting the simulation results (below).

[attach=1]

It's not visible in the screenshot above, but hde doesn't go high until the h_count = 16, and vde doesn't go high until v_count = 16.  Here's some close-ups:

[attach=2]

Above shows hde going high after 16 pixels.

[attach=3]

Above shows vde going high on the 16th line.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2019, 01:12:33 pm
Ok, it's time to get onto points #4 and #5 here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2788698/#msg2788698)

Note: place the register bank in the last 256 bytes of the 16kb addressable memory and tie it's data/address/we inputs to the RS232 debugger outputs in parallel with system 'host_' memory.

Okay, point #4 is nearly done.  I've attached the project below - that's the LATEST version, with all the changes so far including point #4 changes and some tweaks I made to the format of the vid_osd_generator code at the very start to make the I/O declarations easier to read.  I've also made the connections on the design sheet to the outputs of the RS232 module, so should all be present and correct.

Here's a screenshot of the design sheet now - it's getting hard to fit into one screen:

(Attachment Link)

(I'm aware I've set a hex value when it should be INT for the BASE_WRITE_ADDRESS in the design sheet - that's corrected).  However, it won't compile due to bus width errors - it seems Quartus isn't happy with me connecting a 14-lane bus from host_addr in the RS232 debugger module to a 20-lane input bus for addr_in in the GPU_HW_Control_Regs module.  It's also complaining about bus width errors elsewhere where the GPU_HW_REGS_BUS connects to other modules.

I just clicked on 1 error at a time and fixed them.  It compiled fine... See here...
Though, you will eventually need to up, or decide what to do with the RS232_Debugger's 14 bit address.
The desktop param does feed everything else properly.  (Warning, I changer the extension of the GPU_HW_Control_Regs.sv to GPU_HW_Control_Regs.v)
(Attachment Link)

Is there an easy way to interface buses of different sizes without changing parameters in the modules themselves?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2019, 01:39:35 pm
In danger of diluting the focus of our current efforts (#4 & #5 in the current task list), here's my latest on #1.  I've updated the sync_generator to include the 16 pixel X and Y offset.  Not 100% convinced you'll be happy with how I've done it, but it seems to work according to how I'm interpreting the simulation results (below).

(Attachment Link)

It's not visible in the screenshot above, but hde doesn't go high until the h_count = 16, and vde doesn't go high until v_count = 16.  Here's some close-ups:

(Attachment Link)

Above shows hde going high after 16 pixels.

(Attachment Link)

Above shows vde going high on the 16th line.

Your going to have to get rid of the '-1' and accept that the outputs are delayed by 1-Hcount and 1-Vcount.  Unfortunately, with the way it is setup, if you choose an offset of 0x0, the beginning positions would never happen.
The true method of getting a proper H&V count would be to make 2 new output regs, Hcount_out and Vcount_out which latch their values from the source H&V internal counters.
Having the 'Adjusting' -1 for the counter raster limits and for the syncs are fine, bur, you now need to verify that the HH&V syncs begin and stop 16 H&V positions later compared to their original locations so that the output image is still relatively centered.  This one is easy as you will just add the H&V offset to the H&V start and stop of your current formula knowing having a '0' for an offset would move nothing as it should.  Bit, wait a minute, you HDE and VDE are now 1 pixel/line later with the new setup having '0's as an offset.  It looks like your sync offsets were OFF by 1 pixel and line all along.... Who knew?  Wait, everything needs to be re-checked.  Your going to need to verify that you actually have 640 'ON' pixels, not 641... Same with lines.  Also, when does the sync begin and end.  (Remember I said there would be a pitfall...) 

Ok, to clear things up, there is a 1 count delay from the counter when you say you want the start/begin to ==.  This is fine understanding that that 1 delay is everywhere else since you H&V internal counters are preparing their value 1 clock in advance, and the 'IF(a==b) DE=<=1' result 'DE<=#' are set on the next clock.  This is fine for 2 reasons, we do not use these Hcount & Vcount anywhere else, they are just internal for the sync generator & any special trigger controls we may be adding now will also be stuck on that 1 pixel/line clock delay.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 01:48:25 pm

Thanks - so it was just the naming of the bus(es) that was the issue.  |O  I just modified the design on my current project instead of using the one you uploaded above as I have modifications to sync_generator (made a start on #5) and image offset addition.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 02:27:13 pm
Your going to have to get rid of the '-1' and accept that the outputs are delayed by 1-Hcount and 1-Vcount.  Unfortunately, with the way it is setup, if you choose an offset of 0x0, the beginning positions would never happen.

:o  Yeah, you're right. Okay, removed the -1's.

Your going to need to verify that you actually have 640 'ON' pixels, not 641... Same with lines.  Also, when does the sync begin and end.  (Remember I said there would be a pitfall...)

Okay, so vde goes on on line 17 and is going off on line 496, so that seems like 480 + Y_OFFSET is working okay:

[attach=2]

hde is going off on pixel 656, which is 640 + X_OFFSET:

[attach=3]

Both come on at the right time (unless I'm misunderstanding the whole 1 pixel offset thing).

Latest zipped project file attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 04:32:30 pm
5.  Add a new 48 register output to the 'sync_gen.v' called 'raster_HV_trigger[47:0]'.

Okay, that was easy enough - that's already in the project files I attached in my last post.  I may need some clarification of the next bits, though...  ???

Make the even 'raster_HV_trigger[47:0]' wires pulse at a horizontal pixel position and the odd wires pulse on a vertical line according to the new 'GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0]' onput wire, organized as 16 bit words, using the first 10 of 16 bits of each 2x2 bytes coming from the new input "GPU_HW_Control_regs[HW_REGS_SIZE*8-1:0]".

So the even wires [0..46] need to have a positive (one-clock?) pulse when h_count matches a value that matches the 10 bits of each 2-byte pair in GPU_HW_Control_regs?

The odd wires [1..47] will be the same, but trigger when v_count matches a value in the hardware regs?

So only the wire corresponding to the appropriate byte-pair in the hardware registers will pulse?  :-//

You should add a new parameter input to the sync_gen.v which will allow you to shift the beginning byte base (beginning) address of GPU_HW_Controls where the 'raster_HV_trigger' get their 48 settings from.  IE 48x2 bytes = 96 bytes total.

Right, that makes sense.  So we're looking to use 96 bytes from the 256 available hardware registers for these raster triggers?  And this parameter will set the base where the first of 96 bytes will be read from in the hardware registers and have a value between 0 and 160 (or 2**HW_REGS - 96)?

Once done, out on your top block diagram, 'or' these 48 HV triggers outputs together and 'or' tie them to to the upper ro[],go[],bo[] bits of the OSD_img output.  Test with the GPUtalk app.  You should be able to move 24 vertical lines and 24 horizontal lines around the screen, with the first 0-15 coordinates being non-visible as those coordinates are too far to the left and above the top of the picture since we moved the picture window by 16 pixels to the right and down in step (1).  (Once working, mix and combine / change around the 'or' driven ro[]&go[]&bo[] colors VS raster_HV_trigger[47:0] even and odd pairs so each set of coordinate generated lines may generate a different color on the display.)

I was with you all the way to 'once done'...  :-DD :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2019, 05:04:18 pm
Think this one through....

example:

Code: [Select]
for (..i..) begin
     if  ( h_count[9:8] == HW_REGS[i*4+base_offset+0][1:0] && h_count[7:0] == HW_REGS[i*4+base_offset+1][7:0] ) raster_HV_triggers[i*2+0] <= 1;
     else raster_HV_triggers[i*2+0] <= 0;
end
then inside the 'v_count increment 'IF()begin'  Place the vertical version.

Your Syncgen should have a new output register wire called 'raster_HV_triggers[47:0]' each even one should pulse on and off for a pixel.  Make sure the odd wires in there pulse on, then off for an entire line.

Take that bundle and tie it into the current 'color_sel' module.  Make a bunch of the 'raster_HV_triggers[47:0]' force on your choice of color for each wire, over the text box and static noise, or, whatever may be feeding the color_sel modules output so you may see if what you made works...

Now, you better figure out what the 'base_offset' is, otherwise I'll go nuts.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2019, 05:29:14 pm
Your going to miss the vcount position '==0' if you keep your 'VDE' in it's current location.  Move it outside the vcounter increment but leave it inside when the vcoun increment happens...


This is what you have now, it needs correcting...
Code: [Select]
// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin
h_count <= 9'b0; // reset h_count

// Now h_count has been zeroed, check if the V-count should be cleared at end of SCANLINES
if (v_count == SCANLINES - 1)
begin
v_count <= 9'b0;
frame_ctr <= frame_ctr + 1'b1; // Increment the frame counter
end
else
begin // If v_count isn't being cleared, increment v_count
v_count <= v_count + 1'b1; // increment v_count to next scanline

if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area
end
end

Actually, this would still work unless you vde is set to SCANLINES - 1....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 08:47:02 pm
Your going to miss the vcount position '==0' if you keep your 'VDE' in it's current location.  Move it outside the vcounter increment but leave it inside when the vcoun increment happens...


This is what you have now, it needs correcting...
Code: [Select]
// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin
h_count <= 9'b0; // reset h_count

// Now h_count has been zeroed, check if the V-count should be cleared at end of SCANLINES
if (v_count == SCANLINES - 1)
begin
v_count <= 9'b0;
frame_ctr <= frame_ctr + 1'b1; // Increment the frame counter
end
else
begin // If v_count isn't being cleared, increment v_count
v_count <= v_count + 1'b1; // increment v_count to next scanline

if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area
end
end


Actually, this would still work unless you vde is set to SCANLINES - 1....

Soooo... How about I just move the VDE assignment out of the if (v_count == SCANLINES - 1) conditional entirely?  It'll be assigned no matter what the outcome of the if-conditional then.

Code: [Select]
if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area

// Now h_count has been zeroed, check if the V-count should be cleared at end of SCANLINES
if (v_count == SCANLINES - 1)
begin

v_count <= 9'b0;
frame_ctr <= frame_ctr + 1'b1; // Increment the frame counter

end
else
begin // If v_count isn't being cleared, increment v_count

v_count <= v_count + 1'b1; // increment v_count to next scanline

end


Owzat?

example:

Code: [Select]
for (..i..) begin
     if  ( h_count[9:8] == HW_REGS[i*4+base_offset+0][1:0] && h_count[7:0] == HW_REGS[i*4+base_offset+1][7:0] ) raster_HV_triggers[i*2+0] <= 1;
     else raster_HV_triggers[i*2+0] <= 0;
end

then inside the 'v_count increment 'IF()begin'  Place the vertical version.

Your Syncgen should have a new output register wire called 'raster_HV_triggers[47:0]' each even one should pulse on and off for a pixel.  Make sure the odd wires in there pulse on, then off for an entire line.

Take that bundle and tie it into the current 'color_sel' module.  Make a bunch of the 'raster_HV_triggers[47:0]' force on your choice of color for each wire, over the text box and static noise, or, whatever may be feeding the color_sel modules output so you may see if what you made works...

Hmm.. well nothing blows up, so that's good I guess? ???  I'm going to have to remind myself how the values in raster_HV_triggers work.  I'd be lying if I said:

Code: [Select]
h_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET][1:0] && h_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+1][7:0]

...didn't confuse the hell out of me.  :o  Doesn't help that concentration is difficult when I've got a daughter singing the theme tune to Frozen 2 in my ear...  :blah:

Now, you better figure out what the 'base_offset' is, otherwise I'll go nuts.

Oh ye of little faith..  ^-^  (Hoping against all hope that I actually did get it right!)

Code: [Select]
// VGA Sync Generator
//
// Default: 640x480x60
//
// Can take parameters when initialised
// to output sync signals for any screen
// resolution

module sync_generator(

// inputs
input wire pclk, // base pixel clock (125 MHz)
input wire reset, // reset: restarts frame
input wire [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],

// outputs
output reg [3:0] pc_ena,  // Pixel clock enable (4-bit to allow clock division in video sub-modules)
output reg hde, // Horizontal Display Enable - high when in display area (valid drawing area)
output reg vde, // Vertical Display Enable - high when in display area (valid drawing area)
output reg hsync, // horizontal sync
output reg vsync, // vertical sync

output reg [15:0] frame_ctr,
output reg [47:0] raster_HV_triggers

);

// default resolution if no parameters are passed
parameter H_RES = 640; // horizontal display resolution
parameter V_RES = 480; // vertical display resolution

// image offset parameters
parameter IMAGE_OFFSET_X = 16; // offset the display to allow room at the start
parameter IMAGE_OFFSET_Y = 16; // for things to go off edge of screen

// no-draw area definitions
// defined as parameters so you can edit these on Quartus' block diagram editor
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH = 96;
parameter H_BACK_PORCH = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH = 33;
parameter PIX_CLK_DIVIDER = 4;

parameter HW_REGS_SIZE = 8; // hardware register size set by HW_REGS parameter in design sheet
parameter BASE_OFFSET = 32; // hardware register base offset for raster triggers

// total screen resolution
localparam LINE = H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_BACK_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_BACK_PORCH; // total scan lines (inc. vertical blanking area)

// useful trigger points
localparam HS_STA = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1; // horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF

reg [9:0] h_count; // current pixel x position
reg [9:0] v_count; // current line y position

   always @(posedge pclk)
if (pc_ena == PIX_CLK_DIVIDER) pc_ena <= 0;
else pc_ena <= pc_ena +1;

integer i;

// handle signal generation
always @(posedge pclk)
begin

if (reset) // reset to start of frame
begin
h_count <= (IMAGE_OFFSET_X + H_RES - 2);
v_count <= (SCANLINES - 2);
//z_count <= 1'b0;
hsync   <= 1'b0;
vsync   <= 1'b0;
vde     <= 1'b0;
hde     <= 1'b0;
frame_ctr <= 16'h0000;
end
else
begin
if (pc_ena[3:0] == 0) // once per pixel
begin

// horizontal raster trigger generation
for (i = 0; i < 24; i = i + 2) begin

if ( h_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET][1:0] && h_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+1][7:0] )
raster_HV_triggers[i*2+0] <= 1'b1;
else
raster_HV_triggers[i*2+0] <= 1'b0;

end

// horizontal blanking area - set HDE LOW
if (h_count == IMAGE_OFFSET_X + H_RES - 1)
hde <= 1'b0; // Turn off horizontal video data enable
else if (h_count == IMAGE_OFFSET_X)
hde <= 1'b1;  // Turn on horizontal video data enable

// check for generation of HSYNC pulse
if (h_count == HS_STA)
hsync <= 1'b1; // turn on HSYNC pulse
else if (h_count == HS_END)
hsync <= 1'b0; // turn off HSYNC pulse

// check for generation of VSYNC pulse
if (v_count == VS_STA)
vsync <= 1'b1; // turn on VSYNC pulse
else if (v_count == VS_END)
vsync <= 1'b0; // turn off VSYNC pulse

// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin

h_count <= 9'b0; // reset h_count

// vertical raster trigger generation
for (i = 1; i < 24; i = i + 2) begin

if ( v_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET][1:0] && v_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+1][7:0] )
raster_HV_triggers[i*2+0] <= 1'b1;
else
raster_HV_triggers[i*2+0] <= 1'b0;

end

if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area

// Now h_count has been zeroed, check if the V-count should be cleared at end of SCANLINES
if (v_count == SCANLINES - 1)
begin

v_count <= 9'b0;
frame_ctr <= frame_ctr + 1'b1; // Increment the frame counter

end
else
begin // If v_count isn't being cleared, increment v_count

v_count <= v_count + 1'b1; // increment v_count to next scanline

end
end
else // not at end of scanline, so just increment horizontal counter
begin

h_count <= h_count + 1'b1;
if (h_count == IMAGE_OFFSET_X + H_RES - 1)
hde <= 1'b0 ;  // Turn off horizontal video data enable

end // if (h_count == LINE - 1)

end // if (pc_ena)

end // else !reset

end // always @clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2019, 09:18:29 pm
Read carefully....

Code: [Select]
// horizontal raster trigger generation
for (i = 0; i < 24; i = i + 1) begin

if ( h_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET+0][1:0] && h_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+1][7:0] )
raster_HV_triggers[i*2+0] <= 1'b1;
else
raster_HV_triggers[i*2+0] <= 1'b0;

end

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

// vertical raster trigger generation
for (i = 1; i < 24; i = i + 1) begin

if ( v_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET+2][1:0] && v_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+3][7:0] )
raster_HV_triggers[i*2+1] <= 1'b1;
else
raster_HV_triggers[i*2+1] <= 1'b0;

end


Hints, what's i*2+1 = when 'i' is 23?
What's the top 'raster_HV_triggers' wire position.

Read all the other changes...

I'm expecting to see some screenshots with cursor lines which your positioned & moved around with the RS232_Debugger... Maybe video of them animated using the RS232_Debugger's mouse wheel, or +/- keys which actually edit a full 16bit word...

I also expect you to discover 1 problem with the vertical lines...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2019, 11:05:10 pm
Hints, what's i*2+1 = when 'i' is 23?
What's the top 'raster_HV_triggers' wire position.

47... and 47...?

Read all the other changes...

I'm expecting to see some screenshots with cursor lines which your positioned & moved around with the RS232_Debugger... Maybe video of them animated using the RS232_Debugger's mouse wheel, or +/- keys which actually edit a full 16bit word...

I also expect you to discover 1 problem with the vertical lines...

I'll get you screenshots tomorrow, it's late here, but I've had a quick play with the amended code and my limited understanding of how I can connect it all together and test it, and I've managed to get a green crosshairs to appear on the screen by meddling with the GPU memory from 3F00 onwards.  I've been able to move the vertical line to the right and back, but can't move the horizontal line.  I suspect there's something wrong with how I've wired it all up, so here's the design view:

[attach=1]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2019, 12:15:17 am
For now, just use a few of these:
[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2019, 11:10:55 am
Well, I'm certainly no expert at this and have wired up the triggers as best I can currently - I've just OR'd them all together and then OR'd them into the green channel's MSB.  Design pic attached.

I can scroll the lines, make multiple lines etc.

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2019, 11:16:56 am
I also expect you to discover 1 problem with the vertical lines...

Still looking for this one.  The vertical line on the left appears at 16, which seems okay.  The vertical line on the right edge of the screen, however, is at 661, which seems odd...  ???

EDIT:  Latest project files attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2019, 01:50:46 pm
I also expect you to discover 1 problem with the vertical lines...

Still looking for this one.  The vertical line on the left appears at 16, which seems okay.  The vertical line on the right edge of the screen, however, is at 661, which seems odd...  ???

EDIT:  Latest project files attached.

Ok, all I've done is turned off my snow, made the cursors yellow (so you know it's different), changed the base address in the 'sync_generator.sv' to 0, and set the register defaults to what I played with in the RS232_debugger.

I've included a 'cursor_borders.bin' in the .zip to load into the debugger so you may see the numbers.

Step #1 test if all ' raster_HV_triggers[47..0] ' do something....
Problem #1.  raster_HV_triggers[1], the first horizontal line after the first vertical line seems to be dead!!!

These are the coordinates I set in the first 4 functional cursors:

raster_HV_triggers[0] = $0017 = 23 decimal.  First vertical line at left most of screen. (Bad)
raster_HV_triggers[1] = DEAD
raster_HV_triggers[2] = $0295 = 661 decimal.  Right most pixel on screen. (Bad)
raster_HV_triggers[3] = $0010 = 16 decimal.    Top most line on screen.     (The 1 good thing...)
#4 skipped as it is vertical...
raster_HV_triggers[5] = $01EE = 494 decimal.  Bottom most visible line.  (Bad, Error, see if you can figure out why...)

Now, don't threat, I've done this stuff for years and know where your problems are, however, enough development and tools have been doe that you should be able to figure out the solutions.

Use the .zip I sent you and see what you can figure out.  (vid_osd_generator pipe delay)

Here is a photo of all 46 functional cursors, 24 vertical and 23 horizontal.
[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2019, 04:45:38 pm
Step #1 test if all ' raster_HV_triggers[47..0] ' do something....
Problem #1.  raster_HV_triggers[1], the first horizontal line after the first vertical line seems to be dead!!!

Fixed this one.  Line 123 was the problem in sync_generator.sv:

for (i = 1; i < 24; i = i + 1) begin

Just needed changing to this:

for (i = 0; i < 24; i = i + 1) begin

Was a typo or throwback from some earlier iteration of the code that I hadn't picked up on.

These are the coordinates I set in the first 4 functional cursors:

raster_HV_triggers[0] = $0017 = 23 decimal.  First vertical line at left most of screen. (Bad)
raster_HV_triggers[1] = DEAD [FIXED]
raster_HV_triggers[2] = $0295 = 661 decimal.  Right most pixel on screen. (Bad)
raster_HV_triggers[3] = $0010 = 16 decimal.    Top most line on screen.     (The 1 good thing...)
#4 skipped as it is vertical...
raster_HV_triggers[5] = $01EE = 494 decimal.  Bottom most visible line.  (Bad, Error, see if you can figure out why...)

Now, don't threat, I've done this stuff for years and know where your problems are, however, enough development and tools have been doe that you should be able to figure out the solutions.

Horizontal raster triggers:
The first vertical line should appear at 16, but appears at 23 (out by +7).
The last vertical line should appear at 656 (640+16 X_offset) but appears at 661 (out by +5).

Vertical raster triggers:
The first horizontal appears at 16 decimal, so that's okay.
The last appears at 494 decimal, when it should be 496 (480+16 Y_offset) (out by 2).

Could the vertical raster trigger errors be due to a counting problem with a stray -1 somewhere?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2019, 06:01:49 pm
Think through the IF's.  What mutes the video on the screen, or allows it through.
Also think about pixel coordinates and their numbers.
Try setting the X&Y offset parameters down to 0, play with the H&V numbers to give you a hand and really think through what happens when in the 'IF (a==b) statements.  What the numbers are at each clock and what happens to the results and 'WHEN'...

As for the vertical lines, obviously think about when they come out and if I said that the OSD was dead perfect since I simulated the whole thing even before I 'threw' your GPU into one of my scalers, why is the text ok and why is the vertical lines miss located?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2019, 10:07:46 pm
Think through the IF's.  What mutes the video on the screen, or allows it through.
Also think about pixel coordinates and their numbers.
Try setting the X&Y offset parameters down to 0, play with the H&V numbers to give you a hand and really think through what happens when in the 'IF (a==b) statements.  What the numbers are at each clock and what happens to the results and 'WHEN'...

As for the vertical lines, obviously think about when they come out and if I said that the OSD was dead perfect since I simulated the whole thing even before I 'threw' your GPU into one of my scalers, why is the text ok and why is the vertical lines miss located?

Okay... trying it with zero offset on X and Y.

Horizontal raster triggers:
The first vertical line should appear at 16, but appears at 23 (out by +7).
The last vertical line should appear at 656 (640+16 X_offset) but appears at 661 (out by +5).

Vertical raster triggers:
The first horizontal appears at 16 decimal, so that's okay.
The last appears at 494 decimal, when it should be 496 (480+16 Y_offset) (out by 2).

With zero offsets:

The first vertical line appears at 7 - this is out by 7 as before.
The second vertical appears at 645 - this is out by 5 as before.

The first horizontal appears at 0. This is correct, as before with the offsets.
The second horizontal appears at 478.  As before, out by -2.

So the results are consistent, at least.  This must be something to do with the clock delays?  Is it because the checks are not being delayed like the rest of the pixel pipeline?  It can't be when the IF checks are being made - I've tried moving the horizontal raster trigger generation IF block to where h_count gets incremented, but no change.  :-//

I'd suggest using a pipe delay for the triggers, but the errors are not consistent (the vertical line is out by 7 on the left, but 5 only on the right, so a fixed delay line won't remove that error?) In fairness, it's the fact the errors aren't fixed that has me stumped.  If they were out by a constant 7 pixels across the screen and a constant 2 pixels down it, I could likely pin the cause down really quickly, but they change...  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2019, 10:20:11 pm
Lets start with the Horizontal line only.  You say 0 starts at 0.  Fine.  Now, at 640x480, starting coordinate Y 0, where does Y actually end?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 29, 2019, 09:43:48 am
Lets start with the Horizontal line only.  You say 0 starts at 0.  Fine.  Now, at 640x480, starting coordinate Y 0, where does Y actually end?

With no offset, the display area ends at 479 and the last line is 524.  So could it just be a -1 error as it appears at 478?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2019, 12:45:12 pm
Lets start with the Horizontal line only.  You say 0 starts at 0.  Fine.  Now, at 640x480, starting coordinate Y 0, where does Y actually end?

With no offset, the display area ends at 479 and the last line is 524.  So could it just be a -1 error as it appears at 478?
Good, part of 1 problem solved, next...

If IMAGE_OFFSET_Y is 0, what does this line of code do?
Code: [Select]
if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
When does it do it?

Next, assuming IMAGE_OFFSET_Y is till 0, and V_RES is 480: What does this line do?
Code: [Select]
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area
When does it do it?

Please answer the questions next the next post...



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 29, 2019, 05:18:57 pm
If IMAGE_OFFSET_Y is 0, what does this line of code do?
Code: [Select]
if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
When does it do it?

It turns vde on when v_count is 0.  As for when it does it - I guess on the rising edge of the next CLK?

Next, assuming IMAGE_OFFSET_Y is till 0, and V_RES is 480: What does this line do?
Code: [Select]
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area
When does it do it?

It turns vde off when v_count is 479 - again, on the rising edge of the next CLK pulse?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2019, 05:32:14 pm
If IMAGE_OFFSET_Y is 0, what does this line of code do?
Code: [Select]
if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
When does it do it?

It turns vde on when v_count is 0.  As for when it does it - I guess on the rising edge of the next CLK?

Next, assuming IMAGE_OFFSET_Y is till 0, and V_RES is 480: What does this line do?
Code: [Select]
else if (v_count == IMAGE_OFFSET_Y + V_RES - 1)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area
When does it do it?

It turns vde off when v_count is 479 - again, on the rising edge of the next CLK pulse?
Ok, now here is the important bit....
Ignoring the clk for a second, if you have the video enable turning ON on line 0, and your starting coordinate Y is 0 and this is correct on the screen, do you not think turning OFF the visible line at line 479 is a bad idea if you want to visibly see line 479?

Regardless if the counter is behind by 1 CLK, meaning this hidden internal counter is already +1, meaning whend you turn on at line 0, the counter may be at line 1, and the same for at the end since the switch on and off both have the same delay....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 29, 2019, 06:36:49 pm
Ok, now here is the important bit....
Ignoring the clk for a second, if you have the video enable turning ON on line 0, and your starting coordinate Y is 0 and this is correct on the screen, do you not think turning OFF the visible line at line 479 is a bad idea if you want to visibly see line 479?

Regardless if the counter is behind by 1 CLK, meaning this hidden internal counter is already +1, meaning whend you turn on at line 0, the counter may be at line 1, and the same for at the end since the switch on and off both have the same delay....

Okay, so the -1 on line 134 needs removing?

Code: [Select]
if (v_count == IMAGE_OFFSET_Y)  <---- REMOVED -1
vde <= 1'b1; // Turn on vertical video data enable - start of display area
else if (v_count == IMAGE_OFFSET_Y + V_RES)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area

That fixes the bottom horizontal line...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2019, 06:53:00 pm
Code: [Select]
localparam HS_STA = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1; // horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
--------------------------------------------------------------------------------------------
if (h_count == IMAGE_OFFSET_X + H_RES - 1)
--------------------------------------------------------------------------------------------
if (h_count == IMAGE_OFFSET_X + H_RES - 1)
--------------------------------------------------------------------------------------------
Do a simulation and show me the key horizontal numerical points.  Make sure everything is going off and of with the right amount of pixels, regardless that they will all be shifted to the right by 1 pixel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2019, 11:09:45 am
@nockieboy I realize the holidays coming up with family obligations must be adding a toll on your available time to concentrate here.

You have 1 thing left to verify about the sync generator, then, you will be gutting the osd_generator and wiring in 2 or 3 address generators in place of my limited 64x32 column current one.

We'll skip sprites and just do the final 2 palette memories and overlay.  You already have what might already be functional Z80 interface, but you may want to multiplex that GPU memory interface side with a separate module so you may have additional access within the GPU project.

If there is time later, we'll look at piggy-backing on some sprites and other more advanced features.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2019, 10:21:14 am
Do a simulation and show me the key horizontal numerical points.  Make sure everything is going off and of with the right amount of pixels, regardless that they will all be shifted to the right by 1 pixel.

Okay, I'm hoping this is what you're asking for... I've got the start of the visible display (top left of screen) and end of the visible display (bottom right of screen):

Start:
[attachimg=1]

End:
[attachimg=2]

@nockieboy I realize the holidays coming up with family obligations must be adding a toll on your available time to concentrate here.

Yes, work had cranked up the last week as well, so I've been finding it very hard to find time to work on the project.  :'(

You have 1 thing left to verify about the sync generator, then, you will be gutting the osd_generator and wiring in 2 or 3 address generators in place of my limited 64x32 column current one.

We'll skip sprites and just do the final 2 palette memories and overlay.  You already have what might already be functional Z80 interface, but you may want to multiplex that GPU memory interface side with a separate module so you may have additional access within the GPU project.

If there is time later, we'll look at piggy-backing on some sprites and other more advanced features.

I would really appreciate being able to get some form of sprite support implemented, but I understand that your time is limited.  I may have some time this week so I'll try to catch up as best I can.  :)

I have the hardware for the Z80 interface sorted (well, it's just a breadboard with 4 buffers on it to convert from 5V down to 3.3V and a bi-directional buffer for the data bus), I think it's just the mux to allow the RS232 and the Z80_bridge modules to work alongside each other.  I haven't given that any thought past your previous comments on it yet.

EDIT:

Added end of line as well:

[attachimg=3]

So, I've removed a couple of the -1's from the checks for the hde assignment - I've also removed an unnecessary check to turn off hde when leaving the visible area as it's already done further down in the code.  Updated sync_generator code is below, but I've also attached the current project so we're on the same page.

This change means that the bottom horizontal bar is at decimal 495, and the far right vertical is now on decimal 662 (with X_OFFSET and Y_OFFSET set to 16).

Though I'm still going round in circles with this - I'm going to need you to tell me what the issue is, I think, as I'll never find it before Christmas on my own.  :-//

(Okay, can't leave the code for sync_generator in this post as there's a bug in the forum software that doesn't allow me to post code blocks in the same forum post as attachments for some reason.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2019, 10:57:53 am
Code: [Select]
// VGA Sync Generator
//
// Default: 640x480x60
//
// Can take parameters when initialised
// to output sync signals for any screen
// resolution

module sync_generator(

// inputs
input wire pclk, // base pixel clock (125 MHz)
input wire reset, // reset: restarts frame
input wire [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],

// outputs
output reg [3:0] pc_ena,  // Pixel clock enable (4-bit to allow clock division in video sub-modules)
output reg hde, // Horizontal Display Enable - high when in display area (valid drawing area)
output reg vde, // Vertical Display Enable - high when in display area (valid drawing area)
output reg hsync, // horizontal sync
output reg vsync, // vertical sync

output reg [15:0] frame_ctr,
output reg [47:0] raster_HV_triggers

);

// default resolution if no parameters are passed
parameter H_RES = 640; // horizontal display resolution
parameter V_RES = 480; // vertical display resolution

// image offset parameters
parameter IMAGE_OFFSET_X = 16; // offset the display to allow room at the start
parameter IMAGE_OFFSET_Y = 16; // for things to go off edge of screen

// no-draw area definitions
// defined as parameters so you can edit these on Quartus' block diagram editor
parameter H_FRONT_PORCH = 16;
parameter HSYNC_WIDTH = 96;
parameter H_BACK_PORCH = 48;
parameter V_FRONT_PORCH = 10;
parameter VSYNC_HEIGHT = 2;
parameter V_BACK_PORCH = 33;
parameter PIX_CLK_DIVIDER = 4;

parameter HW_REGS_SIZE = 8; // hardware register size set by HW_REGS parameter in design sheet
parameter BASE_OFFSET = 32; // hardware register base offset for raster triggers

// total screen resolution
localparam LINE = H_RES + H_FRONT_PORCH + HSYNC_WIDTH + H_BACK_PORCH; // complete line (inc. horizontal blanking area)
localparam SCANLINES = V_RES + V_FRONT_PORCH + VSYNC_HEIGHT + V_BACK_PORCH; // total scan lines (inc. vertical blanking area)

// useful trigger points
localparam HS_STA = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH - 1; // horizontal sync ON (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam HS_END = IMAGE_OFFSET_X + H_RES + H_FRONT_PORCH + HSYNC_WIDTH - 1; // horizontal sync OFF (the minus 1 is because hsync is a REG, and thus one clock behind)
localparam VS_STA = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH; // vertical sync ON
localparam VS_END = IMAGE_OFFSET_Y + V_RES + V_FRONT_PORCH + VSYNC_HEIGHT; // vertical sync OFF

reg [9:0] h_count; // current pixel x position
reg [9:0] v_count; // current line y position

   always @(posedge pclk)
if (pc_ena == PIX_CLK_DIVIDER) pc_ena <= 0;
else pc_ena <= pc_ena +1;

integer i;

// handle signal generation
always @(posedge pclk)
begin

if (reset) // reset to start of frame
begin
h_count <= (IMAGE_OFFSET_X + H_RES - 2);
v_count <= (SCANLINES - 2);
//z_count <= 1'b0;
hsync   <= 1'b0;
vsync   <= 1'b0;
vde     <= 1'b0;
hde     <= 1'b0;
frame_ctr <= 16'h0000;
end
else
begin
if (pc_ena[3:0] == 0) // once per pixel
begin

// horizontal raster trigger generation
for (i = 0; i < 24; i = i + 1) begin

if ( h_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET+0][1:0] && h_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+1][7:0] )
raster_HV_triggers[i*2+0] <= 1'b1;
else
raster_HV_triggers[i*2+0] <= 1'b0;

end

// start of visible display area - set HDE HIGH
if (h_count == IMAGE_OFFSET_X)
hde <= 1'b1;  // Turn on horizontal video data enable

// check for generation of HSYNC pulse
if (h_count == HS_STA)
hsync <= 1'b1; // turn on HSYNC pulse
else if (h_count == HS_END)
hsync <= 1'b0; // turn off HSYNC pulse

// check for generation of VSYNC pulse
if (v_count == VS_STA)
vsync <= 1'b1; // turn on VSYNC pulse
else if (v_count == VS_END)
vsync <= 1'b0; // turn off VSYNC pulse

// reset h_count & increment v_count at end of scanline
if (h_count == LINE - 1) // end of line
begin

h_count <= 9'b0; // reset h_count

// vertical raster trigger generation
for (i = 0; i < 24; i = i + 1) begin

if ( v_count[9:8] == GPU_HW_Control_regs[i*4+BASE_OFFSET+2][1:0] && v_count[7:0] == GPU_HW_Control_regs[i*4+BASE_OFFSET+3][7:0] )
raster_HV_triggers[i*2+1] <= 1'b1;
else
raster_HV_triggers[i*2+1] <= 1'b0;

end

if (v_count == IMAGE_OFFSET_Y)
vde <= 1'b1; // Turn on vertical video data enable - start of display area
else if (v_count == IMAGE_OFFSET_Y + V_RES)
vde <= 1'b0 ; // Turn off vertical video data enable - reached bottom of display area

// Now h_count has been zeroed, check if the V-count should be cleared at end of SCANLINES
if (v_count == SCANLINES - 1)
begin

v_count <= 9'b0;
frame_ctr <= frame_ctr + 1'b1; // Increment the frame counter

end
else
begin // If v_count isn't being cleared, increment v_count

v_count <= v_count + 1'b1; // increment v_count to next scanline

end
end
else // not at end of scanline, so just increment horizontal counter
begin

h_count <= h_count + 1'b1;
if (h_count == IMAGE_OFFSET_X + H_RES)
hde <= 1'b0 ;  // Turn off horizontal video data enable

end // if (h_count == LINE - 1)

end // if (pc_ena)

end // else !reset

end // always @clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2019, 02:18:24 pm
I've made tentative steps towards getting the data mux started for the RS232 and Z80_bridge modules (the last part needed to get the Microcom talking to the GPU?)

Currently, I've sorted out the inputs and outputs I think I need.  I'm hesitant to actually start writing the HDL for the mux as I'm not 100% clear on how I can create it.  I know it needs to switch between two (or even three?) sets of inputs consisting of:


Design pic below, showing the module (which is currently empty - just has I/O defined) partially connected to the Z80_bridge.

So, my thoughts on how it would work are that it defaults to Port A (the Z80 port), passing through address, data and wr_ena's.  When a rd_req is detected, it waits 2 clocks then passes the data output from the osd_generator module back to the Z80_bridge.

If a read or write request is detected on Port B (i.e. from the RS232 module) and it's doing nothing at that moment, it will switch the above described functions to route the address and data to/from the RS232 module instead.

What I'm not sure about is how it will deal with activity from either port that overlaps with an existing request.  ???  Will it just pipeline it for 2 clocks then push the new request through?

I'm aware this is a sidetrack from the current work on the raster triggers and sync_generator, but am trying to keep myself busy while I have some free time and it doesn't align with yours.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on December 01, 2019, 02:56:00 pm
If your arbiter only samples the request signals when there is no request in progress, there won't be any conflicts.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2019, 03:18:11 pm
Do a simulation and show me the key horizontal numerical points.  Make sure everything is going off and of with the right amount of pixels, regardless that they will all be shifted to the right by 1 pixel.

Okay, I'm hoping this is what you're asking for... I've got the start of the visible display (top left of screen) and end of the visible display (bottom right of screen):

Start:
(Attachment Link)

End:
(Attachment Link)

@nockieboy I realize the holidays coming up with family obligations must be adding a toll on your available time to concentrate here.

Yes, work had cranked up the last week as well, so I've been finding it very hard to find time to work on the project.  :'(

You have 1 thing left to verify about the sync generator, then, you will be gutting the osd_generator and wiring in 2 or 3 address generators in place of my limited 64x32 column current one.

We'll skip sprites and just do the final 2 palette memories and overlay.  You already have what might already be functional Z80 interface, but you may want to multiplex that GPU memory interface side with a separate module so you may have additional access within the GPU project.

If there is time later, we'll look at piggy-backing on some sprites and other more advanced features.

I would really appreciate being able to get some form of sprite support implemented, but I understand that your time is limited.  I may have some time this week so I'll try to catch up as best I can.  :)

I have the hardware for the Z80 interface sorted (well, it's just a breadboard with 4 buffers on it to convert from 5V down to 3.3V and a bi-directional buffer for the data bus), I think it's just the mux to allow the RS232 and the Z80_bridge modules to work alongside each other.  I haven't given that any thought past your previous comments on it yet.

EDIT:

Added end of line as well:

[attachimg=3]

So, I've removed a couple of the -1's from the checks for the hde assignment - I've also removed an unnecessary check to turn off hde when leaving the visible area as it's already done further down in the code.  Updated sync_generator code is below, but I've also attached the current project so we're on the same page.

This change means that the bottom horizontal bar is at decimal 495, and the far right vertical is now on decimal 662 (with X_OFFSET and Y_OFFSET set to 16).

Though I'm still going round in circles with this - I'm going to need you to tell me what the issue is, I think, as I'll never find it before Christmas on my own.  :-//

(Okay, can't leave the code for sync_generator in this post as there's a bug in the forum software that doesn't allow me to post code blocks in the same forum post as attachments for some reason.)
Ok, VDE beginning 1 pixel to the left is OK as it will not affect anything anywhere else.
There is 1 minor change I want you to make, though it wont alter anything, in reading the code, in the future, it will make things easier:

Move this line:
Code: [Select]
if (h_count == IMAGE_OFFSET_X + H_RES)
hde <= 1'b0 ;  // Turn off horizontal video data enable

To right after this line:
Code: [Select]
if (h_count == IMAGE_OFFSET_X)
hde <= 1'b1;  // Turn on horizontal video data enable
adding the word 'ELSE' in front of the 'Turn Off' if().

Ok, now, for that pesky vertical margin bars being off the the right by 6 pixels.  Tell me:
Why do you think we pass the 'hde, vde, vs, hs' coming out of the sync generator, going into the 'vid_ods_generator', then out of the 'vid_osd_generator' into the 'vid_out_stencil' then out of there into the video output pins?  Why didn't we just tie those signals straight from the sync generator to all those adjacent modules and the output pins in parallel?

Where is the test picture coming out of?
Where are the HV triggers currently coming out of?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2019, 03:22:46 pm
If your arbiter only samples the request signals when there is no request in progress, there won't be any conflicts.
Even so, though I designed memory requests to operate on a 1 pulse, if he just makes a 1 bit counter cycling back and forth muxing port A&B, he has so much access speed that it will still be transparent to the Z80 and RS232.  Both Z80 and RS232 have return data ready latches for reads as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2019, 04:24:47 pm
Ok, VDE beginning 1 pixel to the left is OK as it will not affect anything anywhere else.
There is 1 minor change I want you to make, though it wont alter anything, in reading the code, in the future, it will make things easier:

Move this line:
Code: [Select]
if (h_count == IMAGE_OFFSET_X + H_RES)
hde <= 1'b0 ;  // Turn off horizontal video data enable

To right after this line:
Code: [Select]
if (h_count == IMAGE_OFFSET_X)
hde <= 1'b1;  // Turn on horizontal video data enable
adding the word 'ELSE' in front of the 'Turn Off' if().

All done.  :-+

Ok, now, for that pesky vertical margin bars being off the the right by 6 pixels.  Tell me:
Why do you think we pass the 'hde, vde, vs, hs' coming out of the sync generator, going into the 'vid_ods_generator', then out of the 'vid_osd_generator' into the 'vid_out_stencil' then out of there into the video output pins?  Why didn't we just tie those signals straight from the sync generator to all those adjacent modules and the output pins in parallel?

Where is the test picture coming out of?
Where are the HV triggers currently coming out of?

Ahhh... of course!  |O  There's a 6-pixel delay on hde, vde, vs and hs.  How did I not see that?!

So the question now is:  what's the best way to delay the 48 triggers by PIPE_DELAY?  I could create a 48-wide delay pipe, but to my inexperienced mind that seems very wasteful...  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2019, 04:39:46 pm
Ok, VDE beginning 1 pixel to the left is OK as it will not affect anything anywhere else.
There is 1 minor change I want you to make, though it wont alter anything, in reading the code, in the future, it will make things easier:

Move this line:
Code: [Select]
if (h_count == IMAGE_OFFSET_X + H_RES)
hde <= 1'b0 ;  // Turn off horizontal video data enable

To right after this line:
Code: [Select]
if (h_count == IMAGE_OFFSET_X)
hde <= 1'b1;  // Turn on horizontal video data enable
adding the word 'ELSE' in front of the 'Turn Off' if().

All done.  :-+

Ok, now, for that pesky vertical margin bars being off the the right by 6 pixels.  Tell me:
Why do you think we pass the 'hde, vde, vs, hs' coming out of the sync generator, going into the 'vid_ods_generator', then out of the 'vid_osd_generator' into the 'vid_out_stencil' then out of there into the video output pins?  Why didn't we just tie those signals straight from the sync generator to all those adjacent modules and the output pins in parallel?

Where is the test picture coming out of?
Where are the HV triggers currently coming out of?

Ahhh... of course!  |O  There's a 6-pixel delay on hde, vde, vs and hs.  How did I not see that?!

So the question now is:  what's the best way to delay the 48 triggers by PIPE_DELAY?  I could create a 48-wide delay pipe, but to my inexperienced mind that seems very wasteful...  :-\
Yes, adding an HV triggers input to the osd_generator and again a through to an output would fix the problem and for now just do it.  You may use the new HW regs trick to make to verilog code look neater and tie the delay to the 6 'pipeline' parameter.

However, in the future, these HV triggers will never make it that far to an output.  Some will just be used to reset, increment and trigger the start and stop of your address generators.  They will never go through such a pipe.  And also remember, any unused HV triggers anywhere in the chain, automatically get removed by the compiler automatically before fitting into the FPGA.  You do not need to worry about waste.  During this test, since all 48 triggers are driving pixels on the display, yes, adding that 48x6 pipe would use up all registers.  You still need to add the input and output on the OSD with the pipe to try and see if all works correctly.  When we disconnect the output 'or' to the green and red colors, the compiler will drop any unused registers in the design, but in the future, if you need 1 of 2 test debug cursors on the screen, they will be there to tap at will.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2019, 05:30:16 pm
Ahhh... of course!  |O  There's a 6-pixel delay on hde, vde, vs and hs.  How did I not see that?!
it's a side effect of having someone else dictate a design strategy to you without you creating it completely yourself finding out these issues on your own.  I'm trying to balance letting you figure out things you may have missed or not noticed with how much more to just give you.  If everything works ok so far, we have address generators, bytes/pixel selection, 2 color palettes and 1 video superimpose switch.

Then we can look at sprites.

As for you 'Host' ram interface mux, your easiest solution will be a state machine to select what gets sent to the GPU's host ram port.  Since it's an A/B selection, you can do this with an 'IF' statement, and predict the pipe length going through the GPU ram for when it's read_rdy flag should pulse on the output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2019, 05:43:35 pm
Yes, adding an HV triggers input to the osd_generator and again a through to an output would fix the problem and for now just do it.  You may use the new HW regs trick to make to verilog code look neater and tie the delay to the 6 'pipeline' parameter.

Okay, all done.  In testing - using X and Y_OFFSET set to 16 - I'm getting lines appearing at these values:

16, 655, 16, 495

So with X- and Y- offsets set to 0, I would expect values of 0, 639, 0, 479.... which is spot on.  All seems to be working fine now!  :-+ ;D ;D

EDIT: Latest project files.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2019, 09:20:35 pm
Ok, you will now need to generate a configurable - bitplane-2-raster - Verilog module.  You already have a fixed one here in the vid_osd_generator:

Code: [Select]
assign osd_image          = char_line[(~dly6_disp_x[2:0])];

What this is doing is taking the byte 'char_line[7:0]' and selecting the bits from MSB to LSB according to the disp_x coordinate's 3 lsb.

However, we will now have 4 pixel types:

You will have an 8 bit input for bitplane the pixel data.
You will have an 8 bit input for the background default color.
You will have an 'x' coordinate input.
You will have the pena[3:0] input.
You will have a color mode input + 1 special input to latch a second adjacent byte in multi-color text mode and 16 bit RGB color mode.

You will pass through the 'x' coordinate
You will pass through the color mode.


1) monochrome 8bit.  Basically the existing above, however, you will set the output pixel color to the first 4 bits of the background color when the bit on the picture bitplane byte is 0 and use the upper 4 bits when the bit on the bit-plane byte is high.
2) 4 color 2 bit per pixel.  Now, your output will be 2 bits stacked, 2 copies every second X pixel, you will output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3 output bitplane[5:4], pixel 4&5 output bitplane[3:2],
3) 16 color 4 bit.  Now, our output will be 4 bits stacked, 4 copies every four X pixel, you will output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel 4,5,6,7 output bitplane[3:0]
3) 256 color 8 bit.  Now, our output will be 8 bits stacked, 8 copies every eight X pixel, you will output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0], yes that same 1 value will repeat 8 times is the source X counter counts through those numbers sequentially.

4) Special color text mode where you latch the first character as the bit plane graphic and the second character as a replacement for the background default color.  The rest should follow #1.
5) Special 16bit true color mode.  Your taking 2 sequential bytes, like the color text mode, and outputting a full 16 bits parallel on the output, however you will also output a 17th bit as a flag so that proceeding modules will know you are in this 16bit RGB mode.

Come back with ideas on how you want to achieve this...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2019, 09:46:38 pm
Ok, you will now need to generate a configurable - bitplane-2-raster - Verilog module.  You already have a fixed one here in the vid_osd_generator:

Code: [Select]
assign osd_image          = char_line[(~dly6_disp_x[2:0])];

What this is doing is taking the byte 'char_line[7:0]' and selecting the bits from MSB to LSB according to the disp_x coordinate's 3 lsb.

Yeah, just so I'm happy I understand this - char_line[7:0] is a byte returned from the GPU RAM where the character to be drawn is addressed at the current XY-position.  The 8-bits returned refer to the horizontal slice through the character at the current screen raster position, and the exact pixel is the bit in that byte referred to by ~dly6_disp_x[2:0], right?  ???

However, we will now have 4 pixel types:

You will have an 8 bit input for bitplane the pixel data.

Bitplane pixel data?  Is this the character tile set?

You will have an 8 bit input for the background default color.

This will be another bitplane, or a palette entry?

You will have an 'x' coordinate input.

So this sounds like ~dly6_disp_x[2:0]?  Or will this be an 'x' coordinate from the entire width of the display area?

You will have the pena[3:0] input.

This one I can handle.  ^-^

You will have a color mode input + 1 special input to latch a second adjacent byte in multi-color text mode and 16 bit RGB color mode.

These inputs don't sound like they'll be a parameters?  Could these be done with the HW_regs?

You will pass through the 'x' coordinate
You will pass through the color mode.

So these will need to be delayed by PIPE_DELAY accordingly?

1) monochrome 8bit.  Basically the existing above, however, you will set the output pixel color to the first 4 bits of the background color when the bit on the picture bitplane byte is 0 and use the upper 4 bits when the bit on the bit-plane byte is high.

So this is what we're using already, but using 4-bit colour taken from the MSN or LSN of the background colour based on whether the picture bitplane byte (or bit?) is 0 or 1?

2) 4 color 2 bit per pixel.  Now, your output will be 2 bits stacked, 2 copies every second X pixel, you will output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3 output bitplane[5:4], pixel 4&5 output bitplane[3:2],
3) 16 color 4 bit.  Now, our output will be 4 bits stacked, 4 copies every four X pixel, you will output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel 4,5,6,7 output bitplane[3:0]
3) 256 color 8 bit.  Now, our output will be 8 bits stacked, 8 copies every eight X pixel, you will output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0], yes that same 1 value will repeat 8 times is the source X counter counts through those numbers sequentially.

4) Special color text mode where you latch the first character as the bit plane graphic and the second character as a replacement for the background default color.  The rest should follow #1.
5) Special 16bit true color mode.  Your taking 2 sequential bytes, like the color text mode, and outputting a full 16 bits parallel on the output, however you will also output a 17th bit as a flag so that proceeding modules will know you are in this 16bit RGB mode.

 :o  Oh I'm going to need some serious guidance on creating this.   :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2019, 10:06:31 pm
Ok, each byte coming from ram can either be set to:

2 color, B&W, ie, 1 byte of ram = 8 pixels.
4 color,  ie 1 byte of ram = 4 pixels, 4 possible colors each.
16 color, ie 1 byte of ram = 2 pixels, 16 possible colors each
256 color, ie 1 byte of ram = 1 pixel, 256 colors each.

Now it doesn't matter if the byte we receive is from a font memory (tile memory) or just raw pixel data.  The idea is to have a general purpose module where we can set an output video mode type, keep on feeding it bytes, doesn't matter from where, and an X coordinate.  This module should spit out pixels accordingly.

So, in 256 color mode, the X coordinate is ignored.  In 16 color mode, the X coordinate's 2 LSBs are ignored, it's just the 3rd bit which is used to determine whether to show the first half, or second half of the pixel.

In 2 color mode, we want to use the alternate background color byte to define the 2 possible 16 color to show.  If the pixel is 1, then present the upper 4 bits of the default input color byte.  If the pixel is a 0, then present the lower 4 bits of the default color byte input.

Let's start with this much.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2019, 10:20:59 am
Okay, I've got this far:

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] pixel_data_in,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg osd_ena,
output reg [7:0] osd_data_out,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 2;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [1:0] dly_colour_mode [9:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour)

assign osd_data_out <= pixel_data[(x_out[2:0])];

end
2'h1 : begin // 2-bit (4 colour)

assign osd_data_out <= pixel_data[(x_out[2:1])];

end
2'h2 : begin // 4-bit (16 colour)

assign osd_data_out <= pixel_data[(x_out[2])];

end
2'h3 : begin // 8-bit (256 colour)

assign osd_data_out <= pixel_data;

end
endcase


endmodule

Obviously I know the code above won't work in its current state, the case statement is mostly placeholder to assist with my understanding as we flesh it out, but I'm not sure about the delay pipes - whether they're needed at all, for example - but they're there and can be removed if necessary.  Also, am I going in the right direction with the case statement, or should it be in an always block?

I'm a bit confused about this next bit, though - I've obviously misunderstood the output from this module (so it should be an 8-bit output?):

1) monochrome 8bit.  Basically the existing above, however, you will set the output pixel color to the first 4 bits of the background color when the bit on the picture bitplane byte is 0 and use the upper 4 bits when the bit on the bit-plane byte is high.

If the output is an 8-bit value, we're only talking about assigning the upper or lower nibble of that output byte - what happens to the other half?

Is this going in the right direction?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2019, 02:31:43 pm
Will this help:
[attachimg=1]

Now, in 2 byte 1 bit color mode, the 'Default Color Byte' will be the second 'Byte In' instead of the default single value input.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2019, 05:50:03 pm
Sooo... something like this?

Code: [Select]
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

if (pixel_data[(x_out[2:0])] == 1'b1) begin

assign osd_data_out[7:5] <= 1'b0;
assign osd_data_out[4] <= 1'b1;
assign osd_data_out[3:0] <= bg_color[7:4];

end
else begin

assign osd_data_out[7:5] <= 1'b0;
assign osd_data_out[4] <= 1'b0;
assign osd_data_out[3:0] <= bg_color[3:0];

end

end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

assign osd_data_out <= pixel_data[(x_out[2:1])];

end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

assign osd_data_out <= pixel_data[(x_out[2])];

end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

assign osd_data_out <= pixel_data;

end
endcase

So, according to the comments in the code (which I cut 'n' pasted from one of your previous posts for guidance), 1-bit and 8-bit modes should work according to the requirements.  It's just 2-bit and 4-bit I'm not sure about.  And haven't touched the special modes yet.  Your diagram helped me understand 1-bit colour mode, but according to the diagrams, 4-bit mode puts both halves of the pixel_data into two consecutive osd_data_out bytes with the top nibble set to 0 - is that right?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2019, 06:12:51 pm
1 bit looks good.

2 bit should look like 4 bit, but you are tunneling bit AB, then CD, then EF, then GH into the bottom 2 bits of byte color out.

8 bit is obviously correct.

Then expand to 2 byte source data.  (This will mess thing up since the bytes come in sequentially adn you need to turn them into parallel ahead of everything else)


I know this doesn't look like the Amiga style bitplanes.  Where a separate bitplane layer comes from a different section of memory.  The Amiga was done this way since they wanted at least 32/64 colors with 14Mhz ram, 256 kilobytes on the original Amiga 1000.   We don't have speed issues, however, you did say you were going to a larger FPGA for internal ram and we do have the speed for true 8bit color, I chose the Atari800 style 2,4,16 color modes packed in 8 bits.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2019, 07:44:48 pm
Okay, I'm not 100% but I think this is what you're asking for?

Code: [Select]
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

if (pixel_data[(x_out[2:0])] == 1'b1) begin

assign osd_data_out[7:5] <= 1'b0;
assign osd_data_out[4] <= 1'b1;
assign osd_data_out[3:0] <= bg_color[7:4];

end
else begin

assign osd_data_out[7:5] <= 1'b0;
assign osd_data_out[4] <= 1'b0;
assign osd_data_out[3:0] <= bg_color[3:0];

end

end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

assign osd_data_out[7:6] <= pixel_data[1:0];
assign osd_data_out[5:4] <= pixel_data[3:2];
assign osd_data_out[3:2] <= pixel_data[5:4];
assign osd_data_out[1:0] <= pixel_data[7:6];

end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

assign osd_data_out[7:4] <= pixel_data[3:0];
assign osd_data_out[3:0] <= pixel_data[7:4];

end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

assign osd_data_out <= pixel_data;

end
endcase
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2019, 09:07:29 pm
Nope...

Except for 8 bit, Pixels are coming in in a parallel fashion, you need to send them out in a series fashion.

Look at the 2 channels in my hand drawing for the 4 bit color.  The output is only 4 bits, bus switches between the source 2 groups of 4 bits depending on the x coordinate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2019, 09:36:20 pm
Think about is this way, you have 2 pixels in a byte, each can be 1 of the same 16 colors, how do you send those out, 1 16 color pixel at a time?

Now you have 4 pixels in 1 byte, 4 possible colors for each pixel, how do you send those out 1 4 color pixel at a time?

Now, you have 8 pixels in 1 byte, 2 possible colors, how do you send out those out, 1 2 color pixel at a time?  (Ignoring my bg_color[] thing)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2019, 10:36:44 pm
Okay, how about this?

Code: [Select]
if (~two_byte_mode) begin // one-byte mode
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

if (pixel_data[(x_out[2:0])] == 1'b1) begin

assign osd_data_out[7:5] <= 3'b000;
assign osd_data_out[4] <= 1'b1;
assign osd_data_out[3:0] <= bg_color[7:4];

end
else begin

assign osd_data_out[7:5] <= 3'b000;
assign osd_data_out[4] <= 1'b0;
assign osd_data_out[3:0] <= bg_color[3:0];

end

end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

assign osd_data_out[7:4] <= 4'b0000;
case (x_out[2:1])
2'h0 : begin
assign osd_data_out[3:2] <= pixel_data[7:6];
assign osd_data_out[1:0] <= pixel_data[7:6];
end
2'h1 : begin
assign osd_data_out[3:0] <= pixel_data[5:4];
assign osd_data_out[1:0] <= pixel_data[5:4];
end
2'h2 : begin
assign osd_data_out[3:0] <= pixel_data[3:2];
assign osd_data_out[1:0] <= pixel_data[3:2];
end
2'h3 : begin
assign osd_data_out[3:0] <= pixel_data[1:0];
assign osd_data_out[1:0] <= pixel_data[1:0];
end
end

end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

assign osd_data_out[7:4] <= 4'b0000;
if (x_out[3])
assign osd_data_out[3:0] <= pixel_data[3:0];
else
assign osd_data_out[3:0] <= pixel_data[7:4];

end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

assign osd_data_out <= pixel_data;

end
endcase
end // one-byte mode
else begin

end // two-byte mode
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2019, 10:42:03 pm
4 bit is correct.  With 2 bit, 4 color mode, why are you stacking 2 pixels at the output simultaneously.  There should only be 2 bottom bits coming out and all the 6 upper bits should = '0'.

Also, you cant 'assign' when you are making 1 reg equal another.

Also, get rid of the osd_data.  Let's call this one 'pixel_out'.
And for the input, call it 'ram_byte_in'.

These labels would make so much more sense.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2019, 10:53:17 pm
4 bit is correct.  With 2 bit, 4 color mode, why are you stacking 2 pixels at the output simultaneously.  There should only be 2 bottom bits coming out and all the 6 upper bits should = '0'.

Chalk that up to misunderstanding what you'd written previously about stacking bits and making copies every second pixel.  ::)

Also, you cant 'assign' when you are making 1 reg equal another.

pixel_data_in is a wire, if that makes any difference?  I know you can't assign in an 'always' block, but this isn't in one?  So I should just remove the assign keywords?

Also, get rid of the osd_data.  Let's call this one 'pixel_out'.
And for the input, call it 'ram_byte_in'.

These labels would make so much more sense.

Sure do.  Wasn't sure what to call them and, as I was working from the old vid_osd_generator, I used labels from that.  Okay, they're all renamed.  Full module code below.

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg [7:0] pixel_out,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 2;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [1:0] dly_colour_mode [9:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

if (~two_byte_mode) begin // one-byte mode
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

if (ram_byte_in[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

assign pixel_out[7:2] <= 6'b000000;
case (x_out[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte_in[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte_in[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte_in[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte_in[1:0];
end
end

end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

pixel_out[7:4] <= 4'b0000;
if (x_out[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

pixel_out <= ram_byte_in;

end
endcase
end // one-byte mode
else begin

end // two-byte mode

endmodule


Actually, I've just tried compiling the code and it's throwing errors - should the raster generation section be in an 'always' block then?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 12:23:04 am
And this one is tricky, in 2 byte mode the ram_data_in will be giving you the bitplane data like usual when lsb of the X coordinate is 0 and it will be giving you the upper 8bits, or color_data when the X coordinate's lsb is 1.  Since you need the 2 data's in parallel, maybe you should latch these 2 firstly. and remember, 1 will need an extra delay to be parallel and you entire color pixel generator will now be up to a 3 pixel clock delay when all is said and done.


Remember, take and latch the ram data input and delay it.  Latch/hold it's value every second pixel if you are in 16bit pixel mode and latch the odd pixels into the upper 8 bits register.  We will want an output flag to signify 16 bit mode when not in the special colored text mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 12:25:38 am
4 bit is correct.  With 2 bit, 4 color mode, why are you stacking 2 pixels at the output simultaneously.  There should only be 2 bottom bits coming out and all the 6 upper bits should = '0'.

Chalk that up to misunderstanding what you'd written previously about stacking bits and making copies every second pixel.  ::)

Also, you cant 'assign' when you are making 1 reg equal another.

pixel_data_in is a wire, if that makes any difference?  I know you can't assign in an 'always' block, but this isn't in one?  So I should just remove the assign keywords?

Also, get rid of the osd_data.  Let's call this one 'pixel_out'.
And for the input, call it 'ram_byte_in'.

These labels would make so much more sense.

Sure do.  Wasn't sure what to call them and, as I was working from the old vid_osd_generator, I used labels from that.  Okay, they're all renamed.  Full module code below.

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg [7:0] pixel_out,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 2;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [1:0] dly_colour_mode [9:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

if (~two_byte_mode) begin // one-byte mode
case (colour_mode_in)
2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

if (ram_byte_in[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end
2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

assign pixel_out[7:2] <= 6'b000000;
case (x_out[2:1])
2'h0 : begin
pixel_out[1:0] <= ram_byte_in[7:6];
end
2'h1 : begin
pixel_out[1:0] <= ram_byte_in[5:4];
end
2'h2 : begin
pixel_out[1:0] <= ram_byte_in[3:2];
end
2'h3 : begin
pixel_out[1:0] <= ram_byte_in[1:0];
end
end

end
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

pixel_out[7:4] <= 4'b0000;
if (x_out[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end
2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

pixel_out <= ram_byte_in;

end
endcase
end // one-byte mode
else begin

end // two-byte mode

endmodule


Actually, I've just tried compiling the code and it's throwing errors - should the raster generation section be in an 'always' block then?
Not only that, but inside the 'pc_ena[3:0]==0'.  Also, I think you have the 16 color high and low bits backwards/mirrored.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 09:54:30 am
Not only that, but inside the 'pc_ena[3:0]==0'.  Also, I think you have the 16 color high and low bits backwards/mirrored.

Are you sure?  I've set it up as per the comment you'd made previously (included as comments):

Code: [Select]
2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

pixel_out[7:4] <= 4'b0000;
if (x_out[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

I've interpreted the comments to mean if x_out[3] is 1, output bitplane [3:0] - which is the pixel_out[3:0] <= ram_byte_in[3:0]; line?  Does that definitely need swapping around then?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 10:41:16 am
Okay, ignore the content of the case selects for 16-bit mode, they're just placeholders from the 8-bit code.

I've updated the module to make a start on 16-bit mode.  In doing so, I'm wondering if we actually need a 'two_byte_mode' input at all?  It would make sense to just add another bit to colour_mode_in and put the 16-bit code in the main case..select block for any values of colour_mode_in with bit 2 set high?  Or do you have other plans for the separate 'two_byte_mode' input?

You may want to pay special attention to the DELAY PIPES block.  I've delayed RAM_BYTE_IN using the usual pipe method and am setting a new value, COLOUR_DATA, using the byte in the pipeline after the delayed RAM_BYTE value.  Hopefully that should work to get the two bytes in parallel for all cases where PIPE_DELAY > 1.

Now I'm just a little confused about the output in 16-bit mode, so haven't done anything with the placeholder code in the 16-bit case block.  Can you expand a little on what is required to make these two special cases work?

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 3; // minimum value of 2

// internal registers
reg [7:0] colour_data;
reg [7:0] ram_byte;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [9:0] dly_ram_byte [7:0];
reg [9:0] dly_colour_mode [1:0];
reg [9:0] dly_mode_bit [1:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_mode_bit[0] <= two_byte_mode;
dly_mode_bit[9:1] <= dly_mode_bit[8:0];
mode_16bit <= dly_mode_bit[PIPE_DELAY-1];

dly_ram_byte[0] <= ram_byte_in;
dly_ram_byte[9:1] <= dly_ram_byte[8:0];
ram_byte <= dly_ram_byte[PIPE_DELAY-1];
colour_data <= dly_ram_byte[PIPE_DELAY-2]; // in two-byte mode, colour_data should follow the ram_data byte

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

if (~two_byte_mode) begin // 8-bit mode

case (colour_mode_in)

2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end

2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_out[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte[1:0];

end
endcase

end

2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:4] <= 4'b0000;

if (x_out[3])
pixel_out[3:0] <= ram_byte[3:0];
else
pixel_out[3:0] <= ram_byte[7:4];

end

2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode

pixel_out <= ram_byte;

end

endcase

end // 8-bit mode
else begin // 16-bit mode

case (colour_mode_in[0])

1'h0 : begin // special colour text mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end
1'h1 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output, however you will also output
// a 17th bit as a flag so that proceeding modules will know you are
// in this 16bit RGB mode.

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_out[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte[1:0];

end
endcase

end

endcase

end // 16-bit mode

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 04:14:55 pm
Ok, for the 16 bit mode, we will use an alternate parallel byte input.  eg: currently you are using the bg_color[7:0].  place a second input 'ram_byte_h[7:0]'.  Use that byte that byte switch inside the first :

case()
2'h0 : begin   // 1-bit (2 colour) - 8 pixels per byte

Where you select between bg_color[7:0] & ram_byte_h[7:0] depending on 16 bit color mode.  get rid of the second half or your code.

Next, instead of an 'if' just pixel shift/pipe through the 'two_byte_mode' to it's output and shift in a 'ram_byte_h[7:0]' to a 'pixel_out_h[7:0]'.  Make sure the pipes have the same delay as the pixel bitplane to raster processing.

Also, you only have 3 color modes, I want a fourth 'enable/disable'  in the disable, you should shift out '0' on the pixel_out and two_byte_mode outputs.  Remember that all the input controls should operate in parallel and any controls being fed through should come out with the appropriate pixel.

The x pixel positioning looks correct everywhere except in the 1 bit color mode.  You need to have the ' ~ ' just like in the original code when analyzing the bit based on pixel location.  My dyslexia got the 16 color and 2 color modes backwards...


For now, see if you can wire in the module to the existing font ram's output.  Adjust the osd_module's 6 pipeline delay setting, start choosing and wiring HW_Regs to the input controls.  Make a HW_Regs table so you know where your controls are and what they do.  And for the output, we will next make 2 palettes, 1 for text and 1 for regular 256 color graphics.  You will need to made default colors for these as well...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 04:36:21 pm
Ok, for the 16 bit mode, we will use an alternate parallel byte input.  eg: currently you are using the bg_color[7:0].  place a second input 'ram_byte_h[7:0]'.  Use that byte that byte switch inside the first :

case()
2'h0 : begin   // 1-bit (2 colour) - 8 pixels per byte

Where you select between bg_color[7:0] & ram_byte_h[7:0] depending on 16 bit color mode.  get rid of the second half or your code.

Sorry, didn't get that at all. :o  Again with the crayons and single-syllables please!  ;)  I've created an extra input, 'ram_byte_h[7:0]', but I don't follow with the rest of the instructions here.  :-[

Next, instead of an 'if' just pixel shift/pipe through the 'two_byte_mode' to it's output and shift in a 'ram_byte_h[7:0]' to a 'pixel_out_h[7:0]'.  Make sure the pipes have the same delay as the pixel bitplane to raster processing.

Instead of an if??  I've created another output, 'pixel_out_h [7:0]', and created a delay pipeline for ram_byte_h to pixel_out_htwo_byte_mode is already pipelined.

Also, you only have 3 color modes, I want a fourth 'enable/disable'  in the disable, you should shift out '0' on the pixel_out and two_byte_mode outputs.  Remember that all the input controls should operate in parallel and any controls being fed through should come out with the appropriate pixel.

3? Looks like 4 to me? 2, 4, 16 and 256 colour mode?  How would I implement this? Add another bit to colour_mode?  ???

The x pixel positioning looks correct everywhere except in the 1 bit color mode.  You need to have the ' ~ ' just like in the original code when analyzing the bit based on pixel location.  My dyslexia got the 16 color and 2 color modes backwards...

Okay, have fixed that hopefully.  Current code below:

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 3; // minimum value of 2

// internal registers
reg [7:0] colour_data;
reg [7:0] ram_byte;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [9:0] dly_ram_byte [7:0];
reg [9:0] dly_ram_h_byte [7:0];
reg [9:0] dly_colour_mode [1:0];
reg [9:0] dly_mode_bit [1:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_mode_bit[0] <= two_byte_mode;
dly_mode_bit[9:1] <= dly_mode_bit[8:0];
mode_16bit <= dly_mode_bit[PIPE_DELAY-1];

dly_ram_byte[0] <= ram_byte_in;
dly_ram_byte[9:1] <= dly_ram_byte[8:0];
ram_byte <= dly_ram_byte[PIPE_DELAY-1];
colour_data <= dly_ram_byte[PIPE_DELAY-2]; // in two-byte mode, colour_data should follow the ram_data byte

dly_ram_h_byte[0] <= ram_byte_h;
dly_ram_h_byte[9:1] <= dly_ram_h_byte[8:0];
pixel_out_h <= dly_ram_h_byte[PIPE_DELAY-1];

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

if (~two_byte_mode) begin // 8-bit mode

case (colour_mode_in)

2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(~x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end

2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_out[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte[1:0];

end
endcase

end

2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:4] <= 4'b0000;

if (x_out[3])
pixel_out[3:0] <= ram_byte[3:0];
else
pixel_out[3:0] <= ram_byte[7:4];

end

2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode

pixel_out <= ram_byte;

end

endcase

end // 8-bit mode
else begin // 16-bit mode

case (colour_mode_in[0])

1'h0 : begin // special colour text mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end
1'h1 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output, however you will also output
// a 17th bit as a flag so that proceeding modules will know you are
// in this 16bit RGB mode.

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_out[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte[1:0];

end
endcase

end

endcase

end // 16-bit mode

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 04:51:05 pm
In 2 byte mode, if you keep your current mode of thinking, there is no 2bit color mode there, it's just the high byte and low byte being passed through.

It's 16 bit color mode. in other words, 65536 colors.

No palette for this mode.  That's why we need to pass-through flag to tell the palette section to change the way it works with a 16 bit pixel coming in instead of a 8 bit pixel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 05:07:06 pm
In 2 byte mode, if you keep your current mode of thinking, there is no 2bit color mode there, it's just the high byte and low byte being passed through.

It's 16 bit color mode. in other words, 65536 colors.

No palette for this mode.  That's why we need to pass-through flag to tell the palette section to change the way it works with a 16 bit pixel coming in instead of a 8 bit pixel.

There's no 1-bit or 4-bit mode either, surely?  But that doesn't clarify anything from my previous post.  I'm going away to have a lie down for a bit.  Maybe coming back after a break will help.  :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 05:13:09 pm
In 2 byte mode, if you keep your current mode of thinking, there is no 2bit color mode there, it's just the high byte and low byte being passed through.

It's 16 bit color mode. in other words, 65536 colors.

No palette for this mode.  That's why we need to pass-through flag to tell the palette section to change the way it works with a 16 bit pixel coming in instead of a 8 bit pixel.


There's no 1-bit or 4-bit mode either, surely?  But that doesn't clarify anything from my previous post.  I'm going away to have a lie down for a bit.  Maybe coming back after a break will help.  :scared:

No, everything else is correct...
No touch...
In 16bit mode, all 16 bits make a single pixel. Normal ram_byte and ram_byte_h make 1 16 bit pixel
5 bits go straight to red, 6 bits go straight to green, 5 bits go straight to blue.

It's only the 1 bit text mode which is different, where we use the lower byte to construct the text font and the higher byte to select the foreground and background 2 possible 16 colors.

I guess you can engineer a 4 color font mode if you like, re-routing the upper byte into the upper 6 missing bits of the pixel out, then route the 2 top bits into the 2 bottom bits of the pixel_out_h byte.

This is your project after all.  Make what you like.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 05:54:13 pm
I guess you can engineer a 4 color font mode if you like, re-routing the upper byte into the upper 6 missing bits of the pixel out, then route the 2 top bits into the 2 bottom bits of the pixel_out_h byte.

This is your project after all.  Make what you like.

No it's fine, I wasn't suggesting there should be a 4-colour font mode, I was just thinking through the implications of what you'd said.

Anywho, I'm at a bit of a stumbler here - I don't know what I need to do to progress the 16-bit mode code segment.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 06:07:35 pm
In 2 bit color color 2byte mode, the bg_color is swapped with the ram_byte_h.
That's the only mistake you have there.

In 8bit color mode, 2byte mode, you just pass the ram_byte_h to the output pixel_out_h.

When wired to the memory, the ram_byte_h is nothing more than a separate read port's data output.

You should be able to wire this thing into the current OSD mem output, except, only the first color mode would give you pixels if the bg_color has an appropriate value.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 06:35:44 pm
Oh right - I'm not used to there not being loads of things wrong with what I've written! I thought there must be something more... :-DD

Updated code below.  I'm just trying to work out how to connect the bitplane_to_raster module up in the design schematic..  ???

I'm either going to have to make design symbols for gpu_dual_port_ram_INTEL and/or multiport_gpu_ram, or do what we did in vid_osd_generator and instantiate those modules in the bitplane_to_raster code?

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 3; // minimum value of 2

// internal registers
reg [7:0] colour_data;
reg [7:0] ram_byte;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [9:0] dly_ram_byte [7:0];
reg [9:0] dly_ram_h_byte [7:0];
reg [9:0] dly_colour_mode [1:0];
reg [9:0] dly_mode_bit [1:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_mode_bit[0] <= two_byte_mode;
dly_mode_bit[9:1] <= dly_mode_bit[8:0];
mode_16bit <= dly_mode_bit[PIPE_DELAY-1];

dly_ram_byte[0] <= ram_byte_in;
dly_ram_byte[9:1] <= dly_ram_byte[8:0];
ram_byte <= dly_ram_byte[PIPE_DELAY-1];
colour_data <= dly_ram_byte[PIPE_DELAY-2]; // in two-byte mode, colour_data should follow the ram_data byte

dly_ram_h_byte[0] <= ram_byte_h;
dly_ram_h_byte[9:1] <= dly_ram_h_byte[8:0];
pixel_out_h <= dly_ram_h_byte[PIPE_DELAY-1];

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

if (~two_byte_mode) begin // 8-bit mode

case (colour_mode_in)

2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(~x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end

2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_out[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte[1:0];

end
endcase

end

2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:4] <= 4'b0000;

if (x_out[3])
pixel_out[3:0] <= ram_byte[3:0];
else
pixel_out[3:0] <= ram_byte[7:4];

end

2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode

pixel_out <= ram_byte;

end

endcase

end // 8-bit mode
else begin // 16-bit mode

case (colour_mode_in[0])

1'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= ram_byte_h[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= ram_byte_h[3:0];

end

end
1'h1 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;

end

endcase

end // 16-bit mode

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 08:03:31 pm
Oh right - I'm not used to there not being loads of things wrong with what I've written! I thought there must be something more... :-DD

Updated code below.  I'm just trying to work out how to connect the bitplane_to_raster module up in the design schematic..  ???

I'm either going to have to make design symbols for gpu_dual_port_ram_INTEL and/or multiport_gpu_ram, or do what we did in vid_osd_generator and instantiate those modules in the bitplane_to_raster code?

Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire [3:0] pc_ena,
input wire [7:0] ram_byte_in,
input wire [7:0] ram_byte_h,
input wire [7:0] bg_color,
input wire [9:0] x_in,
input wire [1:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [1:0] colour_mode_out

);

// parameters
parameter PIPE_DELAY = 3; // minimum value of 2

// internal registers
reg [7:0] colour_data;
reg [7:0] ram_byte;

// *****************************************************************************
// *                                                                           *
// *  DELAY PIPES                                                              *
// *                                                                           *
// *****************************************************************************
reg [9:0] dly_x [9:0];
reg [9:0] dly_ram_byte [7:0];
reg [9:0] dly_ram_h_byte [7:0];
reg [9:0] dly_colour_mode [1:0];
reg [9:0] dly_mode_bit [1:0];

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

dly_x[0] <= x_in;
dly_x[9:1] <= dly_x[8:0];
x_out <= dly_x[PIPE_DELAY-1];

dly_mode_bit[0] <= two_byte_mode;
dly_mode_bit[9:1] <= dly_mode_bit[8:0];
mode_16bit <= dly_mode_bit[PIPE_DELAY-1];

dly_ram_byte[0] <= ram_byte_in;
dly_ram_byte[9:1] <= dly_ram_byte[8:0];
ram_byte <= dly_ram_byte[PIPE_DELAY-1];
colour_data <= dly_ram_byte[PIPE_DELAY-2]; // in two-byte mode, colour_data should follow the ram_data byte

dly_ram_h_byte[0] <= ram_byte_h;
dly_ram_h_byte[9:1] <= dly_ram_h_byte[8:0];
pixel_out_h <= dly_ram_h_byte[PIPE_DELAY-1];

dly_colour_mode[0] <= colour_mode_in;
dly_colour_mode[9:1] <= dly_colour_mode[8:0];
colour_mode_out <= dly_colour_mode[PIPE_DELAY-1];

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 2-bit signal, providing 4 modes of operation to this module e.g.:
//
// 00 =   2 colour mode - 8 pixels per byte in GPU RAM
// 01 =   4 colour mode - 4 pixels -----"------"------
// 10 =  16 colour mode - 2 pixels -----"------"------
// 11 = 256 colour mode - 1 pixels -----"------"------

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

if (~two_byte_mode) begin // 8-bit mode

case (colour_mode_in)

2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(~x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= bg_color[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_color[3:0];

end

end

2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_out[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte[1:0];

end
endcase

end

2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:4] <= 4'b0000;

if (x_out[3])
pixel_out[3:0] <= ram_byte[3:0];
else
pixel_out[3:0] <= ram_byte[7:4];

end

2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode

pixel_out <= ram_byte;

end

endcase

end // 8-bit mode
else begin // 16-bit mode

case (colour_mode_in[0])

1'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(x_out[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= ram_byte_h[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= ram_byte_h[3:0];

end

end
1'h1 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;

end

endcase

end // 16-bit mode

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule



No more symbols, everything get wired as test inside the 'osd_generator'.

You may only make symbols a separate simulator project in QIIv9.1 to see if you module works on its own.


Fix the multiple bugs in this part:
Code: [Select]
else begin // 16-bit mode

.............

if (ram_byte[(x_out[2:0])] == 1'b1) begin


Also, why did you :
         2'h3 : begin   // 8-bit (256 colour) - 1 pixel per byte

and in 16 bit color mode:
         1'h1 : begin   // 16-bit (true colour)

Why not use 2'h3.

and change your 'case (colour_mode_in[0])' to the normal 'case (colour_mode_in)'?

   
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 08:27:01 pm
I'll tell you what, you may make the next module, 2 palettes plus a color pixel mixer, as it's own module outside the osd_generator block.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 03, 2019, 09:13:29 pm
Fix the multiple bugs in this part:
Code: [Select]
else begin // 16-bit mode

.............

if (ram_byte[(x_out[2:0])] == 1'b1) begin

Yeah they're not bugs as such, the code there is placeholder copied over from the 1-byte code above it (as you'd mentioned that it would follow #1).  I'm still trying to work out exactly what to put in here - your comment here:

Quote
The rest should follow #1.

...is throwing me, slightly.

Also, why did you :
         2'h3 : begin   // 8-bit (256 colour) - 1 pixel per byte

and in 16 bit color mode:
         1'h1 : begin   // 16-bit (true colour)

Why not use 2'h3.

No idea - I've changed it now.

and change your 'case (colour_mode_in[0])' to the normal 'case (colour_mode_in)'?

I think this was because there were only two 'special' modes, so I didn't care about anything other than the LSB of colour_mode_in to select between them?

Had another go at the special colour text mode code...

Code: [Select]
else begin // 16-bit mode

case (colour_mode_in)

2'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte[(x_out[2:0])] == 1'b1) begin

pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;

end
else begin

pixel_out <= ram_byte;
pixel_out_h <= bg_colour;

end

end
2'h3 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out <= ram_byte;
pixel_out_h <= ram_byte_h;

end

endcase

end // 16-bit mode

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 09:34:28 pm
Your fine, place it inside the OSD generator in place of the :

Code: [Select]
//  The resulting 2-bit font image at x is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image          = char_line[(~dly6_disp_x[2:0])];

Note that you will need to make the new 'osd_image' output into a pixel_out and pixel_out_h ports.  Call them pixel_out_top, pixel_out_top_h, and the wire 'pixel_out_top_16bit'

These 3 outputs will leave the vid_osd_generator.  For now, set single byte test mode and wire the bg_color to a spare GPU_HW_REGS.

For now, wile the 8 bits into some of the RGBs wires to the stencil, maybe 'OR' in a few rast_HV triggers for testing, like only 2 or 4 of them.

My next message will contain the palette module which goes in between the vid_osd_generator module and the vid_out_stencil module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2019, 10:10:09 pm
Now for the palette memory.  You will have 2 palettes.
Palette #1, specialized for the ASCII text and sprites.

On the Read only port, IE, pixel_in -to- text_pixel out, you will have:
8 bit address input, ie pixel_in[7:0].
On the data output, you will have a 16bit pixel_out[15:0].
The 16 bit output will be wired as follows:
text_pixel_out[15:12] -will be sent to- alpha_blend[3:0]
text_pixel_out[11:8]   -will be sent to- text_r[7:4] -and- text_r[3:0]
text_pixel_out[7:4]     -will be sent to- text_g[7:4] -and- text_g[3:0]
text_pixel_out[3:0]     -will be sent to- text_b[7:4] -and- text_b[3:0]

On the pixel side you will want the 'CLOCK ENABLE' feature for the address latch coming in and data latch going out.
The clock enables will be connected to the (pc_ena[3:0]==0) wire.

On the 'host' memory side, you will have a 9 bit address [9:0] and 8 bit data in and out.
The write ena will need attention as you will need to position this memory withing the system not to conflict with the main graphics memory.

You will need to generate a .mif default palette, otherwise, everything will be black.

-----------------------------------------------------------------------------------
Palette #2, specialized for the 256 color background.

Same as the text memory except the data_input will be wired to a 'graphics_data_in' and there will be a 'graphics_data_out' which will be wired like this:

graphics_pixel_out[15:11] -will be sent to- graphics_r[7:3] -and the upper bits to - graphics_r[2:0]
graphics_pixel_out[10:5]   -will be sent to- graphics_g[7:2] -and the upper bits to - graphics_g[1:0]
graphics_pixel_out[4:0]     -will be sent to- graphics_b[7:3] -and the upper bits to - graphics_b[2:0]

--------------------------------------------------------------------------------
Don't forget to page the graphics color palette on a different page on the hose writing side.
------------------------------------------------------------------------------
For now, just wire the output of the
text_r[3:0] to the modules output  pixel_out_r[7:4] and pixel_out_r[3:0]
text_g[3:0] to the modules output  pixel_out_g[7:4] and pixel_out_g[3:0]
text_b[3:0] to the modules output  pixel_out_b[7:4] and pixel_out_b[3:0]

Yes, 24 bit color output, you will only pass the top 12 used bits to the pins after the stencil module.

-------------------------------------------------------------------------------
Address generator Beta V 1 comes next, so get these working!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 04, 2019, 08:06:34 pm
Your fine, place it inside the OSD generator in place of the :

Code: [Select]
//  The resulting 2-bit font image at x is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image          = char_line[(~dly6_disp_x[2:0])];

Note that you will need to make the new 'osd_image' output into a pixel_out and pixel_out_h ports.  Call them pixel_out_top, pixel_out_top_h, and the wire 'pixel_out_top_16bit'

These 3 outputs will leave the vid_osd_generator.  For now, set single byte test mode and wire the bg_color to a spare GPU_HW_REGS.

For now, wile the 8 bits into some of the RGBs wires to the stencil, maybe 'OR' in a few rast_HV triggers for testing, like only 2 or 4 of them.

My next message will contain the palette module which goes in between the vid_osd_generator module and the vid_out_stencil module.

Right, back again - work's been keeping me busy - so, when you say 'place it inside the OSD generator', can you be just a little more specific? ???  Are you telling me to cut 'n' paste the code from bitplane_to_raster.v into vid_osd_generator.v in place of the osd_image assignment and work the new I/Os into the existing ones, or instantiate it (if that's even the right terminology?) in the same way that vid_osd_generator creates the multiport_gpu_ram instance?

Sorry about the basic question(s), but remember; a few weeks ago I knew the square root of nothing about FPGAs and Verilog...  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 04, 2019, 08:11:06 pm
Now for the palette memory.  You will have 2 palettes.

Will these palette memories be easily accessible by the host system?  I guess I'll just change the z80_bridge module to redirect reads/writes above address 16384 to the palette memory (or sprite memory or whatever else we add in)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 04, 2019, 08:39:18 pm
It's just more 2 port memories.  1 port dedicated to process the 8 bit pixel data into 16 bit pixel data.
The other side should be used to interface with the host.

With Cyclone, the smallest block of ram is 9kbit, or 8kbit, if 1KB. So, to save every tiny drop, even if you allocate a 256x16 bit block of ram, ie 512bytes, it would still count as a 1024bytes.

Now, I said 16 bits on the read output.  If you want to save every drop imaginable, and combine 2 palettes into 1 1024 byte ram block, you may use another of our 5 port ram and just wire the read addresses correctly to get 2x 16bit parallel port reads, ie 4 read ports in use and you still have the host port.

The saving is you get the 2 palettes in a single MK9 block inside the cyclone IV.  The easier way with separate ram blocks is each palette occupies 1x MK9 block.  You may double each the palette size in this configuration and use no additional memory.  The separate memory blocks eat less logic cells and runs a bit faster.  How you decide to mar the write address, either in parallel with a block from the existing 16kb, or somewhere outside as it is ram as well is your decision.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 04, 2019, 08:43:10 pm
Your fine, place it inside the OSD generator in place of the :

Code: [Select]
//  The resulting 2-bit font image at x is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit
assign osd_image          = char_line[(~dly6_disp_x[2:0])];

Note that you will need to make the new 'osd_image' output into a pixel_out and pixel_out_h ports.  Call them pixel_out_top, pixel_out_top_h, and the wire 'pixel_out_top_16bit'

These 3 outputs will leave the vid_osd_generator.  For now, set single byte test mode and wire the bg_color to a spare GPU_HW_REGS.

For now, wile the 8 bits into some of the RGBs wires to the stencil, maybe 'OR' in a few rast_HV triggers for testing, like only 2 or 4 of them.

My next message will contain the palette module which goes in between the vid_osd_generator module and the vid_out_stencil module.

Right, back again - work's been keeping me busy - so, when you say 'place it inside the OSD generator', can you be just a little more specific? ???  Are you telling me to cut 'n' paste the code from bitplane_to_raster.v into vid_osd_generator.v in place of the osd_image assignment and work the new I/Os into the existing ones, or instantiate it (if that's even the right terminology?) in the same way that vid_osd_generator creates the multiport_gpu_ram instance?

Sorry about the basic question(s), but remember; a few weeks ago I knew the square root of nothing about FPGAs and Verilog...  :o

The 'memory_to_raster.v' module you just created is all on it's own a .v file included in your project.
You are only calling an instance of it inside the vid_osd_generator.  This is important as you will be calling at least 2 of them, and even more when we add sprites.  It may be possible to have 1 instance per sprite depending on architecture, so, you will have something like 10 of them inside the vid_osd_generator.

You've already called instances of our 5 port memory inside the vid_osg_generator, so, I know you know how to do this.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 04, 2019, 09:14:34 pm
Now for the palette memory.  You will have 2 palettes.

Will these palette memories be easily accessible by the host system?  I guess I'll just change the z80_bridge module to redirect reads/writes above address 16384 to the palette memory (or sprite memory or whatever else we add in)?
I'll leave the implementation to you.  However, remember, you may be adding multiple memories at multiple sizes.  Whatever method you choose, make sure you can easily move things around on a whim for no matter how many modules we may add.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 05, 2019, 09:38:48 am
Okay, just need a little more guidance getting the bitplane_to_raster module connected up to the vid_osd_generator module.  Full code for vid_osd_generator at the bottom of this post.

Here's what I've got so far for creating an instance of bitplane_to_raster:

Code: [Select]
// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE:  For testing, GPU_HW_Control_regs [10] sets bg_colour
// *                                         [11] sets two_byte_mode
// *                                         [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(

.clk(clk),
.pc_ena_in(pc_ena[3:0]),

// inputs
.ram_byte_in( [7:0]),
.ram_byte_h( [7:0]),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( [1:0] GPU_HW_Control_regs[12] ),
.two_byte_mode( [0] GPU_HW_Control_regs[11] ),

// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out( [9:0]),
.colour_mode_out( [1:0])

);


Firstly, hopefully the connections I've made so far are all correct?  Secondly, some specific questions:


Code: [Select]
module vid_osd_generator (

// inputs
input clk,
input [3:0] pc_ena,
input hde_in,
input vde_in,
input hs_in,
input vs_in,
input wire host_clk,
input wire host_wr_ena,
input wire [19:0] host_addr,
input wire [7:0] host_wr_data,
input wire [7:0] GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],
input wire [47:0] HV_triggers_in,

// outputs
output reg osd_ena_out,
//output wire osd_image,
output reg pixel_out_top_16bit,   // <--- new
output reg [7:0] pixel_out_top,   // <--- new
output reg [7:0] pixel_out_top_h, // <--- new
output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,
output wire [7:0] host_rd_data,
output reg [47:0] HV_triggers_out

);

// To write contents into the display and font memories, the wr_addr[15:0] selects the address
// the wr_data[7:0] contains a byte which will be written
// the wren_disp is the write enable for the ascii text ram.  Only the wr_addr[8:0] are used as the character display is 32x16.
// the wren_font is the write enable for the font memory.  Only 2 bits are used of the wr_data[1:0] and wr_addr[12:0] are used.
// tie these ports to GND for now disabling them

reg [9:0] disp_x,dly1_disp_x,dly2_disp_x,dly3_disp_x,dly4_disp_x,dly5_disp_x,dly6_disp_x,dly7_disp_x,dly8_disp_x;
reg [8:0] disp_y,dly1_disp_y,dly2_disp_y,dly3_disp_y,dly4_disp_y;

reg dena,dly1_dena,dly2_dena,dly3_dena,dly4_dena,dly5_dena,dly6_dena;
reg [7:0] dly1_letter, dly2_letter, dly3_letter, dly4_letter;
reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe;
reg [47:0] HV_pipe[9:0];

parameter   PIPE_DELAY =  6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.
parameter   FONT_8x16  =  0; // 0 = 8 pixel tall font, 1 = 16 pixel tall font.
parameter HW_REGS_SIZE = 8; // default size for hardware register bus - set by HW_REGS parameter in design view

wire [12:0] font_pos;
wire [10:0] disp_pos;
wire [19:0] read_text_adr;
wire [19:0] read_font_adr;
wire [7:0]  letter;
wire [7:0]  char_line;


// ****************************************************************************************************************************
// *
// * create a multiport GPU RAM handler instance
// *
// ****************************************************************************************************************************
multiport_gpu_ram gpu_RAM(

.clk(clk),
.pc_ena_in(pc_ena[3:0]),

.addr_in_0(read_text_adr[19:0]),
.addr_in_1(read_font_adr[19:0]),
.addr_in_2(20'b0),
.addr_in_3(20'b0),
.addr_in_4(20'b0),

.cmd_in_0(16'b0),
.cmd_in_1(16'b0),
.cmd_in_2(16'b0),
.cmd_in_3(16'b0),
.cmd_in_4(16'b0),

.pc_ena_out(),

.addr_out_0(),
.addr_out_1(),
.addr_out_2(),
.addr_out_3(),
.addr_out_4(),

.cmd_out_0(),
.cmd_out_1(),
.cmd_out_2(),
.cmd_out_3(),
.cmd_out_4(),

.data_out_0(letter[7:0]),
.data_out_1(char_line[7:0]),
.data_out_2(),
.data_out_3(),
.data_out_4(),

.clk_b(host_clk), // Host (Z80) clock input
.write_ena_b(host_wr_ena), // Host (Z80) clock enable
.addr_host_in(host_addr[19:0]),
   .data_host_in(host_wr_data[7:0]),
.data_host_out(host_rd_data[7:0])

);

defparam gpu_RAM.ADDR_SIZE = 14, // pass ADDR_SIZE into the gpu_RAM instance
         gpu_RAM.PIXEL_PIPE = 3;    // set the length of the pixel pipe to offset multi-read port sequencing

// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE:  For testing, GPU_HW_Control_regs [10] sets bg_colour
// *                                         [11] sets two_byte_mode
// *                                         [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(

.clk(clk),
.pc_ena_in(pc_ena[3:0]),

// inputs
.ram_byte_in( [7:0]),
.ram_byte_h( [7:0]),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( [1:0] GPU_HW_Control_regs[12] ),
.two_byte_mode( [0] GPU_HW_Control_regs[11] ),

// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out( [9:0]),
.colour_mode_out( [1:0])

);

//  The disp_x is the X coordinate counter.  It runs from 0 to 512 and stops there
//  The disp_y is the Y coordinate counter.  It runs from 0 to 256 and stops there

// Get the character at the current x, y position
assign disp_pos[5:0]  = disp_x[8:3] ;  // The disp_pos[5:0] is the lower address for the 64 characters for the ascii text.
assign disp_pos[10:6] = disp_y[7+FONT_8x16:3+FONT_8x16] ;  // the disp_pos[10:6] is the upper address for the 32 lines of text

//  The result from the ascii memory component 'altsyncram_component_osd_mem'  is called letter[7:0]
//  Since disp_pos[8:0] has entered the read address, it takes 2 pixel clock cycles for the resulting letter[7:0] to come out.

//  Now, font_pos[12:0] is the read address for the memory block containing the character specified in letter[]

assign font_pos[10+FONT_8x16:3+FONT_8x16] = letter[7:0] ;       // Select the upper font address with the 7 bit letter, note the atari font has only 128 characters.
assign font_pos[2+FONT_8x16:0] = dly3_disp_y[2+FONT_8x16:0] ;  // select the font x coordinate with a 2 pixel clock DELAYED disp_x address.  [3:1] is used so that every 2 x lines are repeats

//  The resulting 2-bit font image at x is assigned to the OSD[1:0] output
//  Also, since there is an 8th bit in the ascii text memory, I use that as a third OSD output color bit

//assign osd_image = char_line[(~dly6_disp_x[2:0])];   <--- edited out - replaced by bitplane_to_raster instance

assign read_text_adr[10:0] = disp_pos[10:0];
assign read_text_adr[19:11] = 9'h2;        // my mistake, I has 1bit instead of 10bits

assign read_font_adr[10+FONT_8x16:0] = font_pos[10+FONT_8x16:0];
assign read_font_adr[19:11+FONT_8x16] = 0;        // my mistake, I has 1bit instead of 10bits

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

// **************************************************************************************************************************
// *** Create a serial pipe where the PIPE_DELAY parameter selects the pixel count delay for the xxx_in to the xxx_out ports
// **************************************************************************************************************************

hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];

vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];

hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];

vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];

HV_pipe[0] <= HV_triggers_in;
HV_pipe[9:1] <= HV_pipe[8:0];
HV_triggers_out <= HV_pipe[PIPE_DELAY-1];

// **********************************************************************************************
// This OSD generator's window is only 512 pixels by 256 lines.
// Since the disp_X&Y counters are the screens X&Y coordinates, I'm using an extra most
// significant bit in the counters to determine if the OSD ena flag should be on or off.

if (disp_x[9] || disp_y[8])
dena <= 0; // When disp_x > 511 or disp_y > 255, then turn off the OSD's output enable flag
else
dena <= 1; // otherwise, turn on the OSD output enable flag

if (~vde_in)
disp_y[8:0] <= 9'b111111111; // preset the disp_y counter to max while the vertical display is disabled

else if (hde_in && ~hde_pipe[0])
begin // isolate a single event at the begining of the active display area

disp_x[9:0] <= 10'b0000000000; // clear the disp_x counter
if (!disp_y[8] | (disp_y[8:7] == 2'b11))
disp_y <= disp_y + 1'b1; // only increment the disp_y counter if it hasn't reached it's end

end
else if (!disp_x[9])
disp_x <= disp_x + 1'b1;  // keep on addind to the disp_x counter until it reaches it's end.

// **********************************************************************************************
// *** These delay pipes registers are explained in the 'assign's above
// **********************************************************************************************
dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;
dly3_disp_x <= dly2_disp_x;
dly4_disp_x <= dly3_disp_x;
dly5_disp_x <= dly4_disp_x;
dly6_disp_x <= dly5_disp_x;
dly7_disp_x <= dly6_disp_x;
dly8_disp_x <= dly7_disp_x;

dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;
dly3_disp_y <= dly2_disp_y;
dly4_disp_y <= dly3_disp_y;

dly1_letter <= letter;
dly2_letter <= dly1_letter;
dly3_letter <= dly2_letter;
dly4_letter <= dly3_letter;

dly1_dena   <= dena;
dly2_dena   <= dly1_dena;
dly3_dena   <= dly2_dena;
dly4_dena   <= dly3_dena;
dly5_dena   <= dly4_dena;
dly6_dena   <= dly5_dena;

// **********************************************************************************************
osd_ena_out  <= dly4_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
// It needs to be delayed by the number of pixel clocks required for the above memories

end // ena

end // always@clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 05, 2019, 10:23:17 am
Yes, for now we are not touching the dly_x_out of the new module.

Sticking the module into 1 bit mode, normal 8 bit with an appropriate background color should create visible test on screen if you feed the new image out into the vid_out_stencil.  I would 'or' in 2 or 4 appropriate HV triggers as test margins.

Get rid of the doctored color_sel.  Next you will need to decide on the simple palette ram, or the complex 5 port ram method I listed above.  The simple one may use 1 additional M9K block, but uses a fraction the gates.  You decide where and how to map the memory.  Remember to protect the main system memory if you are going outside the 16k boundary.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 05, 2019, 10:57:26 am
Yes, for now we are not touching the dly_x_out of the new module.

Hmm... okay, here's where I am with the internal connections:

Code: [Select]
// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE:  For testing, GPU_HW_Control_regs [10] sets bg_colour
// *                                         [11] sets two_byte_mode
// *                                         [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(

.clk(clk),
.pc_ena_in(pc_ena[3:0]),

// inputs
.ram_byte_in(char_line),
.ram_byte_h(8'b00000000),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][1:0] ),
.two_byte_mode( GPU_HW_Control_regs[11][0] ),

// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out(), // disconnected for moment
.colour_mode_out() // disconnected for moment

);

Get rid of the doctored color_sel.

And replace it with...? I'm a little lost as to what we do with the 8-bit (and potentially 16-bit) output from vid_osd_generator now.  The stencil doesn't have an 8-bit wide input - even color_sel doesn't - speaking of which, you want me to get rid of that completely?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 05, 2019, 02:29:05 pm
Yes, for now we are not touching the dly_x_out of the new module.

Hmm... okay, here's where I am with the internal connections:

Code: [Select]
// ****************************************************************************************************************************
// *
// * create a bitplane_to_raster instance
// *
// * NOTE:  For testing, GPU_HW_Control_regs [10] sets bg_colour
// *                                         [11] sets two_byte_mode
// *                                         [12] sets colour_mode_in
// *
// ****************************************************************************************************************************
bitplane_to_raster b2r_1(

.clk(clk),
.pc_ena_in(pc_ena[3:0]),

// inputs
.ram_byte_in(char_line),
.ram_byte_h(8'b00000000),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][1:0] ),
.two_byte_mode( GPU_HW_Control_regs[11][0] ),

// outputs
.pixel_out_ena( osd_ena_out ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out(), // disconnected for moment
.colour_mode_out() // disconnected for moment

);

Get rid of the doctored color_sel.

And replace it with...? I'm a little lost as to what we do with the 8-bit (and potentially 16-bit) output from vid_osd_generator now.  The stencil doesn't have an 8-bit wide input - even color_sel doesn't - speaking of which, you want me to get rid of that completely?
Just tie the upper bits of '.pixel_out( pixel_out_top ),' to R,G,B.

We don't need snow or color settings from the debugger.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 05, 2019, 03:19:50 pm
Just tie the upper bits of '.pixel_out( pixel_out_top ),' to R,G,B.

We don't need snow or color settings from the debugger.

Hokay, well clearly there's a timing issue I need to sort out, though:

[attachimg=2]

Full project files attached so you can view the wiring in the design as well as the code. (Though the project files attached may have pixel_out_top incorrectly wired to the stencil - I've got pixel_out_top[3..0] connected to r_in, g_in and b_in now.)

EDIT: Better image, although it's not aligned to the screen properly (missing a column on the left and some of the top row - that's just the screen misaligned.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 05, 2019, 06:21:17 pm
Shouldn't you be using  'dly6_disp_x'.  Remember, since the first 'disp_x' has been used, there have been 6 pixel clock cycles until the '.ram_byte_in(char_line),' has a valid value.

Your 16 bit text mode doesn't look like the 8 bit text mode.  Copy the 8 bit mode and replace the 'bg_color[]' with the 'ram_byte_h[]'.

How did you move the OSD text across by 5 pixels?  An odd number...
----------------------------------------------
   .pixel_out_ena( osd_ena_out ),
---------------------------------------------
Isn't osd_ena_out being set somewhere else.

Also, I don't see a disable mode in the current 6 modes.  Also in a disable mode, you should also '0' the 2 data outputs.

I haven't a clue about the 5 pixel (ahem 4 pixel delay once you fix an obvious thing).

I turned back on the HV_triggers test lines so you may count the error pixels.

I've attached the first fix only, plus turned back on the 'HV_trigger cursors so you may count the error pixels.
I've also attached the 'Quick-load' for the RS232 debugger which contains the cursor positions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 05, 2019, 06:34:19 pm
What in the world are all those delays for in the 'bitplane_to_raster' module?
Why would you want to add delay anywhere?
You are also missing a 'pixel_in_ena' and it's related function...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 05, 2019, 07:30:54 pm
Shouldn't you be using  'dly6_disp_x'.  Remember, since the first 'disp_x' has been used, there have been 6 pixel clock cycles until the '.ram_byte_in(char_line),' has a valid value.

Your 16 bit text mode doesn't look like the 8 bit text mode.  Copy the 8 bit mode and replace the 'bg_color[]' with the 'ram_byte_h[]'.

Was fairly sure I was following your advice - the code hasn't changed for the last few times I've posted it up here..  ???

----------------------------------------------
   .pixel_out_ena( osd_ena_out ),
---------------------------------------------
Isn't osd_ena_out being set somewhere else.

Ah yes it is.  Fixed that.

Also, I don't see a disable mode in the current 6 modes.  Also in a disable mode, you should also '0' the 2 data outputs.

Is this mode selected by the pixel_ena line you want me to connect to the raster module?

I haven't a clue about the 5 pixel (ahem 4 pixel delay once you fix an obvious thing).

I turned back on the HV_triggers test lines so you may count the error pixels.

Fixed it - looks like the delays I've erroneously added to the bitplane_to_raster module were causing the problems.

[attach=1]

What in the world are all those delays for in the 'bitplane_to_raster' module?
Why would you want to add delay anywhere?
You are also missing a 'pixel_in_ena' and it's related function...

I added them when I was creating the bitplane_to_raster module - you'd mentioned that signals had to be delayed, so they were the first things I created in that module.  Probably a misunderstanding on my part.  ::)

This pixel_in_ena - as I asked above, does this set the disable mode in the bitplane_to_raster module?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 05, 2019, 07:37:56 pm
Your pixels are still off by 1 or 2 according to the image I see.

The original code has 0 delay on the bit selection.  This new code has 1, so long as you remove all the internal delays.  You need the other modules to take that into effect.

Also, the pixel enable input should also mute the output pixels when it low and it should be fed by the original 'osd_ena_out' wire.

You want a disabled mode, and an ability to mute out the non-display area of the OSD text window.  So, both are needed.

You should have the original image, other than the text being blue, exactly if everything is done ok.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 05, 2019, 10:40:37 pm
Your pixels are still off by 1 or 2 according to the image I see.

The original code has 0 delay on the bit selection.  This new code has 1, so long as you remove all the internal delays.  You need the other modules to take that into effect.

Right, fixed that by changing the x_in input to the bitplane_to_raster instance from dly6_disp_x to dly5_disp_x.  :-+

Also, the pixel enable input should also mute the output pixels when it low and it should be fed by the original 'osd_ena_out' wire.

Done.  :-+

You want a disabled mode, and an ability to mute out the non-display area of the OSD text window.  So, both are needed.

Okay, so what enables the disabled mode, if you'll excuse the oxymoron?

You should have the original image, other than the text being blue, exactly if everything is done ok.

Like this then?

[attachimg=2]

Updated project files attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 12:12:59 am
 |O  Arrrrrrggg, how did you do that?  You found a different, yet perfect solution to a weird problem I never thought would end up like this....

Ok...  Fine...  Great...

Next, the 2 palettes.

Now, I'm telling you this so you could construct 2 real palette .mif files...
For the text mode/sprites, the data in the 16 bit output goes like this:
1                                0
6                                0
AAAA RRRR GGGG BBBB


The RGB are 12 bit color data like you are used to.
The A     is a 4 bit translucency value.  0 being 100% opaque, 15 being completely translucent to the graphics mode beneath.

The text colors are as follows:
0 through 15 = The outline color, or, pixel data = 0 color.  Whenever a font has a 0 bit, depending on your character color background selection, one of these 16 colors will be used.

16 through 31 = The pen color, or, pixel data = 1 color.  Whenever a font has a 1 bit, depending on your character color foreground selection, one of these 16 colors will be used.

(When making a default VGA palette, for now, the foreground and background colors may be mirror or offset values.  Whatever mimics VGA's 16 text color settings)

For the graphics palette, colors 0 through 255 are used in order, however, the 16bits hold the color differently:
1                               0
6                               0
RRRRR GGGGGG BBBBB

This is known as 565 color, being 5 bits red, 6 bits green, 5 bits blue.

I would look for an old VGA paint software palette to close as close as possible for the 256 color palette truncated to the 565 standard while for the text, look for the standard 16 colors used by VGA.  Copy those to the text palette in 12bit color, plus, use 0 for the alpha channel except for background color 0.

The palette module should be external between the OSD and Stencil.  It should pass through the HDE,VDE,HS,VS with appropriate internal delay to match the speed of the palette memories.

You will need a host port to read & write to the palette as well.

The palette should have 2 inputs, the text top layer and graphics bottom layer feeding the 2 palettes.  The output for now will just be the text layer palette.  We will do the translucency mixer math after the line address generators as they are needed to feed the graphics bottom layer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 12:32:19 am

You want a disabled mode, and an ability to mute out the non-display area of the OSD text window.  So, both are needed.

Okay, so what enables the disabled mode, if you'll excuse the oxymoron?

Well, you have 4 current modes, why not 7 modes and reserve a number for 'OFF'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 09:11:49 am

You want a disabled mode, and an ability to mute out the non-display area of the OSD text window.  So, both are needed.

Okay, so what enables the disabled mode, if you'll excuse the oxymoron?

Well, you have 4 current modes, why not 7 modes and reserve a number for 'OFF'.

Right, why didn't I think of that? ???

Okay, I've made colour_mode a 3-bit signal now - the 3rd bit enables/disables the output but can be changed later if more modes are created.

|O  Arrrrrrggg, how did you do that?  You found a different, yet perfect solution to a weird problem I never thought would end up like this....

 :-//  Sometimes I almost make it look like I know what I'm doing, but not often...  :-DD

Next, the 2 palettes.

Okay, will get back to you soon on these...  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 10:50:33 am
I've just spent far too long trying to find a program online that will output a file of 565 hex values for a 256-colour palette.  :palm:

Here's my 32-colour text/sprite palette.  I've just based it off of the old Amstrad palette for the moment, there's obviously lots of room in the .mif for more palettes and the potential to swap palette LUTs on the fly, I'm guessing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 11:16:56 am
Sprite mode is 4444, 4A, 4R, 4G, 4B.  The 565 is the 256 color mode.  Instead of throwing something together, I would do the conversion in something like MS Excel.

Also, I noticed that 0 is black, ok, but color 1 is dark blue?
ok.

Better, here is a source code generator where you can calculate any output you like. 
https://github.com/canidlogic/vgapal (https://github.com/canidlogic/vgapal)

Code: [Select]
palette=(
000000 0000AA 00AA00 00AAAA AA0000 AA00AA AA5500 AAAAAA 555555 5555FF
55FF55 55FFFF FF5555 FF55FF FFFF55 FFFFFF 000000 101010 202020 353535
454545 555555 656565 757575 8A8A8A 9A9A9A AAAAAA BABABA CACACA DFDFDF
EFEFEF FFFFFF 0000FF 4100FF 8200FF BE00FF FF00FF FF00BE FF0082 FF0041
FF0000 FF4100 FF8200 FFBE00 FFFF00 BEFF00 82FF00 41FF00 00FF00 00FF41
00FF82 00FFBE 00FFFF 00BEFF 0082FF 0041FF 8282FF 9E82FF BE82FF DF82FF
FF82FF FF82DF FF82BE FF829E FF8282 FF9E82 FFBE82 FFDF82 FFFF82 DFFF82
BEFF82 9EFF82 82FF82 82FF9E 82FFBE 82FFDF 82FFFF 82DFFF 82BEFF 829EFF
BABAFF CABAFF DFBAFF EFBAFF FFBAFF FFBAEF FFBADF FFBACA FFBABA FFCABA
FFDFBA FFEFBA FFFFBA EFFFBA DFFFBA CAFFBA BAFFBA BAFFCA BAFFDF BAFFEF
BAFFFF BAEFFF BADFFF BACAFF 000071 1C0071 390071 550071 710071 710055
710039 71001C 710000 711C00 713900 715500 717100 557100 397100 1C7100
007100 00711C 007139 007155 007171 005571 003971 001C71 393971 453971
553971 613971 713971 713961 713955 713945 713939 714539 715539 716139
717139 617139 557139 457139 397139 397145 397155 397161 397171 396171
395571 394571 515171 595171 615171 695171 715171 715169 715161 715159
715151 715951 716151 716951 717151 697151 617151 597151 517151 517159
517161 517169 517171 516971 516171 515971 000041 100041 200041 310041
410041 410031 410020 410010 410000 411000 412000 413100 414100 314100
204100 104100 004100 004110 004120 004131 004141 003141 002041 001041
202041 282041 312041 392041 412041 412039 412031 412028 412020 412820
413120 413920 414120 394120 314120 284120 204120 204128 204131 204139
204141 203941 203141 202841 2D2D41 312D41 352D41 3D2D41 412D41 412D3D
412D35 412D31 412D2D 41312D 41352D 413D2D 41412D 3D412D 35412D 31412D
2D412D 2D4131 2D4135 2D413D 2D4141 2D3D41 2D3541 2D3141 000000 000000
000000 000000 000000 000000 000000 000000
)

[attachimg=1]

Now, I'm sure you can output this into 565 and 4444.  Remember, the 4444 is for the text and sprites while the 565 is for the graphics layer.

For the text layer palette, we want to copy the first 16 into the second 16 colors, unless we change a wire in the 'bitplane_to_raster' module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 11:52:41 am
Sprite mode is 4444, 4A, 4R, 4G, 4B.  The 565 is the 256 color mode.  Instead of throwing something together, I would do the conversion in something like MS Excel.

Also, I noticed that 0 is black, ok, but color 1 is dark blue?

Like I said, I'd based the palette off of the old Amstrad 27-colour palette.  Just realised, might have confused you with the naming of the palette .mif file.  It's the text/sprite palette, but I just called it 'sprite' palette for brevity (I guess the text could be considered sprites in their own way).

So, just to clarify, the text palette is just 32 colours (two copies of 16, essentially)?  Is the sprite palette the same thing, or a separate palette after the text palette?

Better, here is a source code generator where you can calculate any output you like. 
https://github.com/canidlogic/vgapal (https://github.com/canidlogic/vgapal)

I did find that code during my searching, but disregarded it as I felt it needed a few hours development to turn into what I needed.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 12:12:08 pm
Sprite mode is 4444, 4A, 4R, 4G, 4B.  The 565 is the 256 color mode.  Instead of throwing something together, I would do the conversion in something like MS Excel.

Also, I noticed that 0 is black, ok, but color 1 is dark blue?

Like I said, I'd based the palette off of the old Amstrad 27-colour palette.  Just realised, might have confused you with the naming of the palette .mif file.  It's the text/sprite palette, but I just called it 'sprite' palette for brevity (I guess the text could be considered sprites in their own way).

So, just to clarify, the text palette is just 32 colours (two copies of 16, essentially)?  Is the sprite palette the same thing, or a separate palette after the text palette?

Better, here is a source code generator where you can calculate any output you like. 
https://github.com/canidlogic/vgapal (https://github.com/canidlogic/vgapal)

I did find that code during my searching, but disregarded it as I felt it needed a few hours development to turn into what I needed.  ???
Again:
Code: [Select]
palette=(
000000 0000AA 00AA00 00AAAA AA0000 AA00AA AA5500 AAAAAA 555555 5555FF
55FF55 55FFFF FF5555 FF55FF FFFF55 FFFFFF 000000 101010 202020 353535
454545 555555 656565 757575 8A8A8A 9A9A9A AAAAAA BABABA CACACA DFDFDF
EFEFEF FFFFFF 0000FF 4100FF 8200FF BE00FF FF00FF FF00BE FF0082 FF0041
FF0000 FF4100 FF8200 FFBE00 FFFF00 BEFF00 82FF00 41FF00 00FF00 00FF41
00FF82 00FFBE 00FFFF 00BEFF 0082FF 0041FF 8282FF 9E82FF BE82FF DF82FF
FF82FF FF82DF FF82BE FF829E FF8282 FF9E82 FFBE82 FFDF82 FFFF82 DFFF82
BEFF82 9EFF82 82FF82 82FF9E 82FFBE 82FFDF 82FFFF 82DFFF 82BEFF 829EFF
BABAFF CABAFF DFBAFF EFBAFF FFBAFF FFBAEF FFBADF FFBACA FFBABA FFCABA
FFDFBA FFEFBA FFFFBA EFFFBA DFFFBA CAFFBA BAFFBA BAFFCA BAFFDF BAFFEF
BAFFFF BAEFFF BADFFF BACAFF 000071 1C0071 390071 550071 710071 710055
710039 71001C 710000 711C00 713900 715500 717100 557100 397100 1C7100
007100 00711C 007139 007155 007171 005571 003971 001C71 393971 453971
553971 613971 713971 713961 713955 713945 713939 714539 715539 716139
717139 617139 557139 457139 397139 397145 397155 397161 397171 396171
395571 394571 515171 595171 615171 695171 715171 715169 715161 715159
715151 715951 716151 716951 717151 697151 617151 597151 517151 517159
517161 517169 517171 516971 516171 515971 000041 100041 200041 310041
410041 410031 410020 410010 410000 411000 412000 413100 414100 314100
204100 104100 004100 004110 004120 004131 004141 003141 002041 001041
202041 282041 312041 392041 412041 412039 412031 412028 412020 412820
413120 413920 414120 394120 314120 284120 204120 204128 204131 204139
204141 203941 203141 202841 2D2D41 312D41 352D41 3D2D41 412D41 412D3D
412D35 412D31 412D2D 41312D 41352D 413D2D 41412D 3D412D 35412D 31412D
2D412D 2D4131 2D4135 2D413D 2D4141 2D3D41 2D3541 2D3141 000000 000000
000000 000000 000000 000000 000000 000000
)

How hard is it to separate the RGB 8 bit values, divide by 16 on this source data, then multiply by 1,16,256 and add the sum?
Or in the case of the graphics palette,divide by 8 for red and blue, divide by 4 for green, then multiply by 1,32,2048 and add the sum?

Bit shifting would also work...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 01:58:17 pm
Does this look right for RGB565?

Code: [Select]
0000 0015 0540 0555 A800 A815 AAA0 AD55 52AA 52BF 57EA 57FF FAAA FABF FFEA FFFF
0000 1082 2104 31A6 4228 52AA 632C 73AE 8C51 9CD3 AD55 BDD7 CE59 DEFB EF7D FFFF
001F 401F 801F B81F F81F F817 F810 F808 F800 FA00 FC00 FDE0 FFE0 BFE0 87E0 47E0
07E0 07E8 07F0 07F7 07FF 05FF 041F 021F 841F 9C1F BC1F DC1F FC1F FC1B FC17 FC13
FC10 FCF0 FDF0 FEF0 FFF0 DFF0 BFF0 9FF0 87F0 87F3 87F7 87FB 87FF 86FF 85FF 84FF
BDDF CDDF DDDF EDDF FDDF FDDD FDDB FDD9 FDD7 FE57 FEF7 FF77 FFF7 EFF7 DFF7 CFF7
BFF7 BFF9 BFFB BFFD BFFF BF7F BEFF BE5F 000E 180E 380E 500E 700E 700A 7007 7003
7000 70E0 71C0 72A0 7380 5380 3B80 1B80 0380 0383 0387 038A 038E 02AE 01CE 00EE
39CE 41CE 51CE 61CE 71CE 71CC 71CA 71C8 71C7 7227 72A7 7307 7387 6387 5387 4387
3B87 3B88 3B8A 3B8C 3B8E 3B0E 3AAE 3A2E 528E 5A8E 628E 6A8E 728E 728D 728C 728B
728A 72CA 730A 734A 738A 6B8A 638A 5B8A 538A 538B 538C 538D 538E 534E 530E 52CE
0008 1008 2008 3008 4008 4006 4004 4002 4000 4080 4100 4180 4200 3200 2200 1200
0200 0202 0204 0206 0208 0188 0108 0088 2108 2908 3108 3908 4108 4107 4106 4105
4104 4144 4184 41C4 4204 3A04 3204 2A04 2204 2205 2206 2207 2208 21C8 2188 2148
2968 3168 3168 3968 4168 4167 4166 4166 4165 4185 41A5 41E5 4205 3A05 3205 3205
2A05 2A06 2A06 2A07 2A08 29E8 29A8 2988 0000 0000 0000 0000 0000 0000 0000 0000
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 02:55:22 pm
If I've done my math right, the first 5 should read:

0000 0015 0560 0575 A800

Remember the green is /4, not divide by /8 since the green retains 6 of 8 bits, not 5 of 8 bits like the red and blue.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 04:09:01 pm
Probably because I'm just dropping the least-significant bits - this is my code to reduce from 3 bytes to 2 (C#):

Code: [Select]
rgb_out[1] = (rgb[0] & 0xF8) | (rgb[1] >> 5);
rgb_out[0] = ((rgb[1] & 0x1C) << 3) | (rgb[2] >> 3);

rgb[0] is red, [1] is green, [2] is blue.  rgb_out is an array, rgb_out[1] is MSB, rgb_out[0] is LSB.  They are output like this:

Code: [Select]
String.Format("{0:X2}", rgb_out[1]) + String.Format("{0:X2}", rgb_out[0]) + " ";
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 06:23:57 pm
Probably because I'm just dropping the least-significant bits - this is my code to reduce from 3 bytes to 2 (C#):

Code: [Select]
rgb_out[1] = (rgb[0] & 0xF8) | (rgb[1] >> 5);
rgb_out[0] = ((rgb[1] & 0x1C) << 3) | (rgb[2] >> 3);

rgb[0] is red, [1] is green, [2] is blue.  rgb_out is an array, rgb_out[1] is MSB, rgb_out[0] is LSB.  They are output like this:

Code: [Select]
String.Format("{0:X2}", rgb_out[1]) + String.Format("{0:X2}", rgb_out[0]) + " ";
:palm: Yup, your color codes are correct...
Just do the 4444 as well.  That one is hard to mess up...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 06:28:39 pm
 ;) Okay, this is the output for RGB4444:

Code: [Select]
-- PALConverter-generated Memory Initialisation File (.mif)
-- For use with Quartus II & Quartus Prime.
-- Generated at: 06/12/2019 18:28:05

WIDTH=16;
DEPTH=256;

ADDRESS_RADIX=HEX;
DATA_RADIX=HEX;

CONTENT BEGIN
    000  :   0000;
    001  :   000A;
    002  :   00A0;
    003  :   00AA;
    004  :   0A00;
    005  :   0A0A;
    006  :   0A50;
    007  :   0AAA;
    008  :   0555;
    009  :   055F;
    00A  :   05F5;
    00B  :   05FF;
    00C  :   0F55;
    00D  :   0F5F;
    00E  :   0FF5;
    00F  :   0FFF;
    010  :   0000;
    011  :   0111;
    012  :   0222;
    013  :   0333;
    014  :   0444;
    015  :   0555;
    016  :   0666;
    017  :   0777;
    018  :   0888;
    019  :   0999;
    01A  :   0AAA;
    01B  :   0BBB;
    01C  :   0CCC;
    01D  :   0DDD;
    01E  :   0EEE;
    01F  :   0FFF;
    020  :   000F;
    021  :   040F;
    022  :   080F;
    023  :   0B0F;
    024  :   0F0F;
    025  :   0F0B;
    026  :   0F08;
    027  :   0F04;
    028  :   0F00;
    029  :   0F40;
    02A  :   0F80;
    02B  :   0FB0;
    02C  :   0FF0;
    02D  :   0BF0;
    02E  :   08F0;
    02F  :   04F0;
    030  :   00F0;
    031  :   00F4;
    032  :   00F8;
    033  :   00FB;
    034  :   00FF;
    035  :   00BF;
    036  :   008F;
    037  :   004F;
    038  :   088F;
    039  :   098F;
    03A  :   0B8F;
    03B  :   0D8F;
    03C  :   0F8F;
    03D  :   0F8D;
    03E  :   0F8B;
    03F  :   0F89;
    040  :   0F88;
    041  :   0F98;
    042  :   0FB8;
    043  :   0FD8;
    044  :   0FF8;
    045  :   0DF8;
    046  :   0BF8;
    047  :   09F8;
    048  :   08F8;
    049  :   08F9;
    04A  :   08FB;
    04B  :   08FD;
    04C  :   08FF;
    04D  :   08DF;
    04E  :   08BF;
    04F  :   089F;
    050  :   0BBF;
    051  :   0CBF;
    052  :   0DBF;
    053  :   0EBF;
    054  :   0FBF;
    055  :   0FBE;
    056  :   0FBD;
    057  :   0FBC;
    058  :   0FBB;
    059  :   0FCB;
    05A  :   0FDB;
    05B  :   0FEB;
    05C  :   0FFB;
    05D  :   0EFB;
    05E  :   0DFB;
    05F  :   0CFB;
    060  :   0BFB;
    061  :   0BFC;
    062  :   0BFD;
    063  :   0BFE;
    064  :   0BFF;
    065  :   0BEF;
    066  :   0BDF;
    067  :   0BCF;
    068  :   0007;
    069  :   0107;
    06A  :   0307;
    06B  :   0507;
    06C  :   0707;
    06D  :   0705;
    06E  :   0703;
    06F  :   0701;
    070  :   0700;
    071  :   0710;
    072  :   0730;
    073  :   0750;
    074  :   0770;
    075  :   0570;
    076  :   0370;
    077  :   0170;
    078  :   0070;
    079  :   0071;
    07A  :   0073;
    07B  :   0075;
    07C  :   0077;
    07D  :   0057;
    07E  :   0037;
    07F  :   0017;
    080  :   0337;
    081  :   0437;
    082  :   0537;
    083  :   0637;
    084  :   0737;
    085  :   0736;
    086  :   0735;
    087  :   0734;
    088  :   0733;
    089  :   0743;
    08A  :   0753;
    08B  :   0763;
    08C  :   0773;
    08D  :   0673;
    08E  :   0573;
    08F  :   0473;
    090  :   0373;
    091  :   0374;
    092  :   0375;
    093  :   0376;
    094  :   0377;
    095  :   0367;
    096  :   0357;
    097  :   0347;
    098  :   0557;
    099  :   0557;
    09A  :   0657;
    09B  :   0657;
    09C  :   0757;
    09D  :   0756;
    09E  :   0756;
    09F  :   0755;
    0A0  :   0755;
    0A1  :   0755;
    0A2  :   0765;
    0A3  :   0765;
    0A4  :   0775;
    0A5  :   0675;
    0A6  :   0675;
    0A7  :   0575;
    0A8  :   0575;
    0A9  :   0575;
    0AA  :   0576;
    0AB  :   0576;
    0AC  :   0577;
    0AD  :   0567;
    0AE  :   0567;
    0AF  :   0557;
    0B0  :   0004;
    0B1  :   0104;
    0B2  :   0204;
    0B3  :   0304;
    0B4  :   0404;
    0B5  :   0403;
    0B6  :   0402;
    0B7  :   0401;
    0B8  :   0400;
    0B9  :   0410;
    0BA  :   0420;
    0BB  :   0430;
    0BC  :   0440;
    0BD  :   0340;
    0BE  :   0240;
    0BF  :   0140;
    0C0  :   0040;
    0C1  :   0041;
    0C2  :   0042;
    0C3  :   0043;
    0C4  :   0044;
    0C5  :   0034;
    0C6  :   0024;
    0C7  :   0014;
    0C8  :   0224;
    0C9  :   0224;
    0CA  :   0324;
    0CB  :   0324;
    0CC  :   0424;
    0CD  :   0423;
    0CE  :   0423;
    0CF  :   0422;
    0D0  :   0422;
    0D1  :   0422;
    0D2  :   0432;
    0D3  :   0432;
    0D4  :   0442;
    0D5  :   0342;
    0D6  :   0342;
    0D7  :   0242;
    0D8  :   0242;
    0D9  :   0242;
    0DA  :   0243;
    0DB  :   0243;
    0DC  :   0244;
    0DD  :   0234;
    0DE  :   0234;
    0DF  :   0224;
    0E0  :   0224;
    0E1  :   0324;
    0E2  :   0324;
    0E3  :   0324;
    0E4  :   0424;
    0E5  :   0423;
    0E6  :   0423;
    0E7  :   0423;
    0E8  :   0422;
    0E9  :   0432;
    0EA  :   0432;
    0EB  :   0432;
    0EC  :   0442;
    0ED  :   0342;
    0EE  :   0342;
    0EF  :   0342;
    0F0  :   0242;
    0F1  :   0243;
    0F2  :   0243;
    0F3  :   0243;
    0F4  :   0244;
    0F5  :   0234;
    0F6  :   0234;
    0F7  :   0234;
    0F8  :   0000;
    0F9  :   0000;
    0FA  :   0000;
    0FB  :   0000;
    0FC  :   0000;
    0FD  :   0000;
    0FE  :   0000;
    0FF  :   0000;
END;


My program now outputs Quartus-compatible .MIF files.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 06:39:51 pm
Perfect.  Just for address 0, make the word = F000.

Wire in a memory module called 'palette_mixer.sv'.

For now, wire the 4444 palette address to the pixel_out_top wire & pass through the hde,vde,hs,vs.

Make sure you now use the clk enable on the ram unless you are using my 5 port ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 08:02:36 pm
For anyone following along, the software I wrote to convert these palette values is PALConverter, on github here (https://github.com/nockieboy/PALConverter) and the .exe is available below.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 08:08:54 pm
For anyone following along, the software I wrote to convert these palette values is PALConverter, on github here (https://github.com/nockieboy/PALConverter) and the .exe is available below.
Makes me wonder if we should have wasted the ram and just done a 24bit RGB and 32bit ARGB palette.
@nockieboy, you know it's your GPU, you could have said so at any time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 08:13:08 pm
For anyone following along, the software I wrote to convert these palette values is PALConverter, on github here (https://github.com/nockieboy/PALConverter) and the .exe is available below.
Makes me wonder if we should have wasted the ram and just done a 24bit RGB and 32bit ARGB palette.
@nockieboy, you know it's your GPU, you could have said so at any time.

Would need to work out how much RAM we'd need for 24bit RGB mode at 640x480.  Wouldn't be a massive increase (33%) I suppose.  I think a graphics mode would be out of the question with internal RAM, though.  Would have to look at using an external SRAM for that?

Something I've been wondering - how easy is it to change the text display mode from the current 64x32 to 80x40, or some other arbitrary value?  I haven't looked yet, but I'd like to add parameters to the design to make that an easy option to set.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 09:26:22 pm
For anyone following along, the software I wrote to convert these palette values is PALConverter, on github here (https://github.com/nockieboy/PALConverter) and the .exe is available below.
Makes me wonder if we should have wasted the ram and just done a 24bit RGB and 32bit ARGB palette.
@nockieboy, you know it's your GPU, you could have said so at any time.

Would need to work out how much RAM we'd need for 24bit RGB mode at 640x480.  Wouldn't be a massive increase (33%) I suppose.  I think a graphics mode would be out of the question with internal RAM, though.  Would have to look at using an external SRAM for that?

Something I've been wondering - how easy is it to change the text display mode from the current 64x32 to 80x40, or some other arbitrary value?  I haven't looked yet, but I'd like to add parameters to the design to make that an easy option to set.
Your S-Ram would need to read 175 megabytes a second + CPU access + what about the 125 megabytes a second for the display.  we are at 325 megabytes a second, random row & column access, not counting an accelerated drawing engine.
3ns Fully static ram anyone?  Not only 3ns, but ZBT ram. (Zero Bus Turnaround)  Allows a write, then a read, then a write on adjacent cycles.


#2.  Address generator.  That's what it is for.  You will have to basically erase the OSD generator.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on December 06, 2019, 10:53:28 pm
That would be kind of expensive, as BrianHG pointed out. But... how about some variation on Amiga HAM (hold-and-modify) mode? :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 11:02:48 pm
Makes me wonder if we should have wasted the ram and just done a 24bit RGB and 32bit ARGB palette.
@nockieboy, you know it's your GPU, you could have said so at any time.

Would need to work out how much RAM we'd need for 24bit RGB mode at 640x480.  Wouldn't be a massive increase (33%) I suppose.  I think a graphics mode would be out of the question with internal RAM, though.  Would have to look at using an external SRAM for that?

Okay, further to the above with some "back of an envelope" maths:

640x480 text mode = 80x30 = 2,400 tiles.  So 2.4 KB required for the text mode screen space.
256 colour palette x 3 bytes (RGB888 'true colour' gamut) =  768 B for the palette, OR
2,400 tiles x 4 bytes (RGB888 + character value) = 9.6 KB for a true colour text mode.

For graphics, the story isn't so optimistic:

For true colour graphics, you're looking at 640x480x3 = 921.6 KB.  Couldn't even manage RGB565 graphics at 320x240 on an FPGA with less than 160 KB RAM.

Your S-Ram would need to read 175 megabytes a second + CPU access + what about the 125 megabytes a second for the display.  we are at 325 megabytes a second, random row & column access, not counting an accelerated drawing engine.
3ns Fully static ram anyone?  Not only 3ns, but ZBT ram. (Zero Bus Turnaround)  Allows a write, then a read, then a write on adjacent cycles.

You know, looking at engineering problems like this and some of the amazingly tight timings involved really gives me an appreciation of GPU card manufacturers.  Can't be easy making a GPU that can pump enough pixels to support a 4K display at 100Hz.  Yet they use external memory chips too (is it still GDDR?) - can't imagine the technical issues they must face designing those things.  :scared:

#2.  Address generator.  That's what it is for.  You will have to basically erase the OSD generator.

Ah - great. :D  I'll shut up and press on, then!  :-+

That would be kind of expensive, as BrianHG pointed out. But... how about some variation on Amiga HAM (hold-and-modify) mode? :)

Now, forgive me if I'm completely wrong, jhpadjustable, it's been a few years since I've used my Amigas... but HAM mode - didn't that work by using two bytes for the colour, but reserved the top two bits to create a 4-value command that modified the remaining colour bits for the next pixel, or from the previous pixel (or something)?

That seems like it would require some serious horsepower from the Z80 CPU to get that to work - but that's coming from me with little understanding of how it works in the first place.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 11:24:00 pm
That would be kind of expensive, as BrianHG pointed out. But... how about some variation on Amiga HAM (hold-and-modify) mode? :)
He has a true 16bit capability.  Right now, 565 with dithering will outdo the Amiga.  Though, If I were to implement 422 8 bit grey, 1 pixel U, 1 pixel V, he would have 24 bit color, DVD Grade, but without MPEG2 compression artifacts.  I'm waiting for him to place the palettes, and then the 'nightmare' of getting nockieboy to visualize the address generators, especially 2x2dimensions running with variable increment rates (address 16/32 bit memory steps), and increment sizes (periods), on X&Y axis with a secondary pointed address begin fed through the memory auxiliary port I had designed early in to point to the tiles/fonts, all of this reset, incremented, and enabled/disabled by 5 HV_Trigger inputs which will allow a variable sized floating text/graphics window on the screen.

My design is now running the ram at 5x, meaning, 125Mhz, 5 read ports per pixel.  When going to the Lattice FPGA, or even this CycloneIV, we can use the 250MHz ram with 10 read ports per pixel, meaning 1 ram for everything, including palettes.  And the 14$ Lattice FPGA has 2 Megabits which can run at 400MHz.

I haven't tried, but I wonder if the current CYClone IV memory core can be pushed to 270MHz...  The data sheet says the -c8 can do 235MHz & C7 can handle 274MHz.  We would probably need to extend the 'MUX' tree to a 2 layer pipe since 10:1 on the addressees would probably be too slow for 250MHz-270MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 11:33:07 pm
The address generator shows what memory will be displayed inside the hardware window.
The HV_Triggers control the size and position of the window.

There are 2 hardware windows.  Each with font or true graphics capability.  The top window has 4096 color palette with 16 transparency levels to the second window beneath which uses 565 style 65536 colors.

The sprites share the top window, so you have access to the variable translucent colors on each sprite pixel.
Each sprite size and position will also be set by 4 HV_trigger markers.

We may scrap the 565 color for the bottom window and also use 4096 colors plus an alpha channel, however, what should we do with those 4 programmable bits?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2019, 11:40:04 pm
I'm waiting for him to place the palettes, and then the 'nightmare' of getting nockieboy to visualize the address generators, especially 2x2dimensions running with variable increment rates (address 16/32 bit memory steps), and increment sizes (periods), on X&Y axis with a secondary pointed address begin fed through the memory auxiliary port I had designed early in to point to the tiles/fonts, all of this reset, incremented, and enabled/disabled by 5 HV_Trigger inputs which will allow a variable sized floating text/graphics window on the screen.

 :o

Again I'm worrying that the hardest parts are yet to come and I won't get this done in time.  :-\

I'm making a start on the palette module now (though it's late here and I'm going offline in a sec) - just want to clarify something though;  you mentioned previously to create a 'palette_mixer.sv' file (after the creation of the 4444 palette) - will this module handle both palettes, or will I be creating (and tweaking) a copy of this module for the 565 palette?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 11:44:14 pm
You know, looking at engineering problems like this and some of the amazingly tight timings involved really gives me an appreciation of GPU card manufacturers.  Can't be easy making a GPU that can pump enough pixels to support a 4K display at 100Hz.  Yet they use external memory chips too (is it still GDDR?) - can't imagine the technical issues they must face designing those things.  :scared:
In all honesty, if you insisted on DDR memory, we would have scrapped any low color modes, and make a 2D drawing/rendering engine to emulate a text and palette low res color video modes.  We would be just beyond a frame buffer at this point and the architecture would be complex enough that we would need block diagrams and system commands/functions with an instruction FIFO port and we would need to weave around both the DDR ram and system memory blocks as when emulating the palette, we would still want that instant access as we render pixels again and again every vsync every-time you modify a single palette number.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2019, 11:49:22 pm
I'm waiting for him to place the palettes, and then the 'nightmare' of getting nockieboy to visualize the address generators, especially 2x2dimensions running with variable increment rates (address 16/32 bit memory steps), and increment sizes (periods), on X&Y axis with a secondary pointed address begin fed through the memory auxiliary port I had designed early in to point to the tiles/fonts, all of this reset, incremented, and enabled/disabled by 5 HV_Trigger inputs which will allow a variable sized floating text/graphics window on the screen.

 :o

Again I'm worrying that the hardest parts are yet to come and I won't get this done in time.  :-\

I'm making a start on the palette module now (though it's late here and I'm going offline in a sec) - just want to clarify something though;  you mentioned previously to create a 'palette_mixer.sv' file (after the creation of the 4444 palette) - will this module handle both palettes, or will I be creating (and tweaking) a copy of this module for the 565 palette?

Other than sprites, as they are a piggy back measure, unless you only want 4 of them, the address generator will complete this project to V1.0.  You will need to concentrate and document everything as those 15 settings will create any display possible from your memory's contents.

Fiddle with setting here, and your text or graphics will move on the screen, change in scale and size, even bend/tear horizontally.

Playing with the palette will change color/brightness or everything.

You will need to get the Z80 doing things after this.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 07, 2019, 01:47:38 am
I'm making a start on the palette module now (though it's late here and I'm going offline in a sec) - just want to clarify something though;  you mentioned previously to create a 'palette_mixer.sv' file (after the creation of the 4444 palette) - will this module handle both palettes, or will I be creating (and tweaking) a copy of this module for the 565 palette?
Both palettes will be in 1 .sv module running in parallel, though, their Host address should have a different address point.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 07, 2019, 11:32:32 am
@nockieboy, I hate to do this to you, but once you get the initial palette working, you will need to make a change to the 'multiport_gpu_ram.v' and 'gpu_dual_port_ram_INTEL.v'.  Now, I want to get this change right in 1 shot, so, we will need to go over it after the text palette is fully 100% functional without a single pixel in error.

On the read only port side, we will change the 8 bit data port to 16 bits.  This will double our read speed, however, we still want 8 bit address capability.  To do this, in the 'gpu_dual_port_ram_INTEL.v' altsyncram settings, you will make read port 16 bits, effectively lowering the address size by 1 bit.  However, the module 'gpu_dual_port_ram_INTEL.v' will still take the same read address size, and pass it through.  Into the altsyncram, you will feed the upper address beginning at 1 instead of 0.  For the 16 bit data coming out, you will swap the upper and lower 8 bits of that data depending if the read address[0] is high or low.

Effectively, if the proceeding modules use just the bottom 8 bits of ram data, like the 'bitplane_to_rasterbitplane_to_raster.v' we should be backwards compatible.  However, using the upper 8 bits as a font color for example, within 1 read we get 1 byte ascii text, 1 byte color.  When reading a font, we may now also have a few new pixel modes where we have a 16 pixel wide font, or, 4 color per pixel font on top of the base 16 foreground and 16 background offset colors.

The 'multiport_gpu_ram' will also now need to change the 5 read data_out_# ports to a 16bit word.

Next, change the 5 cmd_(in/out)_# ports in the 'multiport_gpu_ram.v' module from 16 bit to 32 bit.  Don't forget the single cmd_(in/out) pass through in the 'gpu_dual_port_ram_INTEL.v' will need to change to 16 bit as well.

As for the 'bitplane_to_rasterbitplane_to_raster.v', take in a 16 bit word for the '.ram_byte_in()', but, leave everything else the same.  For now, ignore the upper 8 bits.  I will specify the minor alterations once everything else is working.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 07, 2019, 05:49:53 pm
@nockieboy, I hate to do this to you...

No worries - I just need to focus on one thing at a time, otherwise details get lost in the confusion.  :-+

Hoping to get some palette module work done if I can string together a few hours tonight or tomorrow.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 07, 2019, 06:19:21 pm
Okay, some intermediate guidance required...  ???

Palette #1, specialized for the ASCII text and sprites.

On the Read only port, IE, pixel_in -to- text_pixel out, you will have:
8 bit address input, ie pixel_in[7:0].
On the data output, you will have a 16bit pixel_out[15:0].

I'm struggling to follow this.  Dual-port RAM, but one port is read only?  That port has an 8-bit address input and one 16-bit output?

The 16 bit output will be wired as follows:
text_pixel_out[15:12] -will be sent to- text_a[3:0]
text_pixel_out[15:12] -will be sent to- text_r[7:4] -and- text_r[3:0]
text_pixel_out[15:12] -will be sent to- text_g[7:4] -and- text_g[3:0]
text_pixel_out[15:12] -will be sent to- text_b[7:4] -and- text_b[3:0]

This refers to the 16-bit output mentioned above?

Do I need clkb?

On the pixel side you will want the 'CLOCK ENABLE' feature for the address latch coming in and data latch going out.
The clock enables will be connected to the (pc_ena[3:0]==0) wire.

Is this the read only side?  Are the clock enables the .clockenx entries in the altsyncram component declaration?  Also, and perhaps most importantly, can I create these palette memories by just copying and editing the code for the GPU RAM?  Or do they have to be created using the wizard?

On the 'host' memory side, you will have a 9 bit address [9:0] and 8 bit data in and out.
The write ena will need attention as you will need to position this memory withing the system not to conflict with the main graphics memory.

Okay, below are two files - palette_mixer.sv and dual_port_palette_ram_text.v.  Neither are finished, I'm just putting them up here for feedback and guidance whilst I work on them and to check I'm going in the right direction.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: jhpadjustable on December 07, 2019, 07:44:08 pm
Now, forgive me if I'm completely wrong, jhpadjustable, it's been a few years since I've used my Amigas... but HAM mode - didn't that work by using two bytes for the colour, but reserved the top two bits to create a 4-value command that modified the remaining colour bits for the next pixel, or from the previous pixel (or something)?

That seems like it would require some serious horsepower from the Z80 CPU to get that to work - but that's coming from me with little understanding of how it works in the first place.
Close. The top two bits (of six) held a command and the bottom four held a parameter. At each pixel you could load all three primaries from a palette entry, or modify one primary directly while holding the other two. HAM was really best suited to displaying pre-drawn static bitmap images, like a background playfield, and (with care) could be used for compositing in special cases, as long as you remember to always put a fixed palette load at each leftmost pixel.

As BrianHG observed, maybe it's not all that useful anymore, in favor of visually superior and simpler luminance:chrominance encodings like YCbCr. Never mind  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 07, 2019, 08:56:46 pm
When usure about your altsyncram function, use the block diagram megafunction wizard to generate a reference .v file for you. You will see a picture of the memory module as you create it.
Then copy-paste the numbers and names generated in the example .v file.
Use Quartus 9.1 for this on a blank new block diagram on a blank new dummy project.

It should look like this:
[attachimg=1]

making this code:
Code: [Select]
module palette256 (
address_a,
address_b,
clock_a,
clock_b,
data_a,
data_b,
enable_a,
enable_b,
wren_a,
wren_b,
q_a,
q_b);

input [7:0]  address_a;
input [8:0]  address_b;
input   clock_a;
input   clock_b;
input [15:0]  data_a;
input [7:0]  data_b;
input   enable_a;
input   enable_b;
input   wren_a;
input   wren_b;
output [15:0]  q_a;
output [7:0]  q_b;



wire [15:0] sub_wire0;
wire [7:0] sub_wire1;
wire [15:0] q_a = sub_wire0[15:0];
wire [7:0] q_b = sub_wire1[7:0];

altsyncram altsyncram_component (
.clocken0 (enable_a),
.clocken1 (enable_b),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (wren_b),
.clock1 (clock_b),
.address_a (address_a),
.address_b (address_b),
.data_a (data_a),
.data_b (data_b),
.q_a (sub_wire0),
.q_b (sub_wire1),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (),
.rden_a (1'b1),
.rden_b (1'b1));
defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = "palette.mif",
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";


endmodule

Remember, for the A port, we may use the clock enable if you want the palette to look like a 2 pixel pipe delay.
Also, please do not hard-wire the write-enable on that port to a 1 this time around.
Another thing, make sure you have a page address parameter which protects the writing on the host port.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 07, 2019, 11:41:10 pm
Okay, not had much time to work on this tonight, but this is where I am so far.  Would appreciate some tips (like for the wr_ena and page address parameter etc) and corrections where there's bound to be errors.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 07, 2019, 11:53:58 pm
Okay, not had much time to work on this tonight, but this is where I am so far.  Would appreciate some tips (like for the wr_ena and page address parameter etc) and corrections where there's bound to be errors.  ;)
No piping or reging needed on this memory.  Just feed the address in and data out.  Optionally use the clock enable, however, you may accelerate things to 1 pixel by re-latchting the data out of the ram on the pc_ena[3:0]==0 since the memory takes less than 4 clock to return a valid result.

This means just wiring the ram's .clocken# to 1.  Also, the data output would be reged once for now as also will be the HDE,VDE,HS,VS.  I force you to have the .clocken# so you may wire them in the future if needed.

There is no command pipe in or out here anymore, it is straight memory to a final pixel.  Reg that pixel at the output of the palette module with the HDE,VDE,HS,VS.

Once done, you should be able to produce VGA colored text with the current bg_color reg with 1 modification, change this line in the 'bitplane_to_raster.sv'.:

change this line 87 to this:
                  pixel_out[4]   <= 1'b0;   // 1'b1;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2019, 12:45:21 pm
Okay, feel like I've lost my way a little and need some more steerage to get back on course.

Am I piping HDE, VDE, HS and VS through the dual_port_palette_ram_text module, or just through the palette_mixer module?  I guess I'd need to delay them by 1 clock if I don't pipe them through the ram module as well?

What exactly is required of the palette_mixer module?  I've included both files below, but am somewhat lost with what else needs to be added to palette_mixer (other than the pass-thru sync signals above)....?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 01:15:24 pm
The palette mixer module just carries the 2 ram palettes, 1 with the 4444 text palette and the 565 graphics palette.

You do realize the next iteration of the vid_osd_generator will output 2 pictures at the same time, right?

The mixer module will mix/superimpose 1 picture on top of the other, right?

You know, like an over head projector with 2 transparent stencils, 1 with a text engine output using a 4444 palette and another beneath showing conventional pixel graphics using a second palette holding the 565 colors.

We need 2 palettes working in parallel.  The palettes also have a read delay which we need to line up to the pixel clock.  The HS,VS,HDE,VDE also needs to match that delay.  You also need to take into consideration the fact that a new pixel will happen every 5 (or other number) clock cycles set by the pc_ena[3:0]==0.

You also want the palette mixer module to be standard verilog calling the 'memory' modules which are exclusive to Intel Quartus altsyncram function which would be swapped out in a different FPGA vendor's dual port memory scheme.  I guess you should rename the the 'dual_port_palette_ram_text.v' to 'dual_port_palette_ram_INTEL.v'.  Remember, the text and graphics palette ram are identical, so 1 ram module would be used twice.  It's just the way the 16 output bits are wired to the RGB on each ram module inside the 'palette_mixer.v' module.  And each ram just has a different .mif file.  So, I am sure you know how to pass parameters and call 2 different instances of 1 memory module, with different memory address and different wiring to the inputs and outputs.

The output of the 2 palettes will just go through 2xRGB multiplies each, then the sum added together at then end.  The 'Alpha' output on the text palette controls the multiplication factor of each palette's RGB output, mixing the 2 opposite proportions of each image together.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2019, 01:59:44 pm
Quick question:  Can I specify a RAM parameter in the instantiating code?

Code: [Select]
// create a text/sprite palette RAM instance
dual_port_palette_ram_INTEL text_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pc_ena_in(pc_ena_in),
.pixel_in(pixel_in),
.address_b(4'h0000),
.data_a(2'h00),
.data_b(2'h00),
.enable_a(pc_enable),
.enable_b(pc_enable),
.wren_a(1'b0),
.wren_b(1'b0),

// outputs
.pc_ena_out(pc_ena_out),
.pixel_out(pixel_out),
.data_out_b(data_out_b),

// registered outputs
.addr_out_a()

);

defparam text_palette_RAM.init_file = "palette_4444.mif";
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 02:04:13 pm
Yes, just look at our existing examples in the multiport ram and intel ram where we specify memory size.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2019, 04:21:37 pm
The palette mixer module just carries the 2 ram palettes, 1 with the 4444 text palette and the 565 graphics palette.

Got that in palette_mixer.v right now - both palettes are instantiated as text_palette_RAM and graphics_palette_RAM.

You do realize the next iteration of the vid_osd_generator will output 2 pictures at the same time, right?

The mixer module will mix/superimpose 1 picture on top of the other, right?

You know, like an over head projector with 2 transparent stencils, 1 with a text engine output using a 4444 palette and another beneath showing conventional pixel graphics using a second palette holding the 565 colors.

Ah okay, that makes a little more sense.  So it should have two 'image' inputs from the vid_osd_generator to look up the relevant palette entry for each one and mix them together into one 16-bit output?

We need 2 palettes working in parallel.  The palettes also have a read delay which we need to line up to the pixel clock.  The HS,VS,HDE,VDE also needs to match that delay.

You also need to take into consideration the fact that a new pixel will happen every 5 (or other number) clock cycles set by the pc_ena[3:0]==0.

Okay, I've got HS, VS, HDE and VDE passed through the palette_mixer module, with a user-definable delay.  It defaults to 6, but I'm sure you mentioned a delay of 1 or 2 earlier..? Might have imagined that, though.  :-//

You also want the palette mixer module to be standard verilog calling the 'memory' modules which are exclusive to Intel Quartus altsyncram function which would be swapped out in a different FPGA vendor's dual port memory scheme.

I guess you should rename the the 'dual_port_palette_ram_text.v' to 'dual_port_palette_ram_INTEL.v'.

Done.

Remember, the text and graphics palette ram are identical, so 1 ram module would be used twice.  It's just the way the 16 output bits are wired to the RGB on each ram module inside the 'palette_mixer.v' module.  And each ram just has a different .mif file.  So, I am sure you know how to pass parameters and call 2 different instances of 1 memory module, with different memory address and different wiring to the inputs and outputs.

Yes, that's all done.  I'll include dual_port_palette_ram_INTEL.v at the bottom for checking, but that's pretty much done with now.  It's instantiated twice in palette_mixer.v, specifying a different .mif file for each one.  My focus is now on palette_mixer.v and getting it set up properly.

The output of the 2 palettes will just go through 2xRGB multiplies each, then the sum added together at then end.

Can you give me an example please?  Are we splitting the 16-bit data from the dual_port_palette_ram into its RGB components and performing these multiplies, as the two palettes are in different RGB formats?

palette_mixer.v
Code: [Select]
module palette_mixer (

// inputs
input clk,
input vs_in,
input hs_in,
input hde_in,
input vde_in,
input [3:0] pc_ena_in,
input [7:0] txt_pixel_in,
input [7:0] gfx_pixel_in,

// outputs
output reg [15:0] pixel_out,
output reg [3:0]  pc_ena_out,
output reg [7:0]  data_out_b,
output reg vs_out,
output reg hs_out,
output reg hde_out,
output reg vde_out

);

parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

wire pc_enable = (pc_ena[3:0]==0);
wire txt_pixel_out;
wire gfx_pixel_out;

reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe; // passthru delay pipes

// *********************************************************************
// *
// * create a text/sprite palette RAM instance (4444)
// *
// *********************************************************************
dual_port_palette_ram_INTEL text_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pc_ena_in(pc_ena_in),
.pixel_in(txt_pixel_in),
.address_b(4'h0000),
.data_a(2'h00),
.data_b(2'h00),
.enable_a(pc_enable),
.enable_b(pc_enable),
.wren_a(1'b0),
.wren_b(1'b0),

// outputs
.pc_ena_out(pc_ena_out),
.pixel_out(txt_pixel_out),
.data_out_b(data_out_b),

// registered outputs
.addr_out_a()

);

defparam text_palette_RAM.init_file = "palette_4444.mif";

// *********************************************************************
// *
// * create a graphics palette RAM instance (565)
// *
// *********************************************************************
dual_port_palette_ram_INTEL graphics_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pc_ena_in(pc_ena_in),
.pixel_in(gfx_pixel_in),
.address_b(4'h0000),
.data_a(2'h00),
.data_b(2'h00),
.enable_a(pc_enable),
.enable_b(pc_enable),
.wren_a(1'b0),
.wren_b(1'b0),

// outputs
.pc_ena_out(pc_ena_out),
.pixel_out(gfx_pixel_out),
.data_out_b(data_out_b),

// registered outputs
.addr_out_a()

);

defparam graphics_palette_RAM.init_file = "palette_565.mif";

// *********************************************************************

always @(posedge clk) begin

if (pc_ena[3:0] == 0) begin

hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];

vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];

hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];

vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];

pixel_out <= txt_pixel_out & gfx_pixel_out; // *** placeholder *** for palette mixing function

end

end

endmodule

dual_port_palette_ram_INTEL.v
Code: [Select]
module dual_port_palette_ram_text (

// inputs
input clock_a,
input clock_b,
input [3:0]  pc_ena_in,
input [7:0]  pixel_addr_in, // address_a
input [8:0]  address_b,
input [15:0] data_a,
input [7:0]  data_b,
input enable_a,
input enable_b,
input wren_a,
input wren_b,

// outputs
output [3:0]  pc_ena_out,

// registered outputs
output reg [15:0] pixel_out, // data_out_a
output reg [7:0]  data_out_b,
output reg [19:0] addr_out_a

);

// ****************************************************************************************************************************
// Dual-port palette RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clocken0 (1'b1),
.clocken1 (enable_b),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (wren_b),
.clock1 (clock_b),
.address_a (pixel_addr_in),
.address_b (address_b),
.data_a (data_a),
.data_b (data_b),
.q_a (pixel_out),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (1'b0),
.rden_a (1'b1),
.rden_b (1'b1)
);

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone IV",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 04:51:59 pm
Ah okay, that makes a little more sense.  So it should have two 'image' inputs from the vid_osd_generator to look up the relevant palette entry for each one and mix them together into one 16-bit output?
Yes.

Quote
We need 2 palettes working in parallel.  The palettes also have a read delay which we need to line up to the pixel clock.  The HS,VS,HDE,VDE also needs to match that delay.

You also need to take into consideration the fact that a new pixel will happen every 5 (or other number) clock cycles set by the pc_ena[3:0]==0.

Okay, I've got HS, VS, HDE and VDE passed through the palette_mixer module, with a user-definable delay.  It defaults to 6, but I'm sure you mentioned a delay of 1 or 2 earlier..? Might have imagined that, though.  :-//
I will let you figure out what the delay should be.
Quote
The output of the 2 palettes will just go through 2xRGB multiplies each, then the sum added together at then end.

Can you give me an example please?  Are we splitting the 16-bit data from the dual_port_palette_ram into its RGB components and performing these multiplies, as the two palettes are in different RGB formats?

First, make from the palette outputs wires
text_r[7:0],text_g[7:0],text_b[7:0], graphics_r[7:0], graphics_g[7:0], graphics_b[7:0], alpha_blend[3:0].

Wire them to the palette out bits like here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2813672/#msg2813672 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2813672/#msg2813672)

Output regs:
pixel_out_r[7:0], pixel_out_g[7:0], pixel_out_b[7:0]

This is a 1 clock step version (which will probably be too slow for a CycloneIV):
pixel_out_r <=  ( (text_r[7:0] * ~alpha_blend[3:0]) + (graphics_r[7:0] * alpha_blend[3:0]) ) >> 4 ;

Now, you should be able to guess the _g, and _b.
Since you asked, I just wanted the text palette out for now, but let's do the full formula.

     If your F-Max drops below 140Mhz, you will need to separate the 2 multiplies into 2 separate regs shifted down to 8 bits each, then the final pixel_out_r/g/b will need to be the sum of those 2 inbetween 8 bit regs making everything take 2 clocks to compute a pixel instead of 1 clock.  With the 2 stages, you will have 0 trouble ever achieving the FMAX.

YES, the output of the palette mixer is 24 bit color.  Just feed the top 12 bits into the vid_out_stencil
YES, since we are mixing colors, if you really want to see 24bits from your 12 bit dac, you can mix into the final 24bit RGB with my white nose generator before sending that into the 4 bit dac, but, do that in a separate module before feeding the vid_out_stencil.  Lets not complicate things right now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2019, 06:22:27 pm
I've not had much time to work on this today, been busy here and going to have to take another break now.  Here's the latest project zip - everything compiles, I've got a design for the palette_mixer, I just need to wire it up.  Would appreciate a check of the palette_mixer code, though, to make sure there's no glaring mistakes, if you have a spare 5 mins!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 08:19:57 pm
I've not had much time to work on this today, been busy here and going to have to take another break now.  Here's the latest project zip - everything compiles, I've got a design for the palette_mixer, I just need to wire it up.  Would appreciate a check of the palette_mixer code, though, to make sure there's no glaring mistakes, if you have a spare 5 mins!
|O  pixel_out_r <=  ( (text_r[7:0] * ~alpha_blend[3:0]) + (graphics_r[7:0] * alpha_blend[3:0]) ) >> 4 ;   |O

You were supposed to figure that one out, I slipped.....
Ok, I'll I'm doing a quick check now...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 08:41:49 pm
I've not had much time to work on this today, been busy here and going to have to take another break now.  Here's the latest project zip - everything compiles, I've got a design for the palette_mixer, I just need to wire it up.  Would appreciate a check of the palette_mixer code, though, to make sure there's no glaring mistakes, if you have a spare 5 mins!
Ok, on the intel ram: (see stars)
Code: [Select]
module dual_port_palette_ram_text (

// inputs
input clock_a,
input clock_b,
input [3:0]  pc_ena_in,  ***************************** GET RID
input [7:0]  pixel_addr_in, // address_a
input [8:0]  address_b,
input [15:0] data_a,
input [7:0]  data_b,
input enable_a,
input enable_b,
input wren_a,
input wren_b,

// outputs
output [3:0]  pc_ena_out,  *********************************** GET RID

// registered outputs
output reg [15:0] pixel_out, // data_out_a  ************* WIRE not reg
output reg [7:0]  data_out_b,                                   ************* WIRE not reg
output reg [19:0] addr_out_a  *********************************** GET RID

);

// ****************************************************************************************************************************
// Dual-port palette RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clocken0 (1'b1),  ******************************** (enable_a)
.clocken1 (enable_b),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (wren_b),
.clock1 (clock_b),
.address_a (pixel_addr_in),
.address_b (address_b),
.data_a (data_a),
.data_b (data_b),
.q_a (pixel_out),
.q_b (data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (1'b0),
.rden_a (1'b1),
.rden_b (1'b1)
);

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
***************************************************************************
altsyncram_component.init_file = INIT_PALETTE,  ************** You still need to call this something and call it a parameter at the beginning of this .v file, even if the parameter name is 'init_file'...  To be clean use my name

**********************************************************************
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone IV",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

endmodule

You can rename the address & data B to host_  so they match what you see in the vid_osd_generator as port B serves the same function.

Next:
Code: [Select]
module palette_mixer (

// inputs
input clk,
input vs_in,
input hs_in,
input hde_in,
input vde_in,
input [3:0] pc_ena_in,
input [7:0] txt_pixel_in,
input [7:0] gfx_pixel_in,

// outputs
output reg [3:0] pc_ena_out,
//
output reg [7:0] raster_out_r,   *****************  Lets change raster_ for pixel_
output reg [7:0] raster_out_g,
output reg [7:0] raster_out_b,
//
output reg [7:0] data_out_b,   *********************** make a proper complete host_ port ans place it at the bottom of all the graphics port IOs
output reg vs_out,
output reg hs_out,
output reg hde_out,
output reg vde_out

);

parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

wire pc_enable = (pc_ena_in[3:0]==0);

wire [15:0] txt_pixel_out;
wire [3:0] alpha_blend;
wire [7:0] text_r;
wire [7:0] text_g;
wire [7:0] text_b;

wire [15:0] gfx_pixel_out;
wire [7:0] graphics_r;
wire [7:0] graphics_g;
wire [7:0] graphics_b;

reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe; // passthru delay pipes

assign alpha_blend = txt_pixel_out[15:12];
assign text_r[7:4] = txt_pixel_out[11:8];
assign text_r[3:0] = txt_pixel_out[11:8];
assign text_g[7:4] = txt_pixel_out[7:4];
assign text_g[3:0] = txt_pixel_out[7:4];
assign text_b[7:4] = txt_pixel_out[3:0];
assign text_b[3:0] = txt_pixel_out[3:0];

assign graphics_r[7:3] = gfx_pixel_out[15:11];
assign graphics_r[2:0] = gfx_pixel_out[15:13];
assign graphics_g[7:2] = gfx_pixel_out[10:5];
assign graphics_g[1:0] = gfx_pixel_out[10:9];
assign graphics_b[7:3] = gfx_pixel_out[4:0];
assign graphics_b[2:0] = gfx_pixel_out[4:2];

// *********************************************************************
// *
// * create a text/sprite palette RAM instance (4444)
// *
// *********************************************************************
dual_port_palette_ram_INTEL text_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pc_ena_in(pc_ena_in),
.pixel_in(txt_pixel_in),
.address_b(4'h0000),
.data_a(2'h00),
.data_b(2'h00),
.enable_a(pc_enable),
.enable_b(pc_enable),  ********************** Wire this to 1'b1 as the host_ port we don't use the clock enable.
.wren_a(1'b0),
.wren_b(1'b0),

// outputs
.pc_ena_out(pc_ena_out),
.pixel_out(txt_pixel_out),
.data_out_b(data_out_b),   *********************** host_ port...

// registered outputs
.addr_out_a()              ******************** get rid

);

defparam text_palette_RAM.init_file = "palette_4444.mif";

// *********************************************************************
// *
// * create a graphics palette RAM instance (565)
// *
// *********************************************************************
dual_port_palette_ram_INTEL graphics_palette_RAM(

// inputs   **************************** perform the same corrections as above...
.clock_a(clk),
.clock_b(clk),
.pc_ena_in(pc_ena_in),
.pixel_in(gfx_pixel_in),
.address_b(4'h0000),
.data_a(2'h00),
.data_b(2'h00),
.enable_a(pc_enable),
.enable_b(pc_enable),
.wren_a(1'b0),
.wren_b(1'b0),

// outputs
.pc_ena_out(pc_ena_out),
.pixel_out(gfx_pixel_out),
.data_out_b(data_out_b),

// registered outputs
.addr_out_a()

);

defparam graphics_palette_RAM.init_file = "palette_565.mif";

// *********************************************************************

always @(posedge clk) begin

if (pc_ena_in[3:0] == 0) begin

hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];

vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];

hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];

vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];

// mix output rgb
raster_out_r <= ((text_r[7:0] * ~alpha_blend[3:0]) + (graphics_r[7:0] * alpha_blend[3:0])) >> 4;
raster_out_g <= ((text_g[7:0] * ~alpha_blend[3:0]) + (graphics_g[7:0] * alpha_blend[3:0])) >> 4;
raster_out_b <= ((text_b[7:0] * ~alpha_blend[3:0]) + (graphics_b[7:0] * alpha_blend[3:0])) >> 4;

end

end

endmodule


Change the 'raster_out_rgb' ahem, 'pixel_out_rgb' equation into a 2 stage pipe.  Like I wrote in the previous message, stage 1 will be the 2 multiplies/contrasts on their own >>4 to get 2 8 bit results.  Stage 2 will sum those 2 together to give you a final pixel value.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2019, 10:47:10 pm
Latest pixel_mixer.v:

Code: [Select]
module palette_mixer (

// inputs
input clk,
input vs_in,
input hs_in,
input hde_in,
input vde_in,
input [3:0] pc_ena_in,
input [7:0] txt_pixel_in,
input [7:0] gfx_pixel_in,

// outputs
output reg [3:0] pc_ena_out,
//
output reg [7:0] pixel_out_r,
output reg [7:0] pixel_out_g,
output reg [7:0] pixel_out_b,
//
output reg vs_out,
output reg hs_out,
output reg hde_out,
output reg vde_out,

// host port
input [9:0] host_addr_in,
input [7:0] host_data_in,
output reg [7:0] host_data_out

);

parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

wire pc_enable = (pc_ena_in[3:0]==0);

// **** TO DO:
wire host_wren_txt; // need to complete this so that they go high when
wire host_wren_gfx; // the palette is correctly addressed by the host
// ****

wire [15:0] txt_pixel_out;
wire [3:0] alpha_blend;
wire [7:0] text_r;
wire [7:0] text_g;
wire [7:0] text_b;

wire [15:0] gfx_pixel_out;
wire [7:0] graphics_r;
wire [7:0] graphics_g;
wire [7:0] graphics_b;

reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe; // passthru delay pipes
reg [7:0] pixel_r1, pixel_r2, pixel_g1, pixel_g2, pixel_b1, pixel_b2;

assign alpha_blend = txt_pixel_out[15:12];
assign text_r[7:4] = txt_pixel_out[11:8];
assign text_r[3:0] = txt_pixel_out[11:8];
assign text_g[7:4] = txt_pixel_out[7:4];
assign text_g[3:0] = txt_pixel_out[7:4];
assign text_b[7:4] = txt_pixel_out[3:0];
assign text_b[3:0] = txt_pixel_out[3:0];

assign graphics_r[7:3] = gfx_pixel_out[15:11];
assign graphics_r[2:0] = gfx_pixel_out[15:13];
assign graphics_g[7:2] = gfx_pixel_out[10:5];
assign graphics_g[1:0] = gfx_pixel_out[10:9];
assign graphics_b[7:3] = gfx_pixel_out[4:0];
assign graphics_b[2:0] = gfx_pixel_out[4:2];

// *********************************************************************
// *
// * create a text/sprite palette RAM instance (4444)
// *
// *********************************************************************
dual_port_palette_ram_INTEL text_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_in(txt_pixel_in),
.host_address(host_addr_in),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.wren_a(1'b0),
.host_wren(host_wren_txt),

// outputs
.pixel_out(txt_pixel_out),
.host_data_out(host_data_out)

);

defparam text_palette_RAM.INIT_PALETTE = "palette_4444.mif";

// *********************************************************************
// *
// * create a graphics palette RAM instance (565)
// *
// *********************************************************************
dual_port_palette_ram_INTEL graphics_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_in(gfx_pixel_in),
.host_address(host_addr_in),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.wren_a(1'b0),
.host_wren(host_wren_gfx),

// outputs
.pixel_out(gfx_pixel_out),
.host_data_out(data_out_b)

);

defparam graphics_palette_RAM.INIT_PALETTE = "palette_565.mif";

// *********************************************************************

always @(posedge clk) begin

if (pc_ena_in[3:0] == 0) begin

hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];

vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];

hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];

vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];

// mix output rgb
pixel_r1 <= (text_r[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_r2 <= (graphics_r[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_r <= pixel_r1 + pixel_r2;

pixel_g1 <= (text_g[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_g2 <= (graphics_g[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_g <= pixel_g1 + pixel_g2;

pixel_b1 <= (text_b[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_b2 <= (graphics_b[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_b <= pixel_b1 + pixel_b2;

end

end

endmodule


Latest dual_port_palette_ram_INTEL.v:

Code: [Select]
module dual_port_palette_ram_text (

// inputs
input clock_a,
input clock_b,
input [7:0]  pixel_addr_in, // address_a
input [8:0]  host_address,
input [15:0] data_a,
input [7:0]  host_data_in,
input enable_a,
input host_enable,
input wren_a,
input host_wren,

// outputs
output [15:0] pixel_out, // data_out_a
output [7:0]  host_data_out

);

parameter INIT_PALETTE = "palette_565.mif";

// ****************************************************************************************************************************
// Dual-port palette RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clocken0 (enable_a),
.clocken1 (host_enable),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (host_wren),
.clock1 (clock_b),
.address_a (pixel_addr_in),
.address_b (host_address),
.data_a (data_a),
.data_b (host_data_in),
.q_a (pixel_out),
.q_b (host_data_out),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (1'b0),
.rden_a (1'b1),
.rden_b (1'b1)
);

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = INIT_PALETTE,
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone IV",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

endmodule


Need to sort the wr_en's for the graphics and text palette memory though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 10:56:13 pm
Latest pixel_mixer.v:

Code: [Select]
module palette_mixer (

// inputs
input clk,
input vs_in,
input hs_in,
input hde_in,
input vde_in,
input [3:0] pc_ena_in,
input [7:0] txt_pixel_in,
input [7:0] gfx_pixel_in,

// outputs
output reg [3:0] pc_ena_out,
//
output reg [7:0] pixel_out_r,
output reg [7:0] pixel_out_g,
output reg [7:0] pixel_out_b,
//
output reg vs_out,
output reg hs_out,
output reg hde_out,
output reg vde_out,

// host port
input [9:0] host_addr_in,
input [7:0] host_data_in,
output reg [7:0] host_data_out

);

parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

wire pc_enable = (pc_ena_in[3:0]==0);

// **** TO DO:
wire host_wren_txt; // need to complete this so that they go high when
wire host_wren_gfx; // the palette is correctly addressed by the host
// ****

wire [15:0] txt_pixel_out;
wire [3:0] alpha_blend;
wire [7:0] text_r;
wire [7:0] text_g;
wire [7:0] text_b;

wire [15:0] gfx_pixel_out;
wire [7:0] graphics_r;
wire [7:0] graphics_g;
wire [7:0] graphics_b;

reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe; // passthru delay pipes
reg [7:0] pixel_r1, pixel_r2, pixel_g1, pixel_g2, pixel_b1, pixel_b2;

assign alpha_blend = txt_pixel_out[15:12];
assign text_r[7:4] = txt_pixel_out[11:8];
assign text_r[3:0] = txt_pixel_out[11:8];
assign text_g[7:4] = txt_pixel_out[7:4];
assign text_g[3:0] = txt_pixel_out[7:4];
assign text_b[7:4] = txt_pixel_out[3:0];
assign text_b[3:0] = txt_pixel_out[3:0];

assign graphics_r[7:3] = gfx_pixel_out[15:11];
assign graphics_r[2:0] = gfx_pixel_out[15:13];
assign graphics_g[7:2] = gfx_pixel_out[10:5];
assign graphics_g[1:0] = gfx_pixel_out[10:9];
assign graphics_b[7:3] = gfx_pixel_out[4:0];
assign graphics_b[2:0] = gfx_pixel_out[4:2];

// *********************************************************************
// *
// * create a text/sprite palette RAM instance (4444)
// *
// *********************************************************************
dual_port_palette_ram_INTEL text_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_in(txt_pixel_in),
.host_address(host_addr_in),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.wren_a(1'b0),
.host_wren(host_wren_txt),

// outputs
.pixel_out(txt_pixel_out),
.host_data_out(host_data_out)

);

defparam text_palette_RAM.INIT_PALETTE = "palette_4444.mif";

// *********************************************************************
// *
// * create a graphics palette RAM instance (565)
// *
// *********************************************************************
dual_port_palette_ram_INTEL graphics_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_in(gfx_pixel_in),
.host_address(host_addr_in),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.wren_a(1'b0),
.host_wren(host_wren_gfx),

// outputs
.pixel_out(gfx_pixel_out),
.host_data_out(data_out_b)

);

defparam graphics_palette_RAM.INIT_PALETTE = "palette_565.mif";

// *********************************************************************

always @(posedge clk) begin

if (pc_ena_in[3:0] == 0) begin

hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];

vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];

hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];

vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];

// mix output rgb
pixel_r1 <= (text_r[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_r2 <= (graphics_r[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_r <= pixel_r1 + pixel_r2;

pixel_g1 <= (text_g[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_g2 <= (graphics_g[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_g <= pixel_g1 + pixel_g2;

pixel_b1 <= (text_b[7:0] * ~alpha_blend[3:0]) >> 4;
pixel_b2 <= (graphics_b[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_b <= pixel_b1 + pixel_b2;

end

end

endmodule


Latest dual_port_palette_ram_INTEL.v:

Code: [Select]
module dual_port_palette_ram_text (

// inputs
input clock_a,
input clock_b,
input [7:0]  pixel_addr_in, // address_a
input [8:0]  host_address,
input [15:0] data_a,
input [7:0]  host_data_in,
input enable_a,
input host_enable,
input wren_a,
input host_wren,

// outputs
output [15:0] pixel_out, // data_out_a
output [7:0]  host_data_out

);

parameter INIT_PALETTE = "palette_565.mif";

// ****************************************************************************************************************************
// Dual-port palette RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clocken0 (enable_a),
.clocken1 (host_enable),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (host_wren),
.clock1 (clock_b),
.address_a (pixel_addr_in),
.address_b (host_address),
.data_a (data_a),
.data_b (host_data_in),
.q_a (pixel_out),
.q_b (host_data_out),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (1'b0),
.rden_a (1'b1),
.rden_b (1'b1)
);

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = INIT_PALETTE,
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone IV",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK1",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

endmodule


Need to sort the wr_en's for the graphics and text palette memory though.
For the host ADDR in, you will need all 20 addresses & you will want 2 parameters to assign where each 512 bytes of ram will be written to and read from.
You should use a single host_write_ena, it's the base address parameters which will decide if the write should be executed or not.
Wire the thing up and test.
Compute & set the proper default pipeline size for this module.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2019, 11:30:17 pm
Or, you can just put 9 addresses in and wire the msb & ~msb on the address into and && with the host_write_enable input.
Stacking the 2 palettes on top of each other and externally handling the paging of these memory blocks.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 10:07:15 am
Or, you can just put 9 addresses in and wire the msb & ~msb on the address into and && with the host_write_enable input.
Stacking the 2 palettes on top of each other and externally handling the paging of these memory blocks.

Well I'm not sure about the host_write_enable - we can't have both palette memories being written to at the same time, so I've done my own thing to interpret which palette should be written to and which palette's data should be output to the host...  it's probably wrong and I've likely completely misunderstood why you want a common host_write_enable, but here it is in a nutshell:

Code: [Select]
parameter [19:0] TXT_PALETTE_ADDR = 19'h4000; // Position the text palette after the top of the GPU RAM
parameter [19:0] GFX_PALETTE_ADDR = 19'h4200; // Position the graphics palette after the text palette

wire host_gfx_data_out; // host data outputs from the
wire host_txt_data_out; // palette RAMs

wire host_wrena_txt; // write enables to each
wire host_wrena_gfx; // palette RAM
wire txt_addressed;
wire gfx_addressed;

// write enables to either palette RAM only go high if addressed correctly during a write
assign txt_addressed = (host_addr_in[19:10] == TXT_PALETTE_ADDR[19:10]);
assign gfx_addressed = (host_addr_in[19:10] == GFX_PALETTE_ADDR[19:10]);
assign host_wrena_txt = host_wrena & txt_addressed;
assign host_wrena_gfx = host_wrena & gfx_addressed;

always @(posedge clk) begin

// route the correct palette data out to the host
if (txt_addressed)
host_data_out <= host_txt_data_out;
else if (gfx_addressed)
host_data_out <= host_gfx_data_out;

end

Above is pseudo-code effectively as I've just cut 'n' pasted the appropriate bits of code from palette_mixer.v to illustrate the point.  The full code is in the attached project.  host_wrena is tied to ground in the design anyway, so it shouldn't be affecting the issue below...

I've wired up the palette_mixer and tested in the dev board - just getting a black screen apart from the trigger bars; no text or background, despite messing with the bitplane_to_raster settings.  :-\  I've either made a silly wiring mistake that I can't spot or there's a problem with the code.  I haven't worked out the PIPE_DELAY yet as I figured I should get something on the screen, even if the delay is wildly out, but there's nothing.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 12:09:19 pm
Ok, I cannot fault you on this one, change the following lines:

Code: [Select]
// mix output rgb
pixel_r1 <= (text_r[7:0] * (15-alpha_blend[3:0]) ) >> 4;
pixel_r2 <= (graphics_r[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_r <= pixel_r1 + pixel_r2;

pixel_g1 <= (text_g[7:0] * (15-alpha_blend[3:0]) ) >> 4;
pixel_g2 <= (graphics_g[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_g <= pixel_g1 + pixel_g2;

pixel_b1 <= (text_b[7:0] * (15-alpha_blend[3:0]) ) >> 4;
pixel_b2 <= (graphics_b[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_b <= pixel_b1 + pixel_b2;

Is there someone else out there who can tell me why this works?
pixel_r1      <= (text_r[7:0] * (15-alpha_blend[3:0]) ) >> 4;
But, this fails and always returns '0'?
pixel_r1      <= (text_r[7:0] * (~alpha_blend[3:0]) ) >> 4;
Even this fails:
pixel_r1      <= (text_r[7:0] * (4'hF ^ alpha_blend[3:0]) ) >> 4;
And this fails too:
pixel_r1      <= (text_r[7:0] * (4'hF - alpha_blend[3:0]) ) >> 4;
EVEN THIS FAILS!!!  :scared:
pixel_r1      <= (text_r[7:0] * (4'd15 - alpha_blend[3:0]) ) >> 4;  :scared:
BUT WHY DO THESE WORK???
pixel_r1      <= (text_r[7:0] * (32'd15-alpha_blend[3:0]) ) >> 4;
pixel_r1      <= (text_r[7:0] * (16'd15-alpha_blend[3:0]) ) >> 4;

@nockieboy, your text is too far to the left, however, since this is the first time you will see the results, you will need to adjust a few things.

As for selecting the 'Host_data_out'.  Some other adjustments will mat be needed as well.
I'm thinking of using the memories' :

            .rden_a (rden_a),
            .rden_b (rden_b),

Now, feed each rd_en_b(), (read enable) the txt_addressed and gfx_addressed wires.  .rden_a (rden_a), should obviously be (1'b1).

When rd_en_b(), is low, the read contents will be 0.  So, you just 'OR' the output data buses.
Same will go for the GPU main memory.  Assign a base address based on the gpu_RAM.ADDR_SIZE (which you have yet to expose to the top block diagram) and create for that memory an appropriate '.rden_b (rden_b),'.  On the block diagram, just 'OR' that host_data buss with the palette's host_data bus and all the memorie's data output will have a single 7 bit result, no additional register clock delays...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 12:49:47 pm
@nockieboy, your text is too far to the left, however, since this is the first time you will see the results, you will need to adjust a few things.

I tweaked palette_mixer's PIPE_DELAY down to 3 and it appears to be aligned okay now.  :-/O

[attach=1]

I'm not sure that's the right way to fix it, though - the HV triggers seem to be out at 19, 16, 658, 495.  The horizontal triggers seem to be out by 3 pixels?

EDIT: Ignore me, being a dunce.  It's because the HV triggers aren't delayed through the palette_mixer as well, isn't it?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 12:51:17 pm
As for selecting the 'Host_data_out'.  Some other adjustments will mat be needed as well.
I'm thinking of using the memories' :

            .rden_a (rden_a),
            .rden_b (rden_b),

Now, feed each rd_en_b(), (read enable) the txt_addressed and gfx_addressed wires.  .rden_a (rden_a), should obviously be (1'b1).

When rd_en_b(), is low, the read contents will be 0.  So, you just 'OR' the output data buses.

Is this okay?

palette_mixer.v:
Code: [Select]
module palette_mixer (

// inputs
input clk,
input [3:0] pc_ena_in,
input [7:0] txt_pixel_in,
input [7:0] gfx_pixel_in,
input hde_in,
input vde_in,
input hs_in,
input vs_in,

// outputs
output reg [3:0] pc_ena_out,
//
output reg [7:0] pixel_out_r,
output reg [7:0] pixel_out_g,
output reg [7:0] pixel_out_b,
//
output reg hde_out,
output reg vde_out,
output reg hs_out,
output reg vs_out,

// host port
input host_wrena,
input [19:0] host_addr_in,
input [7:0] host_data_in,
output reg [7:0] host_data_out

);

parameter PIPE_DELAY = 6; // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.

parameter [19:0] TXT_PALETTE_ADDR = 19'h4000; // Position the text palette after the top of the GPU RAM
parameter [19:0] GFX_PALETTE_ADDR = 19'h4200; // Position the graphics palette after the text palette

wire pc_enable = (pc_ena_in[3:0]==0);

wire host_gfx_data_out; // host data outputs from the
wire host_txt_data_out; // palette RAMs

wire host_wrena_txt; // write enables to each
wire host_wrena_gfx; // palette RAM
wire txt_addressed;
wire gfx_addressed;

wire [15:0] txt_pixel_out;
wire [3:0]  alpha_blend;
wire [7:0]  text_r;
wire [7:0]  text_g;
wire [7:0]  text_b;

wire [15:0] gfx_pixel_out;
wire [7:0]  graphics_r;
wire [7:0]  graphics_g;
wire [7:0]  graphics_b;

reg [9:0] hde_pipe, vde_pipe, hs_pipe, vs_pipe; // passthru delay pipes
reg [7:0] pixel_r1, pixel_r2, pixel_g1, pixel_g2, pixel_b1, pixel_b2;

assign alpha_blend = txt_pixel_out[15:12];
assign text_r[7:4] = txt_pixel_out[11:8];
assign text_r[3:0] = txt_pixel_out[11:8];
assign text_g[7:4] = txt_pixel_out[7:4];
assign text_g[3:0] = txt_pixel_out[7:4];
assign text_b[7:4] = txt_pixel_out[3:0];
assign text_b[3:0] = txt_pixel_out[3:0];

assign graphics_r[7:3] = gfx_pixel_out[15:11];
assign graphics_r[2:0] = gfx_pixel_out[15:13];
assign graphics_g[7:2] = gfx_pixel_out[10:5];
assign graphics_g[1:0] = gfx_pixel_out[10:9];
assign graphics_b[7:3] = gfx_pixel_out[4:0];
assign graphics_b[2:0] = gfx_pixel_out[4:2];

// write enables to either palette RAM only go high if addressed correctly during a write
assign txt_addressed = (host_addr_in[19:10] == TXT_PALETTE_ADDR[19:10]);
assign gfx_addressed = (host_addr_in[19:10] == GFX_PALETTE_ADDR[19:10]);
assign host_wrena_txt = host_wrena & txt_addressed;
assign host_wrena_gfx = host_wrena & gfx_addressed;

// *********************************************************************
// *
// * create a text/sprite palette RAM instance (4444)
// *
// *********************************************************************
dual_port_palette_ram_INTEL text_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_addr_in(txt_pixel_in),
.host_address(host_addr_in[8:0]),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.rden_a(1'b1),
.rden_b(txt_addressed),
.wren_a(1'b0),
.host_wren(host_wrena_txt),

// outputs
.pixel_out(txt_pixel_out),
.host_data_out(host_txt_data_out)

);

defparam text_palette_RAM.INIT_PALETTE = "palette_4444.mif";

// *********************************************************************
// *
// * create a graphics palette RAM instance (565)
// *
// *********************************************************************
dual_port_palette_ram_INTEL graphics_palette_RAM(

// inputs
.clock_a(clk),
.clock_b(clk),
.pixel_addr_in(gfx_pixel_in),
.host_address(host_addr_in[8:0]),
.data_a(2'h00),
.host_data_in(host_data_in),
.enable_a(pc_enable),
.host_enable(1'b1),
.rden_a(1'b1),
.rden_b(gfx_addressed),
.wren_a(1'b0),
.host_wren(host_wrena_gfx),

// outputs
.pixel_out(gfx_pixel_out),
.host_data_out(host_gfx_data_out)

);

defparam graphics_palette_RAM.INIT_PALETTE = "palette_565.mif";

// *********************************************************************

always @(posedge clk) begin

if (pc_ena_in[3:0] == 0) begin

hde_pipe[0] <= hde_in;
hde_pipe[9:1] <= hde_pipe[8:0];
hde_out <= hde_pipe[PIPE_DELAY-1];

vde_pipe[0] <= vde_in;
vde_pipe[9:1] <= vde_pipe[8:0];
vde_out <= vde_pipe[PIPE_DELAY-1];

hs_pipe[0] <= hs_in;
hs_pipe[9:1] <= hs_pipe[8:0];
hs_out <= hs_pipe[PIPE_DELAY-1];

vs_pipe[0] <= vs_in;
vs_pipe[9:1] <= vs_pipe[8:0];
vs_out <= vs_pipe[PIPE_DELAY-1];

// mix output rgb
pixel_r1 <= (text_r[7:0] * (15-alpha_blend[3:0])) >> 4;
pixel_r2 <= (graphics_r[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_r <= pixel_r1 + pixel_r2;

pixel_g1 <= (text_g[7:0] * (15-alpha_blend[3:0])) >> 4;
pixel_g2 <= (graphics_g[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_g <= pixel_g1 + pixel_g2;

pixel_b1 <= (text_b[7:0] * (15-alpha_blend[3:0])) >> 4;
pixel_b2 <= (graphics_b[7:0] * alpha_blend[3:0]) >> 4;
pixel_out_b <= pixel_b1 + pixel_b2;

end

// route the palette data out to the host
host_data_out <= host_txt_data_out | host_gfx_data_out;

end

endmodule


Same will go for the GPU main memory.  Assign a base address based on the gpu_RAM.ADDR_SIZE (which you have yet to expose to the top block diagram) and create for that memory an appropriate '.rden_b (rden_b),'.  On the block diagram, just 'OR' that host_data buss with the palette's host_data bus and all the memorie's data output will have a single 7 bit result, no additional register clock delays...

Okay, will get on that later this evening.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 01:02:30 pm
As for selecting the 'Host_data_out'.  Some other adjustments will mat be needed as well.
I'm thinking of using the memories' :

            .rden_a (rden_a),
            .rden_b (rden_b),

Now, feed each rd_en_b(), (read enable) the txt_addressed and gfx_addressed wires.  .rden_a (rden_a), should obviously be (1'b1).

When rd_en_b(), is low, the read contents will be 0.  So, you just 'OR' the output data buses.

Is this okay?

palette_mixer.v:
Code: [Select]

// route the palette data out to the host
host_data_out <= host_txt_data_out | host_gfx_data_out;

end

endmodule
Switch the 'host_data_out'  into a wire and assign it to '= host_txt_data_out | host_gfx_data_out'.  Now there will be 0 clock cycles for clocking a register.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 01:16:27 pm
Switch the 'host_data_out'  into a wire and assign it to '= host_txt_data_out | host_gfx_data_out'.  Now there will be 0 clock cycles for clocking a register.

Done.  Also sorted the HV trigger problem - now delayed through palette_mixer, although I imagine that's a temporary debugging thing and I'll be removing them from the final display before too long.

EDIT: Forgot to mention, Fmax is down to 146.63 MHz now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 01:39:18 pm
Found a bug in the 'bitplane_to_raster' module.

Line 146: if (x_out[3])...
I'll let you figure out the bug...

Also, make the HW_regs font default color to 240, that cyan background is ugly...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 02:05:34 pm
Found a bug in the 'bitplane_to_raster' module.

Line 146: if (x_out[3])...
I'll let you figure out the bug...

Ooh.. shouldn't that be x_out[2]?

Also, make the HW_regs font default color to 240, that cyan background is ugly...

Yeah, that was my reaction when I saw it too.  :-DD  Didn't think to change the HW_regs default settings - I was setting it to E1 in the RS232_debugger.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 02:06:12 pm
Your pixels are still off by 1 or 2 according to the image I see.

The original code has 0 delay on the bit selection.  This new code has 1, so long as you remove all the internal delays.  You need the other modules to take that into effect.

Right, fixed that by changing the x_in input to the bitplane_to_raster instance from dly6_disp_x to dly5_disp_x.  :-+

Remember my comment after this fix post of yours:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2816848/#msg2816848 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2816848/#msg2816848)

Doing it the wrong way will come back to haunt you later....  Like soon...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 02:07:00 pm
Found a bug in the 'bitplane_to_raster' module.

Line 146: if (x_out[3])...
I'll let you figure out the bug...

Ooh.. shouldn't that be x_out[2]?
Yes.
But, don't forget this: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2821728/#msg2821728 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2821728/#msg2821728)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 02:49:54 pm
Your pixels are still off by 1 or 2 according to the image I see.

The original code has 0 delay on the bit selection.  This new code has 1, so long as you remove all the internal delays.  You need the other modules to take that into effect.

Right, fixed that by changing the x_in input to the bitplane_to_raster instance from dly6_disp_x to dly5_disp_x.  :-+

Remember my comment after this fix post of yours:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2816848/#msg2816848 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2816848/#msg2816848)

Doing it the wrong way will come back to haunt you later....  Like soon...

Sorry, you've lost me there.  Is the fix you've linked to above incorrect then?  Or is the fault with x_out[3] linked to this previous fix? Should it be x_in[3] instead to remove the one clock delay?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 03:03:28 pm
     You have 2 problems with the code.  Changing the bit from 3 to 2 fixes 1 problem.  Playing with the pixel bitplane mode setting with the on screen text should have shown you a difference and you would have noticed the problem with the [3].
     Now, your home made delay 6 to 5 patch trick will not work with the new address generators as there will no longer be any x position delays to tap from once we go to the new address generators.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 03:42:09 pm
Ok, the ' .rden_b() ' doesn't do what I want, we must use the ' .aclr1 () ' for all the host memory ports.

Do this exactly:

Loose your rden_b port, and make a sclr_n_rd_b input and inside the 'ram_INTEL' module, add this...

reg aclr_delay,aclr_delay2;

on the altsyncram add this port:
            .aclr0 ( 1'b0 ),
            .aclr1 (aclr_delay2)

make sure you don't have doubles and the rden_b is now forced back to ' (1'b1) '

change these defparams:

      altsyncram_component.outdata_aclr_a = "CLEAR0",
      altsyncram_component.outdata_aclr_b = "CLEAR1",

add this at the end of the memory before ' endmodule'

always @(posedge clk_b) begin
aclr_delay  <= ~sclr_n_rd_b;
aclr_delay2 <= aclr_delay;
end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 05:05:02 pm
Ok, the ' .rden_b() ' doesn't do what I want, we must use the ' .aclr1 () ' for all the host memory ports.

Do this exactly:

Loose your rden_b port, and make a sclr_n_rd_b input and inside the 'ram_INTEL' module, add this...

reg aclr_delay,aclr_delay2;

on the altsyncram add this port:
            .aclr0 ( 1'b0 ),
            .aclr1 (aclr_delay2)

make sure you don't have doubles and the rden_b is now forced back to ' (1'b1) '

change these defparams:

      altsyncram_component.outdata_aclr_a = "CLEAR0",
      altsyncram_component.outdata_aclr_b = "CLEAR1",

add this at the end of the memory before ' endmodule'

always @(posedge clk_b) begin
aclr_delay  <= ~sclr_n_rd_b;
aclr_delay2 <= aclr_delay;
end

Okay, done all that - I assume when you said, "we must use the ' .aclr1 () ' for all the host memory ports", you meant the palette memory ports and not the GPU memory as well??

Updated project files attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 05:08:33 pm
     You have 2 problems with the code.  Changing the bit from 3 to 2 fixes 1 problem.  Playing with the pixel bitplane mode setting with the on screen text should have shown you a difference and you would have noticed the problem with the [3].
     Now, your home made delay 6 to 5 patch trick will not work with the new address generators as there will no longer be any x position delays to tap from once we go to the new address generators.

So either I'm screwed or there's some solution you're alluding to that is just beyond my grasp with the meagre time I have to focus on this currently?  :-[
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 06:15:49 pm
     Now, your home made delay 6 to 5 patch trick will not work with the new address generators as there will no longer be any x position delays to tap from once we go to the new address generators.

So either I'm screwed or there's some solution you're alluding to that is just beyond my grasp with the meagre time I have to focus on this currently?  :-[

This isn't difficult.  Think carefully.  If you are shortening the delay of the 'x' counter position by "1" before you feed the input of the bitplane to raster module to fix a problem, then, is it possible that you have a delay in the currently used 'x' coordinates inside the bitplane to raster module which shouldn't be there?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 09:04:00 pm
This isn't difficult.  Think carefully.  If you are shortening the delay of the 'x' counter position by "1" before you feed the input of the bitplane to raster module to fix a problem, then, is it possible that you have a delay in the currently used 'x' coordinates inside the bitplane to raster module which shouldn't be there?

The only 'internal' delay to the x coordinates I can spot is the one I mentioned earlier? It's possible you read that message before I edited the comment in red into the post...  :-/O

Sorry, you've lost me there.  Is the fix you've linked to above incorrect then?  Or is the fault with x_out[3] linked to this previous fix? Should it be x_in[3] instead to remove the one clock delay?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 09:05:54 pm
Ok, the ' .rden_b() ' doesn't do what I want, we must use the ' .aclr1 () ' for all the host memory ports.

Do this exactly:

Loose your rden_b port, and make a sclr_n_rd_b input and inside the 'ram_INTEL' module, add this...

reg aclr_delay,aclr_delay2;

on the altsyncram add this port:
            .aclr0 ( 1'b0 ),
            .aclr1 (aclr_delay2)

make sure you don't have doubles and the rden_b is now forced back to ' (1'b1) '

change these defparams:

      altsyncram_component.outdata_aclr_a = "CLEAR0",
      altsyncram_component.outdata_aclr_b = "CLEAR1",

add this at the end of the memory before ' endmodule'

always @(posedge clk_b) begin
aclr_delay  <= ~sclr_n_rd_b;
aclr_delay2 <= aclr_delay;
end

Okay, done all that - I assume when you said, "we must use the ' .aclr1 () ' for all the host memory ports", you meant the palette memory ports and not the GPU memory as well??

Updated project files attached.

 :( The .aclr1() trick wont work as well, make this change instead...

Change the output to a reg:
...
   output reg [7:0] data_out_b
...
Make a new wire
...
wire [7:0] pre_data_out_b;
...
change the altsyncram IOs:
...
            .q_b (pre_data_out_b),
            .aclr0 (1'b0),
            .aclr1 (1'b0),
...
change the altsyncram defparams:
...
      altsyncram_component.outdata_aclr_a = "NONE",
      altsyncram_component.outdata_aclr_b = "NONE",
      altsyncram_component.outdata_reg_a = "CLOCK0",
      altsyncram_component.outdata_reg_b = "UNREGISTERED",
...
create this true synchronous read with clear data before the 'endmodule':
...
always @(posedge clk_b) begin
aclr_delay  <= rd_en_b;
     if (aclr_delay) data_out_b  <= pre_data_out_b;
     else               data_out_b  <= 0;
end
...

This will keep a 2 clock read, with good performance, and create a synchronous '0' with the read 2 clock timing when the read enable is low.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 09:13:15 pm
This isn't difficult.  Think carefully.  If you are shortening the delay of the 'x' counter position by "1" before you feed the input of the bitplane to raster module to fix a problem, then, is it possible that you have a delay in the currently used 'x' coordinates inside the bitplane to raster module which shouldn't be there?

The only 'internal' delay to the x coordinates I can spot is the one I mentioned earlier? It's possible you read that message before I edited the comment in red into the post...  :-/O

Look carefully at the:
...
line 86               if (ram_byte_in[(~x_out[2:0])] == 1'b1) begin
...
line 112               case (x_out[2:1])
...
line 146               if (x_out[2])
...
line 180               if (ram_byte_in[(~x_out[2:0])] == 1'b1) begin
...

Is it possible that you have a delay in the currently USED 'x' coordinates inside the bitplane to raster module which shouldn't be there?

Prepare to bang your head and see why I was banging mine with the comment:
Quote
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2816848/#msg2816848 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2816848/#msg2816848)
 |O  Arrrrrrggg, how did you do that?  You found a different, yet perfect solution to a weird problem I never thought would end up like this....

Ok...  Fine...  Great...

Next...

If I need to make 1 more comment on this, your gonna feel worse...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 09:43:28 pm
Look at line #37:
      x_out               <= x_in;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 10:28:08 pm
:( The .aclr1() trick wont work as well, make this change instead...

Change the output to a reg:
...
   output reg [7:0] data_out_b
...
Make a new wire
...
wire [7:0] pre_data_out_b;
...
change the altsyncram IOs:
...
            .q_b (pre_data_out_b),
            .aclr0 (1'b0),
            .aclr1 (1'b0),
...
change the altsyncram defparams:
...
      altsyncram_component.outdata_aclr_a = "NONE",
      altsyncram_component.outdata_aclr_b = "NONE",
      altsyncram_component.outdata_reg_a = "CLOCK0",
      altsyncram_component.outdata_reg_b = "UNREGISTERED",
...
create this true synchronous read with clear data before the 'endmodule':
...
always @(posedge clk_b) begin
aclr_delay  <= rd_en_b;
     if (aclr_delay) data_out_b  <= pre_data_out_b;
     else               data_out_b  <= 0;
end
...

This will keep a 2 clock read, with good performance, and create a synchronous '0' with the read 2 clock timing when the read enable is low.

All done.  Updated dual_port_palette_RAM_INTEL.v below:

Code: [Select]
module dual_port_palette_ram_INTEL (

// inputs
input clock_a,
input clock_b,
input [7:0]  pixel_addr_in, // address_a
input [8:0]  host_address,
input [15:0] data_a,
input [7:0]  host_data_in,
input enable_a,
input host_enable,
input wren_a,
input host_wren,
input rden_a,
input rden_b,
input sclr_n_rd_b,

// outputs
output [15:0] pixel_out, // data_out_a
output reg [7:0]  host_data_out

);

parameter INIT_PALETTE = "palette_565.mif";

wire [7:0] pre_data_out_b;

reg aclr_delay;

// ****************************************************************************************************************************
// Dual-port palette RAM
// ****************************************************************************************************************************
altsyncram altsyncram_component (
.clocken0 (enable_a),
.clocken1 (host_enable),
.wren_a (wren_a),
.clock0 (clock_a),
.wren_b (host_wren),
.clock1 (clock_b),
.address_a (pixel_addr_in),
.address_b (host_address),
.data_a (data_a),
.data_b (host_data_in),
.q_a (pixel_out),
.q_b (pre_data_out_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.eccstatus (1'b0),
.rden_a (rden_a),
.rden_b (rden_b)
);

defparam
altsyncram_component.address_reg_b = "CLOCK1",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK1",
altsyncram_component.init_file = INIT_PALETTE,
altsyncram_component.init_file_layout = "PORT_A",
altsyncram_component.intended_device_family = "Cyclone IV",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 512,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 9,
altsyncram_component.width_a = 16,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK1";

// ****************************************************************************************************************************

always @(posedge clock_b) begin

aclr_delay <= rd_en_b;
if (aclr_delay)
data_out_b <= pre_data_out_b;
else
data_out_b <= 1'b0;

end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2019, 10:32:08 pm
If I need to make 1 more comment on this, your gonna feel worse...

Look at line #37:
      x_out               <= x_in;


Darnit, you didn't give me time to reply before you posted another message!  :-\

I'm using x_out in the code, which is delayed by a clock due to the line you've quoted above, when I should be using x_in.  I spotted that earlier and updated the reply I'd made, suggesting it as a modification, but you missed it?  Either that, or you're saying that I shouldn't be assigning x_in to x_out at all and it should just pass straight through without being registered?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2019, 10:45:39 pm
Sorry, you've lost me there.  Is the fix you've linked to above incorrect then?  Or is the fault with x_out[3] linked to this previous fix? Should it be x_in[3] instead to remove the one clock delay?

Oooops, I saw the x_in[3] and focused on the '3' not the '_in'.  Yes, inside the 'if' your should only be using the x_in[] since it's the input which also needs comparing with the input data.  Everything should run in parallel...

Yes, you did get it earlier...

Ok, gotta do the 2-3 fixes to the main GPU_RAM module, then the address generators.

Next, do this: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2818788/#msg2818788 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2818788/#msg2818788)

Then we can tackle the address generator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 09:33:34 am
Ok, gotta do the 2-3 fixes to the main GPU_RAM module, then the address generators.

Sorry, just remind me what these 2-3 fixes were, exactly?  I'm working on making the gpu_dual_port_ram_INTEL module output 16-bits as per your linked previous post - are there other changes to be made as well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 10:18:46 am
@nockieboy, I hate to do this to you, but once you get the initial palette working, you will need to make a change to the 'multiport_gpu_ram.v' and 'gpu_dual_port_ram_INTEL.v'.  Now, I want to get this change right in 1 shot, so, we will need to go over it after the text palette is fully 100% functional without a single pixel in error...

Okay, I've made all the changes you've specified, but I'm getting the following error:

Error (272006): In altsyncram megafunction, when OPERATION_MODE parameter is set to BIDIR_DUAL_PORT, total number of bits of port A and port B must be the same

The RAM isn't happy with 8-bit and 16-bit ports.  I'd made a start making the host port 16-bit, planning to use the same technique to swap bytes around depending on the address's LSB, but then I realised that writing to the 16-bit port by an 8-bit host will be... messy... at best, and will corrupt the RAM contents at worst.  So I'm holding here to see if you have any pearls of wisdom?

Current project attached so you can review the changes made to the RAM so far.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: hamster_nz on December 10, 2019, 11:17:54 am
@nockieboy, I hate to do this to you, but once you get the initial palette working, you will need to make a change to the 'multiport_gpu_ram.v' and 'gpu_dual_port_ram_INTEL.v'.  Now, I want to get this change right in 1 shot, so, we will need to go over it after the text palette is fully 100% functional without a single pixel in error...

Okay, I've made all the changes you've specified, but I'm getting the following error:

Error (272006): In altsyncram megafunction, when OPERATION_MODE parameter is set to BIDIR_DUAL_PORT, total number of bits of port A and port B must be the same

The RAM isn't happy with 8-bit and 16-bit ports.  I'd made a start making the host port 16-bit, planning to use the same technique to swap bytes around depending on the address's LSB, but then I realised that writing to the 16-bit port by an 8-bit host will be... messy... at best, and will corrupt the RAM contents at worst.  So I'm holding here to see if you have any pearls of wisdom?

Current project attached so you can review the changes made to the RAM so far.

Did you change the width of the address line too? The address line for the 8-bit port needs to be one bit wider than the 16-bit port (as 16*1024 = 8*2048 = 16384 bits)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 11:28:44 am
There were the primary mistakes:
Code: [Select]
altsyncram_component.numwords_a = NUM_WORDS /2,

altsyncram_component.widthad_a = ADDR_SIZE - 1 ,  // *************************** 1 less address since we are now 16 bit

altsyncram_component.init_file_layout = "PORT_B",      // *************** assign .mif file to layout 'B'


Too many other changes all at once.  Before making these changes, did everything else work properly?

Like, why did 'PIPE_DELAY' go from the proper value of 7 down to 6 from the last version to this version?
This would have messed up the display by 1 pixel.
I cannot track compound errors...

Too many other changes all at once...

Now, I've gone back 1 version, and just changes the ram_INTEL to make port 'A' 16bit, and use the assign 'mux' ram_data_a from 16bit to 8 bit out, and with 1 change of the addr[0], to the correct delay of addr[0], it works properly.  You will need to reverse the additional compound errors yourself as I cannot figure out why your latest  upload has numerous crap text errors and green background.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 11:58:18 am
There were the primary mistakes:
Code: [Select]
altsyncram_component.numwords_a = NUM_WORDS /2,

altsyncram_component.widthad_a = ADDR_SIZE - 1 ,  // *************************** 1 less address since we are now 16 bit

altsyncram_component.init_file_layout = "PORT_B",      // *************** assign .mif file to layout 'B'


Ah, that's got it compiling again...

Too many other changes all at once.  Before making these changes, did everything else work properly?

Like, why did 'PIPE_DELAY' go from the proper value of 7 down to 6 from the last version to this version?

Yes, it was working fine - the PIPE_DELAY error was because I'd fixed the x_in/x_out issue and changed PIPE_DELAY back to 7, but because of a work distraction here, I came back and got confused about the original value and changed it back to 6.  |O

Now, I've gone back 1 version, and just changes the ram_INTEL to make port 'A' 16bit, and use the assign 'mux' ram_data_a from 16bit to 8 bit out..

I've made the changes you specified in the main post previously, including making the command bus 32 bit etc., have had to expand the pipelines from 8- to 16-bit according to the changes made to the data bus etc.  As far as I can tell, the changes are according to what you've specified.  I'd marked all the requested changes in the code with comments to make them easier to spot.

This is my output currently:

[attach=1]

...and with 1 change of the addr[0], to the correct delay of addr[0], it works properly.  You will need to reverse the additional compound errors yourself as I cannot figure out why your latest  upload has numerous crap text errors and green background.

Well, it should be a blue background.  It compiles with no errors now, but the text is clearly corrupted.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 12:02:35 pm
Ignore the green background, I'd been messing with the default values.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 02:19:49 pm
There were the primary mistakes:
Code: [Select]
altsyncram_component.numwords_a = NUM_WORDS /2,

altsyncram_component.widthad_a = ADDR_SIZE - 1 ,  // *************************** 1 less address since we are now 16 bit

altsyncram_component.init_file_layout = "PORT_B",      // *************** assign .mif file to layout 'B'


Ah, that's got it compiling again...

Too many other changes all at once.  Before making these changes, did everything else work properly?

Like, why did 'PIPE_DELAY' go from the proper value of 7 down to 6 from the last version to this version?

Yes, it was working fine - the PIPE_DELAY error was because I'd fixed the x_in/x_out issue and changed PIPE_DELAY back to 7, but because of a work distraction here, I came back and got confused about the original value and changed it back to 6.  |O
Noooooooooo.  The x_in/x_out fixes the:
Code: [Select]
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( dly6_disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][2:0] ),
.x_in( dly5_disp_x ),
 Back to the proper:
.x_in( dly6_disp_x ),

This bug had nothing to do with the 'PIPE_DELAY', which had the proper value of '7'.

The PIPE_DELAY went from 6 to 7 because the 'bitplane_to_raster' takes 1 clock cycle to create an output pixel where the older pixel character[~xsel] selection from the ram took 0 clock cycles.

Now, your garbage text, did you fix the 'addr[0]' so that the addr which selects the correct memory output byte is the same addr with the same byte we expect to receive from the altsyncram's memory output when the original address was fed in.

Remember, we are feeding 125 million new read addresses second.  Non stop.  The ram coming out keeps on changing 125 million times a second, even though it is 2 clocks behind.  Take this info into consideration when selecting the high and low byte.

(You still have other errors as even the green seems impossible.  I only re-wrote your code from the last version to what you were supposed to create, and it correctly worked with the 16 bit memory and 16 bit mux and 32 bit aux ports and I got perfect blue text.)

After the address generator, we will be modding the gpu_INTEL ram into a new wrapper module, running the the INTEL ram at 250MHz, making it's 2 ports into 4 ports at 125MHz.  And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port.  I hope you are up to the challenge.  (We would need 1GHz 8 bit static ram to replicate this, not counting the palette memory which would double that as we might do the same 15 ports there for true multiple degrees of translucency between all layers instead of between 2 layers, then just transparent color 0 / vs non-transparent.  Also in the lattice part, you will ran the ram at 500Mhz, in other words, you would need a 4GHz 8 bit static ram to replicate that display engine with it's 40 parallel read ports and 2x equivalent host_ ports.)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 02:38:25 pm
I've rolled back the 16-bit changes I made (except the 32-bit changes to the command bus - this isn't used yet so won't affect the output at the moment) and I'm getting a good display again.  Clearly something I'm doing with the 16-bit changes is incorrect.  Here's a summary of the changes I made: (NOTE: these are JUST the changes to the data bus, not the full code)

In multiport_gpu_ram.v:
Code: [Select]
// data buses (output)
output reg [15:0] data_out_0, // ****** changed to 16 bit width
output reg [15:0] data_out_1, // ****** changed to 16 bit width
output reg [15:0] data_out_2, // ****** changed to 16 bit width
output reg [15:0] data_out_3, // ****** changed to 16 bit width
output reg [15:0] data_out_4, // ****** changed to 16 bit width

wire [15:0] data_mux_out; // ****** changed to 16 bit width

reg [DEMUX_PIPE_TOP*16+15:0] data_pipe; // ****** changed to 16 bit width

data_pipe[15:0]                     <= data_mux_out[15:0]; // fill the first 16-bit word in the register pipe with data from RAM
data_pipe[DEMUX_PIPE_TOP*16+15:1*16] <= data_pipe[ (DEMUX_PIPE_TOP-1) *16+15:0*16]; // shift over the next 9 words in this 10 word, 16-bit wide pipe

data_out_0 <= data_pipe[MUX_0_POS*16+15:MUX_0_POS*16]; // ****** changed to 16 bit width
data_out_1 <= data_pipe[MUX_1_POS*16+15:MUX_1_POS*16];
data_out_2 <= data_pipe[MUX_2_POS*16+15:MUX_2_POS*16];
data_out_3 <= data_pipe[MUX_3_POS*16+15:MUX_3_POS*16];
data_out_4 <= data_pipe[MUX_4_POS*16+15:MUX_4_POS*16];

In gpu_dual_port_ram_INTEL:
Code: [Select]
output wire [15:0] data_out_a, // ****** changed to 16 bit data width

// ********************************************************************************
// * NEW SECTION to reverse byte order of read-only port if addressed LSB is 0
// ********************************************************************************

wire [15:0] ram_out_a;
assign data_out_a[15:8] = (addr_a[0] == 1'b0) ? ram_out_a[15:8] : ram_out_a[7:0];
assign data_out_a[7:0] = (addr_a[0] == 1'b0) ? ram_out_a[7:0]  : ram_out_a[15:8];

altsyncram altsyncram_component (
.address_a (addr_a[ADDR_SIZE - 1:1]), // ****** changed LSB from 0 to 1
.data_a (16'b0000000000000000), // ****** changed to 16 bit data width
.q_a (ram_out_a), // ****** changed from data_out_a to ram_out_a

altsyncram_component.numwords_a = NUM_WORDS / 2,   // ****** changed to NUM_WORDS / 2
altsyncram_component.widthad_a = ADDR_SIZE - 1,  // ****** changed to ADDR_SIZE - 1
altsyncram_component.width_a = 16, // ****** changed from 8 to 16
altsyncram_component.init_file_layout = "PORT_B",

In bitplane_to_raster.v:
Code: [Select]
input wire [7:0] ram_byte_in, // ****** changed to 16 bit width

These are all the changes I made (other than the cmd bus ones) - I've reverted all these changes and the output is fine again.  Any chance you could share the changes you've made to get it to work?

Noooooooooo.  The x_in/x_out fixes the:
Code: [Select]
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( dly6_disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][2:0] ),
.x_in( dly5_disp_x ),
 Back to the proper:
.x_in( dly6_disp_x ),

This bug had nothing to do with the 'PIPE_DELAY', which had the proper value of '7'.

Yes, realised this later.   :palm:

Now, your garbage text, did you fix the 'addr[0]' so that the addr which selects the correct memory output byte is the same addr with the same byte we expect to receive from the altsyncram's memory output when the original address was fed in.

Fix as in register it? Err... no?  Would this code not work then, unless addr_a[0] is registered?

Code: [Select]
assign data_out_a[15:8] = (addr_a[0] == 1'b0) ? ram_out_a[15:8] : ram_out_a[7:0];
assign data_out_a[7:0] = (addr_a[0] == 1'b0) ? ram_out_a[7:0]  : ram_out_a[15:8];

(You still have other errors as even the green seems impossible.  I only re-wrote your code from the last version, and it correctly worked with the 16 bit memory and 16 bit mux and 32 bit aux ports and I got perfect blue text.)

The green isn't an error, it's where I'd changed the default HW_regs settings and forgot to change them back before posting the project.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 04:10:15 pm
Okay, at first glance I seem to have fixed the corrupt text.  :-/O Instead of using addr_a coming IN to the gpu_dual_port_ram_INTEL module, I switched it to the address going OUT (addr_out_a) - it's a clock behind, but it's a register so should stay valid long enough to lift the data from both bytes in the word... and it does.  :)

Obligatory pic:

[attach=1]

EDIT: Latest project files attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 05:23:01 pm
After the address generator, we will be modding the gpu_INTEL ram into a new wrapper module, running the the INTEL ram at 250MHz, making it's 2 ports into 4 ports at 125MHz.  And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port.  I hope you are up to the challenge.  (We would need 1GHz 8 bit static ram to replicate this, not counting the palette memory which would double that as we might do the same 15 ports there for true multiple degrees of translucency between all layers instead of between 2 layers, then just transparent color 0 / vs non-transparent.  Also in the lattice part, you will ran the ram at 500Mhz, in other words, you would need a 4GHz 8 bit static ram to replicate that display engine with it's 40 parallel read ports and 2x equivalent host_ ports.)

 :-\  I hope I'm up to the challenge, as well!  I might have to fold and ask for more breadcrumbs to get me through this more quickly, though.  Can't believe I've wasted a day today hunting for (and thankfully fixing) two silly bugs.  |O

And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port.

I'm going to need a bigger FPGA! :o  It'll maybe stretch to doubling the multiport_gpu_ram module with it's ~33 KB of RAM, but certainly won't manage three or more such modules.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 05:38:36 pm
Okay, at first glance I seem to have fixed the corrupt text.  :-/O Instead of using addr_a coming IN to the gpu_dual_port_ram_INTEL module, I switched it to the address going OUT (addr_out_a) - it's a clock behind, but it's a register so should stay valid long enough to lift the data from both bytes in the word... and it does.  :)

Obligatory pic:

(Attachment Link)

EDIT: Latest project files attached.
How did you come to the conclusion that the 'addr_out_a' is a clock behind the ram 'data_out_a'?
Does this image not represent the GPU_INTEL memory:
[attachimg=1]
Count the number of clocks from address in to data out by counting the number of D-flipflops in the attached image...
How many do you count?
How many D-flipflops has the 'addr_out_a' gone through since the 'addr_a' input?

It's important you understand what's going on here.  All these pipes I made, though they all might not be used, the address generator will feed some values through them, IE coordinates, new memory to point to, expecting a ram read/or/pixel and these values/settings to be parallel at the output for everything to work properly at the next stage.  Without this parallel infrastructure, you will have code like in the current OSD generator's old junk like this obsolete patch work:
Code: [Select]

// **********************************************************************************************
// *** These delay pipes registers are explained in the 'assign's above
// **********************************************************************************************
dly1_disp_x <= disp_x;
dly2_disp_x <= dly1_disp_x;
dly3_disp_x <= dly2_disp_x;
dly4_disp_x <= dly3_disp_x;
dly5_disp_x <= dly4_disp_x;
dly6_disp_x <= dly5_disp_x;
dly7_disp_x <= dly6_disp_x;
dly8_disp_x <= dly7_disp_x;

dly1_disp_y <= disp_y;
dly2_disp_y <= dly1_disp_y;
dly3_disp_y <= dly2_disp_y;
dly4_disp_y <= dly3_disp_y;

dly1_letter <= letter;
dly2_letter <= dly1_letter;
dly3_letter <= dly2_letter;
dly4_letter <= dly3_letter;

dly1_dena   <= dena;
dly2_dena   <= dly1_dena;
dly3_dena   <= dly2_dena;
dly4_dena   <= dly3_dena;
dly5_dena   <= dly4_dena;
dly6_dena   <= dly5_dena;

// **********************************************************************************************
osd_ena_out <= dly4_dena; // This is used to drive a graphics A/B switch which tells when the OSD graphics should be shown
// It needs to be delayed by the number of pixel clocks required for the above memories
pixel_ena <= dly4_dena;
Which is about to be all deleted.  But, if you have a mistake somewhere in the 'multiport_gpu_ram' and it's parallel pipe, when we feed it a continuous address with embedded in the auxiliary pipe x coordinates and start and stop pixel coordinates to be displayed in parallel with 3 to 12 other address generator on every addr_in_# channel, you will never be able to back track and find any error at all if 1 single thing is out with this code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 05:47:47 pm
How did you come to the conclusion that the 'addr_out_a' is a clock behind the ram 'data_out_a'?
Does this image not represent the GPU_INTEL memory:
(Attachment Link)
Count the number of clocks from address in to data out by counting the number of D-flipflops in the attached image...
How many do you count?
How many D-flipflops has the 'addr_out_a' gone through since the 'addr_a' input?

I actually meant that addr_out_a is one clock behind addr_a, not data_out_a.  It's actually two clocks behind:

Code: [Select]
rd_addr_pipe_a <= addr_a;
addr_out_a <= rd_addr_pipe_a;

That's what I was referring to, but in any case the reason for using it was that data_out_a was getting ahead of itself using addr_a, which wasn't holding the right data and corrupting the output, I guess.  :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 06:04:16 pm

And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port.

I'm going to need a bigger FPGA! :o  It'll maybe stretch to doubling the multiport_gpu_ram module with it's ~33 KB of RAM, but certainly won't manage three or more such modules.  :-\
I hate to burst your bubble, but, I just compiled you project for your Cyclone IV EP4CE6E22C8 after removing the bulk of the HV_triggers which would never reach the display directly.  You are only using 20% of your logic gates.

In your compilation report, under Fitter section, under resource section, under 'resource utilization by entity':
[attachimg=1]
It says that 82 logic cells are used, and we are using 50% of the module, so, 1 full module would be around 164 logic cells.  * by 3 = 492, - original 82 = 410, since we are not adding ram, the change means 410 new additional logic cells for 15 read ports.  So, your current design total of 1330 logic cells of 6272 will increase to 1740 or 6272 = 28% usage.  That's only an 8% increase of used logic cells.

You are clear for a 15 port, 25Mhz x 16 bit read ram, or a read rate of 750 megabytes a second not counting the additional speed of the host port's 125 megabytes a second plus the palettes read speed.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 06:10:31 pm
You are clear for a 15 port, 25Mhz x 16 bit read ram, or a read rate of 750 megabytes a second not counting the additional speed of the host port's 125 megabytes a second plus the palettes read speed.

Well colour me impressed, then.  ^-^ I thought you meant there'd be three RAM modules (each 16 KB).  ???

Ooh, latest project files attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 06:20:46 pm
You are clear for a 15 port, 25Mhz x 16 bit read ram, or a read rate of 750 megabytes a second not counting the additional speed of the host port's 125 megabytes a second plus the palettes read speed.

Well colour me impressed, then.  ^-^ I thought you meant there'd be three RAM modules (each 16 KB).  ???

Ooh, latest project files attached.
The first 3 ports are the text and bottom display windows.  The new 12 will be the 12 sprites, each again 1 window anywhere on the screen positioned by the HV_triggers, and any width and any height pointing anywhere in your bulk of GPU memory.
If you go to the 2 megabit lattice part, with it's 500MHz capable core ram, you will have room and cycle time for 30 read ports, leaving 27 sprites, or graphics windows overplayed on top of each other.

Now these window sprites can be larger than the display area too.  Any X&Y size from memory meaning a 27 layer parallax scrolling game scenery is possible in full color.  Talk about roasting the Amiga.

Each window layer can be at any resolution, any bitplane color depth, any zoom level, as long as they all share the same 256 color palette or, you set a layer to 65536 color mode where the palette will be bypassed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 06:37:10 pm
A little more perspective:
The Amiga could only do 4 bitplanes in highres.

Here, in high res, you have a maximum of 16 bit per pixel with 14 superimposed parallel layers.  That's a 224 bitplane display.  Double that on the lattice part.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 06:49:49 pm
The first 3 ports are the text and bottom display windows.  The new 12 will be the 12 sprites, each again 1 window anywhere on the screen positioned by the HV_triggers, and any width and any height pointing anywhere in your bulk of GPU memory.
If you go to the 2 megabit lattice part, with it's 500MHz capable core ram, you will have room and cycle time for 30 read ports, leaving 27 sprites, or graphics windows overplayed on top of each other.

Now these window sprites can be larger than the display area too.  Any X&Y size from memory meaning a 27 layer parallax scrolling game scenery is possible in full color.  Talk about roasting the Amiga.

Each window layer can be at any resolution, any bitplane color depth, any zoom level, as long as they all share the same 256 color palette or, you set a layer to 65536 color mode where the palette will be bypassed.

Aye carumba!  :o

So, the address generators are next?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 06:59:33 pm
Yes.

An address generator resets to a base HW_REGS reg stored memory address once every v-sync.
Every (Y size) H-syncs, a second HW_REGS is added to that address generator base defining the horizontal size of the bitmap to be displayed.
Another HW reg store a pixel X size counter and Y size counter defining the width and height of the active window.
Another 2 store the X&Y beginning point of the window already setup with the HV_triggers.
2 more X&Y period size counters define the width and height of the pixels. (call this an X&Y zoom, or scale)
Another HW reg stores the bitplane color mode, background color and enable/disable.

This above address generator is identical for all graphics / sprite layers.

For the text mode, another HW_Reg stores the base address and X&Y pixel size of the font to be passed through the read port ram a second time from it's first address generator.  Later in the Lattice part, with it's size, you may have the room for a text mode for every sprite layer making the Supernintendo's tile system look like a toy peanut.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 07:13:14 pm
An expansion patch to the bitplane to raster module:
Everywhere you have unused surplus pixel_out bits, ie:
---------------------------------
pixel_out[7:2] <= 6'b000000;
pixel_out[7:4] <= 4'b0000;
---------------------------------
Change it to:
---------------------------------
pixel_out[7:2] <= bg_color[7:2];
pixel_out[7:4] <= bg_color[7:4];
---------------------------------


You know what, just copy and paste the changes from here:
Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire pixel_in_ena,
input wire [3:0] pc_ena,
input wire [15:0] ram_byte_in, // ****** changed to 16 bit width
input wire [7:0] ram_byte_h,
input wire [7:0] bg_colour,
input wire [9:0] x_in,
input wire [2:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [2:0] colour_mode_out

);

// internal registers
//reg [7:0] colour_data;

// *****************************************************************************
// *                                                                           *
// *  PASS-THRUS                                                               *
// *                                                                           *
// *****************************************************************************

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

x_out <= x_in;
//colour_data <= ram_byte_in; // in two-byte mode, colour_data should follow the ram_data byte
colour_mode_out <= colour_mode_in;

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 =   2 colour mode - 8 pixels per byte in GPU RAM
// 001 =   4 colour mode - 4 pixels -----"------"------
// 010 =  16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output

if (~pixel_in_ena || colour_mode_in[2]) begin

// nothing to see here (disabled)
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;

end
else if (~two_byte_mode) begin // 8-bit mode

case (colour_mode_in)

2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= 4'b0000; // was: pixel_out[7:5] <= 3'b000;
pixel_out[3:0] <= bg_colour[7:4];

end
else begin

pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[3:0];

end

end

2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:2] <= bg_color[7:2];

case (x_in[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte_in[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte_in[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte_in[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte_in[1:0];

end
endcase

end

2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:4] <= bg_color[7:4];

if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end

2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode

pixel_out <= ram_byte_in[7:0];

end

endcase

end // 8-bit mode
else begin // 16-bit mode

case (colour_mode_in)

2'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= bg_color[7:4];
pixel_out[3:0] <= ram_byte_h[7:4];

end
else begin

pixel_out[7:4] <= bg_color[7:4];
pixel_out[3:0] <= ram_byte_h[3:0];

end

end
2'h3 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out <= ram_byte_in[7:0];
pixel_out_h <= ram_byte_h;

end

endcase

end // 16-bit mode

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule


So now, if you define a sprite with 4 or 16 color pixels, you may choose the upper palette bits of that sprite's layer by setting the matching upper bits of it's bg_color.  This way, each sprite can share or have it's own palette anywhere inside the 256 color palette as long as it isn't 256 color sprite where it obviously uses all 256 entries in the palette.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 07:23:25 pm
An address generator resets to a base HW_REGS reg stored memory address once every v-sync.
Every (Y size) H-syncs, a second HW_REGS is added to that address generator base defining the horizontal size of the bitmap to be displayed.
Another HW reg store a pixel X size counter and Y size counter defining the width and height of the active window.
Another 2 store the X&Y beginning point of the window already setup with the HV_triggers.
2 more X&Y period size counters define the width and height of the pixels. (call this an X&Y zoom, or scale)
Another HW reg stores the bitplane color mode, background color and enable/disable.

This above address generator is identical for all graphics / sprite layers.

Okay, having read that I'm thinking of moving the existing three HW registers (fore/background colour, two_byte_mode and colour_mode_in) from their current positions to 00, 01 and 02.  I can then just use the regs sequentially after that for the new features we're adding.  I feel it's more logical than them currently being sat in an island from 0A-0C, which was just an arbitrary address I plucked out of thin air.  Any issues with that?

For the text mode, another HW_Reg stores the base address and X&Y pixel size of the font to be passed through the read port ram a second time from it's first address generator.  Later in the Lattice part, with it's size, you may have the room for a text mode for every sprite layer making the Supernintendo's tile system look like a toy peanut.

Toy peanut. Love it.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 07:33:10 pm
Hang on, I'll lay out the address generator controls by byte tonight and we will decide the base for each address line generator since the HV_Triggers are separate of the line generators  and the first text mode and controls reside inside the 32 reset defaults.  This way when the 'reset' is hit, a default functional display will be produced.

With your current layout, before switching you core GPU INTEL ram from 125MHz to 250MHz, you will only have access to 1 text display and 3 sprites, 1 of which is the bottom background graphics display while the other 2 sit on top of everything else including the text.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 07:40:18 pm
An expansion patch to the bitplane to raster module...

...So now, if you define a sprite with 4 or 16 color pixels, you may choose the upper palette bits of that sprite's layer by setting the matching upper bits of it's bg_color.  This way, each sprite can share or have it's own palette anywhere inside the 256 color palette as long as it isn't 256 color sprite where it obviously uses all 256 entries in the palette.

Excellent, thanks.  :-+

I'm especially intrigued to find out how the sprites will move - I guess this will be driven by the Z80 setting an X,Y position in the HW regs every frame?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 07:59:30 pm
Yes, you need to set the HV trig as an X&Y, I'm still deciding if you will need to set the right side and bottom, or will I have additional X&Y counter...
To scroll the image off the left hand side of the screen or scroll it above the top of the display, your going to need to adjust 2 more bytes to reposition the raster's memory base address and shrink the visible width.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2019, 08:41:45 pm
After the address generator, we will be modding the gpu_INTEL ram into a new wrapper module, running the the INTEL ram at 250MHz, making it's 2 ports into 4 ports at 125MHz.  And, we will be multiplying the 'multiport_gpu_ram' module 3 fold making a 15 read address ports for 15 parallel pixel reads, plus the 1 host_ port.  I hope you are up to the challenge.  (We would need 1GHz 8 bit static ram to replicate this, not counting the palette memory which would double that as we might do the same 15 ports there for true multiple degrees of translucency between all layers instead of between 2 layers, then just transparent color 0 / vs non-transparent.  Also in the lattice part, you will ran the ram at 500Mhz, in other words, you would need a 4GHz 8 bit static ram to replicate that display engine with it's 40 parallel read ports and 2x equivalent host_ ports.)

 :-\  I hope I'm up to the challenge, as well!  I might have to fold and ask for more breadcrumbs to get me through this more quickly, though.  Can't believe I've wasted a day today hunting for (and thankfully fixing) two silly bugs.  |O
Remember this one: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2782402/#msg2782402 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2782402/#msg2782402)
Just scroll down the message and look for that big red '1' and you will see what took me hours to find...
In the new year, I wont have the same time as now, your gonna have to get used to finding bugs all on your own...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2019, 11:21:00 pm
:-\  I hope I'm up to the challenge, as well!  I might have to fold and ask for more breadcrumbs to get me through this more quickly, though.  Can't believe I've wasted a day today hunting for (and thankfully fixing) two silly bugs.  |O
Remember this one: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2782402/#msg2782402 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2782402/#msg2782402)
Just scroll down the message and look for that big red '1' and you will see what took me hours to find...
In the new year, I wont have the same time as now, your gonna have to get used to finding bugs all on your own...

I know, and I really do appreciate the time and effort you've put in to help me.  :)  I'm operating on the assumption that you won't be around after the new year to help at all, so I'm hoping to get as much done before Christmas as possible; stupid mistakes allowing, of course.  :-[
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 04:26:53 am
Next is the address generator/graphics instruction engine.

Here are the targeted controls/capable features:  (We want to make 1 identical algorithm which will be used 4 times.)

1) Enable/disable.  Requires 1 bit.

2) The base/beginning of a memory address which contains either the screen text data, font data, graphics data and sprite data.  (This eats 20 bits since we can address 1 megabyte for this address)

3) Vertical memory increment size.  When beginning a new line, this is the amount added every time to the base address.  (16 bits is fair, maximum 64kb wide picture.)

4) Pixel type.  1bit=8 pixels wide per byte 2 colors per pixel,
                       2bit=4 pixels per byte 4 colors per pixel,
                       4bit=2 pixels per byte 16 colors,
                       8bit=1 pixel per byte, 256 colors,
                      16bit=2 bytes per pixel, 65k true-color
          = 5 settings possible meaning requires 3 bits for this setting.

5)  X scale.  Counts the number of pixels wide each bitmap image pixel will occupy.  1 through 16 (4 bits)

6)  Y scale.  Counts the number of lines each bitmap image line  will occupy.  1 through 16 (4 bits)

7) Sub-pixel starting X&Y coordinates.  This setting vertically & horizontally shifts the image up and to the left by single pixels in text mode and 4/2/1 bit color modes.  IE, smooth scrolling of text horizontally by up to 7/8th of 1 character, then you can change the base memory address by 1 character and reset this setting back to 0 allowing you to move the text pixel by pixel horizontally and vertically. The shift 16 pixels x by 16 pixels y , or 8 bits total.

8 )  Special control for font size.  8x8 pixel bitmap to 16x16 bitmap.  4 bit control.

9)  Total number of video lines to render before loading a new set of the above controls.  This will allow you to switch video modes mid screen, EG: have a window of 40 column text for half the screen, then switch to 80 column text for the bottom half.

Have I missed anything.  The total here is around 14 control bytes, or, we will reserve 16 bytes per address generator and call it safe.

Extra Note: The horizontal and vertical windows and enables for the 16 sprites will be stored separately.  10bit X 10 bit Y.
Palettes also have a dedicated separate set of registers.  A programmable interrupt generator based on a selected line of video will also be added for smooth animation apps.

Ok, here we go:

     We will have a master H & V trigger for the horizontal reset and vertical reset.  This will be parameter assigned inside the address_generator-s, bitplane_to_raster-s, and palette_mixer-s.

     All register controls should be latched on the parameter selected ' H && V ' triggers so that the Z80 can make changes during the entire display time, however, the entire bulk of graphics / coordinate settings will be updated/refreshed once every V-sync.  The down side (except for the H&V trigger which we will fix later on) is that you cannot take 1 sprite and manipulate it's settings in real time during the middle of the screen refresh to trick construct multiple additional sprites.  However, the pros are a ton of CPU cycles may be used to construct an animated display during the entire display time while the next V-sync, all screen geometries will be refreshed all at once.  Also, with 12 sprites, and a jump to 24 sprites with the Lattice FPGA part, each one of the 24 being able to be larger than 640x480, like 65536x65536 viewport window, if you complain about this real-time limitation, I'll be on a flight over seas to murder you...  ;)

Each line generator will also have a parameter to identify which 1 set of H&V trigger will be used to position their top-left X&Y coordinate location and a second H&V trigger to define the bottom right screen coordinates of the image.

Next, #1 & #4.  We will squeeze these 2 together with a few other options.  This HW_REG will hold the control for the bitplane_to_raster module.  All 8 bits will be sent into that module and define the video mode.  Off, 1 bit color, 2 bit color, 4 bit color, 8 bit color, 16 bit color, special 2 byte text color font.  Color Palette type (either ARGB 4444, RGB 565, or 16 bit 565 thru, or mixed 16bit 656 thru with last 256 colors assigned through the palette).  (5 or 6 bits consumed, 2 spare bits for future features)

Next, bg_color and fg_color.  These are 2 HW_REG byte values used for the 1 bit color mode and for where within the palette the remaining missing upper bits of the 16 and 4 color modes will be placed.

Next, #2  The base/beginning of a memory address which contains either the screen text data, font data, graphics data and sprite data. 3 HW_REG bytes.
Next, #3  The X size/width in bytes of the image in memory being displayed.  2 HW_REG bytes.

next, X&Y scale, and sub_pixel X&Y start.  1 byte each for a total of 4 bytes.

We are at 16 bytes to control every feature of the window line generator.  15 address generators, + 16 bytes for a few global controls means 256 bytes for the HE_REGS.  You will need to double this setting on the Lattice FPGA as it will have 30 address generators.  More if you want to add an audio system.

When a line generator is in the special ascii text mode, it will have the same controls, but with 1 or 2 changes to define the font's X&Y size attributes plus 1 input in the module will be used to receive an incoming ASCII character from the multiport_ram output from a previous line generator to realtime point to a font's position to construct a bitmap.  This means you need 2 address generators with 2 ram ports to construct a text/character tile based display on the screen, though the second line generator is mostly dead and just passes through a bunch of wired signals.

For our development path, we will start with a simple line generator which will open a 256 color display window on the screen, with adjustable X&Y coordinates and X&Y size.  We will use port 3 on our multiport ram and add bitplane to raster module to receive the output, then feed the palette mixer module 565 input.

We wont touch the text yet.  Need to first get the basics working.

More to come after some sleep...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 12:07:00 pm
Step #1, minor touch up to the bitplane_to_raster.v module:

     Add HW_REGS input to the bitplane_to_raster module.
     Add a parameter which defines the base of the 3 control bytes:
             The video mode byte, the bg_color byte and fg_color byte.
     Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte.  Like 16bit color mode, pixel color bits, ect.  (document these bit switches)

     Add a new input wire named 'enable_in'.  When low, the pixel outputs will go to '0', identical to having the video mode set to 'off'.

     Add a new output reg called 'enable_out'.  Goes low when 'off' or 'enable_in' is low.  Goes high when 'enable_in' is high and any selected valid video mode.

Start documenting the new controls.  Also note that each display layer will have it's own bitplane_to_raster.v, so, this means 5 of them in you current design going up to 15 once we double the clock of your core memory, each with their own controls.

First part of the address generator, window coordinates, H&V size and H&V scale coming this afternoon.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 12:59:16 pm
Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte.  Like 16bit color mode, pixel color bits, ect.  (document these bit switches)

And now you know why within my RS232_Debugger HEX editor, you may click on the bits in the Binary view of the memory byte you are editing, and that bit will toggle allowing you to switch on and off multiple features controlled by different bits in a single byte.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 01:34:59 pm
Step #1, minor touch up to the bitplane_to_raster.v module:

     Add HW_REGS input to the bitplane_to_raster module.
     Add a parameter which defines the base of the 3 control bytes:
             The video mode byte, the bg_color byte and fg_color byte.
     Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte.  Like 16bit color mode, pixel color bits, ect.  (document these bit switches)

     Add a new input wire named 'enable_in'.  When low, the pixel outputs will go to '0', identical to having the video mode set to 'off'.

     Add a new output reg called 'enable_out'.  Goes low when 'off' or 'enable_in' is low.  Goes high when 'enable_in' is high and any selected valid video mode.

Start documenting the new controls.  Also note that each display layer will have it's own bitplane_to_raster.v, so, this means 5 of them in you current design going up to 15 once we double the clock of your core memory, each with their own controls.

First part of the address generator, window coordinates, H&V size and H&V scale coming this afternoon.

All done.  Have hardwired enable_in HIGH in vid_osd_generator for testing.

I've removed colour_mode_in and colour_mode_out from the bitplane_to_raster module as they're not used now that the video_mode byte has taken over setting the mode.  All working as expected so far.

bitplane_to_raster.v:
Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire pixel_in_ena,
input wire two_byte_mode,
input wire enable_in,
input wire [3:0]  pc_ena,
input wire [15:0] ram_byte_in,
input wire [7:0]  ram_byte_h,
input wire [7:0]  bg_colour,
input wire [9:0]  x_in,
//input wire [2:0]  colour_mode_in,
input wire [7:0]  GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],

// outputs
output reg enable_out,
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out
//output reg [2:0] colour_mode_out

);

parameter CTRL_BYTE_BASE = 8'h0; // defines the base address of the 3 control bytes (video_mode, bg_colour, fg_colour) in the HW_REGS

// *****************************************************************************
// video_mode byte - CTRL_BYTE_BASE + 0
//
// This HW_REG defines the video mode:
//
// 0000 - Off
// 0001 - 1 bit color
// 0010 - 2 bit color
// 0011 - 4 bit color
// 0100 - 8 bit color
// 0101 - 16 bit color
// 0110 - Special 2-byte text colour mode
// 0111 - ARGB4444
// 1000 - RGB565
// 1001 - 16 bit 565 thru
// 1010 - Mixed 16-bit 656 thru with last 256 colors assigned through the palette
// *****************************************************************************

parameter HW_REGS_SIZE = 8; // default size for hardware register bus - set by HW_REGS parameter in design view

// *****************************************************************************
// *                                                                           *
// *  PASS-THRUS                                                               *
// *                                                                           *
// *****************************************************************************

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

x_out <= x_in;
//colour_mode_out <= colour_mode_in;

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 =   2 colour mode - 8 pixels per byte in GPU RAM
// 001 =   4 colour mode - 4 pixels -----"------"------
// 010 =  16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output
enable_out <= enable_in;

if (~pixel_in_ena || ~enable_in) begin

// disable output as not in display area or enable_in is LOW
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;

end
else begin

case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg

2'h0 : begin // off
// disable output as turned off
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
enable_out <= 1'b0; // set enable_out LOW
end

2'h1 : begin // 1-bit (2 colour) - 8 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[7:4];

end
else begin

pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[3:0];

end

end

2'h2 : begin // 2-bit (4 colour) - 4 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out[7:2] <= bg_colour[7:2];

case (x_in[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte_in[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte_in[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte_in[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte_in[1:0];

end
endcase

end

2'h3 : begin // 4-bit (16 colour) - 2 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out[7:4] <= bg_colour[7:4];

if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end

2'h4 : begin // 8-bit (256 colour) - 1 pixel per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out <= ram_byte_in[7:0];

end

2'h5 : begin // 16-bit (true colour)

mode_16bit <= 1'b1; // set mode_16bit output to 16-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out <= ram_byte_in[7:0];
pixel_out_h <= ram_byte_h;

end

2'h6 : begin // special colour text mode

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[7:4];

end
else begin

pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[3:0];

end

end

endcase

end

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 01:37:36 pm
Obviously, the case doesn't have any selects for the palette modes (0111-1010) yet - I assume that's correct and have left them out for the moment.

And now you know why within my RS232_Debugger HEX editor, you may click on the bits in the Binary view of the memory byte you are editing, and that bit will toggle allowing you to switch on and off multiple features controlled by different bits in a single byte.

It's almost as if you're working to some kind of plan...  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 01:54:26 pm
Step #1, minor touch up to the bitplane_to_raster.v module:

     Add HW_REGS input to the bitplane_to_raster module.
     Add a parameter which defines the base of the 3 control bytes:
             The video mode byte, the bg_color byte and fg_color byte.
     Change you 'case' statement to accommodate the the new byte bitplane mode selection from the above post which controls everything in 1 byte.  Like 16bit color mode, pixel color bits, ect.  (document these bit switches)

     Add a new input wire named 'enable_in'.  When low, the pixel outputs will go to '0', identical to having the video mode set to 'off'.

     Add a new output reg called 'enable_out'.  Goes low when 'off' or 'enable_in' is low.  Goes high when 'enable_in' is high and any selected valid video mode.

Start documenting the new controls.  Also note that each display layer will have it's own bitplane_to_raster.v, so, this means 5 of them in you current design going up to 15 once we double the clock of your core memory, each with their own controls.

First part of the address generator, window coordinates, H&V size and H&V scale coming this afternoon.

All done.  Have hardwired enable_in HIGH in vid_osd_generator for testing.

I've removed colour_mode_in and colour_mode_out from the bitplane_to_raster module as they're not used now that the video_mode byte has taken over setting the mode.  All working as expected so far.

bitplane_to_raster.v:
Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire pixel_in_ena,
input wire two_byte_mode,
input wire enable_in,
input wire [3:0]  pc_ena,
input wire [15:0] ram_byte_in,
input wire [7:0]  ram_byte_h,
input wire [7:0]  bg_colour,
input wire [9:0]  x_in,
//input wire [2:0]  colour_mode_in,
input wire [7:0]  GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],

// outputs
output reg enable_out,
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out
//output reg [2:0] colour_mode_out

);

parameter CTRL_BYTE_BASE = 8'h0; // defines the base address of the 3 control bytes (video_mode, bg_colour, fg_colour) in the HW_REGS

// *****************************************************************************
// video_mode byte - CTRL_BYTE_BASE + 0
//
// This HW_REG defines the video mode:
//
// 0000 - Off
// 0001 - 1 bit color
// 0010 - 2 bit color
// 0011 - 4 bit color
// 0100 - 8 bit color
// 0101 - 16 bit color
// 0110 - Special 2-byte text colour mode
// 0111 - ARGB4444
// 1000 - RGB565
// 1001 - 16 bit 565 thru
// 1010 - Mixed 16-bit 656 thru with last 256 colors assigned through the palette
// *****************************************************************************

parameter HW_REGS_SIZE = 8; // default size for hardware register bus - set by HW_REGS parameter in design view

// *****************************************************************************
// *                                                                           *
// *  PASS-THRUS                                                               *
// *                                                                           *
// *****************************************************************************

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

x_out <= x_in;
//colour_mode_out <= colour_mode_in;

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 =   2 colour mode - 8 pixels per byte in GPU RAM
// 001 =   4 colour mode - 4 pixels -----"------"------
// 010 =  16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output
enable_out <= enable_in;

if (~pixel_in_ena || ~enable_in) begin

// disable output as not in display area or enable_in is LOW
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;

end
else begin

case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg

2'h0 : begin // off
// disable output as turned off
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;
enable_out <= 1'b0; // set enable_out LOW
end

2'h1 : begin // 1-bit (2 colour) - 8 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[7:4];

end
else begin

pixel_out[7:4] <= 4'b0000;
pixel_out[3:0] <= bg_colour[3:0];

end

end

2'h2 : begin // 2-bit (4 colour) - 4 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out[7:2] <= bg_colour[7:2];

case (x_in[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte_in[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte_in[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte_in[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte_in[1:0];

end
endcase

end

2'h3 : begin // 4-bit (16 colour) - 2 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out[7:4] <= bg_colour[7:4];

if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end

2'h4 : begin // 8-bit (256 colour) - 1 pixel per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out <= ram_byte_in[7:0];

end

2'h5 : begin // 16-bit (true colour)

mode_16bit <= 1'b1; // set mode_16bit output to 16-bit mode
enable_out <= 1'b1; // set enable_out HIGH

pixel_out <= ram_byte_in[7:0];
pixel_out_h <= ram_byte_h;

end

2'h6 : begin // special colour text mode

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[7:4];

end
else begin

pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= ram_byte_h[3:0];

end

end

endcase

end

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule


Dont forget to remove the bg_color input and make a bg_color and fg_color wires which are assigned to the adjacent HW_Register for the control mode.  Also, for now, make the default base address 16 decimal as we don't want to interfere with the first HV_Triggers.

Also, we never got into this, but, are you using little or big endian for your data in the Z80?  I don't know how the Z80 handles 16bit and 32bit math.  We may want to get this fixed now...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 02:04:58 pm
Also, we never got into this, but, are you using little or big endian for your data in the Z80?  I don't know how the Z80 handles 16bit and 32bit math.  We may want to get this fixed now...

Little-endian.  But it's what you do with it that counts.  :-DD

EDIT:  In terms of 16-bit and 32-bit math, it doesn't really do a lot - it is capable of doing limited 16-bit math with the instruction set, but mostly it's up to the user to write routines that do anything more complicated than addition or subtraction of 16-bit numbers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 02:22:10 pm
Dont forget to remove the bg_color input and make a bg_color and fg_color wires which are assigned to the adjacent HW_Register for the control mode.  Also, for now, make the default base address 16 decimal as we don't want to interfere with the first HV_Triggers.

Done - although fg_colour isn't set up in the case yet, so I can only change the background colour.  Foreground is black, so I guess I need to replace all the pixel_out[7:4] assignments from 4'b0000 to fg_colour?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 04:36:33 pm
Fixed foreground (font) colour in 1-bit mode:

Code: [Select]
2'h1 : begin // 1-bit (2 colour) - 8 pixels per byte

mode_16bit <= 1'b0; // set mode_16bit output to 8-bit mode
enable_out <= 1'b1; // set enable_out HIGH

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out <= fg_colour;

end
else begin

pixel_out <= bg_colour;

end

end

I figured that's how you planned on it working in 2-colour mode - there's either going to be the foreground or background colour, which the above case caters for.  I've removed the old byte-splitting and am just assigning the entire colour byte to the pixel output now, so it's 2-colour mode, from a palette of 256 colours.  Hope that's okay?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 05:08:35 pm
Also, we never got into this, but, are you using little or big endian for your data in the Z80?  I don't know how the Z80 handles 16bit and 32bit math.  We may want to get this fixed now...

Little-endian.  But it's what you do with it that counts.  :-DD

EDIT:  In terms of 16-bit and 32-bit math, it doesn't really do a lot - it is capable of doing limited 16-bit math with the instruction set, but mostly it's up to the user to write routines that do anything more complicated than addition or subtraction of 16-bit numbers.
As I'm sure you know, this is important as it defines when you write or copy all these settings, right now, the lower memory address holds the MSB of a 16 bit or 32 bit number.  As you increase the memory address, you head toward the LSB.  So, I assume we are keeping this setup?

IE, you wont be using any compilers/interpreters which store 16bit ints backwards making this graphics card incompatible?

ANY other viewers with Z80 experience have any comments?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 06:43:41 pm
As I'm sure you know, this is important as it defines when you write or copy all these settings, right now, the lower memory address holds the MSB of a 16 bit or 32 bit number.  As you increase the memory address, you head toward the LSB.  So, I assume we are keeping this setup?

IE, you wont be using any compilers/interpreters which store 16bit ints backwards making this graphics card incompatible?

Hmm..  ???  This could be a bit of an issue if the conversion for little-endian to big-endian is done by the Z80 - it'll add processing overhead to any interactions with the GPU.

EDIT: Of course my suggestion to convert in the z80_bridge wouldn't work, as only 1 byte is written at a time by the Z80 so it would be impossible to work out if a 16-bit word is being written and thus needed to be reversed...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 06:56:18 pm
As I'm sure you know, this is important as it defines when you write or copy all these settings, right now, the lower memory address holds the MSB of a 16 bit or 32 bit number.  As you increase the memory address, you head toward the LSB.  So, I assume we are keeping this setup?

IE, you wont be using any compilers/interpreters which store 16bit ints backwards making this graphics card incompatible?

Hmm..  ???  This could be a bit of an issue if the conversion for little-endian to big-endian is done by the Z80 - it'll add processing overhead to any interactions with the GPU.

EDIT: Of course my suggestion to convert in the z80_bridge wouldn't work, as only 1 byte is written at a time by the Z80 so it would be impossible to work out if a 16-bit word is being written and thus needed to be reversed...
It's just 1 more thing I need to also consider.  What we might do is make an Invert feature on the LSB bit of the HW_Regs address input and only worry about the 16 bit ints.  Only the base address setting in the address generator is 24 bit and we can do the same invert with the palette memory reads easily enough.  As for the 16bit color raster graphics, we can use a spare bit in the video mode setting to swap the byte_in and byte_in_h.  This would be near all control register software select able, however, any 8 bit control settings will be swapped with their adjacent control settings.

Note that all 16 bit data, whether big or little endian will need to be 16 bit word aligned, as it is currently setup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 08:39:32 pm
This would be near all control register software select able, however, any 8 bit control settings will be swapped with their adjacent control settings.

So that would just require a little adjustment of the documentation - instead of video_mode being at HW_REGS[16 + 0], it would be at HW_REGS[16 + 1]?  Ditto for each pair of bytes in memory?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 08:42:16 pm
This would be near all control register software select able, however, any 8 bit control settings will be swapped with their adjacent control settings.

So that would just require a little adjustment of the documentation - instead of video_mode being at HW_REGS[16 + 0], it would be at HW_REGS[16 + 1]?  Ditto for each pair of bytes in memory?
Nope, if we are going to do it, it needs to be done right.  Otherwise, all your HW_Regs would begin on an odd address.  No future compatibility with a 16 bit processor as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 09:06:30 pm
Nope, if we are going to do it, it needs to be done right.  Otherwise, all your HW_Regs would begin on an odd address.  No future compatibility with a 16 bit processor as well.

Future compatibility is important too - no telling when I might get the urge to make a computer based on one of the 68010s I have in a box somewhere...  ???

Okay, so how hard is it going to be to do it right?  It affects any memory in the GPU (including the hardware registers) that the host system can access for a 16-bit value, but only when it accesses that memory using one of the (few) 16-bit opcodes - but they're useful for the kind of work I'd be doing here with graphics; lots of copying and moving data.  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 09:46:25 pm
Ok, the address generator's IOs.

Code: [Select]
1) inputs:
clk
pc_ena[]==0
all HW_regs
all HV_triggers
cmd_in[31:0]

2) outputs: (use all wires as we will embed the connected registers inside the module)
read_addr[19:0]
cmd_out[31:0]
bp_2_rast_cmd[23:0]

3) parameters:
HW_REG_BASE = #
H_RESET_TRIG = #
H_POS_TRIG    = #

localparam
V_RESET_TRIG = H_RESET_TRIG + 1
V_POS_TRIG    = H_POS_TRIG + 1
BP2RAST_cmd = HW_REG_BASE + 0   // transfers the video mode setting to the new bitplane_2_raster module
BP2RAST_bgc  = HW_REG_BASE + 1  // transfers the bg_color setting to the new bitplane_2_raster module
BP2RAST_fgc   = HW_REG_BASE + 2  // transfers the fg_color setting to the new bitplane_2_raster module
RST_ADDR_H  = HW_REG_BASE +      // MSB bits of 24 bit base read address
RST_ADDR_M  = HW_REG_BASE +      // MID bits of 24 bit base read address
RST_ADDR_L  = HW_REG_BASE +       // LSB bits of 24 bit base read address
YINC_ADDR_H = HW_REG_BASE +      // MSB bits of 16 bit Y-Line increment for read address
YINC_ADDR_L = HW_REG_BASE +      // LSB bits of 16 bit Y-Line increment for read address
X_SIZE_H = HW_REG_BASE +      // MSB bits of 16 bit display width screen pixels
X_SIZE_L = HW_REG_BASE +      // LSB bits of 16 bit display width screen pixels
Y_SIZE_H = HW_REG_BASE +      // MSB bits of 16 bit display height screen y lines
Y_SIZE_L = HW_REG_BASE +      // LSB bits of 16 bit display height screen y lines
X_SCALE  = HW_REG_BASE +      // Compound of two 4 bit words.  upper 4 bits controls the X increment every period, lower 4 bits is a pixel period counter to define the number of pixels until the upper 4 bits are added to the address-pointer.
Y_SCALE  = HW_REG_BASE +      // Compound of two 4 bit words.  upper 4 bits reserved for text tile mode Y size while the lower lower 4 bits is a line period counter to define the number of lines until YINC_ADDR is added to the address-pointer
X_START_SUB  = HW_REG_BASE +      //  An 8 bit word which defines an odd pixel start position within the period counter and X position within a bitplane's X coordinate position
Y_START_SUB  = HW_REG_BASE +      // An 8 bit word which defines and odd line start within within the period counter and Y coordinates inside a font.

Damn, we are at 20 control bytes per window, not 16...
This means 15 windows = 300 register control bytes.
We will stick with this for now as we only have 5 windows to worry about.

You will also need to take into account we are using other HV_Triggers, so assign you byte offseta around everything else.

Also, copy the current 'bitplane_to_raster' into a 'bitplane_to_raster_v2' as we will change the IO and depricate the old one soon.  In the new 'bitplane_to_raster_v2':

change '   .ram_byte_in' into 16 bit and get rid of '   .ram_byte_in_h'.

get rid of :

   .bg_colour( GPU_HW_Control_regs[10] ),
   .x_in( dly6_disp_x ),
   .colour_mode_in( GPU_HW_Control_regs[12][2:0] ),
   .two_byte_mode( GPU_HW_Control_regs[11][0] ),

and make a inputs:
       .bp_2_rast_cmd[23:0]
       .cmd_in[31:0]

assignments:
assign colour_mode_in[7:0] = bp_2_rast_cmd[7:0]
assign bg_colour[7:0] =  bp_2_rast_cmd[15:8]
assign fg_colour[7:0] =  bp_2_rast_cmd[23:16]
assign window_enable = cmd_in[7]                      // used to be "pixel_in_ena"
assign x_in[4:0]         = cmd_in[4:0]
assign two_byte_mode = colour_mode_in[6]


More to come (window counter and scale in address generator)....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 09:47:22 pm
Nope, if we are going to do it, it needs to be done right.  Otherwise, all your HW_Regs would begin on an odd address.  No future compatibility with a 16 bit processor as well.

Future compatibility is important too - no telling when I might get the urge to make a computer based on one of the 68010s I have in a box somewhere...  ???

Okay, so how hard is it going to be to do it right?  It affects any memory in the GPU (including the hardware registers) that the host system can access for a 16-bit value, but only when it accesses that memory using one of the (few) 16-bit opcodes - but they're useful for the kind of work I'd be doing here with graphics; lots of copying and moving data.  |O
Don't worry, it will be a parameter thing, also with the Lattice part, you may embed a full 125MHz 68020 + FPU & add external DDR ram for main system memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 10:43:34 pm
Ok, the address generator's IOs.
...
Damn, we are at 20 control bytes per window, not 16...
This means 15 windows = 300 register control bytes.
We will stick with this for now as we only have 5 windows to worry about.

Going to need a bigger FPGA!  The Lattice one is really looking like the best option - shame there's not a cheap(ish) dev board for it.

You will also need to take into account we are using other HV_Triggers, so assign you byte offseta around everything else.

Question regarding this line:  Do you mean that because there's more than one MAGGIE, their offsets will need to take every other MAGGIE's HV_Triggers into account so they don't end up using the same ones?  I feel I'm getting confused between HV_triggers and HW_regs.  (It is late here though).

Also, copy the current 'bitplane_to_raster' into a 'bitplane_to_raster_v2' as we will change the IO and depricate the old one soon.  In the new 'bitplane_to_raster_v2':

change '   .ram_byte_in' into 16 bit and get rid of '   .ram_byte_in_h'.

get rid of :

   .bg_colour( GPU_HW_Control_regs[10] ),
   .x_in( dly6_disp_x ),
   .colour_mode_in( GPU_HW_Control_regs[12][2:0] ),
   .two_byte_mode( GPU_HW_Control_regs[11][0] ),

and make a inputs:
       .bp_2_rast_cmd[23:0]
       .cmd_in[31:0]

assignments:
assign colour_mode_in[7:0] = bp_2_rast_cmd[7:0]
assign bg_colour[7:0] =  bp_2_rast_cmd[15:8]
assign fg_colour[7:0] =  bp_2_rast_cmd[23:16]
assign window_enable = cmd_in[7]                      // used to be "pixel_in_ena"
assign x_in[4:0]         = cmd_in[4:0]
assign two_byte_mode = colour_mode_in[6]


More to come (window counter and scale in address generator)....

Apart from making the new inputs and assigns, most of those changes I'd already made, so that's good.  What's going to replace x_in, though?  I should also get rid of pixel_in_ena and pixel_out_ena as well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2019, 10:48:32 pm
Future compatibility is important too - no telling when I might get the urge to make a computer based on one of the 68010s I have in a box somewhere...  ???

Okay, so how hard is it going to be to do it right?  It affects any memory in the GPU (including the hardware registers) that the host system can access for a 16-bit value, but only when it accesses that memory using one of the (few) 16-bit opcodes - but they're useful for the kind of work I'd be doing here with graphics; lots of copying and moving data.  |O
Don't worry, it will be a parameter thing, also with the Lattice part, you may embed a full 125MHz 68020 + FPU & add external DDR ram for main system memory.

Yeah, I could have done that with the Z80 as well - could have fit everything onto an FPGA, but that would have sidestepped the reason I started the project in the first place; to learn about electronics and how to build a computer 'the old fashioned way', soldering and designing PCBs etc.  Plus I didn't really know anything about FPGAs until about 2 months ago.  I must admit, it's really tempting to stick a whole load of stuff onto the FPGA, not just the GPU... I'm certainly keen to get a programmable sound generator on it, and it would be remiss of me not to include a PS/2 port for a keyboard and maybe even an SD card interface as well...  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 11:06:56 pm
Now, more on the address generator.

Code: [Select]
Make the following regs

ram_read_pointer_y[19:0]
ram_read_pointer_x[23:0]
run_x
run_y
period_x[4:0]
period_y[4:0]

make the following assignments (don't forget to declare wires for new next names)

assign bp_2_rast_cmd[23:0] = { hw_regs[BP2RAST_fgc] , hw_regs[BP2RAST_bgc] , hw_regs[BP2RAST_cmd] }


assign x_rst         = HV_trig[H_RESET_TRIG]
assign xy_rst        = HV_trig[V_RESET_TRIG] && x_rst

assign v_trig        = HV_trig[V_POS_TRIG]
assign h_trig        = HV_trig[H_POS_TRIG]
assign window_enable = (HV_trig[H_POS_TRIG] || run_x) && run_y
assign cmd_out[7]    = window_enable  // commands the pixel/by/pixel window enable for the bitplane_2_raster module
assign cmd_out[6]    = 1'b0        // for now, disables the 2 byte color mode.

assign reset_addr[23:0]  = { hw_regs[RST_ADDR_H] , hw_regs[RST_ADDR_M] , hw_regs[RST_ADDR_L]  }
assign inc_addr_y[15:0]  = { hw_regs[YINC_ADDR_H] , hw_regs[YINC_ADDR_L] }
assign inc_addr_x[3:0]   =   hw_regs[X_SCALE][7:4]

assign read_addr[19:0]   = ram_read_pointer_x[22:3]
assign cmd_out[2:0]      = ram_read_pointer_x[2:0]   // commands the sub pixel X position for the bitplane_2_raster module

assign period_x[3:0]     = hw_regs[X_SCALE][3:0]
assign period_y[3:0]     = hw_regs[Y_SCALE][3:0]

assign period_x_rst[3:0] = hw_regs[X_START_SUB][3:0]
assign period_y_rst[3:0] = hw_regs[Y_START_SUB][3:0]

assign x_size[11:0]      = { hw_regs[X_SIZE_H][3:0], hw_regs[X_SIZE_L][7:0] }
assign y_size[11:0]      = { hw_regs[Y_SIZE_H][3:0], hw_regs[Y_SIZE_L][7:0] }


You got a killer, though a feature or 2 not yet implemented, starting here...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 11:15:50 pm
You will also need to take into account we are using other HV_Triggers, so assign you byte offseta around everything else.

Question regarding this line:  Do you mean that because there's more than one MAGGIE, their offsets will need to take every other MAGGIE's HV_Triggers into account so they don't end up using the same ones?  I feel I'm getting confused between HV_triggers and HW_regs.  (It is late here though).

The raster HV_triggers are a set 48 of X&Y coordinates, 24 horizontal, 24 vertical, which pulse the 'HV_trigger' output wires when that pixel coordinate or line number has been reached on the screen.

Those 48 raster HV_trigger screen coordinate positions are stored in the bulk first 96 bytes of the GPU_HW_REGS.  This doesn't mean wan cannot use each reg for more than 1 thing, just that if it shares a HV_Trigger setting, writing 1 number there would alter one of the raster triggers as well as whatever else you are controlling.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 11:25:41 pm
Also, copy the current 'bitplane_to_raster' into a 'bitplane_to_raster_v2' as we will change the IO and depricate the old one soon.  In the new 'bitplane_to_raster_v2':

change '   .ram_byte_in' into 16 bit and get rid of '   .ram_byte_in_h'.

get rid of :

   .bg_colour( GPU_HW_Control_regs[10] ),
   .x_in( dly6_disp_x ),
   .colour_mode_in( GPU_HW_Control_regs[12][2:0] ),
   .two_byte_mode( GPU_HW_Control_regs[11][0] ),

and make a inputs:
       .bp_2_rast_cmd[23:0]
       .cmd_in[31:0]

assignments:
assign colour_mode_in[7:0] = bp_2_rast_cmd[7:0]
assign bg_colour[7:0] =  bp_2_rast_cmd[15:8]
assign fg_colour[7:0] =  bp_2_rast_cmd[23:16]
assign window_enable = cmd_in[7]                      // used to be "pixel_in_ena"
assign x_in[4:0]         = cmd_in[4:0]
assign two_byte_mode = colour_mode_in[6]


More to come (window counter and scale in address generator)....

Apart from making the new inputs and assigns, most of those changes I'd already made, so that's good.  What's going to replace x_in, though?  I should also get rid of pixel_in_ena and pixel_out_ena as well?

x_in is now an internal wire and it has been assigned to a set of bits on the new cmd_in input port:
'assign x_in[4:0]         = cmd_in[4:0]', read code.

pixel_in_ena has been renamed to window_enable and is has been assigned to a cmd_in bit.  Read code.

pixel_ena_out, the one change I would make is rename it to 'window_ena_out' and keep it's same function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2019, 11:40:06 pm
How the address generator is wired and works:

The address generator takes a clk, pc_ena, HW_Regs & HV_Trigger inputs, plus a spare 32 bit cmd_in which will be used later.

It outputs a 24 bit control 'bp_2_rast_cmd[23:0]'  for it's mated 'bitplane_2_raster' module.

It also outputs a 20 address to go to it's mated read GPU memory address read port _#.

It also outputs a 32 bit cmd_out port which feeds the matching GPU multiport memory cmd_in_# port.

The new 'bitplane_2_raster' command module's new cmd_in port receives the cmd_out_# from the GPU multiport ram module which contains real-time pixel drawing instructions, like sub-x coordinates and window enable/disable functions.  In the next iteration, this output will also feed the next address generator's cmd_in & ram read address allowing font/tile graphics memory pointers.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 09:22:35 am
Latest versions of the two new modules attached.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 01:20:43 pm
#2, bitplane_to_raster_v2.v :

   input wire enable_in,   *** no longer in use.

   input wire [7:0]  GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)],   *** no longer in use

   output reg enable_out,  *** no longer in use, replaced by window_ena_out,

   output reg [7:0] pixel_out,
   output reg [7:0] pixel_out_h,      **** merge these 2 into 1 single pixel_out[15:0]
                                                        **** correct all the appropriate code below.

   output reg [9:0] x_out     **** not used

parameter CTRL_BYTE_BASE = 16;    **** no longer used
parameter HW_REGS_SIZE   = 8;     **** no longer used

wire [7:0] bg_colour = GPU_HW_Control_regs[CTRL_BYTE_BASE + 1];
wire [7:0] fg_colour = GPU_HW_Control_regs[CTRL_BYTE_BASE + 2];
***** get rid of the "  = GPU_HW_Control_regs[CTRL_BYTE_BASE + #]; " in both cases

assign two_byte_mode         = cmd_in[6];  **** obsolete, get rid

      window_ena_out   <= window_enable;   // pass pixel_ena through to the output
              **** this output is also dependent if the video mode is on or off

      enable_out       <= enable_in;    **** no longer used

***** fix...
         case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg

----------------------
Next, the maggie.v...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 01:50:30 pm
next: maggie.v.

parameter H_RESET_TRIG   = 4;
parameter H_POS_TRIG   = 6;

add a parameter:
RAM_READ_CYCLES = 3;

add a reg:
h_trig_delay[7:0]

add an assign under bp_2_rast...:
assign text_mode_master = hw_regs[BP2RAST_cmd][7]

change :
assign window_enable         = run_x && run_y;

add just above
h_rst                =    text_mode_master ? h_trig_delay[0] : h_trig_delay[RAM_READ_CYCLES];  // When in text mode, push the window left by 'RAM_READ_CYCLES' as it takes a second memory read to get the font image

------
And all the way at the bottom:
------

always @(posedge clk) begin
   if (pc_ena_in[3:0] == 0) begin

      h_trig_delay[7:0] <= { h_trig_delay[6:0] ,  h_trig };

         if ( xy_rst ) begin // equivalent to a vertical sync/reset

         end else if (x_rst) begin   // equivalent to a horizontal sync/increment

         end else begin
            -------------------------------
            snap to it....
            -------------------------------
         end // ~x_rst

   end // if (pc_ena_in[3:0] == 0)
end //@(posedge clk)
endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 03:09:55 pm
      window_ena_out   <= window_enable;   // pass pixel_ena through to the output
              **** this output is also dependent if the video mode is on or off

***** fix...
         case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg

Both of the above changes require an input that specifies the video mode.  This was specified in the HW_REGS, but we're not using those now - so what do I use in their place?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 03:19:28 pm
Latest updates to bart and maggie.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 05:34:19 pm
      window_ena_out   <= window_enable;   // pass pixel_ena through to the output
              **** this output is also dependent if the video mode is on or off

***** fix...
         case (GPU_HW_Control_regs[CTRL_BYTE_BASE + 0]) // select case based on video_mode HW_reg

Both of the above changes require an input that specifies the video mode.  This was specified in the HW_REGS, but we're not using those now - so what do I use in their place?
Tadaaaaaa:
-----------------------------------------------------------------------
assign colour_mode_in[7:0]   = bp_2_rast_cmd[7:0];
------------------------------------------------------------------------

Line #63 > NO
window_ena_out   <= window_enable && (##);   // pass pixel_ena through to the output

Line #67 > Put this:
window_ena_out   <= 1'b0 ;

Line #78 > What?  Its window_ena_out.
enable_out    <= 1'b0;            // set enable_out LOW
Make it:
window_ena_out    <= 1'b0;            // set enable_out LOW

Line #84, 102, 134, 148, 157, 166> What?  Its window_ena_out.
enable_out <= 1'b1;   // set enable_out HIGH

Change these lines:
Code: [Select]
if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin
pixel_out[7:4] <= fg_colour[7:4];
pixel_out[3:0] <= font_color[7:4];

end
else begin

pixel_out[7:4] <= bg_colour[7:4];
pixel_out[3:0] <= font_color[3:0];

Add an assign and wire at the top of the code:
assign  font_color[7:0] = cmd_in[15:8]

************* ALSO,
What's with all the case 2'h# ?  2 bits?  When you are going up to over 5 or more cases?

Also, try to keep the pixels per byte in the mode numbers constant for the least significant bits.
IE:
00 = 8 pixels per byte
01 = 4 pixels per byte
10 = 2 pixels per byte
11 = 1 pixel per byte.

Use the next bit to the left for 16 bit modes on and off, also adhering to the first 2 bits pixels per byte.

Use the next bit over for video window mode ON/OFF.

We need the first 2 bottom bits to always reflect the 8pixels, 4pixels, 2 pixels, 1 pixels as 'MAGGIE' also uses these same 2 bits to know how fast to increment the memory read address.  IE, 1 inc per pixel, 1 inc every 2 pixels, 1 inc every 4 pixels, 1 inc every 8 pixels.  If you break this rule in the bitplane_2_raster module settings, the 2 modules will never sync pixel with memory.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 05:46:19 pm
Tadaaaaaa:
-----------------------------------------------------------------------
assign colour_mode_in[7:0]   = bp_2_rast_cmd[7:0];
------------------------------------------------------------------------

Line #63 > NO
window_ena_out   <= window_enable && (##);   // pass pixel_ena through to the output

Okay, the ## was there because I didn't know what signal to use.  Now I know it's colour_mode_in, would this work?

Code: [Select]
window_ena_out <= window_enable && colour_mode_in; // pass pixel_ena through to the output[/quote]

The idea being that if colour_mode_in is anything other than zero (off), and window_enable is high, then window_ena_out should be high?

************* ALSO,
What's with all the case 2'h# ?  2 bits?  When you are going up to over 5 or more cases?

Well spotted.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 05:58:58 pm
Tadaaaaaa:
-----------------------------------------------------------------------
assign colour_mode_in[7:0]   = bp_2_rast_cmd[7:0];
------------------------------------------------------------------------

Line #63 > NO
window_ena_out   <= window_enable && (##);   // pass pixel_ena through to the output

Okay, the ## was there because I didn't know what signal to use.  Now I know it's colour_mode_in, would this work?

Code: [Select]
window_ena_out <= window_enable && colour_mode_in; // pass pixel_ena through to the output[/quote]

The idea being that if colour_mode_in is anything other than zero (off), and window_enable is high, then window_ena_out should be high?

Well spotted.  :-+
Nope, do it as I said.

     The colour_mode_in is an 8 bit number, and if you read my text further, I want the bottom 2 bits of that variable to reflect specifically the number of pixels per byte.  This means having a color mode 0 = 1 byte to 8 pixels, usually text mode.

     The next bit#3 is the count of bytes per pixel, IE 16 bit color modes.  BUT YOU must keep the pattern of the 4 possible "pixels per byte".  The bit #4 will enable/disable the window completely.  We need a 'HARD' window disable setting since the layer may be active for font/tile mode, but the data coming through is the font's address data, not to be display.  That return data goes to the next line generator ad fed through to memory a second time then to that bitplane_2_raster module where that one will be enabled to generate an image.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 06:50:42 pm
This should help.  it is the internal full GPU MAGGIE wiring layout:

[attachimg=1]

Once the MAGGIE is complete and pair's with the previous MAGGIE for tile text support, there will be no other code inside the vid_osd_generator other than wires between the first 4 modules in the image.  All that obsolete code with delays and reg delays making the current ascii text function will be erased and forgotten.

The only 1 remaining delay code will be the HS,VS,HDE, & VDE which need compensation for the number of pixel cycles the pipe you see above takes to generate the first pixel.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 07:35:22 pm
Tadaaaaaa:
-----------------------------------------------------------------------
assign colour_mode_in[7:0]   = bp_2_rast_cmd[7:0];
------------------------------------------------------------------------

Line #63 > NO
window_ena_out   <= window_enable && (##);   // pass pixel_ena through to the output

Okay, the ## was there because I didn't know what signal to use.  Now I know it's colour_mode_in, would this work?

Code: [Select]
window_ena_out <= window_enable && colour_mode_in; // pass pixel_ena through to the output[/quote]

The idea being that if colour_mode_in is anything other than zero (off), and window_enable is high, then window_ena_out should be high?

Well spotted.  :-+
Nope, do it as I said.

     The colour_mode_in is an 8 bit number, and if you read my text further, I want the bottom 2 bits of that variable to reflect specifically the number of pixels per byte.  This means having a color mode 0 = 1 byte to 8 pixels, usually text mode.

I thought I was going mad, then I went back to look at your previous post and you'd edited in the extra information below!

Also, try to keep the pixels per byte in the mode numbers constant for the least significant bits.
IE:
00 = 8 pixels per byte
01 = 4 pixels per byte
10 = 2 pixels per byte
11 = 1 pixel per byte.

Use the next bit to the left for 16 bit modes on and off, also adhering to the first 2 bits pixels per byte.

Use the next bit over for video window mode ON/OFF.

We need the first 2 bottom bits to always reflect the 8pixels, 4pixels, 2 pixels, 1 pixels as 'MAGGIE' also uses these same 2 bits to know how fast to increment the memory read address.  IE, 1 inc per pixel, 1 inc every 2 pixels, 1 inc every 4 pixels, 1 inc every 8 pixels.  If you break this rule in the bitplane_2_raster module settings, the 2 modules will never sync pixel with memory.

And there I was thinking I was going mad as I was unaware of this info when I wrote my reply..   |O

I'm a tad confused though - if bit 2 determines 16-bit mode, what value of colour_mode_in equates to the special colour text mode?  It's marked as an 8-bit mode in the comments, but there aren't enough bits unless I move everything left one bit and use bit 3 to increase the number of modes to 8?

Currently I've got:

000 - 1-bit mode
001 - 2-bit mode
010 - 4-bit mode
011 - 8-bit mode
111 - 16-bit mode

I'm using bit 4 for on/off:

Code: [Select]
if (~window_enable | ~colour_mode_in[4]) begin
// disable output as turned off
pixel_out <= 16'b0000000000000000;
// disable output as not in display area
window_ena_out <= 1'b0;
end

So bit 3 is free, but you state that's for bytes per pixel?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 07:52:49 pm

Currently I've got:

000 - 1-bit mode
001 - 2-bit mode
010 - 4-bit mode
011 - 8-bit mode
111 - 16-bit mode

I'm using bit 4 for on/off:

Code: [Select]
if (~window_enable | ~colour_mode_in[4]) begin
// disable output as turned off
pixel_out <= 16'b0000000000000000;
// disable output as not in display area
window_ena_out <= 1'b0;
end

So bit 3 is free, but you state that's for bytes per pixel?
bit 3 is 16 bits per pixel, ie 111

Mode
111 - 16-bit mode

but you are missing
100 - 16 bit text mode, ie 1 byte = 8 pixels.  This one uses the upper part of the byte, [15:12] for the bottom bits of the foreground color and [11:8] for the background color while the upper 4 bit palette bits still use the fg_colour and bg_colour.

101 - 16 bit mode with a 2 bit color pixel, ie 2 bits per pixel, and the upper color bits come from the upper ram byte[15:10], IE used in fonts with 4 colors per pixel.  (heheheh - the byte[9:8] allow addressing a 1024 character font, 8x8 pixel or 1024 tiles)

110 - 16 bit mode with a 4 bit color pixel, ie 4 bits per pixel, and the upper color bits come from the upper ram byte[15:12], IE used in fonts with 16 colors per pixel. (heheheh - the byte[11:8] allow addressing a 4096 character font, 4x8 pixel or 4096 tiles for display with 16 color pixels spread across 16 positions in a 16 color palette.  Imagine what you can do with that.)

bits 0,1 are the bitplane depth, bit 2 is the 16bit wide source data, bit 3 is enable/disable, bits 4 are for the new output mode_565.

Also add an output wire to the bitplane_2_raster:
mode_565
and assign it
assign  mode_565 = colour_mode_in[4];

---------------------------------------------------
Also, take a look at the upper image again, I just forgot to add a feedback green signal for the MAGGA when in tile/font mode.

Add an input wire to the MAGGIE:
ram_din[15:0]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 08:36:28 pm
bit 3 is 16 bits per pixel, ie 111

Mode
111 - 16-bit mode

but you are missing
100 - 16 bit text mode, ie 1 byte = 8 pixels.  This one uses the upper part of the byte, [15:12] for the bottom bits of the foreground color and [11:8] for the background color while the upper 4 bit palette bits still use the fg_colour and bg_colour.

101 - 16 bit mode with a 2 bit color pixel, ie 2 bits per pixel, and the upper color bits come from the upper ram byte[15:10], IE used in fonts with 4 colors per pixel.  (heheheh - the byte[9:8] allow addressing a 1024 character font, 8x8 pixel or 1024 tiles)

110 - 16 bit mode with a 4 bit color pixel, ie 4 bits per pixel, and the upper color bits come from the upper ram byte[15:12], IE used in fonts with 16 colors per pixel. (heheheh - the byte[11:8] allow addressing a 4096 character font, 4x8 pixel or 4096 tiles for display with 16 color pixels spread across 16 positions in a 16 color palette.  Imagine what you can do with that.)

I'm having a complete brain fart setting these modes up.  I've read and re-read what you've written, but I'm still not 100% certain on what to do.   :-[  I've done what I can to the best of my understanding, but 110 (16-bit, 4 bits per pixel) is incomplete and I've probably messed-up on the other 16-bit modes as well.  Take a look at the attached files - they have all the changes you've mentioned so far, but these 16-bit modes are testing my focus tonight.  :(

bits 0,1 are the bitplane depth, bit 2 is the 16bit wide source data, bit 3 is enable/disable, bits 4 are for the new output mode_565.

Yep, understand that now.  Have corrected line 69 in the BitplAne_to_RasTer module to use bit 3 instead of 4.

Code: [Select]
if (~window_enable | ~colour_mode_in[3]) begin

// disable output as turned off
pixel_out <= 16'b0000000000000000;
// disable output as not in display area
window_ena_out <= 1'b0;

end

Also add an output wire to the bitplane_2_raster:
mode_565
and assign it
assign  mode_565 = colour_mode_in[4];

Done.  :-+

Also, take a look at the upper image again, I just forgot to add a feedback green signal for the MAGGA when in tile/font mode.

Add an input wire to the MAGGIE:
ram_din[15:0]

That image makes it all much easier for me to visualise - thanks for that.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 08:56:39 pm
Ooyoyoy...
ok, 1:
Code: [Select]
3'b100 : begin // 16-bit text mode - 8 pixels per word

mode_16bit <= 1'b0; // I know this is weird, the 16 bit mode is reserved for turning off the palette and passing 16 bits straight to the DAC
window_ena_out <= 1'b1; // set enable_out HIGH


if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[3:0] <= font_color[7:0];
pixel_out[7:4] <= fg_color[7:4];

end
else begin

pixel_out[3:0] <= font_color[3:0];
pixel_out[7:4] <= bg_color[7:4];

end

next:
Code: [Select]
3'b101 : begin // 16-bit text mode - 4 pixels per word

mode_16bit <= 1'b0; // I know this is weird, the 16 bit mode is reserved for turning off the palette and passing 16 bits straight to the DAC
window_ena_out <= 1'b1; // set enable_out HIGH

pixel_out[7:2] <= font_color[7:2];

case (x_in[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte_in[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte_in[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte_in[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte_in[1:0];

end
endcase
and:
Code: [Select]
3'b101 : begin // 16-bit text mode - 4 pixels per word

mode_16bit <= 1'b0; // I know this is weird, the 16 bit mode is reserved for turning off the palette and passing 16 bits straight to the DAC
window_ena_out <= 1'b1; // set enable_out HIGH

pixel_out[7:4] <= font_color[7:4];

if (x_in[3]) *********************** 3, again????? it should be 2!!! ALSO ~x_in[2] or swap the ram_byte_in to look like the above code.
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end

And also line 138:
               if (x_in[3]) *********************** 3, again????? it should be 2!!! ALSO ~x_in[2] or swap the ram_byte_in to look like the above code.


get rid of lines 230-246.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2019, 11:09:16 pm
A tad confused by the code you've posted...  Specifically blocks 2 and 3???

next:
Code: [Select]
3'b101 : begin // 16-bit text mode - 4 pixels per word

mode_16bit <= 1'b0; // I know this is weird, the 16 bit mode is reserved for turning off the palette and passing 16 bits straight to the DAC
window_ena_out <= 1'b1; // set enable_out HIGH

pixel_out[7:2] <= font_color[7:2];

case (x_in[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte_in[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte_in[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte_in[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte_in[1:0];

end
endcase
and:
Code: [Select]
3'b101 : begin // 16-bit text mode - 4 pixels per word

mode_16bit <= 1'b0; // I know this is weird, the 16 bit mode is reserved for turning off the palette and passing 16 bits straight to the DAC
window_ena_out <= 1'b1; // set enable_out HIGH

pixel_out[7:4] <= font_color[7:4];

if (x_in[3]) *********************** 3, again????? it should be 2!!! ALSO ~x_in[2] or swap the ram_byte_in to look like the above code.
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end

Is it me, or do they have exactly the same first line?  (The select case - both are 3'b101 with the same comment??)

I've put the third block of code (or the second one above) in as 3'b110 and kept the comment name for it - 16-bit 4-bit colour pixel - 4 bits per pixel.

And also line 138:
               if (x_in[3]) *********************** 3, again????? it should be 2!!! ALSO ~x_in[2] or swap the ram_byte_in to look like the above code.

I've changed x_in[3] to [2] on line 212 (see the attached updated BART module below) and swapped the ram_byte_in order in the if...else - hopefully that's right now?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2019, 11:42:37 pm

Is it me, or do they have exactly the same first line?  (The select case - both are 3'b101 with the same comment??)
Sorry, copy and paste error...
Only 1 mistake, again my error.  Line 160 should read this:

pixel_out[3:0] <= font_color[7:4];

Everything else looks good.

Wire the current MAGGIE and BART into memory channel 3, as per diagram, and wire the bottom 8 bits of the 16 bit BART output into 'pixel_out_top_h' which you should rename to 'gfx_pixel[7:0] for now and feed it into the palette gfx_pixel input.  On the current OSD text generator, don't for get to erase the current 'pixel_out_top_h'.

This should be enough to develop the MAGGIE code.

(This is a lot of work, isn't it?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 08:52:22 am
Wire the current MAGGIE and BART into memory channel 3, as per diagram, and wire the bottom 8 bits of the 16 bit BART output into 'pixel_out_top_h' which you should rename to 'gfx_pixel[7:0] for now and feed it into the palette gfx_pixel input.  On the current OSD text generator, don't for get to erase the current 'pixel_out_top_h'.

Stupid question time:  where/how am I instantiating MAGGIE?  I'm guessing this will be done in the existing video_osd_generator module and connected up to port 3 of the multiport_gpu_ram instance via wires?  What happens to the old outputs from the video_osd_generator?  Seems I've got some gutting to do with the video_osd_generator's internals?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 09:19:54 am
Wire the current MAGGIE and BART into memory channel 3, as per diagram, and wire the bottom 8 bits of the 16 bit BART output into 'pixel_out_top_h' which you should rename to 'gfx_pixel[7:0] for now and feed it into the palette gfx_pixel input.  On the current OSD text generator, don't for get to erase the current 'pixel_out_top_h'.

Stupid question time:  where/how am I instantiating MAGGIE?  I'm guessing this will be done in the existing video_osd_generator module and connected up to port 3 of the multiport_gpu_ram instance via wires?  What happens to the old outputs from the video_osd_generator?  Seems I've got some gutting to do with the video_osd_generator's internals?
Not yet.  Read the text.  The BART output feeds the GFX input in the palette mixer module.  Look at the top hierarchy of your project.  You made a mistake.  You were feeding the GFX input of the palette mixer the OSD text 'pixel_out_top_h'.  That supposed to be the output of the new BART's 'pixel_out' bottom 8 bits.

The gutting will only take place once the MAGGIE can produce ASCII text.  We got a way to go.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 09:53:09 am
I've tried to update the symbol file for the vid_osd_generator due to the IO port name change etc suggested above, but am getting this error:

Error (10703): SystemVerilog error at vid_osd_generator.v(133): can't resolve aggregate expression in connection to port 8 on instance "b2r_1" because the instance has no module binding


It relates to this line in vid_ost_generator.v:
Code: [Select]
.GPU_HW_Control_regs(GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)]),

I can't seem to find the issue - bitplane_to_raster.v is present in the project.  :-//

I've resolved quite a few variable-name errors in MAGGIE too, but as I can't get vid_osd_generator to build at the moment, I'm relatively stuck in trying to make the wiring changes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 10:03:01 am
That isn't the error I'm getting:

[attach=1]

Choose now, American, or European English...

There is a lot more of 1 or the other out there, you might have to go through all the modules.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 10:16:32 am
After changing the 'color' issue, it compiles fine.  Yet, you haven't inserted the new MAGGIE & BART yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 10:18:21 am
That isn't the error I'm getting:

(Attachment Link)

Choose now, American, or European English...

There is a lot more of 1 or the other out there, you might have to go through all the modules.

That's odd - I'm not getting any of those errors (I'm compiling in Quartus Prime).  I 'translate' your code into UK English as I enter it, so there shouldn't be any 'color' spellings in the code?

One change I had made was to rename bitplane_to_raster_v2.v to bart.v.  I've removed the old bitplane_to_raster_v2.v file from the project.  Neither maggie.v or bart.v are referenced in the project code yet, so they're just 'sitting' there in the file list in the project but are still getting compiled, of course.

[attachimg=1]

Above error relates to this line of code in maggie.v:

Code: [Select]
h_trig_delay[7:0] <= { h_trig_delay[6:0],  h_trig };

EDIT: Changed it to this:

Code: [Select]
h_trig_delay[7:1] <= h_trig_delay[6:0];
h_trig_delay[0] <= h_trig;

... and then got the 'color' errors in bart...  :palm:  Compiles now.  :phew:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 10:31:00 am
So, where are we at?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 10:35:02 am
So, where are we at?

[attachimg=1]

Back to here again.  I'm ignoring this error for now as I presume we're removing the old bitplane_to_raster module and replacing it with bart.  Just working on those changes at the moment.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 10:40:38 am
Give me you project .zip, because mine compiles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 10:57:00 am
Give me you project .zip, because mine compiles.

It compiles now for me too - but only once I removed the instantiation of the old bitplane_to_raster.  I've removed it from the project files now and all compiles well.  I'm just in the process of finishing up the bart connections and instantiating maggie.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 11:08:20 am
Give me you project .zip, because mine compiles.

It compiles now for me too - but only once I removed the instantiation of the old bitplane_to_raster.  I've removed it from the project files now and all compiles well.  I'm just in the process of finishing up the bart connections and instantiating maggie.
What did you do?
You need both barts, the old for the existing text and the new for the graphics layer with maggie.
The new bart isn't compatible with the old text generator.  Or at least, I never thought about doing that.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 11:15:16 am
[attachimg=1]

Still getting this error now I've added the HW_regs inputs - it's not happy with this line in the instantiation of bart OR maggie:

Code: [Select]
.GPU_HW_Control_regs(GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)]),

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 12:02:58 pm
How do you keep on making multiple changes to multiple working modules at multiple times?

Here is the functional original 'bitplane_to_raster.v'
Code: [Select]
module bitplane_to_raster (

// inputs
input wire clk,
input wire pixel_in_ena,
input wire [3:0] pc_ena,
input wire [15:0] ram_byte_in, // ****** changed to 16 bit width
input wire [7:0] ram_byte_h,
input wire [7:0] bg_colour,
input wire [9:0] x_in,
input wire [2:0] colour_mode_in,
input wire two_byte_mode,

// outputs
output reg pixel_out_ena,
output reg mode_16bit, // high when in 16-bit mode
output reg [7:0] pixel_out,
output reg [7:0] pixel_out_h,
output reg [9:0] x_out,
output reg [2:0] colour_mode_out

);

// internal registers
//reg [7:0] colour_data;

// *****************************************************************************
// *                                                                           *
// *  PASS-THRUS                                                               *
// *                                                                           *
// *****************************************************************************

always @ ( posedge clk ) begin

if (pc_ena[3:0] == 0) begin

x_out <= x_in;
//colour_data <= ram_byte_in; // in two-byte mode, colour_data should follow the ram_data byte
colour_mode_out <= colour_mode_in;

end // pc_ena

end // always@clk
// *****************************************************************************


// *****************************************************************************
// *                                                                           *
// *  RASTER GENERATION                                                        *
// *                                                                           *
// *****************************************************************************

// color_mode_in determines the operating mode for the bitplane_to_raster module
// it is a 3-bit signal, providing 4 modes of operation to this module e.g.:
//
// 000 =   2 colour mode - 8 pixels per byte in GPU RAM
// 001 =   4 colour mode - 4 pixels -----"------"------
// 010 =  16 colour mode - 2 pixels -----"------"------
// 011 = 256 colour mode - 1 pixels -----"------"------
// 1xx = OFF

always @ (posedge clk) begin

if (pc_ena[3:0] == 0) begin

pixel_out_ena <= pixel_in_ena; // pass pixel_ena through to the output

if (~pixel_in_ena || colour_mode_in[2]) begin

// nothing to see here (disabled)
pixel_out <= 8'b00000000;
pixel_out_h <= 8'b00000000;

end
else if (~two_byte_mode) begin // 8-bit mode

case (colour_mode_in)

2'h0 : begin // 1-bit (2 colour) - 8 pixels per byte
// set the output pixel color to the first 4 bits of the background color
// when the bit on the picture bitplane byte is 0 and use the upper 4 bits
// when the bit on the bit-plane byte is high

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:4] <= 4'b0000; // was: pixel_out[7:5] <= 3'b000;
//pixel_out[4] <= 1'b1; // changed for new palette_mixer module
pixel_out[3:0] <= bg_colour[7:4];

end
else begin

pixel_out[7:4] <= 4'b0000;
//pixel_out[4] <= 1'b0;
pixel_out[3:0] <= bg_colour[3:0];

end

end

2'h1 : begin // 2-bit (4 colour) - 4 pixels per byte
// output will be 2 bits stacked, 2 copies every second X pixel, you will
// output a 2 bit color. EG pixel 0&1 output bitplane[7:6],  pixel 2&3
// output bitplane[5:4], pixel 4&5 output bitplane[3:2]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:2] <= 6'b000000;

case (x_in[2:1])
2'h0 : begin

pixel_out[1:0] <= ram_byte_in[7:6];

end
2'h1 : begin

pixel_out[1:0] <= ram_byte_in[5:4];

end
2'h2 : begin

pixel_out[1:0] <= ram_byte_in[3:2];

end
2'h3 : begin

pixel_out[1:0] <= ram_byte_in[1:0];

end
endcase

end

2'h2 : begin // 4-bit (16 colour) - 2 pixels per byte
// output will be 4 bits stacked, 4 copies every four X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3 output bitplane[7:4], EG pixel
// 4,5,6,7 output bitplane[3:0]

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

pixel_out[7:4] <= 4'b0000;

if (x_in[3])
pixel_out[3:0] <= ram_byte_in[3:0];
else
pixel_out[3:0] <= ram_byte_in[7:4];

end

2'h3 : begin // 8-bit (256 colour) - 1 pixel per byte
// output will be 8 bits stacked, 8 copies every eight X pixel, you will
// output a 4 bit color.  EG pixel 0,1,2,3,4,5,6,7 output bitplane[7:0],
// yes that same 1 value will repeat 8 times is the source X counter
// counts through those numbers sequentially

mode_16bit <= 1'b0; // update the mode output to show whether it's 8 or 16-bit mode

pixel_out <= ram_byte_in[7:0];

end

endcase

end // 8-bit mode
else begin // 16-bit mode

case (colour_mode_in)

2'h0 : begin // special colour text mode
// 2-bit colour 2-byte mode
// latch ram_byte as the bit plane graphic and colour_data
// as a replacement for the background default color. The
// rest should follow #1.

mode_16bit <= 1'b0; // update mode_16bit output to 8-bit mode

if (ram_byte_in[(~x_in[2:0])] == 1'b1) begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b1;
pixel_out[3:0] <= ram_byte_h[7:4];

end
else begin

pixel_out[7:5] <= 3'b000;
pixel_out[4] <= 1'b0;
pixel_out[3:0] <= ram_byte_h[3:0];

end

end
2'h3 : begin // 16-bit (true colour)
// taking 2 sequential bytes, like the color text mode, and outputting
// a full 16 bits parallel on the output

mode_16bit <= 1'b1; // update mode_16bit output to 16-bit mode

pixel_out <= ram_byte_in[7:0];
pixel_out_h <= ram_byte_h;

end

endcase

end // 16-bit mode

end // if (pc_ena[3:0] == 0)

end // always@clk

endmodule


Here is the original working initiation of that module:

Code: [Select]
bitplane_to_raster b2r_1(

.clk(clk),
.pc_ena(pc_ena[3:0]),

// inputs
.pixel_in_ena(pixel_ena),
.ram_byte_in(char_line),
.ram_byte_h(8'b00000000),
.bg_colour( GPU_HW_Control_regs[10] ),
.x_in( dly6_disp_x ),
.colour_mode_in( GPU_HW_Control_regs[12][2:0] ),
.two_byte_mode( GPU_HW_Control_regs[11][0] ),

// outputs
.pixel_out_ena( pixel_out_ena ),
.mode_16bit( pixel_out_top_16bit ),
.pixel_out( pixel_out_top ),
.pixel_out_h( pixel_out_top_h ),
.x_out(), // disconnected for moment
.colour_mode_out() // disconnected for moment

);


Now, we are left with you error on MAGGIE when " Creating Symbol Files For Current File " :
It's a Quartus bug, or we just don't have the ' Perfect Syntax '  Quartus is expecting.

Temporarily change the line to:
Code: [Select]
.hw_regs( GPU_HW_Control_regs[2**HW_REGS_SIZE] ),
Then 'Creating Symbol Files For Current File'.
Then change the line back to:
Code: [Select]
.hw_regs( GPU_HW_Control_regs[0:(2**HW_REGS_SIZE-1)] ),
Then compile the project.

In maggie, all these are wrong:

// registers
reg ram_read_pointer_y[19:0];
reg ram_read_pointer_x[23:0];
reg period_x[4:0];
reg period_y[4:0];
reg h_trig_delay[7:0];

The [#:#] belongs on the left side when defining a reg.  The right side is to define an array size.

I'm going to check what's up with Quartus not liking the 'regs[0:(2**HW_REGS_SIZE-1)] ' inside a function, but my trick listed above for now will work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 12:34:15 pm
Found the Quartus bug,

Rename the MAGGIE.v to MAGGIE.sv
Rename the vid_osd_generator.v to vid_osd_generator.sv

Then everything works including create symbols.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 12:47:45 pm
Found the Quartus bug,

Rename the MAGGIE.v to MAGGIE.sv
Rename the vid_osd_generator.v to vid_osd_generator.sv

Then everything works including create symbols.

Well done.  It compiles!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 12:51:22 pm
Do we need to make some changes to the palette_mixer now?  Your diagram shows:
as outputs from BART to the Palette_Mixer, but the existing palette_mixer module has no matching inputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 01:03:07 pm
Do we need to make some changes to the palette_mixer now?  Your diagram shows:
  • window_ena_out
  • mode_16_bit
  • mode_565
  • pixel_out
as outputs from BART to the Palette_Mixer, but the existing palette_mixer module has no matching inputs.
Next week, for now, just feed 8 bits of the current pixel out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 01:08:10 pm
Found the Quartus bug,

Rename the MAGGIE.v to MAGGIE.sv
Rename the vid_osd_generator.v to vid_osd_generator.sv

Then everything works including create symbols.

Well done.  It compiles!  ;D
Did you check for a picture?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 01:12:58 pm
Okie dokie, well that seems to be working okay.  Has gone back to the old way of setting colours via HW_REGS[10].
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 01:19:30 pm
Arrrg, again, why?

Line 225 in vid_osd_generator:

      gfx_pixel <= pixel_out[7:0];

Erase that line!!!

Line 190:
   .pixel_out( pixel_out ),

Change that to :
.pixel_out( gfx_pixel ),


Lines 18 through 22:
   output reg osd_ena_out,
   output reg window_ena_out,
   output reg pixel_out_top_16bit,
   output reg [7:0] pixel_out_top,
   output reg [7:0] gfx_pixel,

Are all supposed to be 'WIRE', though except for the gfx_pixel fiasco, quartus automatically converted them to wires when compiling.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 01:35:01 pm
All sorted, image is good.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 03:58:16 pm
Here we go.

In that attached files, you have:
GPU_256char_font_MAGGIE_beta.zip    -> With a rudimentary MAGGIE address generator & other bug patches.
RS232_Debugger_Quick_file_MAGGIE_test.zip -> Quick load binary files which setup & turn on the new MAGGIE.

Changes I made to 'GPU_256char_font'.

1. Fixed a bug in the palette_mixer module.
    I for some reason had to assign the wire 'alpha_blend' to an 'integer' which I called blend.  This was connected with the '* (15-alpha_blend[3:0])' bug from a few days ago.  The multiply function seems to want an 'integer' in the math, otherwise it returns a '0' which made the second line on the mixer which didn't have the '15-' return a black image.

2.  Changed the 4444 text layer palette's .mif so that color 1, blue, is now semi translucent to the graphics layer below.  Color 0, black, is fully transparent.

3.  Changed the 565 palette's .mif so that color 255 is now white instead of black.

4.  Removed all the yellow H&V_Trigger cursors except for the first 4 of them.

5.  Added a code making rudimentary MAGGIE address generator:
    a) Moved the H&V resets to HV_trigger to 8, address 0x3F10, 0x3F12.             (do not touch)
    b) Moved the H&V window starting HV_trigger to 10, address 0x3F14, 0x3F16 (you can play with these)
    c) Base address 0x3F60 begins the MAGGIE controls.
        keep the BP2RAST setting the same
        play with RST_ADDR, YINC_ADDR, X_SIZE, Y_SIZE.  These are the only variables which function.

For now, use 8 bit color setting.

HV_trigger 10/11 tells MAGGIE where to position the top left coordinates of the window.

X_SIZE & Y_SIZE tells MAGGIE how many pixels wide and tall it's open window will be on the screen.

RST_ADDR tells MAGGIE the beginning byte position of the source bitmap graphics data.  You can write to this setting to also scroll horizontally and vertically the shown bitmap graphic inside the open window.

YINC_ADDR tells MAGGIE the width of the source bitmap graphics data in bytes.

Give me a report.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2019, 08:22:37 pm
Hmm.. okay, so I've downloaded the project, compiled and flashed it to the FPGA and downloaded and loaded the binaries into RS232_debugger.  This is what I'm getting:

[attach=1]

I'm able to move it around, resize the overlay window etc. but I can't get a sensible image out of the overlay.  I haven't changed anything, I've just copied the project into a new folder and compiled it in Quantus Prime.  :-//  Also, it seems both quick binaries for the RS232_debugger are identical?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 09:04:52 pm
Hmm.. okay, so I've downloaded the project, compiled and flashed it to the FPGA and downloaded and loaded the binaries into RS232_debugger.  This is what I'm getting:

(Attachment Link)

I'm able to move it around, resize the overlay window etc. but I can't get a sensible image out of the overlay.  I haven't changed anything, I've just copied the project into a new folder and compiled it in Quantus Prime.  :-//  Also, it seems both quick binaries for the RS232_debugger are identical?
Did you program a paint software to draw in there?
Do you have the ram for a 256x256 pixel, 8 bit image?

Your looking at the existing ram contents being fed through the palette.
Play with the controls I listed...

Ok, maybe, first, you should add the the MAGGIE support for different bitplane sizes.  This way, in 1 bit color, you could render the font in memory into the sprite if you made it 8 pixels wide with a 1 byte width setting for the graphics.

Looking at the code I sent you, and knowing where the pixels / bits setting is stored, show me how you would modify my MAGGIE code to recognizes the different bitplane modes horizontal sizes.


Yes, both quick binaries are identical.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 09:57:20 pm
Grrr, line 141 in bart.v reads:
               if (x_in[3])

Take a look at line 215...  You know what is should be...

also, lines 142 & 144 are backwards....

                   pixel_out[3:0] <= ram_byte_in[3:0];

                  pixel_out[3:0] <= ram_byte_in[7:4];

See lines 216 & 218...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2019, 10:07:19 pm
Here are 2 different quick save files for when you get the MAGGIE to respond to the 'color depth'.

This time, they are both different.

You only need to modify 1 key line in the MAGGIE to get the pixels / bits setting to work.
I also recommend making a new wire called 'pixel_per_byte[1:0]' and assign it to the right place.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 14, 2019, 11:15:34 am
Hmm.. okay, so I've downloaded the project, compiled and flashed it to the FPGA and downloaded and loaded the binaries into RS232_debugger.  This is what I'm getting:

(Attachment Link)

I'm able to move it around, resize the overlay window etc. but I can't get a sensible image out of the overlay.  I haven't changed anything, I've just copied the project into a new folder and compiled it in Quantus Prime.  :-//  Also, it seems both quick binaries for the RS232_debugger are identical?
Did you program a paint software to draw in there?

Not yet... I'd just assumed that there would be something meaningful in there as I could see a pattern of sorts, it was just out of phase.

Do you have the ram for a 256x256 pixel, 8 bit image?

No - I've only got 33KB to play with in total on this Cyclone IV EP4CE6 FPGA.

I'm considering designing and building a dev board for the Lattice LFE5U FPGA as there doesn't seem to be many cheap ones about (or many about at all - I found one that doesn't look great) - it would be a good practice run before starting on the GPU card build and if I slap an ADV7125 in there, I could have 24-bit VGA output to test with too.  Does anyone know of or have schematics with basic circuits to support an LFE5U FPGA?  Might start another thread on that question.  Obviously, a head start before I dive into the datasheets would speed up development.

Ok, maybe, first, you should add the the MAGGIE support for different bitplane sizes.  This way, in 1 bit color, you could render the font in memory into the sprite if you made it 8 pixels wide with a 1 byte width setting for the graphics.

Looking at the code I sent you, and knowing where the pixels / bits setting is stored, show me how you would modify my MAGGIE code to recognizes the different bitplane modes horizontal sizes.

Let me get back to you on this one.  Busy day today and I'm going to need a clear block of time to look at the code and concentrate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 14, 2019, 11:42:50 am
Is this line right?

Code: [Select]
wire [1:0]  pixel_per_byte;

assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 14, 2019, 03:41:11 pm
Yes.  Now make the address generator count at the right speed according to the setting.
Study my code carefully how I assigned the wiring around of the counters and how I am accumulating the address position.

It's 1 line to edit with only a 1 new term to get it working.

You will know it's working if 1 of the new quick save file generates a meaningful image.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 14, 2019, 06:54:15 pm
Okay, I've had 10 minutes to look at this, so don't be too critical.  This is what I've come up with:

Code: [Select]
assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)

So now pixel_per_byte relates directly to the current mode.  Further down, in the always @(posedge clk) block, I've tweaked the ram_read_pointer_x increment to be sensitive to the current mode:

Code: [Select]
if (run_x) begin

width <= width - 1;
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;

end

So ram_read_pointer_x is incremented by 1 bit in mode 0, 2 bits in mode 1, 4 bits in mode 2 and a byte in mode 3, instead of just being incremented by a byte each time previously.  This results in the following output based on the two binaries you supplied:

[attach=1]

Looking good so far.  8)

[attach=2]

Oh shazbut.  |O

Not sure what I'm doing wrong, I thought I'd got it in the bag...  :-[
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 14, 2019, 09:21:42 pm
Nope, you did great.  I also would have accepted:
ram_read_pointer_x <= ram_read_pointer_x + ( 1 << pixel_per_byte );

So, you truly need me to prepare graphics...
Maybe on Sunday.

Next, X - Zoom, or scale.  Also known as X period or horizontal period.
The setting is stored in ' period_x[3:0] '.
The goal, when 'period_x[3:0]' = '0', the picture you get should be the same.
When 'period_x[3:0]' = '1' then the picture should be twice as wide, or, every X pixel is repeated twice.
When 'period_x[3:0]' = '2' then the picture should be 3 times as wide, or, every X pixel is repeated 3 times.
When 'period_x[3:0]' = '3' then the picture should be 4 times as wide, or, every X pixel is repeated 4 times.
......
When 'period_x[3:0]' = '7' then the picture should be 8 times as wide, or, every X pixel is repeated 8 times.

You get the idea.

Around 3 controls left, then some fancy manipulation to get the text working.

Now you understand the text you saw was only a sprite set to 8 pixels wide, 1 bit color, 1 byte per line and 32 lines tall pointing to the letter 'A' in the GPU ram's current font.  You could play with the base address to vertically shift the image to a new letter, or, increased the size of the window to show more letters as the font is stored vertically, all 256 characters in 1 straight line.

You also could adjust the bg_ & fg_ color to your liking, or, try 4 color mode messing up the graphic, but you would recognize a font squeezed half-width as 2 bits now generate 1 4 colour pixel.  Also, now, the bg_color now would select which 4 colors in the palette would be used for those 4 possible colors.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2019, 12:43:56 pm
Nope, you did great.  I also would have accepted:
ram_read_pointer_x <= ram_read_pointer_x + ( 1 << pixel_per_byte );

Ah of course - didn't think about bit-shifting.  :)  I guess the hardware output would be the same and there's no performance penalty for squaring instead of bit-shifting?

Next, X - Zoom, or scale.  Also known as X period or horizontal period.
The setting is stored in ' period_x[3:0] '.
The goal, when 'period_x[3:0]' = '0', the picture you get should be the same.
When 'period_x[3:0]' = '1' then the picture should be twice as wide, or, every X pixel is repeated twice.
When 'period_x[3:0]' = '2' then the picture should be 3 times as wide, or, every X pixel is repeated 3 times.
When 'period_x[3:0]' = '3' then the picture should be 4 times as wide, or, every X pixel is repeated 4 times.
......
When 'period_x[3:0]' = '7' then the picture should be 8 times as wide, or, every X pixel is repeated 8 times.

You get the idea.

Okay, not such a simple solution for X-scaling.  I'm sure it's not the most efficient way of doing it, but here's my solution:

Code: [Select]
wire [7:0]  width_count;   <----- new wire

if (run_x) begin

if (period_x[3:0] == width_count) begin
width <= width - 1;
width_count <= 0;
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
end
else begin
width_count <= width_count + 1;
ram_read_pointer_x <= ram_read_pointer_x;
end

end

width_count is zeroed in the xy_rst, x_rst and h_rst if... blocks as well.  Full project attached below.

Here's a screenshot of a pixel scaled to 8x width:

[attachimg=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2019, 02:18:44 pm
Okay, so I've pushed on a little further and implemented the Y-scale function as well.  :-/O

[attach=1]

Nice 8x8 scaling on the original sprite.  ^-^

Again, don't know if I'm using the optimal method to scale the sprite, but I've attached the updated MAGGIE code.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2019, 04:42:06 pm
Have you tried moving the text around inside a zoomed box with and without the original 'Y' code, taking care of the source read address, you will see a little problem...

Are you sure your width and height is correct ad 1x and 2x zooms?
Is the right read address getting through?

Change the base memory address to 0x0B10 & 0x0B00.  Move it up and down 1 or 2 at different Y zoom levels 0 & 1.  Something is off.

Your top line of the font is off by 1 byte as 0x0B0F renders the beginning of the character properly.  And when zoomed, vertically to 1, you are also 1 line short at the bottom of the image.  In fact, at all zoom levels above 0, you are missing 1 line at the bottom.

(I counted using the test vertical bar cursor at address 0x3F03)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2019, 06:01:40 pm
Have you tried moving the text around inside a zoomed box with and without the original 'Y' code, taking care of the source read address, you will see a little problem...

Are you sure your width and height is correct ad 1x and 2x zooms?
Is the right read address getting through?

Change the base memory address to 0x0B10 & 0x0B00.  Move it up and down 1 or 2 at different Y zoom levels 0 & 1.  Something is off.

Your top line of the font is off by 1 byte as 0x0B0F renders the beginning of the character properly.  And when zoomed, vertically to 1, you are also 1 line short at the bottom of the image.  In fact, at all zoom levels above 0, you are missing 1 line at the bottom.

(I counted using the test vertical bar cursor at address 0x3F03)

Thought I was doing too well.  :-\

I've been staring at the code for the last 30 minutes and, short of randomly moving stuff about to test the results, I don't think I'm likely to spot the problem any time soon.  :-//

One thing I've found is that it's missing the first line even without the Y-scale code changes.

Is it because width[] and height[] are registers, and thus are a clock behind? 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2019, 06:55:55 pm
Have you tried moving the text around inside a zoomed box with and without the original 'Y' code, taking care of the source read address, you will see a little problem...

Are you sure your width and height is correct ad 1x and 2x zooms?
Is the right read address getting through?

Change the base memory address to 0x0B10 & 0x0B00.  Move it up and down 1 or 2 at different Y zoom levels 0 & 1.  Something is off.

Your top line of the font is off by 1 byte as 0x0B0F renders the beginning of the character properly.  And when zoomed, vertically to 1, you are also 1 line short at the bottom of the image.  In fact, at all zoom levels above 0, you are missing 1 line at the bottom.

(I counted using the test vertical bar cursor at address 0x3F03)

Thought I was doing too well.  :-\

I've been staring at the code for the last 30 minutes and, short of randomly moving stuff about to test the results, I don't think I'm likely to spot the problem any time soon.  :-//

One thing I've found is that it's missing the first line even without the Y-scale code changes.

Is it because width[] and height[] are registers, and thus are a clock behind?

Ok, lets see if I can help you out of this one...
Read my attached code carefully and compare the changes I made compared to yours.
Also read the comments I added.

Code: [Select]
// **************************************************************
// *                                                            *
// *  Multiple Address Generator & Graphics Instruction Engine  *
// *                                                            *
// **************************************************************

module maggie (

//inputs
input wire clk,
input wire [3:0]  pc_ena_in,
input wire [7:0]  hw_regs[0:(2**HW_REGS-1)],
input wire [47:0] HV_trig,
input wire [31:0] cmd_in,
input wire [15:0] ram_din,

//outputs (all wires as we will embed the connected registers inside the module)
output wire [19:0] read_addr,
output wire [31:0] cmd_out,
output wire [23:0] bp_2_rast_cmd

);

// parameters
parameter HW_REGS = 8;
parameter HW_REG_BASE = 96;
parameter H_RESET_TRIG = 8;
parameter H_POS_TRIG = 10;
parameter RAM_READ_CYCLES = 3;

// local parameters
localparam V_RESET_TRIG = H_RESET_TRIG +  1;
localparam V_POS_TRIG = H_POS_TRIG +  1;
localparam BP2RAST_cmd = HW_REG_BASE +  0; // Transfers the video mode setting to the new bitplane_2_raster module
localparam BP2RAST_bgc = HW_REG_BASE +  1; // Transfers the bg_colour setting to the new bitplane_2_raster module
localparam BP2RAST_fgc = HW_REG_BASE +  2; // Transfers the fg_colour setting to the new bitplane_2_raster module
localparam RST_ADDR_H = HW_REG_BASE +  3; // MSB bits of 24 bit base read address
localparam RST_ADDR_M = HW_REG_BASE +  4; // MID bits of 24 bit base read address
localparam RST_ADDR_L = HW_REG_BASE +  5; // LSB bits of 24 bit base read address
localparam YINC_ADDR_H = HW_REG_BASE +  6; // MSB bits of 16 bit Y-Line increment for read address
localparam YINC_ADDR_L = HW_REG_BASE +  7; // LSB bits of 16 bit Y-Line increment for read address
localparam X_SIZE_H = HW_REG_BASE +  8; // MSB bits of 16 bit display width screen pixels
localparam X_SIZE_L = HW_REG_BASE +  9; // LSB bits of 16 bit display width screen pixels
localparam Y_SIZE_H = HW_REG_BASE + 10; // MSB bits of 16 bit display height screen y lines
localparam Y_SIZE_L = HW_REG_BASE + 11; // LSB bits of 16 bit display height screen y lines
localparam X_SCALE = HW_REG_BASE + 12; // Compound of two 4 bit words. Upper 4 bits controls the X increment every period, lower 4 bits is a pixel period counter to define the number of pixels until the upper 4 bits are added to the address-pointer.
localparam Y_SCALE = HW_REG_BASE + 13; // Compound of two 4 bit words. Upper 4 bits reserved for text tile mode Y size while the lower lower 4 bits is a line period counter to define the number of lines until YINC_ADDR is added to the address-pointer
localparam X_START_SUB = HW_REG_BASE + 14; // An 8 bit word which defines an odd pixel start position within the period counter and X position within a bitplane's X coordinate position
localparam Y_START_SUB = HW_REG_BASE + 15; // An 8 bit word which defines an odd line start within within the period counter and Y coordinates inside a font.

// registers
reg [19:0] ram_read_pointer_y;
reg [23:0] ram_read_pointer_x;
reg [4:0] period_x;
reg [4:0] period_y;
reg [7:0] h_trig_delay;
reg [11:0] width;
reg [11:0] height;
wire run_x;
wire run_y;
assign run_x = width[11];
assign run_y = height[11];

// wires
wire h_rst, x_rst, xy_rst;
wire h_trig, v_trig;
wire window_enable;
wire [23:0] reset_addr;
wire [15:0] inc_addr_x;
wire [15:0] inc_addr_y;
wire [3:0]  period_x_rst;
wire [3:0]  period_y_rst;
wire [11:0] x_size;
wire [11:0] y_size;
wire [1:0]  pixel_per_byte;
wire [7:0]  width_count;
wire [7:0]  height_count;

// assignments
assign bp_2_rast_cmd[23:0] = { hw_regs[BP2RAST_fgc] , hw_regs[BP2RAST_bgc] , hw_regs[BP2RAST_cmd] };
assign text_mode_master = hw_regs[BP2RAST_cmd][7];

assign x_rst = HV_trig[H_RESET_TRIG];
assign xy_rst = HV_trig[V_RESET_TRIG] && x_rst;

assign v_trig = HV_trig[V_POS_TRIG];
assign h_trig = HV_trig[H_POS_TRIG];
assign h_rst = text_mode_master ? h_trig_delay[0] : h_trig_delay[RAM_READ_CYCLES-1];  // When in text mode, push the window left by 'RAM_READ_CYCLES' as it takes a second memory read to get the font image

assign window_enable = run_x && run_y;
assign cmd_out[7] = window_enable; // commands the pixel/by/pixel window enable for the bitplane_2_raster module
assign cmd_out[6] = 1'b0; // for now, disables the 2 byte colour mode

assign reset_addr[23:0] = { hw_regs[RST_ADDR_H] , hw_regs[RST_ADDR_M] , hw_regs[RST_ADDR_L]  };
assign inc_addr_y[15:0] = { hw_regs[YINC_ADDR_H] , hw_regs[YINC_ADDR_L] };
assign inc_addr_x[3:0] = hw_regs[X_SCALE][7:4];

assign read_addr[19:0] = ram_read_pointer_x[22:3];
assign cmd_out[2:0] = ram_read_pointer_x[2:0]; // commands the sub pixel X position for the bitplane_2_raster module

assign period_x[3:0] = hw_regs[X_SCALE][3:0];
assign period_y[3:0] = hw_regs[Y_SCALE][3:0];

assign period_x_rst[3:0] = hw_regs[X_START_SUB][3:0];
assign period_y_rst[3:0] = hw_regs[Y_START_SUB][3:0];

assign x_size[11:0] = { hw_regs[X_SIZE_H][3:0], hw_regs[X_SIZE_L][7:0] };
assign y_size[11:0] = { hw_regs[Y_SIZE_H][3:0], hw_regs[Y_SIZE_L][7:0] };

assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)

always @(posedge clk) begin

   if (pc_ena_in[3:0] == 0) begin

      h_trig_delay[7:1] <= h_trig_delay[6:0];
h_trig_delay[0] <= h_trig;

      if (xy_rst) begin // equivalent to a vertical sync/reset

height             <= 0;
width_count <= 0;
height_count <= 0;

end
else if (x_rst) begin // equivalent to a horizontal sync/increment

width <= 0;
width_count <= 0;

if (v_trig) begin              // V_TRIG is high for the entire first line of video to be displayed.  This is the point in place and time where the read address must be equal to the setting in the reset_addr.
height[11]   <= 1;      // set run_y bit active
height[10:0] <= y_size[10:0];
height_count <= 0;     // * must reset as well.

ram_read_pointer_y <= reset_addr << 3;  // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= reset_addr << 3;  // the backup and currrent display address to the exact reset base address during this line.
end // V_TRIG
else begin  // ~V_TRIG

if (run_y) begin                // after the first line, do these functions.
if (period_y[3:0] == height_count) begin   // If the vertical scale period count has reached it's end
height <= height - 1;                  // count down the visible window size
height_count <= 0;                     // reset the vertical period
ram_read_pointer_y <= ram_read_pointer_y + (inc_addr_y[15:0] << 3);  // vertical increment display position in backup buffer
ram_read_pointer_x <= ram_read_pointer_y + (inc_addr_y[15:0] << 3);  // vertical increment display position in current display address
end // (period_y[3:0] == height_count
else begin                                // if the period count hasn't reached it's end,
height_count <= height_count + 1;  // increment the period count
ram_read_pointer_x <= ram_read_pointer_y; // restore the memory read address to the previous backup buffer address
end

end // ~V_TRIG
end

      end
else begin


if (h_rst) begin

width[11]   <= 1;       // set run_x bit active
width[10:0] <= x_size[10:0];
width_count <= 0;

end

if (run_x) begin

if (period_x[3:0] == width_count) begin
width <= width - 1;
width_count <= 0;
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
end
else begin
width_count <= width_count + 1;
end

end

         //-------------------------------
         //snap to it....
         //-------------------------------

      end // ~x_rst

   end // if (pc_ena_in[3:0] == 0)

end //@(posedge clk)

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2019, 07:02:38 pm
Next, we want to shift the horizontal position within the sprite/window by a sub-bitplane-pixel.

This means shift the text image in the window to the left by 1 pixel at a time.
This figure is stored inside the 'period_x_rst'

Please do not touch the 'period_y_rst' as this has specifically to do with rendering tiles/fonts on the 'Y' axis.  We have 2 other variables to do first, then we need to gut the old OSD text and wire in the new MAGGIE in it's place before you can edit this last variable of the MAGGIE.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2019, 08:57:14 pm
I cannot find a .pal or .act file of the VGA palette which I need to properly convert some bitmap files using photoshop.

If I convert an image using a different palette, you will need to edit the 565.mif file to see the image properly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 01:28:38 am
Okay, I've had 10 minutes to look at this, so don't be too critical.  This is what I've come up with:

Code: [Select]
assign pixel_per_byte = BP2RAST_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)

So now pixel_per_byte relates directly to the current mode.  Further down, in the always @(posedge clk) block, I've tweaked the ram_read_pointer_x increment to be sensitive to the current mode:
Another mistake, this line should read:
Code: [Select]
assign pixel_per_byte = bp_2_rast_cmd[1:0]; // bitplane setting equates to pixels per byte (0 = 1, 1 = 2, 2 = 4, or 3 = 8)

Fix it up....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 03:12:31 am
Another mistake in BART.v module.

Lines 141 and 215 currently read:

if (x_in[2])

When they should actually read:

if (~x_in[2])

Now that you fixed the issues in my last 2 posts, load these attached test graphics files.

I deliberately left them a binary files you need to load into spare empty memory.  I recommend $1200 i.e. 0x1200.  This will place a bit of the graphics into the end of your text buffer, but there is no other space as they will go all they way up to address $3EFF.

The 4 files are:
z80_360x256x1.bin
pac_208x204x4.bin
z80_192x120x16.bin
z80_120x96x256.bin

I tested them all ok, so I expect proper screen shots.  You will need to figure out the MAGGIE settings for the X&Y resolution by # of colors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2019, 09:29:36 am
The 4 files are:
z80_360x256x1.bin
pac_208x204x4.bin
z80_192x120x16.bin
z80_120x96x256.bin

I tested them all ok, so I expect proper screen shots.  You will need to figure out the MAGGIE settings for the X&Y resolution by # of colors.

Here's what I've got - the palette is out mostly, but I think I can decipher the images:  ;)

z80_360x256x1.bin:
[attach=1]

pac_208x204x4.bin:
[attach=2]

z80_192x120x16.bin:
[attach=3]

z80_120x96x256.bin: (I moved the sprite down out of the way of the garbage text above it)
[attach=4]

The images are appearing BEHIND the text though - is there a setting I'm missing somewhere?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 09:53:02 am
The 4 files are:
z80_360x256x1.bin
pac_208x204x4.bin
z80_192x120x16.bin
z80_120x96x256.bin

I tested them all ok, so I expect proper screen shots.  You will need to figure out the MAGGIE settings for the X&Y resolution by # of colors.

Here's what I've got - the palette is out mostly, but I think I can decipher the images:  ;)

z80_360x256x1.bin:
(Attachment Link)
You couldn't choose a better set of colors, like White and Black?
Remmeber, bg_color anf FG_color...
What about turning off the text layer?
Remember, the old bitplane_to_raster controls...
Quote
pac_208x204x4.bin:
(Attachment)
Ok, I was limited here.  You could only get the right image by editing the palette.  So for this one, I forgive you.
Quote

z80_192x120x16.bin:
(Attachment)
You couldn't choose an alternate palette base number from bg_color?
You would be surprised...
Quote

z80_120x96x256.bin: (I moved the sprite down out of the way of the garbage text above it)
(Attachment)
Ok, unless you want to change the entire palette, this is the best I could do...
Quote

The images are appearing BEHIND the text though - is there a setting I'm missing somewhere?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2019, 10:31:05 am
You couldn't choose a better set of colors, like White and Black?
Remmeber, bg_color anf FG_color...
What about turning off the text layer?
Remember, the old bitplane_to_raster controls...

I was just interested in getting the images to show, and to make the text overlapping the sprites visible.  I know I can turn the text off, just wondered if the 'z-order' of the drawing was correct and intended, that's all?

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 10:43:40 am
You couldn't choose a better set of colors, like White and Black?
Remmeber, bg_color anf FG_color...
What about turning off the text layer?
Remember, the old bitplane_to_raster controls...

I was just interested in getting the images to show, and to make the text overlapping the sprites visible.  I know I can turn the text off, just wondered if the 'z-order' of the drawing was correct and intended, that's all?

(Attachment Link)
When all 15 sprites/layers are in place, the z-order priority goes from top sprite to bottom sprite.

Ok, now, go back to the Yellow/Blue AB text test, make this function work:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2830598/#msg2830598 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2830598/#msg2830598)

We then have 16 bit addressing, Y font/tile scale/size, MAGGIE Font-slave-addressing mode, replace old OSD Font algorithm with 5x MAGGIE with new font capabilities, update palette to 5 port ram function to receive 5 MAGGIE, switch 5 port rams to 15 port rams on GPU ram palette, fix up Z80 bridge to cope with 16bit GPU ram, and then you have finished your GPU V1.0 core.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2019, 02:59:42 pm
Well, that got weird fast...  :o

I had a think about how best to implement horizontal scrolling as you've stated:

[attach=1]

Being more of someone who learns by experimentation, I cracked on and started writing code to get the sprite going horizontally, tweaking and adding bits to get the desired output.  I decided to stop when I realised I hadn't a clue what I was doing anymore and the sprite wasn't scrolling horizontally properly for every height it could have.  :-//

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + (x_size * y_size) + x_size*((1 << y_size[7:4]) - 1) + 1 + y_size[7:4];

Can't be good when it starts to get that complicated and it still doesn't cover sizes of Y above 0x20.

Full code for MAGGIE attached so you can see what a convoluted mess I've made with my attempt.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 06:31:40 pm
Well, that got weird fast...  :o

I had a think about how best to implement horizontal scrolling as you've stated:

(Attachment Link)

Being more of someone who learns by experimentation, I cracked on and started writing code to get the sprite going horizontally, tweaking and adding bits to get the desired output.  I decided to stop when I realised I hadn't a clue what I was doing anymore and the sprite wasn't scrolling horizontally properly for every height it could have.  :-//

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + (x_size * y_size) + x_size*((1 << y_size[7:4]) - 1) + 1 + y_size[7:4];

Can't be good when it starts to get that complicated and it still doesn't cover sizes of Y above 0x20.

Full code for MAGGIE attached so you can see what a convoluted mess I've made with my attempt.  ::)
You only needed 8 pixels.  Your Z80 fills in the reset address.  This is all you should have written:
Lines 137 & 138: (undo your other changes)
ram_read_pointer_y <= (reset_addr << 3) + period_x_rst;  // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= (reset_addr << 3) + period_x_rst;  // the backup and current display address to the exact reset base address during this line.

This allows byte/bitplane sub-pixel horizontal alignment along the X-axis when the sprite begins it's first pixel.  If you like, there is the potential to add 1 other thing to make this add always = to 1 pixel when dealing with 4 color and 16 bit color.  It's useless with 256 color at the base address increments as 1 for moving the image 1 pixel.

Next, the really weird 16 bit pixel mode.  Add this assign:
assign pixel_16_bit         = bp_2_rast_cmd[2];  // setting goes high when we expect 16 bit, 2 byte pixels.

Now, what this setting does is when set to 1, every time the 'X' read address increases, it will need to increase by 2, not 1 as it currently does.  If you truly figure the really simple way to get this one to work right, you will get a prize...   Remember, that 'Increment by 2' doe not affect the lower 3 bits which horizontally position the bitplane sub-pixel positioning.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2019, 07:05:22 pm
You only needed 8 pixels.  Your Z80 fills in the reset address.  This is all you should have written:
Lines 137 & 138: (undo your other changes)
ram_read_pointer_y <= (reset_addr << 3) + period_x_rst;  // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= (reset_addr << 3) + period_x_rst;  // the backup and current display address to the exact reset base address during this line.

This allows byte/bitplane sub-pixel horizontal alignment along the X-axis when the sprite begins it's first pixel.  If you like, there is the potential to add 1 other thing to make this add always = to 1 pixel when dealing with 4 color and 16 bit color.  It's useless with 256 color at the base address increments as 1 for moving the image 1 pixel.

... but that doesn't do what I thought you wanted?  I had in mind, for example for an 8x16 sprite, it would show the letter 'A' and when you scroll it, it would scroll to the left and show the letter 'B' coming in from the right, stopping one pixel short of showing the full tile (for the Z80 to re-set the start address and show the next char completely)?  :-\

Also, the 'new' tile scrolling in from the right is moved up a line?  Is that intended?

Next, the really weird 16 bit pixel mode.  Add this assign:
assign pixel_16_bit         = bp_2_rast_cmd[2];  // setting goes high when we expect 16 bit, 2 byte pixels.

Now, what this setting does is when set to 1, every time the 'X' read address increases, it will need to increase by 2, not 1 as it currently does.  If you truly figure the really simple way to get this one to work right, you will get a prize...   Remember, that 'Increment by 2' doe not affect the lower 3 bits which horizontally position the bitplane sub-pixel positioning.

Erm... well, I'd change lines 151 and 152 to this:

Code: [Select]
ram_read_pointer_y <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 + pixel_16_bit));  // vertical increment display position in backup buffer
ram_read_pointer_x <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 + pixel_16_bit));  // vertical increment display position in current display address

Latest MAGGIE code attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 07:33:01 pm
You only needed 8 pixels.  Your Z80 fills in the reset address.  This is all you should have written:
Lines 137 & 138: (undo your other changes)
ram_read_pointer_y <= (reset_addr << 3) + period_x_rst;  // V_TRIG is high during the first active line of video, set the read pointer, both
ram_read_pointer_x <= (reset_addr << 3) + period_x_rst;  // the backup and current display address to the exact reset base address during this line.

This allows byte/bitplane sub-pixel horizontal alignment along the X-axis when the sprite begins it's first pixel.  If you like, there is the potential to add 1 other thing to make this add always = to 1 pixel when dealing with 4 color and 16 bit color.  It's useless with 256 color at the base address increments as 1 for moving the image 1 pixel.

... but that doesn't do what I thought you wanted?  I had in mind, for example for an 8x16 sprite, it would show the letter 'A' and when you scroll it, it would scroll to the left and show the letter 'B' coming in from the right, stopping one pixel short of showing the full tile (for the Z80 to re-set the start address and show the next char completely)?  :-\

Also, the 'new' tile scrolling in from the right is moved up a line?  Is that intended?
I you are showing 1 pixel less, then you may want to shrike the horizontal width of the window so you don't see the extra junk on the right hand side.  Remember, the text font is 1 byte wide.  Try playing with the 1bit color, B&W graphic I gave you which is multiple bytes wide.  Shifting it to the left 1 pixel at a time will not make the right hand side vertically jump except all the way on the right hand side of the window.  Increase the read reset address by 1 and the image will shift 8 pixels to the left.  Increase the base address by the width byte setting and the image will vertically shift by 1 line.  We have not yet touched tiles/fonts.  You are missing a chunk of code which defines the current vertical location within a tile since you cannot add the current 'Y' address every line at the same character memory needs to be re-read every line while a sub-Y position is needed to compute where to read the font memory a second time around passing through the GPU ram again bases on the contents of the prior read character ram.

I'm curious, have you ever programmed direct HW registers for a video display on an Atari 800, or Amiga?  Did you not know this is how their internal video processors work the same way.  Or are you just used to library calls with do this control 'bit' manipulation under the hood?

Quote
Next, the really weird 16 bit pixel mode.  Add this assign:
assign pixel_16_bit         = bp_2_rast_cmd[2];  // setting goes high when we expect 16 bit, 2 byte pixels.

Now, what this setting does is when set to 1, every time the 'X' read address increases, it will need to increase by 2, not 1 as it currently does.  If you truly figure the really simple way to get this one to work right, you will get a prize...   Remember, that 'Increment by 2' doe not affect the lower 3 bits which horizontally position the bitplane sub-pixel positioning.

Erm... well, I'd change lines 151 and 152 to this:

Code: [Select]
ram_read_pointer_y <= ram_read_pointer_y + ((inc_addr_y[15:0] << 3) * (1+pixel_16_bit));  // vertical increment display position in backup buffer
ram_read_pointer_x <= ram_read_pointer_y + ((inc_addr_y[15:0] << 3) * (1+pixel_16_bit));  // vertical increment display position in current display address

Latest MAGGIE code attached.

EDIT: Hang on - testing a simpler way to do the 16-bit scroll..
Nope, that's wrong.  Right now, every time the horizontal address needs to increase, every 8, 4, 2 ,or every pixel, it increments by 1 address.  Meaning, 1 byte at a time.  We need to double this addition once every 8, 4, 2, or every pixel.  This has nothing to do with the vertical increment as that setting specifies the number of horizontal bytes you source image is.  So, naturally you would just have the correct number set there by the Z80 defining the number of bytes per line in the source graphic.  This is not what I am asking.  When MAGGIE is drawing the image, as it requests every single pixel, when the 16bit setting is high, it needs to recognize that every pixel is 2 bytes (16 bit) wide, not 1 byte.  How will you adapt MAGGIE to handle this.


Think about it this way, if you want color text.  Now don't go into reading the font yet as the font is still 8 bit.  But your memory has an 8 bit character stored as 1 bit monochrome.  And, the upper 8 bits, being read at the same time, stores the 256 possible colors, 16 foreground and 16 background colors.  Now, our ram is already wired to read 16 bits in 1 shot, but, the upper 8 bits is just the adjacent address according to the opposite LSB address as we wired it that way as a backwards compatibility to 8 bit mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2019, 08:01:10 pm
...Shifting it to the left 1 pixel at a time will not make the right hand side vertically jump except all the way on the right hand side of the window.

Okay, well that's what I'm seeing then - way over at the right-hand side of the window, the image is re-appearing, but one line higher.

I'm curious, have you ever programmed direct HW registers for a video display on an Atari 800, or Amiga?  Did you not know this is how their internal video processors work the same way.  Or are you just used to library calls with do this control 'bit' manipulation under the hood?

I've never done anything like this in my life!  Closest I got to the hardware on the Amiga was with Blitz Basic 2 (https://www.amigacoding.com/index.php/Blitz:Versions) when I wrote a Scorched Earth (https://en.wikipedia.org/wiki/Scorched_Earth_(video_game)) clone and some other basic games instead of studying.  ;) So, not even vaguely close.  I hadn't even really touched assembly on my Amstrad as a kid; I've learned the vast majority of what I know in the last two years working on my DIY computer.  It's been a learning curve!  :o

Nope, that's wrong.  Right now, every time the horizontal address needs to increase, every 8, 4, 2 ,or every pixel, it increments by 1 address.  Meaning, 1 byte at a time.  We need to double this addition once every 8, 4, 2, or every pixel.  This has nothing to do with the vertical increment as that setting specifies the number of horizontal bytes you source image is.  So, naturally you would just have the correct number set there by the Z80 defining the number of bytes per line in the source graphic.  This is not what I am asking.  When MAGGIE is drawing the image, as it requests every single pixel, when the 16bit setting is high, it needs to recognize that every pixel is 2 bytes (16 bit) wide, not 1 byte.  How will you adapt MAGGIE to handle this.

Ah okay, back to the drawing board.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2019, 08:12:54 pm
Now I want you to think out of the box here.  Having the ram read address increment 2 for every 1 pixel instead of 1 for every 1 pixel, yet not touch the sub-bitplane-pixel counter isn't hard with a little thought.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 17, 2019, 02:39:08 pm
It's no good, I've gone code-blind staring at MAGGIE trying to work out exactly WHERE ram_read_pointer_x is incremented by one pixel.   :o |O 

Should I be looking to make changes in the if (run_x) begin block?

Also notice inc_addr_x isn't used at all?  Is that for a later feature?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2019, 06:30:30 pm
Yes, the ram read pointer is being incremented inside the if(run_x).
At line 174.

But if you think about it, you might run into trouble here as the sub-pixel X position is also buried into the X increment here.  You don't want to alter how the bit-plane sub pixel positioning is generated.

Try looking at line 98.  You might be able to come up with a few ideas there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 17, 2019, 07:59:46 pm
Yes, the ram read pointer is being incremented inside the if(run_x).
At line 174.

But if you think about it, you might run into trouble here as the sub-pixel X position is also buried into the X increment here.  You don't want to alter how the bit-plane sub pixel positioning is generated.

Try looking at line 98.  You might be able to come up with a few ideas there.

Okay, so here's what I'm thinking.  This is where the ram_read_pointer is incremented by a value relating to the mode (line 183 in my MAGGIE):

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
If MAGGIE is operating in 16-bit mode, this needs to add another 8 bits on this line?  So something like this?

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte + 8 * pixel_16_bit;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2019, 08:22:11 pm
Yes, the ram read pointer is being incremented inside the if(run_x).
At line 174.

But if you think about it, you might run into trouble here as the sub-pixel X position is also buried into the X increment here.  You don't want to alter how the bit-plane sub pixel positioning is generated.

Try looking at line 98.  You might be able to come up with a few ideas there.

Okay, so here's what I'm thinking.  This is where the ram_read_pointer is incremented by a value relating to the mode (line 183 in my MAGGIE):

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte;
If MAGGIE is operating in 16-bit mode, this needs to add another 8 bits on this line?  So something like this?

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte + 8 * pixel_16_bit;
Still thinking inside the box...  ;)

Unfortunately, with your code, when in 1 bitplane mode, 16 bit pixel, you will increment the X address every pixel, plus increment the X address twice every 8th pixel.  With a 16 bit data pixel, we would still want the X to increment twice every 8 pixels, but not during the middle of the 7 pixels of the bitmap.

Take a long hard look at line 98 once again and ask yourself, this read address increases by 1 at the right time, in 16 bit mode, when it increases by 1, I want it to increase by 2 instead...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 17, 2019, 11:59:43 pm
Unfortunately, with your code, when in 1 bitplane mode, 16 bit pixel, you will increment the X address every pixel, plus increment the X address twice every 8th pixel.  With a 16 bit data pixel, we would still want the X to increment twice every 8 pixels, but not during the middle of the 7 pixels of the bitmap.

Take a long hard look at line 98 once again and ask yourself, this read address increases by 1 at the right time, in 16 bit mode, when it increases by 1, I want it to increase by 2 instead...

Okay, so I tried this:
Code: [Select]
assign read_addr[19:0] = ram_read_pointer_x[22:3] + 8*pixel_16_bit;
Didn't work. :-\

And I tried this in if (run_x) begin:
Code: [Select]
if (width == 0) begin

ram_read_pointer_x <= ram_read_pointer_x + 8*pixel_16_bit;

end

Didn't work. :-[

The idea being with the above piece of code was to add 8 bits to the pixel address pointer at the end of the tile...  :-//  I think the problem is, I don't fully understand what the existing code is doing.  If I did, I'd see the bigger picture and probably find the solution, even if it's not the most efficient way to do what you're asking.  But as it is, I'm almost groping in the dark for the solution.

So, I want MAGGIE to read a pixel, which is represented in memory by 1, 2, 4 or 8 bits.  In 8-bit mode, the next pixel immediately follows on from the current one, so line 184 handles this increment to the next pixel, incrementing ram_read_pointer_x by 1, 2, 4 or 8 bits according to the mode.  However, in 16-bit mode, the pixel size remains the same (either 1, 2, 4 or 8 bits in size, specified by the 2 LSBs), but for each increment we need to skip a byte which contains palette or colour information??

This is my understanding of how MAGGIE is working, in a nutshell and to me the solution is to change line 184 to add 8 bits to ram_read_pointer_x every time it increments to skip the current pixel's associated palette/colour byte??  This means:

Code: [Select]
ram_read_pointer_x <= ram_read_pointer_x + 2**pixel_per_byte + 8*pixel_16_bit;
...but then I remember that for all the sub-pixels in the same tile, they share the same colour/palette byte, so incrementing by the extra 8 bits isn't necessary until the end of the tile.  But then I'm getting confused with tiles, sprites and variable widths, etc.  But where in the code does the 'end of tile' trigger occur?

 |O :horse:

I'm off to bed. Perhaps all this might make more sense tomorrow.  :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 18, 2019, 03:45:52 am
Ok, I'll give you half of this one.  Line 98 should be:

assign read_addr[19:0]      = ram_read_pointer_x[22:3] << pixel_16_bit;

This multiplies the ram read pointer address by 2 when in 16 bit mode.
Now, you need to patch 4 other lines so that the read address is still correct during reset and image width setting.  See lines 137,138, & 146,147.

If you coded things correctly, when viewing my 256 color test image, enabling the 16 bit mode should horizontally shrink the image in half with a replica image to the right of it shifted up by 1 line.

If you got this working, we will tackle the getting rid of the old OSD text and wire in 2 MAGGIES in it's place to generate text, including color text.  Then, the palette mixer will need re-working to accept 5 inputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 18, 2019, 08:47:08 am
Ok, I'll give you half of this one.  Line 98 should be:

assign read_addr[19:0]      = ram_read_pointer_x[22:3] << pixel_16_bit;

This multiplies the ram read pointer address by 2 when in 16 bit mode.

:wtf:  Now this is where bit operations start to look like a dark art to me.  :-\  ram_read_pointer_x is a 20-bit address, pointing to the current pixel.  Bit-shifting that value left 1 place if in 16-bit mode doubles the value, why would that doubled value point to the next byte?

If ram_read_pointer_x is, e.g., 0x40 - doubling that to 0x80 via a <<1 operation won't point to the next byte, it'll point to an arbitrary area of RAM, an increasing distance from the previous memory location as the address increases?  If ram_read_pointer_x is operating anywhere in the top half of memory, this operation will put the pointer out of bounds, surely?   :-//

EDIT:  Ignore the above - boy did my thoughts go off on a tangent there!!  :-DD

Of course it won't double the number (at least not in the sense that it will exceed the top of memory) as it's capped at 20 bits.

Now, you need to patch 4 other lines so that the read address is still correct during reset and image width setting.  See lines 137,138, & 146,147.

Our line numbers are out of sync - 147 is an empty line, and the others don't make much sense.  Rather than try to guess which lines you're talking about (139,140 and 151, 152 presumably), here's the latest version of MAGGIE; if you use this one, the line numbers you're quoting will match up to what I'm seeing.

EDIT:  I'm off to go learn more about bit-shift operations (well, the concepts we're dealing with more than the operations themselves). :o  There's clearly a hole in my understanding here.  But bit-wise tantrum aside, here's what I've done with MAGGIE to get 16-bit mode working as you've specified:

Code: [Select]
Line 139: ram_read_pointer_y <= (reset_addr << (3 - pixel_16_bit)) + period_x_rst; // V_TRIG is high during the first active line of video, set the read pointer, both
Line 140: ram_read_pointer_x <= (reset_addr << (3 - pixel_16_bit)) + period_x_rst; // the backup and currrent display address to the exact reset base address + x_offset during this line

Line 151: ram_read_pointer_y <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 - pixel_16_bit));  // vertical increment display position in backup buffer
Line 152: ram_read_pointer_x <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 - pixel_16_bit));  // vertical increment display position in current display address

I've just countered the doubling of ram_read_pointer by only shifting it left twice instead of 3 times in 16-bit mode.  Seems to work - the image is doubled, as you stated.  ^-^

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 18, 2019, 09:59:35 am
Just in case you want photographic evidence.  ;)

8-bit mode:
[attach=1]

16-bit mode:
[attach=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 18, 2019, 08:25:27 pm
Ok, you got that all correct.

Now, 1 last thing before making wiring the MAGGIE into text mode.  A font 'Y' coordinate counter.

This one is weird as it sort of sits in parallel with the 'Y' period counter, but, it needs to either be off, count between 0 and 7, or 0 and 15.  It needs to increment after every number of period sequence counts for the 'Y' scale, yet, it also needs to prevent the height, height_count and inc_addr_y[15:0] from taking place until it reaches it's end.

Lets add an assign:
assign font_y_size[3:0] = hw_regs[Y_SCALE][7:4];

font_y_size will define the height of the font.  With this, you should be able to define a font tile size of '0' being 1 line font, to 15, being a font 16 lines tall.

The second assign will be: (It is actually taking the place of the 'period_y_rst[3:0]')
assign font_y_rst[3:0] = hw_regs[Y_START_SUB][3:0];

This reset position will define the beginning first line to be shown of the font at the top left hand of the window.  It performs the equivalent function to the bitplane's period_x_rst.


Now, you will also need a reg:
font_y_pos[3:0]

This reg will reg will hold the counter of the current display's font's 'Y' coordinates.

Let's see how you weave the font Y position into the current 'Y' coordinate counting system.  Unfortunately, there is nothing for you to display and if you haven't set up a simulation, you will have to guess/assume your results as a vertical font size of '7' ie 8, should stretch your picture vertically 8 fold.

To properly test this, we would need to wire the 2xMAGGIEs in place of the current text generator, assign the font Y coordinates to the cmd_out, and make the font 'SLAVE' mode in the second MAGGIE receive the command in, process it's base address with the incoming memory character data and font Y coordinates buried in the cmd_in port, and generate a new output address to sen to the memory to read a second time to fetch the font image to send to the BART for display.

This is the last of the truly tricky stuff.  Once done, we will fix up the palette mixer to handle multiple inputs, combine the 2 palettes (4444 & 565) into 1 larger palette and touch up how the layers are blended.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 18, 2019, 08:42:10 pm
Ok, I'll give you half of this one.  Line 98 should be:

assign read_addr[19:0]      = ram_read_pointer_x[22:3] << pixel_16_bit;

This multiplies the ram read pointer address by 2 when in 16 bit mode.

:wtf:  Now this is where bit operations start to look like a dark art to me.  :-\  ram_read_pointer_x is a 20-bit address, pointing to the current pixel.  Bit-shifting that value left 1 place if in 16-bit mode doubles the value, why would that doubled value point to the next byte?

If ram_read_pointer_x is, e.g., 0x40 - doubling that to 0x80 via a <<1 operation won't point to the next byte, it'll point to an arbitrary area of RAM, an increasing distance from the previous memory location as the address increases?  If ram_read_pointer_x is operating anywhere in the top half of memory, this operation will put the pointer out of bounds, surely?   :-//

EDIT:  Ignore the above - boy did my thoughts go off on a tangent there!!  :-DD

Of course it won't double the number (at least not in the sense that it will exceed the top of memory) as it's capped at 20 bits.

Now, you need to patch 4 other lines so that the read address is still correct during reset and image width setting.  See lines 137,138, & 146,147.

Our line numbers are out of sync - 147 is an empty line, and the others don't make much sense.  Rather than try to guess which lines you're talking about (139,140 and 151, 152 presumably), here's the latest version of MAGGIE; if you use this one, the line numbers you're quoting will match up to what I'm seeing.

EDIT:  I'm off to go learn more about bit-shift operations (well, the concepts we're dealing with more than the operations themselves). :o  There's clearly a hole in my understanding here.  But bit-wise tantrum aside, here's what I've done with MAGGIE to get 16-bit mode working as you've specified:

Code: [Select]
Line 139: ram_read_pointer_y <= (reset_addr << (3 - pixel_16_bit)) + period_x_rst; // V_TRIG is high during the first active line of video, set the read pointer, both
Line 140: ram_read_pointer_x <= (reset_addr << (3 - pixel_16_bit)) + period_x_rst; // the backup and currrent display address to the exact reset base address + x_offset during this line

Line 151: ram_read_pointer_y <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 - pixel_16_bit));  // vertical increment display position in backup buffer
Line 152: ram_read_pointer_x <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 - pixel_16_bit));  // vertical increment display position in current display address

I've just countered the doubling of ram_read_pointer by only shifting it left twice instead of 3 times in 16-bit mode.  Seems to work - the image is doubled, as you stated.  ^-^

You are thinking of this the wrong way.  I'm multiplying the read address by 2.  So, if you start at read address 0, then increase to 1, then increase to 2, then 3, the output will be 0, 2, 4, 6.  IE, every increment of 1 jumps 2 instead.

Now, the initial starting address, and Y increment every line, those we are dividing by 2, so when beginning a line, they also begin the memory address at the right position.

However, you may notice that we have lost the first address bit, or, the possibility of addressing ODD pixels here.  This is fine.  We will not be starting a display's memory address at an ODD memory location when using 16bit wide pixels.  Sort of like when using a 68000 to copy & manipulate 16bit pointers.  It also wants even word aligned address pointers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 19, 2019, 04:04:01 pm
Now, 1 last thing before making wiring the MAGGIE into text mode.  A font 'Y' coordinate counter.

This one is weird as it sort of sits in parallel with the 'Y' period counter, but, it needs to either be off, count between 0 and 7, or 0 and 15.  It needs to increment after every number of period sequence counts for the 'Y' scale, yet, it also needs to prevent the height, height_count and inc_addr_y[15:0] from taking place until it reaches it's end.

Lets add an assign:
assign font_y_size[3:0] = hw_regs[Y_SCALE][7:4];

font_y_size will define the height of the font.  With this, you should be able to define a font tile size of '0' being 1 line font, to 15, being a font 16 lines tall.

The second assign will be: (It is actually taking the place of the 'period_y_rst[3:0]')
assign font_y_rst[3:0] = hw_regs[Y_START_SUB][3:0];

This reset position will define the beginning first line to be shown of the font at the top left hand of the window.  It performs the equivalent function to the bitplane's period_x_rst.


Now, you will also need a reg:
font_y_pos[3:0]

This reg will reg will hold the counter of the current display's font's 'Y' coordinates.

...it needs to either be off, count between 0 and 7, or 0 and 15.

How is this decided?  Which HW_regs value am I using (if any) to set this behaviour?  Is this based on the screen mode?

Right, time is short for me these next few days so I'm going to try to make small changes in the time I have and post them up here for checking.  I've added the wire and reg you've mentioned above, and also the counting system to increment font_y_pos.  That's all it does at the moment - no checks or actions - it just increments the counter (hopefully in the right positions!)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2019, 09:07:55 pm
Ok, to begin, ok so far.  Yes, implementation is all messy.

The 'font_y_pos' limit is set by the  font_y_size hw_reg.  Having a  font_y_size of 0 means every new line is a new vertical address increment, or just call that mode 'OFF'.  Setting the  font_y_size to 7 means the Y font_y_pos will count from 0, 1, 2,... 7 before a inc_addr_y.  This means you font has 8 vertical position, or a font of 8x8.  Also, don't forget with the period_y setting, each of those 8 positions may be repeated 1, 2,3,4,...16 times stretching out you text vertically.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 20, 2019, 07:10:54 pm
Some changes made around lines 160-180 to reset font_y_pos at the right time.  I'm not convinced it's right, though, as I'm confused about what is required and how to implement it.

So font_y_pos should increment on each pc_ena[3:0]==0 clock, if run_y is true, and not allow increments to height_count unless font_y_size is zero or font_y_pos == font_y_size, in which case allow a vertical increment to occur..... hmm.  No, I'm confused about this bit.  The whole if (run_y) begin block needs a close look at - this is where I'm presuming all the font_y_pos tweakery goes on, but I'm unsure what I should be doing.  I'd need a whole day to filter out the conditions of what you're asking for, then to try to understand MAGGIE in more detail than I do currently to then make the modifications to get it all to work as you want.  I'm struggling with time at the moment.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 20, 2019, 07:22:14 pm
Since you arent simulating, you are going to have to wire everything in.
Remove the old OSD text and wire in 2 MAGGIEs on the first 2 read ports, assign H&V + normal HW regs for each, and on the second MAGGIE's ram output, wire that one's BART's output into the palette mixer's text layer input and begin to play, except, the current MAGGIE is missing the function to receive the last MAGGIE's memory character and point to a font memory address.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 20, 2019, 07:34:25 pm
Remove the old OSD text and wire in 2 MAGGIEs on the first 2 read ports...

So when you say 'remove the old OSD text', are you just talking about disconnecting read_text_addr and read_font_addr from the gpu_RAM in the vid_osd_generator, or completely replacing the vid_osd_generator with a module that handles the two MAGGIEs?

...assign H&V + normal HW regs for each, and on the second MAGGIE's ram output...

That would be the data_out#x from the gpu_RAM to the BART, right?

...wire that one's BART's output into the palette mixer's text layer input and begin to play, except, the current MAGGIE is missing the function to receive the last MAGGIE's memory character and point to a font memory address.

 :o Will have a go this weekend...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 20, 2019, 07:44:27 pm
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2826458/#msg2826458 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2826458/#msg2826458)

Since your current palette mixer has only 2 inputs, you will have to use the second MAGGIE's/BART's read channel to feed the first input of the current 2 channel palette mixer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 20, 2019, 07:45:12 pm
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2826458/#msg2826458 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2826458/#msg2826458)

Already using it.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 20, 2019, 07:46:58 pm
Since your current palette mixer has only 2 inputs, you will have to use the second MAGGIE's/BART's read channel to feed the first input of the current 2 channel palette mixer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 22, 2019, 05:45:39 pm
I just don't have the time to put into this at the moment.  :-[ I started trying to wire up the two MAGGIEs and their BARTs in the vid_osd_generator a few days back and have come back to it to work on it again for half an hour and spent that time trying to work out where I was with it all instead of progressing it further.  :palm:

Doesn't help that I feel what you've asked me to do should be easy, but I'm struggling with it and feel that I've used up my question quota and should understand it all by now.  :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2019, 09:38:12 am
Merry Christmas,

I've done a huge deal of work for you, something like 2-3 months worth based the current trend.

Here is all the work I have done:

Increased ram to 28672 bytes + 1024 bytes for the palette filling out your current Cyckone IV.

The main GPU ram begins at address 0 and reads/writes up until byte 28671. (address $6FFF).

The palette is currently stored at $007C00 through $007FFF.  The first 512 bytes is the ARGB 4444 palette while the second 512 bytes is the RGB 565 palette.

HW_regs now begin at address $006F00 through $6FFF.

MAGGIE code has been patched and text_mode_master/slave have been implemented.

Added MAGGIEs 0 through 4, 5 graphics layers in total.

When presenting bitmap/tile windows, the top MAGGIE, lower MAGGIE # has higher priority / sits above the lower ones.

All of the MAGGIEs have their HV resets set to HV_Trigger 8 & 9.

MAGGIE H&V top left window position begin with MAGGIE 0 @ 10 & 11.  Increase each HV trigger pair for each sequential MAGGIE.

MAGGIE 0 control HW_regs + 128 bytes, for 16 bytes.  Increase 16 bytes for each sequential MAGGIE.

When using text/font/tile mode, 2 adjacent MAGGIES must be used.  The first one must have the 'text_mode_master' bit set in the 'BP2RAST_cmd' while the second MAGGIE must have the 'text_mode_slave' bit set in the 'BP2RAST_cmd'.  The 'BP2RAST_cmd' video mode in both must match except in the master where the BP2RAST_cmd video enable [4] must be disabled, otherwise you will get junk on the screen.

The 16 control bytes for the 'text_mode_master' MAGGIE points to the text/tile IDs.  All other controls are identical as when using it as a bitmap graphics window.  The 'font_y_size', combined upper bits of '{hw_regs[Y_START_SUB][7:6],hw_regs[Y_SCALE][7:4]}' in the text_mode_master which must also be set to the font/tile height -1. EG: 0=1 line, 7=8lines, 15=16lines, 31=32lines when in text/font/tile master mode...

For the 'text_mode_slave' MAGGIE, the only functioning 4 controls are the 'reset_addr' which now points to the base memory address of the font/tiles graphics data, period_x[4] which defines a font being 16 pixels wide when set, or, 8 pixels when low, period_x[3:0] which mask out the upper bits for fonts/tile addressing for 256, 512, 1024, 2048, 4096 characters (used in 16 bit addressing mode, otherwise set these bits to 0), period_y[1:0] which defines the font height, 0=8, 1=16, 2=32, 3=64 lines tall, and 'BP2RAST_cmd' which should match the text_mode_master MAGGIE settings except for the master and slave bit.

All base memory address settings should be on an even byte when using 16 bit mode.  Fonts/tile graphics data should always begin on an even byte address.

BART has been patched to embed the .window_ena_out,.mode_16bit,.mode_565 into it's .pixel_out bus.

Palette_mixer has been updated to receive the new BART's .pixel_out bus with the embeded .window_ena_out,.mode_16bit,.mode_565.
The palette is now 512 entries wide, with the 4444 color palette occupying the first 256x16 entries while the 565 palette occupies the second 256x16 entries.
It also now has 5 inputs which get mixed together to form 1 output.

This means without text, you can mix 5 on-screen sprites, or, 1 text layer and 4 sprites.
Other than a ram limitation, there are no other output limitations.  Any mode ant any res with any palette may be all mixed simultaneously onscreen.

Right now, I disables the linear translucent alpha blending for a basic transparent of opaque pixel on each sprite layer until I figure out a good way to accomplish this across multiple layers without filling up your tiny FPGA.  Maybe we can reserve the alpha blend technique for 2 sets of different paired layers while going back to basic stencil layering between all the remaining layers.

I'm having trouble with clock domain crossing in trying to get the 2x core GPU ram working which will give you all 15 graphic layers.  Running everything at 2x clock would be simple, but I don't have the time to optimize your code to make this cyclone run at 250MHz.

Let's see if I can find the bug over the next day or 2.

Everything else is ready for you to get you Z80 running.

See the attached files and check the RS232_debugger quick load files which have a 16bit color text demo with 3 additional scaled sprites onscreen.  Photograph to make sure that everything works.  If you want nicer graphics, you will have to start generating you own files...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2019, 09:58:25 am
There has been so many changes, you will need to throw out your old project folder.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 25, 2019, 03:34:57 pm
Wow - thank you so much!!   :-+

Okay, so I've got some documentation to do and some work on the Z80 interface (the mux with the RS232_debugger interface is nowhere near done yet) and it's done.  ^-^

Merry Christmas to you too!! (and anyone else reading this!)

[attach=1]

[attach=2]

In the image above, the white fade-out on the right-side of the Z80 image isn't a photographic artefact - could that be caused by capacitance in the output wires?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2019, 06:29:49 pm
In the image above, the white fade-out on the right-side of the Z80 image isn't a photographic artefact - could that be caused by capacitance in the output wires?
Strange.  Since I'm using a real DAC, I see nothing but a perfect image on my end.  Maybe something happened with the IO current strength settings, or, too much on screen for the the method of the analog dac.

When you have time, see if you can get a scope shot.

BTW, I now have all 15 layers working now on my side, but, your Cyclone IV is too small.  Maybe I will come up with an idea.  1 Cyclone larger and 15 would be no problem on your side too as you are ran out of logic cells and ram needs to shrink to fit the design as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2019, 06:41:27 pm
Wow - thank you so much!!   :-+

Okay, so I've got some documentation to do and some work on the Z80 interface (the mux with the RS232_debugger interface is nowhere near done yet) and it's done.  ^-^

Merry Christmas to you too!! (and anyone else reading this!)

(Attachment Link)

(Attachment Link)

In the image above, the white fade-out on the right-side of the Z80 image isn't a photographic artefact - could that be caused by capacitance in the output wires?

Check your IOs as I have made the outputs 24 bits instead of 12 bits.  You only want the upper 12 bits [7:4] wired to the DAC pins.  Maybe check IO assignments as you may be using the lower IOs or having new adjacent IOs new interfering with the video.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 25, 2019, 07:07:28 pm
Strange.  Since I'm using a real DAC, I see nothing but a perfect image on my end.  Maybe something happened with the IO current strength settings, or, too much on screen for the the method of the analog dac.

When you have time, see if you can get a scope shot.

Will check IOs when I get the time - it probably doesn't help that I've got wires from the FPGA board to the resistor DAC breadboard, then more wires to the VGA connector.  I'm waiting on a couple of parts to arrive in the post then I'll have a proper PCB-based 24-bit DAC up and running.

BTW, I now have all 15 layers working now on my side, but, your Cyclone IV is too small.  Maybe I will come up with an idea.  1 Cyclone larger and 15 would be no problem on your side too as you are ran out of logic cells and ram needs to shrink to fit the design as well.

Hmm.. I knew this Cyclone IV board was cheap, but it's got the smallest Cyclone IV imaginable on it!  >:(

Well, I'm guessing the Lattice LFE5U won't have these issues.

Check your IOs as I have made the outputs 24 bits instead of 12 bits.  You only want the upper 12 bits [7:4] wired to the DAC pins.  Maybe check IO assignments as you may be using the lower IOs or having new adjacent IOs new interfering with the video.

Hmm.. will go check this in a bit.  :-+

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 25, 2019, 08:18:23 pm
Check your IOs as I have made the outputs 24 bits instead of 12 bits.  You only want the upper 12 bits [7:4] wired to the DAC pins.  Maybe check IO assignments as you may be using the lower IOs or having new adjacent IOs new interfering with the video.

Yeah, that's an improvement.  I can see the HV_trigger lines around edges now, too.  There is still a very faint amount of 'runoff' from the white background on the sprite into the black background behind it, but nowhere near as noticeable as before.  I'm no electronics expert, but I'd be happy to bet that once I've got a less 'cobbled-together' DAC created, that runoff will disappear.

Thanks again, BrianHG.  Hope you're taking a break over the holiday season?!!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2019, 10:41:44 pm
Hmm.. I knew this Cyclone IV board was cheap, but it's got the smallest Cyclone IV imaginable on it!  >:(

Well, I'm guessing the Lattice LFE5U won't have these issues.

Check your IOs as I have made the outputs 24 bits instead of 12 bits.  You only want the upper 12 bits [7:4] wired to the DAC pins.  Maybe check IO assignments as you may be using the lower IOs or having new adjacent IOs new interfering with the video.

Hmm.. will go check this in a bit.  :-+

Well, 15 layers as the current project stands takes 11K logic gates and your CycloneIV has 6K.
To turn back on transparency between a number of layers, add 1K-2k more gates as it is all a bit table of 3x3x3 multiply adds.

I just compiled the project with the LFE5U settings as my old CycloneIII EP3C55 has the gates and ram for the job.  It takes 17% of the logic elements and 76% of the ram bits with over 220kilobytes of graphics ram.  The Lattice LFE5U is 10% smaller FPGA, so no problem there.

With the addition of a 1$ DDR ram chip on you PCB, you can reserve 1 MAGGIE channel to that ram controller and get a 32 bit graphics layer with 16mb of addressable space.  Making a DDR ram controller which only has to deal with a single 27million pixels a second read and a Z80 at 2-8 million transactions a second is a joke compared to the all the cross-reads going between all the other 14 MAGGIEs which read all random memory locations every-which-way as I designed the core to do so.

Basically you would treat the onboard 220kb as texture and sprite memory as the bulk DDR ram would be for background and swapping of large chunks of additional animation graphics.

The rest of the FPGA logic would be 75% empty for a cool hardware accelerated drawing engine.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 25, 2019, 11:37:20 pm
Well, 15 layers as the current project stands takes 11K logic gates and your CycloneIV has 6K.
To turn back on transparency between a number of layers, add 1K-2k more gates as it is all a bit table of 3x3x3 multiply adds.

I'm making a start on designing a custom board for an LFE5U - it'll be a few months and probably a few test runs before I get to attaching a BGA to a custom board, but once that's done it seems the sky is the limit.

With the addition of a 1$ DDR ram chip on you PCB, you can reserve 1 MAGGIE channel to that ram controller and get a 32 bit graphics layer with 16mb of addressable space.  Making a DDR ram controller which only has to deal with a single 27million pixels a second read and a Z80 at 2-8 million transactions a second is a joke compared to the all the cross-reads going between all the other 14 MAGGIEs which read all random memory locations every-which-way as I designed the core to do so.

DDR RAM, not the SDRAM that I've got on the dev board at the moment?  Might have to look into that - very tempting.

Basically you would treat the onboard 220kb as texture and sprite memory as the bulk DDR ram would be for background and swapping of large chunks of additional animation graphics.

The rest of the FPGA logic would be 75% empty for a cool hardware accelerated drawing engine.

 :o  Sounds awesome.  I wish I had 10% of the knowledge you have with FPGAs..  but then I'd be in a different career, I guess.

Random question - would there be any mileage in a hardware scrolling capability for text mode?  Specifically, I was thinking of using the sub-pixel offset capabilities to scroll text upwards (or downwards) when a new line is written to a single-line buffer which would be 'off the top or bottom of screen' and not visible?  Or having a 'viewport sub-pixel' setting, to allow the entire screen (of text) to be smoothly scrolled by offsetting the viewport up to a single line of text?  Too much work for little payoff?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 26, 2019, 12:19:35 am
Random question - would there be any mileage in a hardware scrolling capability for text mode?  Specifically, I was thinking of using the sub-pixel offset capabilities to scroll text upwards (or downwards) when a new line is written to a single-line buffer which would be 'off the top or bottom of screen' and not visible?  Or having a 'viewport sub-pixel' setting, to allow the entire screen (of text) to be smoothly scrolled by offsetting the viewport up to a single line of text?  Too much work for little payoff?

It's all there.  If you hadn't noticed, I literally finished your graphics engine.  Sup-pixel scrolling is there.  As well as modifying the base address to shift 1 character at a time, or a line at a time.  Including the source bitmap/raster 'width' setting which allows you to set a display width of up to 65535 characters wide.  This is how side scrolling video games like Super Mario Bros is where the backdrop is nothing more that character tiles from a font memory with a horizontal display set larger than the width of the screen.  With what you have now, memory limiting of course, you can use 16 bit characters for a 4096 character font of 4x8 or 4x16 pixels, or 8x8/8x16 pixels to make a huge display of regular repeated items.  Or, you can use multiple layers in graphics modes, 1 for a bottom background, next layer for onscreen animated objects and another layer or 2/3.../10 for player sprites.

Even the soft blending in the palette mixer is there, I just removed the multiplies in place for a layer switch, but, all the controls and assigns are present.

Your just going to have to learn play and re-document every control to date to get a feel for what is possible.
Though I specified all the control names and they are all organized into defparams in the beginning of the MAGGIE & BART, you still need to fill the ram with usable image data and play with all the controls to see what happens.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 27, 2019, 07:46:45 am
How to generate rich compact code in C++17 for x86, though the code example here is also finally translated into 6502 for the Commodore C64, the example output given here is assembled into x86 code, and the presenter shows you how to generate Z80 driven bitmap graphics and color tables using the right C++17 headers in the compiler to make the tiniest, most compact Z80 assembly code possible which directly addresses memory in connected hardware.  He gets the C++17 to actually synthesize bitplane data from arrays and encode them into the smallest x86 assembly possible.  You would just need to get a x86 to Z80 converter, or a direct Z80 output of the C++ compiler.

https://www.youtube.com/watch?v=zBkNBP00wJE (https://www.youtube.com/watch?v=zBkNBP00wJE)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2019, 07:16:18 am
 :phew: Ok, here is the GPU, with the core ram at 250MHz.  Though I selected the -C7 FPGA, in -C8 it is so close to 250MHz, it should still work fine. (My Cyclone III -C8 works fine and it compiles with even a slightly slower FMAX (220MHz) than the Cyclone IV -C8 (238MHz) The -C7 compiles with a 270MHz FMAX.)

Here are the changes:
Code: [Select]
Latest memory layout.

24576 = size of current GPU ram

    0 -   511 = All HW_Regs shared with generic GPU RAM.
                00 thru 07 = H&V triggers for 4 yellow test cursors
                12..15     = H&V triggers which is the H&V reset coordinates for all 15 MAGGIE_Layer#s
                16..19  +  2*MAGGIE_Layer# = H&V Top left edge of each MAGGIE_Layer# window.
                    96  + 16*MAGGIE_Layer# = 16 byte controls for each of the 15 MAGGIE layers.


  512 -  4607 = Default IBM VGA 8x16 Font
 4608 -  7007 = Default ASCII text buffer, 80 characters x 30 lines (MAGGIE 0&1)

 7008 -  8207 = Color text buffer, 2 bytes per character, 40 characters x 15 lines.  (MAGGIE 2&3)
13056 - 24575 = 16 color Z80 CPU graphic image. (Rendered at 3 sizes across 3 different palettes, MAGGIE 4,5,6)

31744 - 32255 = Primary palette, ARGB 4444 style.
32256 - 32767 = Secondary palette, RGB 565 style.


New GPU project parameters:
NUM_LAYERS   = 2 through 15 = 2 layers through 15 layers.
PALETTE_ADDR = Sets the base address for the 2 palettes.
               This one is automatically set to (2**ADDR_SIZE - 1024), so the palettes are the last 1024 bytes.

Though you lost a little ram because of the all 16bit core, and memory allocation size parameter, you now have 7 active layers.  And with this final code, all you need to do is change the parameter setting on the block diagram to 15 to get 15 layers as well as increase memory size once you get a larger FPGA as the HW Regs is now at the bottom of the ram, it will always powerup to the right default settings.

The only thing missing is the semi-translucent layer feature which I will finish off tomorrow.  However, turning the feature on may eat more logic cells, lowering your layer count since now you are at 94% utilization with 7 layers.

All the other changes means I also had to update the RS232_Debugger files.
Send photos of the powerup test screen once compiled.  I hope it works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2019, 09:15:01 am
:phew: Ok, here is the GPU, with the core ram at 250MHz.  Though I selected the -C7 FPGA, in -C8 it is so close to 250MHz, it should still work fine. (My Cyclone III -C8 works fine and it compiles with even a slightly slower FMAX (220MHz) than the Cyclone IV -C8 (235MHz) The -C7 compiles with a 270MHz FMAX.)

 :o :clap:

[attachimg=1]

That looks great!  Well done!!

Though you lost a little ram because of the all 16bit core, and memory allocation size parameter, you now have 7 active layers.  And with this final code, all you need to do is change the parameter setting on the block diagram to 15 to get 15 layers as well as increase memory size once you get a larger FPGA as the HW Regs is now at the bottom of the ram, it will always powerup to the right default settings.

I've just scanned through the changes - I'm liking the vid_osd_generator parameters and starting GPU RAM contents file.  It's all working, as the screenshot above shows.  Thank you so much for this! :-+

The only thing missing is the semi-translucent layer feature which I will finish off tomorrow.  However, turning the feature on may eat more logic cells, lowering your layer count since now you are at 94% utilization with 7 layers.

I can manage without that for the moment until I get a bigger FPGA sorted ;) - I've been working on getting the Z80_bridge and data_mux modules finished (though that sounds like I've actually had any time to work on them - I've basically just sorted out the wiring for them so far); when I get more time I'll see about getting a Lattice dev board done.

Thanks again.  ^-^

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2019, 09:53:52 am
It's a close match to my board's display on a CRT...

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2019, 10:14:17 am
DVI output on LCD version:

[attachimg=1]

In person, the CRT obviously looks best!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2019, 11:03:40 am
In person, the CRT obviously looks best!

Seems you can't beat quality CRT output.  :)

It's a quiet morning here at the moment, so I've just soldered together my 12-bit resistor DAC since the SSOP 74HCT541s I ordered arrived this weekend.  Have gone from this:

[attach=1]

... to this:

[attach=2]

... and the run-off in the white areas has pretty much disappeared.  It plugs straight into the dev board, so no annoying jumper cables anymore. ;) Just waiting on an ADV7125 to arrive in the post and I'll have a 24-bit DAC to use in its place as well.  :-+

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2019, 01:01:19 pm
 |O

I'm trying to make some progress on the data_mux to gate the RS232 and Z80_bridge I/O to the GPU RAM.  I'm making baby steps, and testing as I go, but something really odd is going on.

In the attached project, the RS232_debugger should NOT be able to read or write to the GPU RAM.  I've only attempt to implement reading anyway, but the data_mux should be disabled, yet when I test the project it works normally (reading AND writing)...  :-//

Note that this isn't the latest version of the project, but it is the latest version of the data_mux work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2019, 07:04:28 pm
|O

I'm trying to make some progress on the data_mux to gate the RS232 and Z80_bridge I/O to the GPU RAM.  I'm making baby steps, and testing as I go, but something really odd is going on.

In the attached project, the RS232_debugger should NOT be able to read or write to the GPU RAM.  I've only attempt to implement reading anyway, but the data_mux should be disabled, yet when I test the project it works normally (reading AND writing)...  :-//

Note that this isn't the latest version of the project, but it is the latest version of the data_mux work.
Ok, you made a few booboos.  Take a look at the changes I made on the main .bdf and inside your bridge.

You have too many cross versions of everything going around....
You will eventually need to upgrade everything to my 7-layer MAGGIE version as it is not backwards compatible as you have things now...

This means re-editing the top .bdf as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2019, 08:01:59 pm
You have too many cross versions of everything going around....
You will eventually need to upgrade everything to my 7-layer MAGGIE version as it is not backwards compatible as you have things now...

This means re-editing the top .bdf as well.

Yeah, I'd already made a start on the bridge and mux module modifications when you dropped the 7-layer project, so I shunted my existing project to the side with the intention of working on the bridge/mux portion and porting their .v files over to the 7-layer project once they're done.

I'll go take a look at the mods you've made - thanks very much.  :) :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2019, 08:34:36 pm
Thanks for clarifying the DFFs on the RS232 output - I was going to use them (or another set) on the mux output to the vid_osd_generator, but I guess I won't need them as the mux runs at system clock speed?

As for the mux code - ENABLED is only there whilst I was trying to debug the RS232_debugger still being able to communicate with the GPU RAM, I'll remove that - or make it specific to the RS232 module.

Thanks for updating the code - I'd have got there eventually!  :o ;D  Port A code will just be a copy-pasta of the existing two if-else-end blocks with vars renamed appropriately?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2019, 11:47:07 pm
What you should better do is make 2 wires, run_portA and run_portB.

Assign a set of rules for each wire with simple Boolean terms.

And use those wires to drive the 1-2 if statements and read/write request flags...


Remember to set and clear busy status for each port in the 'if's, use those as status in the boolean selection and make sure the Z80 get's first choice/priority over the RS232.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2019, 10:51:06 am
What you should better do is make 2 wires, run_portA and run_portB.

Assign a set of rules for each wire with simple Boolean terms.

And use those wires to drive the 1-2 if statements and read/write request flags...

Hmm.. not sure I follow..  run_portA and run_portB would just reflect the existing 'if' conditions?

Remember to set and clear busy status for each port in the 'if's, use those as status in the boolean selection and make sure the Z80 get's first choice/priority over the RS232.

The read-ready flags are handled by the sequencer pipelines and assign statements.  It's just the write flag to the GPU that is shared between the two ports and needs a little extra logic to enable the inclusion of port A?  (Would it make sense to have two gpu_wr_ena's, one for each port, that are OR'd together to make the existing gpu_wr_ena output?) Otherwise it'll be set to zero each clock cycle by the port B 'else' condition in the write if.. block.

No doubt you're describing a more efficient way of doing what I was going to do by just copying the existing port B if.. statements, but I can't see it at the moment.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2019, 11:01:49 am
Does this help any?

wire run_r_porta, run_r_portb,run_w_porta, run_w_portb;

assign run_r_porta  = rd_req_a && ~portb_bsy;
assign run_w_porta = wr_ena_a && ~portb_bsy;
assign run_r_portb  = rd_req_b && ~porta_bsy && ~run_r_porta && ~run_w_porta;
assign run_w_portb = wr_ena_b && ~porta_bsy && ~run_r_porta && ~run_w_porta;

Note that there is no latching or latching logic here.  Everything is realtime.
(Hint, since port B, the RS232 is running at 50MHz, it's write and read request will always be at least 2 or more clock cycles long.  In fact, the way I programmed it, you can multiply that figure by a good 3x.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2019, 11:20:56 am
Does this help any?

wire run_r_porta, run_r_portb,run_w_porta, run_w_portb;

assign run_r_porta  = rd_req_a && ~portb_bsy;
assign run_w_porta = wr_ena_a && ~portb_bsy;
assign run_r_portb  = rd_req_b && ~porta_bsy && ~run_r_porta && ~run_w_porta;
assign run_w_portb = wr_ena_b && ~porta_bsy && ~run_r_porta && ~run_w_porta;

Note that there is no latching or latching logic here.  Everything is realtime.

Ah okay, thanks.

I've copied the data_mux.v and Z80_bridge.v files from the older project that you updated yesterday into the current project (7-layer one), so I'm working on the mux from the current project now.

Code: [Select]
gpu_wr_ena <= run_w_porta || run_w_portb;

Would the above be okay in the always loop?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2019, 11:24:15 am
Code: [Select]
always @ (posedge clk) begin

gpu_wr_ena <= run_w_porta || run_w_portb;
porta_bsy <= run_r_porta || run_w_porta;
portb_bsy <= run_r_portb || run_w_portb;

if (run_r_portb) begin
rd_sequencer_b[9:0] <= { rd_sequencer_b[8:0], 1'b1 };
gpu_address      <= address_b;
end else begin
rd_sequencer_b[9:0] <= { rd_sequencer_b[8:0], 1'b0 }; // this line must always run no matter any other state
end

if (run_w_portb) begin
gpu_address      <= address_b;
gpu_data_out        <= data_in_b;
end

end

Would that be better?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2019, 11:27:33 am
Does it work?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2019, 11:31:21 am
Does it work?

Sure does.

Compiles are taking 1 min 50 seconds now.  ;)

Code: [Select]
always @ (posedge clk) begin

// *** UPDATE GPU_WR_ENA AND FLAGS EACH CLOCK ***
gpu_wr_ena <= run_w_porta || run_w_portb;
porta_bsy <= run_r_porta || run_w_porta;
portb_bsy <= run_r_portb || run_w_portb;

// *** HANDLE PORT A READ REQUESTS AND SEQUENCER ***
if (run_r_porta) begin
rd_sequencer_a[9:0] <= { rd_sequencer_a[8:0], 1'b1 };
gpu_address    <= address_a;
end else begin
rd_sequencer_a[9:0] <= { rd_sequencer_a[8:0], 1'b0 }; // this line must always run no matter any other state
end

// *** HANDLE PORT A WRITE REQUESTS ***
if (run_w_porta) begin
gpu_address      <= address_a;
gpu_data_out        <= data_in_a;
end

// *** HANDLE PORT B READ REQUESTS AND SEQUENCER ***
if (run_r_portb) begin
rd_sequencer_b[9:0] <= { rd_sequencer_b[8:0], 1'b1 };
gpu_address     <= address_b;
end else begin
rd_sequencer_b[9:0] <= { rd_sequencer_b[8:0], 1'b0 }; // this line must always run no matter any other state
end

// *** HANDLE PORT B WRITE REQUESTS ***
if (run_w_portb) begin
gpu_address     <= address_b;
gpu_data_out        <= data_in_b;
end

end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2019, 11:35:23 am
So next, wire in the Z80,...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 01, 2020, 09:43:47 pm
So next, wire in the Z80,...

Got that done today, have just been debugging the connection with a little spare time.  Started out oddly - clearly a bad connection for bit 1 on the data bus, fixed that now but am still not getting 100% results.

I'm using two methods to read and set the contents of the GPU RAM from the Microcom - the PEEK direct command in my monitor program (DMI) and MEMX, a memory viewer/editor program in the DMI.  I'm trying to set contents using the POKE direct command.

Here's the output from MEMX when viewing the first page of the GPU RAM (a 16KB bank of the GPU's memory window mapped to $C000), compared with the (simultaneous) output from the RS232_debugger viewing the same page:

MEMX:
[attachimg=1]

RS232_debug:
[attachimg=2]

As you can see, there are some errors in the MEMX output (addresses $C01C, $C01E, $C02C are the first).  Looks like a timing issue getting data out from the GPU to the Z80?

Writing the GPU RAM using POKE seems to be fine for the most part, unless I try to perform a block write - I have another command that sets a block of RAM to a user-specified value (it uses LDIR (http://z80-heaven.wikidot.com/instructions-set:ldir) iirc - one of the Z80's block data-shifting commands) - that completely fails - doesn't change anything according to the RS232_debugger, but returns all zeros (or whatever value was written) on the Microcom.

Going to dig out the Z80 manual and see what it says around the memory RD/WR cycles.  I'm wondering if I need to keep the data valid on the data bus for a short while AFTER the end of the memory cycle, but I'm pretty sure the Z80 doesn't require the data to be held after RD goes high...

Sometimes PEEK returns the correct value, sometimes it just returns $FF and the data returned using MEMX changes each time I view the page (well, the errors change in terms of value and location).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 01, 2020, 11:40:21 pm
Have looked at the level converters - I'm using a 74LVC245 to shift the data bus from 5v down to 3v3 for the FPGA - it's powered at 3v3, so it will be outputting to the Z80's data bus at 3.8v maximum, according to the datasheet (http://www.ti.com/lit/ds/symlink/sn74lvc245a.pdf) and the Z80 has a buffer on its data bus anyway (a 74HCT245) which takes 2v as a high input, so I don't think there should be any voltage level issues...  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2020, 12:10:01 am
Have looked at the level converters - I'm using a 74LVC245 to shift the data bus from 5v down to 3v3 for the FPGA - it's powered at 3v3, so it will be outputting to the Z80's data bus at 3.8v maximum, according to the datasheet (http://www.ti.com/lit/ds/symlink/sn74lvc245a.pdf) and the Z80 has a buffer on its data bus anyway (a 74HCT245) which takes 2v as a high input, so I don't think there should be any voltage level issues...  :-//
?  How do you get more voltage out of an output buffer, IE3.8v, when powering it at 3.3v?

Do you have a scope shot?

It looks as if you may be decoding/latching the GPU ram at the wrong time, or forgetting to latch it at all.
Also, for the Z80 writes, it may be wise to scope both sides of the buffer.
As for the block writes, we rely on the cycling of the WRn from the Z80, if during a block write that signal remains low throughout multiple writes, we may need to adapt our Z80 bridge write logic.

The fact you got this far on the first day is actually a good sign.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2020, 09:15:38 am
Change your Z80 buss interface so it responds on every rising clock edge, both whether it is a read or write.  Ignore the edge transitions of the mreq and wrn.  In in other words, if there are 2 or 3 consecutive mreqs across multiple clocks, trigger and respond at each one.

Also make a switch input which will allow you to switch triggering on the positive edge clock, or, the negative edge clock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 02, 2020, 11:19:08 am
Have looked at the level converters - I'm using a 74LVC245 to shift the data bus from 5v down to 3v3 for the FPGA - it's powered at 3v3, so it will be outputting to the Z80's data bus at 3.8v maximum, according to the datasheet (http://www.ti.com/lit/ds/symlink/sn74lvc245a.pdf) and the Z80 has a buffer on its data bus anyway (a 74HCT245) which takes 2v as a high input, so I don't think there should be any voltage level issues...  :-//
?  How do you get more voltage out of an output buffer, IE3.8v, when powering it at 3.3v?

I was just quoting from here in the linked datasheet:

[attachimg=1]

It's immaterial, anyway, as the Z80 buffer reads anything above 2v as HIGH, so there should be no issues with the voltage conversion.

Do you have a scope shot?

Scope or logic analyser?  My scope is of limited use as it's not digital and is very old - unless I'm worried about voltage levels or analogue signals, I tend to default to the logic analyser.  In either case, no, I don't have any shots (yet) - setting them up is a pain and I go to them as a last resort, usually. 

It looks as if you may be decoding/latching the GPU ram at the wrong time, or forgetting to latch it at all.

This is highly possible, as I've taken the z80_bridge module to be working since I last posted the code for it some time ago and didn't get any comments from you on it?  :o

The data output from the Z80_bridge module (Z80_rData[7:0]) is a register though, so should latch anyway? 

I've attached the latest code for the z80_bridge module below.

As for the block writes, we rely on the cycling of the WRn from the Z80, if during a block write that signal remains low throughout multiple writes, we may need to adapt our Z80 bridge write logic.

Even during 'block' writes, WR is cycled by the Z80 - the normal WR cycle is observed, it's just that LDIR (http://z80-heaven.wikidot.com/instructions-set:ldir) (and others (http://z80-heaven.wikidot.com/instructions-set:ldi)) simplifies the assembly for the programmer by removing the need for a loop.  You just specify the source and destination addresses, number of bytes to copy, then LDIR does the rest.  Each step in the loop is a load (RD) from the source address, then a WR to the destination address, then the Z80 increments the address pointers and decrements the number of bytes to copy before looping.  There is no RD-MODIFY-WR or anything like that on the Z80 - all the RD and WR cycles are as shown in the timing diagram in the Z80 datasheet.

[attachimg=2]

According to one source I found, the Z80 latches the data during a RD operation on the falling edge of T3. This appears to be very close to the rising edges of MREQ and RD, but according to the datasheet should be no more than 60ns before the rise of RD for a Z84C008 (timing 23 in the below chart).  No minimum is given, but that's because of 'overclocking' - my Z84C008 runs at 8 MHz, so that figure should be close to 60ns.

[attach=3]

[attach=4]

The fact you got this far on the first day is actually a good sign.

I was actually hugely surprised, to be honest, that I got it working at all.  It's a rat's nest of wires at the moment - will be glad when I've got a Lattice dev board done and have some confidence in BGA soldering...  but that's a way off yet!  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2020, 11:52:13 am
Without an analog scope shot, how can you be certain that the CMOS buffer output signals cleanly clears 2v when driving the CPU's input loads?

A logic analyzer is a powerful debug tool, but if it considers 1.5v a high and the CMOS buffer is outputting a 1.9v signal, you still need to verify everything is ok.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 02, 2020, 01:17:36 pm
Without an analog scope shot, how can you be certain that the CMOS buffer output signals cleanly clears 2v when driving the CPU's input loads?

:o Fair point.  Well, I wrote a (very) short program to repeatedly read the first address in GPU RAM and loop.  Literally two lines of code (well, three as I had to disable interrupts).  I have to get repeating signals otherwise my scope will just display garbage - it has no hold/freeze.  From what I can tell, at least 3v are going out of the converter.

If the voltages weren't high enough to be read as HIGHs, surely the corrupt values would be missing bits (LOWs) or bytes coming out as zeroes, rather than the current case where the corrupt bits are high or low?  I'm sometimes getting $FF instead $00, for example, which leads me to think it's a timing issue rather than a voltage one.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 02, 2020, 01:39:45 pm
It looks as if you may be decoding/latching the GPU ram at the wrong time, or forgetting to latch it at all.

Still thinking about this - I'm not sure the Z80_bridge module is 100% correct - I'm not latching the data at all, other than the output to the Z80 is a register?  Should I have some DFFs on the output to the Z80 from the Z80_bridge like you did with the RS232 outputs to the GPU RAM, but clocked from the Z80 (or the Z80's RD?) instead of the GPU clock?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 02, 2020, 11:39:12 pm
So close...

Console output:
[attach=1]

GPU output:
[attach=2]

EDIT: Yes - I know the year is out on my RTC!  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2020, 12:21:58 am
Start with my recommended changes to the Z80 bridge code.  I don't know if I have time to look at it myself.  Maybe on the weekend.

Also think about assigning 'Fast Input Registers' and 'Fast Output Registers' and 'Fast Output Enable' registers in Quartus.  Note that these don't get assigned in the verilog, they are project assignments.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2020, 12:28:42 am
Start with my recommended changes to the Z80 bridge code.  I don't know if I have time to look at it myself.  Maybe on the weekend.

Also think about assigning 'Fast Input Registers' and 'Fast Output Registers' and 'Fast Output Enable' registers in Quartus.  Note that these don't get assigned in the verilog, they are project assignments.

Okay, will take a look at the changes tomorrow.  Will do some research on these Fast Input/Fast Output registers too.  Thanks.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2020, 05:44:00 am
Try this:

   if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1;            // set 245 dir toward FPGA
   if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0;            // set FPGA pins to input (should be by default)

   if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0;            // enable 245 output

   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wdata        <= Z80_wData;      // latch data bus onto GPU data bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b1;            // turn on FPGA RAM we

   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  gpu_wr_ena       <= 1'b0;            // turn off FPGA RAM we
   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  Z80_245_oe       <= 1'b1;            // disable 245 output


This will force 2 sequential write pulses, perhaps patching a bug within the MUX algorithm.

Also in the MUX, take a 1-shot approach to read and writes from the RS232 debugger port.  (Make the read and write req go through a 1 clk delay and run once only if the signal does a low to high transition.)   Since the RS232 operates at 50MHz, a write or read command remains on for multiple clocks.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2020, 12:03:31 pm
Try this:

   if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1;            // set 245 dir toward FPGA
   if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0;            // set FPGA pins to input (should be by default)

   if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0;            // enable 245 output

   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wdata        <= Z80_wData;      // latch data bus onto GPU data bus
   if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b1;            // turn on FPGA RAM we

   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  gpu_wr_ena       <= 1'b0;            // turn off FPGA RAM we
   if ( Z80_write_sequencer[DELAY_CYCLES + 3] )  Z80_245_oe       <= 1'b1;            // disable 245 output


This will force 2 sequential write pulses, perhaps patching a bug within the MUX algorithm.

Also in the MUX, take a 1-shot approach to read and writes from the RS232 debugger port.  (Make the read and write req go through a 1 clk delay and run once only if the signal does a low to high transition.)   Since the RS232 operates at 50MHz, a write or read command remains on for multiple clocks.

Ah - the changes above seem to have fixed it (including one-shotting the RS232 read/writes)! ^-^

I'm getting no errors, either reading from or writing to the GPU now from the Z80 (and the RS232_debugger is unaffected) - I'm able to do block memory ops as well, so clearing the screen (eg) is dead easy now.  I'll keep an eye on the interface stability as I develop the driver for the GPU, but it's looking good so far.  :-+

 ;D ^-^ ;D ^-^ ;D ^-^ ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2020, 12:11:00 pm
You have cornered the problem and made a quick workaround according to my recommendations.  Do not assume it is wise not to properly fix the code.  For now, you are fine, but with the addition of a hardware accelerated drawing engine in the future, you will by that time want to get the read and write mux and Z80 interface to properly work with a single write pulse as you do not want to waste R/W cycles when you have a fast drawing engine sharing the GPU ram bus.

The proper thing is within the MUX would be to unilaterally acknowledge a single read and write pulse, holding it internally until that address and write_ena makes it way out to the GPU ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2020, 11:22:24 pm
You have cornered the problem and made a quick workaround according to my recommendations.  Do not assume it is wise not to properly fix the code.  For now, you are fine, but with the addition of a hardware accelerated drawing engine in the future, you will by that time want to get the read and write mux and Z80 interface to properly work with a single write pulse as you do not want to waste R/W cycles when you have a fast drawing engine sharing the GPU ram bus.

The proper thing is within the MUX would be to unilaterally acknowledge a single read and write pulse, holding it internally until that address and write_ena makes it way out to the GPU ram.

I've been trying to get the mux to hold off all other requests until a read cycle is completed, but not had much luck so far.  I presume this is what you're talking about above?  I've attached the files below for reference - data_mux has the work I've tried to hold off on requests, although the lines are commented-out at the moment.

It seems I spoke too soon about the interface stability earlier - whilst I am able to block-write zeros to part of the GPU RAM as part of a CLS (or clear screen) command, it really doesn't like me trying to scroll the screen data upwards one line when the cursor tries to go past the bottom of the screen (the idea being to scroll all lines up 'one line' apart from the top line, which would be overwritten, and blank the bottom line).  I'm getting all kinds of write/read errors when I try to copy the data (I'm basically starting at the second line, copying each byte to an address 50 bytes earlier (one line up) and cycling through to the bottom of the screen before blanking the last 50 bytes of data).

Change your Z80 buss interface so it responds on every rising clock edge, both whether it is a read or write.  Ignore the edge transitions of the mreq and wrn.  In in other words, if there are 2 or 3 consecutive mreqs across multiple clocks, trigger and respond at each one.

Also make a switch input which will allow you to switch triggering on the positive edge clock, or, the negative edge clock.

I haven't tried these modifications yet.  You're asking me to ignore MREQ and WR, just respond to ANY RD or WR trigger?  I guess the 'valid_address' would gate reads or writes to non-GPU RAM space effectively.

One other thing I've failed miserably at is in z80_bridge.v (attached below).  I want it to ignore reads or writes to addresses above the GPU's RAM space.  The GPU window is 512KB, but I'd like the GPU to return $FF for any reads to addresses above 32 KB (or a user-definable value, at least).  This is important for two reasons - it prevents bad data being returned and the Microcom determines if a memory bank is RAM, ROM, or something else by the values it receives when it reads the last page of a 16KB block of memory.  I'd like the GPU to be able to return a pre-defined value if a read to that page is detected.  What I've tried in z80_bridge just isn't working - I'm just getting garbled data (all the time), even when accessing the proper GPU RAM.  mem_valid is the trigger I'd set up, commented out in the z80_bridge code.  Would appreciate some tips (from anyone!) on getting that particular requirement working.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 11:52:09 am
.....
Ok,...
Here we go....

I replaced your data_mux with a dumb AB, back and forth version.
I changed RS232_Debugger to operate at 125MHz.
I corrected your Z80_bridge as it wasn't posting and releasing the reads correctly.

Using the PC RS232_Debugger software, you can set debug port bits 'OUT3[6]' and 'OUT3[7]' to change which edge or edges of the  Z80_CLK input the bus controls will be latched on.

OUT3[6] is active low, when low, the Z80_bridge will latch the Z80 bus controls on the falling edge of the Z80_CLK input.  When high, the falling edge clock is disabled.

OUT3[7] is active high, when high, the Z80_bridge will latch the Z80 bus controls on the rising edge of the Z80_CLK input.  When low, the rising edge clock is disabled.

Enabling both clock edge control bits means that the Z80_bridge double clocks, once on the rising, then again on the falling.


*** You did not do your assignments 'Fast Input/Output/OE' for all your bus controls and OEs.  You have 2 choices, assign setup and hold timing settings in nanoseconds, or, use the 'Fast ***' feature to achieve the best possible logic cell placement of each IO for best clocking capability.  Without these assignments, every time you compile your project, each IO pin will randomly be slower or faster since the compiler will try to best locate the internal logic and not care about the speed and performance of your IOs.  This means every compile, your Z80 bus may get random IO errors which may have nothing to do with any code changes.  This is FPGA 101.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 12:51:40 pm
.....
Ok,...
Here we go....

I replaced your data_mux with a dumb AB, back and forth version.
I changed RS232_Debugger to operate at 125MHz.
I corrected your Z80_bridge as it wasn't posting and releasing the reads correctly.

Using the PC RS232_Debugger software, you can set debug port bits 'OUT3[6]' and 'OUT3[7]' to change which edge or edges of the  Z80_CLK input the bus controls will be latched on.

OUT3[6] is active low, when low, the Z80_bridge will latch the Z80 bus controls on the falling edge of the Z80_CLK input.  When high, the falling edge clock is disabled.

OUT3[7] is active high, when high, the Z80_bridge will latch the Z80 bus controls on the rising edge of the Z80_CLK input.  When low, the rising edge clock is disabled.

Enabling both clock edge control bits means that the Z80_bridge double clocks, once on the rising, then again on the falling.


*** You did not do your assignments 'Fast Input/Output/OE' for all your bus controls and OEs.  You have 2 choices, assign setup and hold timing settings in nanoseconds, or, use the 'Fast ***' feature to achieve the best possible logic cell placement of each IO for best clocking capability.  Without these assignments, every time you compile your project, each IO pin will randomly be slower or faster since the compiler will try to best locate the internal logic and not care about the speed and performance of your IOs.  This means every compile, your Z80 bus may get random IO errors which may have nothing to do with any code changes.  This is FPGA 101.

Thanks for the patch - I'm looking at the assignments currently and am getting them sorted first.  It may be FPGA 101, but as I'm starting out learning about FPGAs then maybe I can be forgiven for not knowing about this just yet?  ;)  Just to make sure, I'm in the Assignment Editor, going down the list of pins/IO connections, and changing 'Location' in the 'Assignment Name' column to Fast Output or Fast Input Register as appropriate, then selecting 'On' in the 'Value' column in place of the PIN_xx number that was there?  What do I do with the bi-directional Z80_data pins?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 01:16:10 pm
You have other errors:
---------------------------------
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[13] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[13] and I/O node Z80_ADDR[13] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[12] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[12] and I/O node Z80_ADDR[12] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[10] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[10] and I/O node Z80_ADDR[10] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[11] to I/O pin
   Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[11] and I/O node Z80_ADDR[11] -- I/O node is a dedicated I/O pin
----------------------------------------------

Also, something weird, is says that :

   Warning (13410): Pin "245_DIR" is stuck at GND

This needs to be fixed...
Give me 30 minutes...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 01:20:43 pm
 ???

I didn't get those errors - but just compiled the project and got some messages about ignoring invalid assignments (funnily enough, all the fast assignments I'd made) and when running the GPU, the RS232_debugger reads/writes just fine, but nothing is displaying from the Microcom.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 01:40:53 pm
Here you go, latest assignments added and fixed the Z80_bridge code, it should now work, but:

[attach=1]

I've added the assignments, 4 errors appear on 4 address lines.  Check the compilation reports now.
Did you wire those to dedicated inputs?  Their timing will not match the other address inputs if you do that.

Code: [Select]
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[13] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[13] and I/O node Z80_ADDR[13] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[12] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[12] and I/O node Z80_ADDR[12] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[10] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[10] and I/O node Z80_ADDR[10] -- I/O node is a dedicated I/O pin
Warning (176225): Can't pack node Z80_bridge:inst7|gpu_addr[11] to I/O pin
Warning (176228): Can't pack node Z80_bridge:inst7|gpu_addr[11] and I/O node Z80_ADDR[11] -- I/O node is a dedicated I/O pin
Warning (176250): Ignoring invalid fast I/O register assignments. See the Ignored Assignments panel in the Fitter Compilation Report for more information.

You may want to move those 4 pins to regular IOs, they may create addressing errors.

Try out the new attached version.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 01:46:29 pm
OOOPPPSSS Change this 1 line, LINE #62 in the Z80_bridge to what I've written below:

Code: [Select]
assign Read_GPU_RAM_END =  Z80_clk_trig && (~Z80_read || ~Z80_mreq || ~mem_window) ;   // Define the ending of a Z80 read request of GPU Ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:01:37 pm
Here you go, latest assignments added and fixed the Z80_bridge code, it should now work, but:

(Attachment Link)

I've added the assignments, 4 errors appear on 4 address lines.  Check the compilation reports now.
Did you wire those to dedicated inputs?  Their timing will not match the other address inputs if you do that.
...
You may want to move those 4 pins to regular IOs, they may create addressing errors.

Oooh... maybe.  I just connected up the wires consecutively to the IO pins on the dev board, I didn't give any thought as to the type of pin they were... Chalk that one up to learning about FPGAs!  :-//

So I'm going to need to find alternative pins for those connections then.  ::)  Running out of pins if I want to use 24-bit RGB output as well (I've got 8 left, not including the mass of pins over the other side of the board I'd reserved for the video output...)

OOOPPPSSS Change this 1 line, LINE #62 in the Z80_bridge to what I've written below:

Code: [Select]
assign Read_GPU_RAM_END =  Z80_clk_trig && (~Z80_read || ~Z80_mreq || ~mem_window) ;   // Define the ending of a Z80 read request of GPU Ram.

Haha! Caught me mid-compilation, too.  ;)

Okay, hmmm... it's not working - I'm getting the usual display output on the screen, but when I start up the Microcom it displays the usual 'Press space to begin' in the console, but when I press space nothing happens - it just locks up - and that's before it does anything with trying to access the GPU RAM...  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:04:45 pm
In the RS232 debugger, try setting the OUT3[7] bit to 1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:10:18 pm
In the RS232 debugger, try setting the OUT3[7] bit to 1.

Okay, that stops the Microcom from hanging - but there's no output on the screen because it seems the writes are not being received properly at all.  The GPU RAM is getting corrupted badly, with $FFs where there's no writing going on, and $00s where a value should be written...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:11:25 pm
Try changing these 3 lines:

Code: [Select]
assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  ~Z80_read ;   // Define the ending of a Z80 read request of GPU Ram.

This ignores the clocks and makes the FPGA look like static ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:16:24 pm
Ok, here is a new fix for the Z80 bridge:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END, mem_valid_range;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay;
reg [9:0] Z80_write_sequencer;
//reg [18:0] rd_addr;

//assign mem_valid  = (rd_addr[15] == 1'b0); // HIGH if address is inside GPU RAM bounds (GPU RAM may not fill the 512KB host memory window, so this flag determines if the address is within GPU RAM bounds)

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  ~Z80_read ;   // Define the ending of a Z80 read request of GPU Ram.

assign mem_valid_range    = (gpu_addr <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir     <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena     <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END && ~Write_GPU_RAM ) begin
Z80_245_oe <= 1'b1; // disable 245 output
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


//last_Z80_WR <= Z80_WRn;
//last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


When not reading, it would always reset the 245 buffer even if a write was being performed.  I had to make a few changes...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:17:32 pm
Try changing these 3 lines:

Code: [Select]
assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  ~Z80_read ;   // Define the ending of a Z80 read request of GPU Ram.

This ignores the clocks and makes the FPGA look like static ram.

Everything is overwritten with $FF now.  Just updated with your latest post and re-compiling.  Will update with results of that code in a minute or three.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:19:42 pm
Check my last msg.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:21:50 pm
Ok, here is a new fix for the Z80 bridge:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END, mem_valid_range;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay;
reg [9:0] Z80_write_sequencer;
//reg [18:0] rd_addr;

//assign mem_valid  = (rd_addr[15] == 1'b0); // HIGH if address is inside GPU RAM bounds (GPU RAM may not fill the 512KB host memory window, so this flag determines if the address is within GPU RAM bounds)

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  ~Z80_read ;   // Define the ending of a Z80 read request of GPU Ram.

assign mem_valid_range    = (gpu_addr <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir     <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena     <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END && ~Write_GPU_RAM ) begin
Z80_245_oe <= 1'b1; // disable 245 output
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


//last_Z80_WR <= Z80_WRn;
//last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


When not reading, it would always reset the 245 buffer even if a write was being performed.  I had to make a few changes...


Ookay... the writes seem to be working, I can see the correct settings for the text mode when the Microcom boots into the DMI, but everywhere else is $FF... which means the screen display is corrupted because ALL the unused HV triggers, HW_regs, MAGGIEs etc are filled with $FF values.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:25:50 pm
... but with bit 7 set HIGH in OUTPUT[3] in the debugger, the mass of $FF's stops.  Output to the screen is corrupted, though - looks like some chars are being displayed twice.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:29:11 pm
No, I take that back - bit 7 isn't making a difference.  Writes are corrupted, so sometimes enough get through to set up the display properly, but there is visible corruption in the on-screen text, other times the display setup is corrupted and all kinds of weirdness happen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:30:53 pm
Ok, I've made the reads and writes snap for 1 shot.

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END, mem_valid_range;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD;
reg [9:0] Z80_write_sequencer;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

assign mem_valid_range    = (gpu_addr <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir     <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena     <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_245_oe <= 1'b1; // disable 245 output
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:36:08 pm
Ok, I just patched the 'mem_valid_range' bug for the reads (fixes the reading of only 'FF'):

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range;
reg [9:0] Z80_write_sequencer;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr     <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output

mem_valid_range  <= (gpu_addr[18:0] <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_245_oe <= 1'b1; // disable 245 output
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:38:05 pm
ONE thing that is consistent, though, is that the Microcom is reporting the correct amount of memory now - so the changes to the Z80_bridge to prevent reads/writes above the memory limit obviously works.  :-+

Ok, I've made the reads and writes snap for 1 shot.

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END, mem_valid_range;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD;
reg [9:0] Z80_write_sequencer;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

assign mem_valid_range    = (gpu_addr <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir     <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena     <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_245_oe <= 1'b1; // disable 245 output
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


Hmm... nope.  Reads/writes are all over the place - and the GPU seems to be driving the data pins at the wrong time as the Microcom is sometimes crashing as well.  I'm just compiling your latest post with the patched 'mem_valid_range'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 02:42:55 pm
Latest patch compiled and tested - writes to the GPU are corrupted; display setup is corrupted as a result and at one point I could see what I was typing into the Microcom via the console appearing on the screen, but the characters didn't match what I was typing.  Several resets later and during one reset, the Microcom crashed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 02:54:34 pm
Try this:
Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range;
reg [9:0] Z80_write_sequencer;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr     <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output

mem_valid_range  <= (gpu_addr[18:0] <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


I can only recommend changing those 4 address pins if this doesn't work.
Also, try doing some reads exclusively to see if they work with the correct data before doing any writing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 03:03:02 pm
Note that the writes outside the 32kb range are not protected.  Also, I might need to turn off the 245 at the end of a read....
try this:
Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; // number of cycles to delay write for 245

wire mem_window, Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range;
reg [9:0] Z80_write_sequencer;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign mem_window = (Z80_addr[21:19]            == MEMORY_RANGE); // Define an active memory range
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Write_GPU_RAM )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Write_GPU_RAM )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Write_GPU_RAM )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_addr         <= Z80_addr[18:0];// latch address bus onto GPU address bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= (gpu_addr[18:0] <  2**MEM_SIZE_BITS); // Define GPU addressable memory space  -  turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_addr     <= Z80_addr[18:0];// pass address to GPU RAM (cropped to 512KB range as that's all we're interested in)
gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output

mem_valid_range  <= (gpu_addr[18:0] <  2**MEM_SIZE_BITS); // Define GPU addressable memory space

end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // enable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 03:15:55 pm
Which Z80 are you using?
EXACT part number! Manufacturer name as well.
The timing on the data sheet has some NEGATIVE setup times for the bus control signals on some models.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 03:22:42 pm
Which Z80 are you using?
EXACT part number! Manufacturer name as well.
The timing on the data sheet has some NEGATIVE setup times for the bus control signals on some models.

Right.  So you may be on to something here.  I've been convinced I'm using an 8 MHz CPU, but it would appear not and this is quite embarrassing.  :-[  It's a Zilog Z80, Z84C0010PEG.  A 10 MHz model.

That could be the cause of the timing headaches right there. (It is DEFINITELY running at 8 MHz, however). :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 03:27:51 pm
CANCEL THAT.

It's a Zilog Z84C008PEG CPU.

Sorry for the confusion.  My main Microcom is wired up to the GPU and the CPU isn't the top card, so I couldn't get to it without taking the stack apart, so I referred to my second Microcom I've got sitting on a shelf - it would appear THAT one has a 10 MHz CPU in it.  I've just disassembled my main Microcom stack and checked out the CPU - it's definitely an 8 MHz Zilog part.

Raises an interesting point though - I got both the Z80's at the same time from the same supplier a few years ago...  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 03:37:04 pm
The project was working mostly at the start of the day - it only seemed to fall over when I tried to scroll the screen.  I might roll back to that state and try to sort out the pins that can't be assigned with fast regs, unless there's any changes you've made that definitely need to stay in?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 04:06:13 pm
CANCEL THAT.

It's a Zilog Z84C008PEG CPU.

Sorry for the confusion.  My main Microcom is wired up to the GPU and the CPU isn't the top card, so I couldn't get to it without taking the stack apart, so I referred to my second Microcom I've got sitting on a shelf - it would appear THAT one has a 10 MHz CPU in it.  I've just disassembled my main Microcom stack and checked out the CPU - it's definitely an 8 MHz Zilog part.

Raises an interesting point though - I got both the Z80's at the same time from the same supplier a few years ago...  :-//
ok, blahhh, anyways, try this after a bunch of code changes for the 10&20mhz variants...:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 0; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_mreq_dly[MREQ_DLY_CLK+1] && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
end


Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


I would still change those 4 pins if possible.  All addresses should be on a similar matching IO type.  Same for all data.

Do you have enough GND connections between the Z80 and GPU?
You might have massive ground bounce happening...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 04:28:57 pm
Ok, go to this version:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 0; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_unmreq_pulse = Z80_mreq_dly[MREQ_DLY_CLK] && ~Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_mreq_dly[MREQ_DLY_CLK+1] && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn ; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
end else if (Z80_unmreq_pulse) begin
mem_valid_range  <= 1'b0; // Define GPU addressable memory space
mem_window   <= 1'b0; // Define an active memory range
end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 04:36:37 pm
I woul still change those 4 pins if possible.  All addresses should be on a similar matching IO type.  Same for all data.

It's top of my to-do list now.

Do you have enough GND connections between the Z80 and GPU?
You might have massive ground bounce happening...

Errrr... *goes away and looks up ground bounce*  Hmm... maybe not.  Just to explain the setup - I have the Microcom, I have a single breadboard with the level converters on it, then I have the FPGA dev board.

The Microcom's GND is connected to the breadboard via a single wire.  The breadboard GND is connected to the FPGA GND via a single wire.

I'm doubting that fulfils the 'enough GND connections between the Z80 and GPU question...  :o

Previous code changes doesn't help - mostly getting $FFs written to GPU RAM.  PEEK is returning garbage.  Seems to be just returning $1A.

Ok, go to this version:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 0; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_unmreq_pulse = Z80_mreq_dly[MREQ_DLY_CLK] && ~Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_mreq_dly[MREQ_DLY_CLK+1] && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
end else if (Z80_unmreq_pulse) begin
mem_valid_range  <= 1'b0; // Define GPU addressable memory space
mem_window   <= 1'b0; // Define an active memory range
end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


Compiling as we speak.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 04:38:07 pm
I woul still change those 4 pins if possible.  All addresses should be on a similar matching IO type.  Same for all data.

It's top of my to-do list now.

Do you have enough GND connections between the Z80 and GPU?
You might have massive ground bounce happening...

Errrr... *goes away and looks up ground bounce*  Hmm... maybe not.  Just to explain the setup - I have the Microcom, I have a single breadboard with the level converters on it, then I have the FPGA dev board.

The Microcom's GND is connected to the breadboard via a single wire.  The breadboard GND is connected to the FPGA GND via a single wire.

I'm doubting that fulfils the 'enough GND connections between the Z80 and GPU question...  :o

Previous code changes doesn't help - mostly getting $FFs written to GPU RAM.  PEEK is returning garbage.  Seems to be just returning $1A.

Ok, go to this version:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 0; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 0; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_unmreq_pulse = Z80_mreq_dly[MREQ_DLY_CLK] && ~Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_mreq_dly[MREQ_DLY_CLK+1] && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn && last_Z80_RD; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
end else if (Z80_unmreq_pulse) begin
mem_valid_range  <= 1'b0; // Define GPU addressable memory space
mem_window   <= 1'b0; // Define an active memory range
end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


Compiling as we speak.

Error, fix this line #59:

assign Z80_read       = ~Z80_RDn;            // Isolate a single read transaction


1 GND wire, WTF??????
You should have 1 GND wire for every 2-4 signal wires.  Otherwise the GND is waving up and down, bouncing with it's lower impedance and inductance characteristics, messing up everything.

A proper high frequency design usually has 1-1.  Like your old IDE/floppy drive cables, 1 row side was almost all GND wires.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 04:44:03 pm
I had better not been fiddling with all this just because you used 1 tiny thin ground wire which was competing against 35 CPU IO signals...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2020, 05:12:15 pm
Also try these parameter settings:

parameter DELAY_CYCLES  = 2;      // number of cycles to delay write for 245
parameter MREQ_DLY_CLK  = 2;      // number of cycles +1 to delay mreq trigger


Don't forget to update the symbol and edit the 2 values on the top hierarchy.
This slows down, adds a delay to the latching of the address and data during the read and write.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 06:19:45 pm
1 GND wire, WTF??????
You should have 1 GND wire for every 2-4 signal wires.  Otherwise the GND is waving up and down, bouncing with it's lower impedance and inductance characteristics, messing up everything.

A proper high frequency design usually has 1-1.  Like your old IDE/floppy drive cables, 1 row side was almost all GND wires.

I had better not been fiddling with all this just because you used 1 tiny thin ground wire which was competing against 35 CPU IO signals...

Each IO group is grounded and is working at no more than 8 MHz, which is better than nothing I guess?  It was working fine(-ish) this morning and yesterday with only the one ground...  but that's not to say this test setup is anything near suitable - one reason I'm hoping to get a custom dev board created soon. :-[

Also try these parameter settings:

parameter DELAY_CYCLES  = 2;      // number of cycles to delay write for 245
parameter MREQ_DLY_CLK  = 2;      // number of cycles +1 to delay mreq trigger

Don't forget to update the symbol and edit the 2 values on the top hierarchy.
This slows down, adds a delay to the latching of the address and data during the read and write.

Okay, that's a step forward - but it seems the data is still getting randomly corrupted.  It was able to display text on the screen this time and I could write some stuff there to test it.  It seems to be dropping characters and replacing them with null bytes ($00).

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2020, 06:40:39 pm
Reading seems to be quite accurate with individual PEEKs, but when I try to dump a page from the GPU, the system locks up.  Seems to lock up frequently trying to initialise the GPU as well.

For a sanity check, earlier I tested the project from this morning which I backed-up before we started making all these changes (at least I think I did before we made any sweeping changes).  It still works, but not very well - so I'm holding making any more changes until tomorrow when I can sort out exactly what's going wrong (it's going to be a bad connection on one of the buses) with a fresh head.   :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 01:34:04 am
Ok.  Without superimposed multichannel scope shots, I cant tell if all your addresses are properly being asserted at the same time or not.

If you have a logic analyzer, you will want one with a good 100MHz sampling rate on at least half the data and and the first addresses + buss control signals, including the 'WAIT' states which may be asserted by a third device on the bus.

I made the current code sample the address at the fall of MREQn, after the fall of MREQ_DLY_CLK which run at 125MHz.

I downloaded the newer Zlog Z80 documents which have the 8/10/20 MHz variants included.  The bus transactions and timing is not as simple as that old dumb 4MHz data sheet.  The MREQn going up and down between bus cycles is not guaranteed, or, it can be such a small value in NS, that unless we make a true static interface, or a proper synchronous interface, things will go haywire.  Also, there are other cycles right after transactions, like refresh cycles, or program code fetch which may also hold or shrink the MREQn.

It's not that the interface needs to be any more complicated that it is, it that I cannot see what is going on remotely and 95% of the Z80 docs out there assume a cheap static type design.  And with you bread board wiring & choice of voltage level shifting, and choice of IOs, I'm not sure where the true problem is creeping in.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 09:02:23 am
Upload the latest copy of what you are compiling with...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 12:15:28 pm
Upload the latest copy of what you are compiling with...

Attached is latest copy of the project with all the changes made yesterday.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 12:25:35 pm
Ok.  Without superimposed multichannel scope shots, I cant tell if all your addresses are properly being asserted at the same time or not.

If you have a logic analyzer, you will want one with a good 100MHz sampling rate on at least half the data and and the first addresses + buss control signals, including the 'WAIT' states which may be asserted by a third device on the bus.

My scope is next to useless for digital testing and my logic analyser isn't really up to that sort of work - it's just an 8-channel 25 MHz 'cheapy' off eBay.  It's served me just fine building the Microcom, but we're well out of '8 MHz-league', here.

I have a bit of time right now, so I'm going to try and sort the address bus and get those offending lanes moved to fast-input pins.

I made the current code sample the address at the fall of MREQn, after the fall of MREQ_DLY_CLK which run at 125MHz.

I downloaded the newer Zlog Z80 documents which have the 8/10/20 MHz variants included.  The bus transactions and timing is not as simple as that old dumb 4MHz data sheet.  The MREQn going up and down between bus cycles is not guaranteed, or, it can be such a small value in NS, that unless we make a true static interface, or a proper synchronous interface, things will go haywire.  Also, there are other cycles right after transactions, like refresh cycles, or program code fetch which may also hold or shrink the MREQn.

It's not that the interface needs to be any more complicated that it is, it that I cannot see what is going on remotely and 95% of the Z80 docs out there assume a cheap static type design.  And with you bread board wiring & choice of voltage level shifting, and choice of IOs, I'm not sure where the true problem is creeping in.

I know, it's a haystack and there's probably some fake needles in there to confuse things as well.  Is there a better way of doing the voltage level shifting then?  I'm always open to suggestions and guidance!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 12:48:46 pm
Without seeing, I have nothing to go on.

Try changing these 2 values:
Also try these parameter settings:

parameter DELAY_CYCLES  = 0;      // number of cycles to delay write for 245
parameter MREQ_DLY_CLK  = 0;      // number of cycles +1 to delay mreq trigger

This should accelerate the response.  If it doesn't work, we can try full static approach.  However, this isn't too wise a strategy for future upgrade.


Also, you shouldn't use pins 88,89,90,91 for your addresses.  Please move them.
For these pins, you should only use them for Z80_CLK, only, or you may also tie MREQ, RD, WR to these pins as well.  They are dedicated inputs and their timing to logic cells slightly differs to the main IOs where the rest of the addresses are wired.

This is important especially if we want to clock off of the Z80_CLK input.

Also, in assignment settings, compiler settings, 'Advanced Settings (Fitter)...', please turn on :
Perform Register Retiming For Performance.

PLEASE SWAP THE INPUT PINS LIKE I SAID...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 01:06:49 pm

I know, it's a haystack and there's probably some fake needles in there to confuse things as well.  Is there a better way of doing the voltage level shifting then?  I'm always open to suggestions and guidance!
Its more than just level shifting.  With a bread board and 1 GND wire to something like 35 signal wires, do you have proper signal termination?
What does your signal bounce look like?  The FPGA is still sensitive to signals in the 100MHz to 200MHz range even though the Z80 may only be sensitive to 20MHz.

When you build a PCB, will you be able to do proper resistor series and parallel termination on the right sides of the CMOS buffers?
Can you measure the signal bounce?

Without the above question being answered, you may want to use series resistor packs in dip or sip form so you may insert alternate values, or, you will have to design a quality layout PCB, with more than 1 GND wire going to the Z80...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 02:03:51 pm
Without seeing, I have nothing to go on.

Try changing these 2 values:
Also try these parameter settings:

parameter DELAY_CYCLES  = 0;      // number of cycles to delay write for 245
parameter MREQ_DLY_CLK  = 0;      // number of cycles +1 to delay mreq trigger

Okay, that's done, but shouldn't there be some delay for the 245 to enable?

Also, you shouldn't use pins 88,89,90,91 for your addresses.  Please move them.
For these pins, you should only use them for Z80_CLK, only, or you may also tie MREQ, RD, WR to these pins as well.  They are dedicated inputs and their timing to logic cells slightly differs to the main IOs where the rest of the addresses are wired.

This is important especially if we want to clock off of the Z80_CLK input.

Okay, the offending address lanes have been moved to alternate input pins (84, 86, 105 & 106) - I've moved the Z80_CLK line to pin 90.

Also, in assignment settings, compiler settings, 'Advanced Settings (Fitter)...', please turn on :
Perform Register Retiming For Performance.

Done.  Am just testing the output now - seems with DELAY_CYCLES set to zero and MREQ_DLY_CLK set to zero, I'm unable to read or write to the GPU RAM, although the Microcom was stable.  Have just tried it with DELAY_CYCLES back to 2, that wasn't good - Microcom wouldn't boot into the DMI (where the GPU is set up) without locking up and the GPU RAM being corrupted.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 02:10:29 pm
Its more than just level shifting.  With a bread board and 1 GND wire to something like 35 signal wires, do you have proper signal termination?
What does your signal bounce look like?  The FPGA is still sensitive to signals in the 100MHz to 200MHz range even though the Z80 may only be sensitive to 20MHz.

When you build a PCB, will you be able to do proper resistor series and parallel termination on the right sides of the CMOS buffers?
Can you measure the signal bounce?

Without the above question being answered, you may want to use series resistor packs in dip or sip form so you may insert alternate values, or, you will have to design a quality layout PCB, with more than 1 GND wire going to the Z80...

Aaaaaand it's at this point I realise I'm in waaaay over my head!   :o :o :o ???

How do you prototype circuits that run at silly speeds (100MHz+) if breadboard (clearly) isn't up to the task?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 02:14:19 pm
Ok, this one is static read, one shot write:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 2; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 2; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_unmreq_pulse = Z80_mreq_dly[MREQ_DLY_CLK] && ~Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_mreq_dly[MREQ_DLY_CLK+1] && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

//if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
//end else if (Z80_unmreq_pulse) begin
// mem_valid_range  <= 1'b0; // Define GPU addressable memory space
// mem_window   <= 1'b0; // Define an active memory range
//end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

//if ( Read_GPU_RAM_END ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
// end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


Change the 2 delay parameters to 0, then try 1 and 2.  The parameters should only effect the writes.

Also, if your get timing violations, IE an FMAX too low, disable the 'register retiming' feature I told you to turn on earlier.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 02:20:17 pm
Its more than just level shifting.  With a bread board and 1 GND wire to something like 35 signal wires, do you have proper signal termination?
What does your signal bounce look like?  The FPGA is still sensitive to signals in the 100MHz to 200MHz range even though the Z80 may only be sensitive to 20MHz.

When you build a PCB, will you be able to do proper resistor series and parallel termination on the right sides of the CMOS buffers?
Can you measure the signal bounce?

Without the above question being answered, you may want to use series resistor packs in dip or sip form so you may insert alternate values, or, you will have to design a quality layout PCB, with more than 1 GND wire going to the Z80...

Aaaaaand it's at this point I realise I'm in waaaay over my head!   :o :o :o ???

How do you prototype circuits that run at silly speeds (100MHz+) if breadboard (clearly) isn't up to the task?
Good thick grounding wiring.  Decoupling caps everywhere, and, wire-wrap or soldered prototype boards usually do the trick.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 02:28:01 pm
Ooops, logic bomb on the 245 controls during write.  Here is the fix:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 2; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 2; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_unmreq_pulse = Z80_mreq_dly[MREQ_DLY_CLK] && ~Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_mreq_dly[MREQ_DLY_CLK+1] && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

//if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
//end else if (Z80_unmreq_pulse) begin
// mem_valid_range  <= 1'b0; // Define GPU addressable memory space
// mem_window   <= 1'b0; // Define an active memory range
//end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN && Z80_WRn ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Z80_WRn ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


Delay cycles needs to be at least 2.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 02:42:04 pm
How do you prototype circuits that run at silly speeds (100MHz+) if breadboard (clearly) isn't up to the task?

Good thick grounding wiring.  Decoupling caps everywhere, and, wire-wrap or soldered prototype boards usually do the trick.

Everything has decoupling caps - all the chips on the breadboard are decoupled (I'm using SOIC->DIP converters with a 100nF cap on the mini-PCB).  There's two GND wires now (yay!) connecting the breadboard to both the FPGA and the Microcom.

Am just testing the delay settings now:

Both DLY valuse set to 0: Reading the GPU RAM caused a system crash.  Timing's definitely out on the 245, I presume.

Both DLY values set to 1: Writing any value to the GPU RAM writes $FF to that location.  Any read crashes the system.

Both DLY values set to 2: Writing any value to the GPU RAM writes $FF to that location.  Any read crashes the system.

EDIT: Just spotted your last post! Above results don't take that into account.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 02:50:34 pm
Ooops, accidentally delaying the 'MREQ'.  Ok, this one should work and not crash the system.

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 2; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 2; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;



assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq_pulse = ~Z80_mreq_dly[MREQ_DLY_CLK] && Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_unmreq_pulse = Z80_mreq_dly[MREQ_DLY_CLK] && ~Z80_mreq_dly[MREQ_DLY_CLK+1];
assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.
assign Read_GPU_RAM_END =  Z80_readn ;   // Define the ending of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

//if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
//end else if (Z80_unmreq_pulse) begin
// mem_valid_range  <= 1'b0; // Define GPU addressable memory space
// mem_window   <= 1'b0; // Define an active memory range
//end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)
if ( Z80_write_sequencer[DELAY_CYCLES + 2] )  Z80_245_oe <= 1'b1; // disable 245 output

if ( Read_GPU_RAM_BEGIN && Z80_WRn ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

if ( Z80_WRn ) begin
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
   Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 03:13:05 pm
Okay, with that latest update:

 DELAY_CYCLES  |   MREQ_DLY_CLK   |  RESULTS
-------------------+----------------------+----------------------------------------------------------------------
          2             |              2              | Unstable. Crash on read. Write only writes $FF to GPU RAM.
          2             |              1              | Unstable. Crash on read. Write only writes $FF to GPU RAM.
          2             |              0              | Unstable. Crash on read. Write only writes $FF to GPU RAM.

1) When I've tried writing, I've tried values $00, $55, $AA, $01 etc. to a variety of addresses across the entire first page of GPU RAM.

2) Unstable means it's taken a couple of resets to get the Microcom's Bootstrap to show on the console.  The Bootstrap does nothing to the GPU, other than a quick write/read loop through all the banks of memory to ascertain what's RAM and what's ROM.  It's most likely the read part of that routine that is causing the crash when it tries to write to, then read from the GPU memory.

3) All attempts to read data manually (via the PEEK command) have resulted in a crash.

Should I start increasing the DLY values?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 03:33:55 pm
Seriously man, the read shouldn't be able to crash.  The read delay is being ignored.  It only delays the write capture of the Z80's data output.

Try this:
Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 2; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 2; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn && last_Z80_WR; // Isolate a single write transaction
assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read  && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

//if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
//end else if (Z80_unmreq_pulse) begin
// mem_valid_range  <= 1'b0; // Define GPU addressable memory space
// mem_window   <= 1'b0; // Define an active memory range
//end



Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)

if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse
Z80_245data_dir   <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena <= 1'b0; // re-set bidir pins to input

if ( Z80_WRn ) begin
   //Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


If this one still crashes on read, something went haywire with your wiring changes, or new IO pin assignments, or breadboard wiring contacts.

When single writing, make sure the written 'FF' appear in the correct address.  It would seem your are not outputting the 245 to the GPU FPGA.  This may mean controls to the 245, or it's VCC/GND isn't wired good.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 03:59:12 pm
Seriously man, the read shouldn't be able to crash.  The read delay is being ignored.  It only delays the write capture of the Z80's data output.

Try this:
...

If this one still crashes on read, something went haywire with your wiring changes, or new IO pin assignments, or breadboard wiring contacts.

When single writing, make sure the written 'FF' appear in the correct address.  It would seem your are not outputting the 245 to the GPU FPGA.  This may mean controls to the 245, or it's VCC/GND isn't wired good.

I know, it's weird.  I've had this a lot during development, though, so I almost figure it's normal for electronics development.. I take it that it isn't.  ???  It's likely a loose connection somewhere, which frustrates me even more.

Well, that last update has certainly done something.

Writing to GPU RAM is now a little hit and miss - sometimes characters are dropped for null ($00) values, but infrequently.  I can almost get the DMI boot screen to display, but because of the write errors the Microcom isn't setting up the display properly.  If I load the default values using the RS232_debugger, I can see what I'm writing on the screen (but with the odd dropped character as mentioned previously).

Reading values appears to be solid - even if I 'dump' the entire first page of the GPU RAM to the console/screen, it's reading it accurately.

Here's the settings I'm using for this build:

DELAY_CYCLES  2
MREQ_DLY_CLK 0
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 04:04:35 pm
Increase the delay cycles to 4 or 6 or 8 or 10 or 12.
You may have to increase the delay register size and it's shift register values...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 04:16:19 pm
Increase the delay cycles to 4 or 6 or 8 or 10 or 12.
You may have to increase the delay register size and it's shift register values...

Will do - not changing MREQ_DLY_CLK at all, right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 04:17:53 pm
Increase the delay cycles to 4 or 6 or 8 or 10 or 12.
You may have to increase the delay register size and it's shift register values...

Will do - not changing MREQ_DLY_CLK at all, right?
Its no longer being used...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 04:23:24 pm
Will do - not changing MREQ_DLY_CLK at all, right?
Its no longer being used...

Aha, okay - removed it from the parameter block then.  Just tried with DELAY_CYCLES set to 4 - still dropping chars, but noticed that the screen actually shifted up a couple of lines when I got to the bottom, with minimal corruption, so it seems we're going in the right direction..  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 04:31:46 pm
Go to a delay of 8.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2020, 05:15:02 pm
This version is fully static, the delays are ignored...

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter DELAY_CYCLES  = 2; // number of cycles to delay write for 245
parameter MEM_SIZE_BITS = 15; //
parameter MREQ_DLY_CLK  = 2; // number of cycles +1 to delay mreq trigger

wire Z80_mreq, Z80_mreq_pulse, Z80_unmreq_pulse, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM_BEGIN, Read_GPU_RAM_END;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, MREQn_dly, MREQn_dly2, mem_window ;
reg [9:0] Z80_write_sequencer,Z80_mreq_dly;

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn ; // && last_Z80_WR; // Isolate a single write transaction

assign Z80_read     = ~Z80_RDn; // Isolate a single read transaction
assign Z80_readn     =  Z80_RDn && ~last_Z80_RD; // Isolate a single read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM_BEGIN =  mem_window && Z80_mreq && Z80_read  && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

Z80_mreq_dly[9:0] <= { Z80_mreq_dly[8:0], Z80_MREQn };

//if (Z80_mreq_pulse) begin
gpu_addr         <=  Z80_addr[18:0];                         // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE); // Define an active memory range
//end else if (Z80_unmreq_pulse) begin
// mem_valid_range  <= 1'b0; // Define GPU addressable memory space
// mem_window   <= 1'b0; // Define an active memory range
//end



// Z80_write_sequencer[9:0] <= { Z80_write_sequencer[8:0], Write_GPU_RAM };

// if ( Z80_write_sequencer[0] )                 Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
// if ( Z80_write_sequencer[0] )                 Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
// if ( Z80_write_sequencer[0] )                 Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)

// if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
// if ( Z80_write_sequencer[DELAY_CYCLES] )  gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we

// if ( Z80_write_sequencer[DELAY_CYCLES + 1] )  gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we (WAS STEP +2, now STEP +3 for additional WR)


if ( Write_GPU_RAM ) begin
Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)
 
gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we
end else begin
gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we
end


if ( Read_GPU_RAM_BEGIN ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux
Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output


end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse
Z80_245data_dir   <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena <= 1'b0; // re-set bidir pins to input

if ( Z80_WRn ) begin
   //Z80_245_oe <= 1'b1; // disable 245 output
end
end

if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];// Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Z80_WRn;
last_Z80_RD <= Z80_RDn;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

end

// **********************************************************************************************************

endmodule


If this works, first I'll need to do a cleanup, then we'll decide what to do next...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 05, 2020, 06:37:06 pm
If this works, first I'll need to do a cleanup, then we'll decide what to do next...

Oh boy does it work... CLS is clearing the screen nicely now and screen scrolling is working great with no artefacts at all...   ;D

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 12:01:50 am
I need a copy of your current project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 08:19:57 am
I need a copy of your current project.

Oops...  ::)  Here it is.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 11:29:10 am
Ok, here you go.

I cleaned up the project.  I had to also patch the MUX algorithm.

First, try the complete cleaned project 'GPU_Z80_bridge_staticIO.zip'.

If everything is ok, then switch the Z80_Bridge.v to the attached 'Z80_bridge_1-write.v'.  This version only does 1 single write to the GPU ram once at the end of every write cycle instead of 62.5 million writes / second during the entire time the Z80_WRn signal is low with a valid address.

Only if the 1-write version works, next switch to the 'Z80_bridge_1-read.v', 1 read / cycle version.  This version will send out a single read_req to the GPU ram at the beginning of the read cycle, latch the result and hold it on the output while the Z80_RDn is low instead of the static version which does a continuous 62.5 million reads / second during the entire time the Z80_RDn is low.

If the 1 read version works, then you have a good Z80 bridge interface which will eat practically no clock cycles from the GPU ram as a read and write to and from GPU ram will only come around once every 6 or more 8 MHz clock cycles.

In the future, it may be possible to enhance the MUX.v to better select the source A/B - READ/WRITE ports based on priority, but for now, it basically does a dumb 1 clk A, 1 clk B cycle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 12:55:38 pm
Ok, here you go.

I cleaned up the project.  I had to also patch the MUX algorithm.

First, try the complete cleaned project 'GPU_Z80_bridge_staticIO.zip'.

If everything is ok, then switch the Z80_Bridge.v to the attached 'Z80_bridge_1-write.v'.  This version only does 1 single write to the GPU ram once at the end of every write cycle instead of 62.5 million writes / second during the entire time the Z80_WRn signal is low with a valid address.

Only if the 1-write version works, next switch to the 'Z80_bridge_1-read.v', 1 read / cycle version.  This version will send out a single read_req to the GPU ram at the beginning of the read cycle, latch the result and hold it on the output while the Z80_RDn is low instead of the static version which does a continuous 62.5 million reads / second during the entire time the Z80_RDn is low.

If the 1 read version works, then you have a good Z80 bridge interface which will eat practically no clock cycles from the GPU ram as a read and write to and from GPU ram will only come around once every 6 or more 8 MHz clock cycles.

In the future, it may be possible to enhance the MUX.v to better select the source A/B - READ/WRITE ports based on priority, but for now, it basically does a dumb 1 clk A, 1 clk B cycle.

I seem to be fighting with a little instability today with one (or several) of the connections (which I've confirmed with the previous stable version of the project, it's not specific to the new project and Z80_bridge versions), but that aside, the new updates seems to be working very nicely.

EDIT: No - hang on..  more testing required.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 01:21:11 pm
No, the Z80_bridge updates aren't working properly - the first one causes write errors.  Haven't tested the second as a result.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 01:36:52 pm
No, the Z80_bridge updates aren't working properly - the first one causes write errors.  Haven't tested the second as a result.
The first one, the one which is in the .zip file, is identical to the one you deemed perfect.  All I've done is remove the comments and unused registers and parameters.

The only other difference is that I turned off the 'Perform Register Retiming For Performance' feature in the assignment settings, compiler settings, 'Advanced Settings (Fitter)...' button.

You can try turning that back on and see if there is a difference.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 02:07:05 pm
The project was fine - it's the first z80_bridge.v.txt update that seems to have caused issues?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 02:08:46 pm
The project was fine - it's the first z80_bridge.v.txt update that seems to have caused issues?

Are you talking about ''Z80_bridge_1-write.v''?

If so, I need to know...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 02:36:36 pm
Yes.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 03:02:40 pm
Ok, change line 104 of 'Z80_bridge_1-write.v' to this:

Code: [Select]
gpu_wr_ena      <=  Write_GPU_RAM && ~last_Z80_WR ; // Pulse the GPU ram's write enable at the BEGINNING of the Z80 write cycle.
And test.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 03:30:33 pm
Ok, change line 104 of 'Z80_bridge_1-write.v' to this:

Code: [Select]
gpu_wr_ena      <=  Write_GPU_RAM && ~last_Z80_WR ; // Pulse the GPU ram's write enable at the BEGINNING of the Z80 write cycle.
And test.

No, that's not working either - lots of errors caused when writing to the GPU RAM.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 03:44:45 pm
You have got to be kidding me....
Right?

It's almost as if for some silly reason, we need to fire off multiple of the same writes...
Unless the data lines are bouncing around and eventually the right data gets in...

Give this a try.  All I have done is make the gpu_wr_ena go active for 2 consecutive clocks instead of 1 single clock after a Z80 write has been confirmed.

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter MEM_SIZE_BITS = 15; //

wire Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, mem_window, last_Z80_WR2, last_Z80_WR3 ;


assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn ; // write transaction

assign Z80_read     = ~Z80_RDn; // read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read  && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

gpu_addr         <=  Z80_addr[18:0];                        // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE);    // Define an active memory range

if ( Write_GPU_RAM ) begin
Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)
 
gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
//gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we
end else begin
//gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we
end


if ( Read_GPU_RAM ) begin

gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux

Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output
end else begin
gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

Z80_245data_dir   <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end


if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];  // Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111;      // return $FF if addressed byte is outside the GPU's upper RAM limit
end


last_Z80_WR <= Write_GPU_RAM;
last_Z80_WR2 <= last_Z80_WR;
last_Z80_WR3 <= last_Z80_WR2;
last_Z80_RD <= Read_GPU_RAM;
Z80_clk_delay <= Z80_CLK; // find the rising clock edge

gpu_wr_ena      <= Write_GPU_RAM && ~last_Z80_WR2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
//gpu_rd_req      <= Read_GPU_RAM && ~ last_Z80_RD ; // Pulse the read request only once at the beginning of a read cycle.

end

// **********************************************************************************************************

endmodule


Maybe something fishy is going on inside the MUX and it is not seeing the single clock wide write pulse, though, then, the RS232_debugger should also have similar write errors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 03:55:40 pm
TYPO ERROR:, fix this line 106:

gpu_wr_ena      <= Write_GPU_RAM && ~last_Z80_WR2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed


(I just edited the line in the above post as well.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 04:02:25 pm
That seems to work fine?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 04:16:40 pm
That seems to work fine?

Ok, Good.  Next, the new single cycle read version:

Code: [Select]
module Z80_bridge (

// input
input wire reset, // GPU reset signal
input wire GPU_CLK, // GPU clock (125 MHz)
input wire Z80_CLK, // Microcom clock signal (8 MHz)
input wire Z80_M1n, // Z80 M1 - active LOW
input wire Z80_MREQn, // Z80 MREQ - active LOW
input wire Z80_WRn, // Z80 WR - active LOW
input wire Z80_RDn, // Z80 RD - active LOW
input wire [21:0] Z80_addr, // Microcom 22-bit address bus
input wire [7:0] Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
input wire [7:0] gpu_rData,
input wire gpu_rd_rdy, // one-shot signal from mux that data is ready

// output
output reg Z80_245data_dir, // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
output reg [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
output reg Z80_rData_ena, // flag HIGH to write data back to Z80
output reg Z80_245_oe, // OE for 245 level translator *** ACTIVE LOW ***
output reg gpu_wr_ena, // flag HIGH for 1 clock when writing to GPU RAM
output reg gpu_rd_req, // flag HIGH for 1 clock when reading from GPU RAM
output reg [19:0] gpu_addr, // connect to Z80_addr in vid_osd_generator to address GPU RAM
output reg [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator

    input wire  sel_pclk,  // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
    input wire  sel_nclk   // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
);

// TODO:
//
// 1) Prevent reads to GPU RAM above top of GPU RAM
// 2) Respond with appropriate data to any requests from Microcom ROM identification routines
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter MEM_SIZE_BITS = 15; //

wire Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, mem_window, last_Z80_WR2, last_Z80_WR3, last_Z80_RD2, last_Z80_RD3 ;


assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);


assign Z80_mreq     = ~Z80_MREQn && Z80_M1n; // Define a bus memory access state
assign Z80_write = ~Z80_WRn ; // write transaction

assign Z80_read     = ~Z80_RDn; // read transaction

assign Write_GPU_RAM =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read  && mem_valid_range;   // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

gpu_addr         <=  Z80_addr[18:0];                        // latch address bus onto GPU address bus
mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
mem_window   <= (Z80_addr[21:19] == MEMORY_RANGE);    // Define an active memory range

if ( Write_GPU_RAM ) begin
Z80_245data_dir  <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena    <= 1'b0; // set FPGA pins to input (should be by default)
Z80_245_oe       <= 1'b0; // enable 245 output (WAS 1 - moved forward to step 0)
 
gpu_wdata        <= Z80_wData; // latch data bus onto GPU data bus
//gpu_wr_ena       <= 1'b1; // turn on FPGA RAM we
end else begin
//gpu_wr_ena       <= 1'b0; // turn off FPGA RAM we
end


if ( Read_GPU_RAM ) begin

//gpu_rd_req <= 1'b1; // flag a read request to the mux which is one-shotted in the mux

Z80_245data_dir <= 1'b0; // set 245 direction (TO Z80)
Z80_245_oe <= 1'b0; // enable 245 output
Z80_rData_ena    <= 1'b1; // set bidir pins to output
end else begin
//gpu_rd_req <= 1'b0; // end GPU read req after 1 pulse

Z80_245data_dir   <= 1'b1; // set 245 dir toward FPGA
Z80_rData_ena <= 1'b0; // re-set bidir pins to input
end


if ( gpu_rd_rdy ) begin
if (mem_valid_range) Z80_rData[7:0] <= gpu_rData[7:0];  // Latch the GPU RAM read into the output register for the Z80
else Z80_rData[7:0]  <= 8'b11111111;      // return $FF if addressed byte is outside the GPU's upper RAM limit
end


Z80_clk_delay <= Z80_CLK; // find the rising clock edge

last_Z80_WR <= Write_GPU_RAM;
last_Z80_WR2 <= last_Z80_WR;
last_Z80_WR3 <= last_Z80_WR2;

last_Z80_RD <= Read_GPU_RAM;
last_Z80_RD2 <= last_Z80_RD;
last_Z80_RD3 <= last_Z80_RD2;

gpu_wr_ena      <= Write_GPU_RAM && ~last_Z80_WR2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
gpu_rd_req      <= Read_GPU_RAM  && ~last_Z80_RD2 ; // Pulse the read request only once at the beginning of a read cycle.

end

// **********************************************************************************************************

endmodule


I've done the same thing for the read as the write, so, it should also work fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 04:28:31 pm
Yes, that's working.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 04:35:08 pm
Ok, version 1.0 finished.
Archive it away and show us something 'interesting' working in the Z80.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 05:05:28 pm
Ok, version 1.0 finished.
Archive it away and show us something 'interesting' working in the Z80.

Okay, v1.0 project files attached.  Will get something 'interesting' up here in the next few days, work allowing.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2020, 05:08:25 pm
Ok, version 1.0 finished.
Archive it away and show us something 'interesting' working in the Z80.

Okay, v1.0 project files attached.  Will get something 'interesting' up here in the next few days, work allowing.  :-+

I still cant believe we got the Z80 bus interface working without a single scope shot or logic analyzer view.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 05:43:53 pm
I still cant believe we got the Z80 bus interface working without a single scope shot or logic analyzer view.

And there I was worrying that it wasn't working on the first day I connected it all up. ::)  Was starting to think that there was something major wrong with my wiring and you were going to run out of suggestions to try next. :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 05:47:27 pm
I've just realised, I've been spending time trying to get 8-bit and 16-bit text modes working and swapping between them with a command in the DMI... but then I stopped and thought, "Why?"  :-//  Is there any reason I'd need to use 8-bit text mode?  I mean, if the FPGA is so small that the difference between a 2.4 KB and 4.8 KB screen buffer is the difference between it working or not, then there's bigger issues with the choice of FPGA...?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 06, 2020, 06:12:48 pm
What would be the most straight-forward way to modify the existing 'return any reads to addresses above mem_valid_range as $FF' to return a byte addressed from a string (say 'GPU v1.0' for example) virtually addressed in the last $0F bytes of each page ($FF bytes) in the ~mem_valid_range?

As a practical example, the Microcom identifies the contents of each 16 KB bank of memory by the last 16 bytes.  If it's a ROM bank (and it's not empty), it'll have something like "DMI v1.34" in the last 16 bytes of that bank.

It'd be handy if the GPU could return the core version, for example, so the Microcom could identify that a GPU is attached and report to the user what version the GPU core is.

I'd be considering something like this (pseudo-code):

Code: [Select]
   if ( gpu_rd_rdy ) begin
      if (mem_valid_range)
          Z80_rData[7:0] <= gpu_rData[7:0];  // Latch the GPU RAM read into the output register for the Z80
      end else begin
          if (mem_ID_range == gpu_addr[13:4]) begin
              Z80_rData[7:0] <= ID_array[gpu_addr[3:0]][7:0];  // where ID_array = ['GPU v1.0' + 8'b11111111] *** for example ***
          else
              Z80_rData[7:0] <= 8'b11111111;     // return $FF if addressed byte is outside the GPU's upper RAM limit
      end
   end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 07, 2020, 07:38:12 am
Now @nockieboy, when we were team-viewing awhile back, you setup a test bench simulation for your Z80_Bridge.  Update it's Z80_bridge.v to the new one, try a few different read addresses and test the code you want to create.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 07, 2020, 11:25:47 am
Okay, it's not all that 'interesting', but here's a screenshot of the video output using the memory editor in the DMI:

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 07, 2020, 11:35:01 am
And a screenshot of the memory editor viewing the first page of the GPU RAM, with the HV_triggers and MAGGIE settings.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on January 07, 2020, 04:33:36 pm
Nice!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 07, 2020, 05:57:24 pm
Right off the bat, with 7 layers, if he uses 1 graphics layer, he has another 6 layers for sprites, he can make an authentic hi-res version on games like PacMan.  4 colors for the hires background maze & pellets, and 4 or 16 colors for the player sprites.  Or he can use a colored font layer for the background.

No audio though...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 07, 2020, 06:00:13 pm
Playing around with the Z80 code now and 'colouring-in' lots of the output has made me realise how restrictive my MMU is.  4x16KB areas just isn't cutting it anymore - especially if I want to get the GPU running with CP/M; I'm going to have to make it more fine-grained.  I'm halfway through designing a much more flexible MMU in hardware, but I haven't touched that since I started down this FPGA GPU route a couple of months ago - now I'm thinking that I might as well build the MMU into the FPGA, seeing as it has access to (nearly) all the address lines it needs and some spare RAM space. I'm running out of IOs on this dev board though!  :o

PS2 keyboard is next, and whenever @jhpadjustable is up for it, perhaps some sound.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 07, 2020, 06:01:59 pm
Nice!
Already have colored text functional.
Excellent.

Also got rid of the monochrome junk.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 07, 2020, 06:02:30 pm
Right off the bat, with 7 layers, if he uses 1 graphics layer, he has another 6 layers for sprites, he can make an authentic hi-res version on games like PacMan.  4 colors for the hires background maze & pellets, and 4 or 16 colors for the player sprites.  Or he can use a colored font layer for the background.

All I need is another 48 hours in the day, and I'll be set!  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 07, 2020, 06:12:31 pm
Playing around with the Z80 code now and 'colouring-in' lots of the output has made me realise how restrictive my MMU is.  4x16KB areas just isn't cutting it anymore - especially if I want to get the GPU running with CP/M; I'm going to have to make it more fine-grained.  I'm halfway through designing a much more flexible MMU in hardware, but I haven't touched that since I started down this FPGA GPU route a couple of months ago - now I'm thinking that I might as well build the MMU into the FPGA, seeing as it has access to (nearly) all the address lines it needs and some spare RAM space. I'm running out of IOs on this dev board though!  :o

PS2 keyboard is next, and whenever @jhpadjustable is up for it, perhaps some sound.  ;D
Can't use simple page-able ram?  You'll get 256 pages of 64kb.  Simple enough to implement in the FPGA, or anywhere else.  Though, I'm not sure about your Z80 code & you will need to reserve a memory location for the paging.  You can also have 2 paging spaces, 1 for executable code and 1 for program data, though, some of the advance features of the Z80 instruction set wont be able to cross page boundaries on their own.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 10, 2020, 09:09:19 am
Playing around with the Z80 code now and 'colouring-in' lots of the output has made me realise how restrictive my MMU is.  4x16KB areas just isn't cutting it anymore - especially if I want to get the GPU running with CP/M; I'm going to have to make it more fine-grained.  I'm halfway through designing a much more flexible MMU in hardware, but I haven't touched that since I started down this FPGA GPU route a couple of months ago - now I'm thinking that I might as well build the MMU into the FPGA, seeing as it has access to (nearly) all the address lines it needs and some spare RAM space. I'm running out of IOs on this dev board though!  :o

PS2 keyboard is next, and whenever @jhpadjustable is up for it, perhaps some sound.  ;D
Can't use simple page-able ram?  You'll get 256 pages of 64kb.  Simple enough to implement in the FPGA, or anywhere else.  Though, I'm not sure about your Z80 code & you will need to reserve a memory location for the paging.  You can also have 2 paging spaces, 1 for executable code and 1 for program data, though, some of the advance features of the Z80 instruction set wont be able to cross page boundaries on their own.

I'll just extend the same system I'm using now from reading A14-A15 and outputting EA14-EA21 to reading A12-A15 and outputting EA12-EA21 to break the banks down to smaller sizes. No issues crossing boundaries - the Z80 just sees 64KB of contiguous RAM, it doesn't know (or care) that the RAM could be made up of banks of RAM from all over a much larger physical memory space.

I'm designing a PCB for the 'next-level' dev board at the moment - it'll fit directly onto my computer and eliminate all the wiring, breadboards and dev board I'm currently contending with.  It'll basically be a v1 final board, but will have perhaps more IO considerations than the final board needs (for testing/developing an SD interface, etc).  For one, I'm looking to replace a couple of the 373 level converters on the address bus with 245s so I have the option of driving the expanded address bus from the FPGA - the FPGA will be able to fulfil the MMU's role if I decide to go that route, without any wiring, connection or PCB changes.  Will just need to modify the memory cards slightly to cater for the changes in A13/A12 being driven instead by EA13/EA12 from the FPGA etc.

I'm going to stick with Cyclone IV's for the moment as I have the dev environment set up for them - the above board will either use an EP4CE10 or CE15 FPGA, so the RAM will jump to 51 or 77KB respectively (and logic gate numbers increase respectively), but the package remains an easy-to-solder LQFP-144, minimising risk of problems/cost whilst I learn how to solder BGAs.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 10, 2020, 12:10:55 pm
For the future, the Lattice chip has 6x6 more pins than this chip Louis Rossmann is repairing in this video.

https://www.youtube.com/watch?v=2eXMFIkdA0o (https://www.youtube.com/watch?v=2eXMFIkdA0o)

The secret here is the cleaning tinning of the pads and all that flux which helps transport the heat.
And a new PCB would be 100x cleaner than that water damaged mac.

Do not got to the 30$ lattice chip, that one has it's solder balls at 0.5mm instead of 0.8mm.  But, if you do got that route and have your PCB manufacturer place the BGA for you, you will have 4megabits of graphics memory.

30$ part: https://www.mouser.com/ProductDetail/Lattice/LFE5U-85F-6MG285C?utm_term=LFE5U-85F&qs=Rp3RbKSfAt3i%252b4nmoAgpiw%3D%3D&utm_campaign=LFE5U-85F-6MG285C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice (https://www.mouser.com/ProductDetail/Lattice/LFE5U-85F-6MG285C?utm_term=LFE5U-85F&qs=Rp3RbKSfAt3i%252b4nmoAgpiw%3D%3D&utm_campaign=LFE5U-85F-6MG285C&utm_medium=aggregator&utm_source=findchips&utm_content=Lattice)

This one would need research on how to build a PCB with larger vias for cheap mode with larger, but, you use so few IO, all the core VCC&GNDs would be shared and the outer edge IOs would be the only ones in use.

The 0.8mm 2megabit part should be easy peasy.

Also, if you want a 240pin QFP, these Cyclone III exist:
https://www.aliexpress.com/item/33040049112.html?spm=a2g0o.productlist.0.0.1fb0572cf1SudS&algo_pvid=c9decdb7-cb39-4c61-a5e7-e7d7fb87dbaa&algo_expid=c9decdb7-cb39-4c61-a5e7-e7d7fb87dbaa-15&btsid=29a7fbad-6c65-48e0-acb4-eb26363f6e85&ws_ab_test=searchweb0_0,searchweb201602_7,searchweb201603_55 (https://www.aliexpress.com/item/33040049112.html?spm=a2g0o.productlist.0.0.1fb0572cf1SudS&algo_pvid=c9decdb7-cb39-4c61-a5e7-e7d7fb87dbaa&algo_expid=c9decdb7-cb39-4c61-a5e7-e7d7fb87dbaa-15&btsid=29a7fbad-6c65-48e0-acb4-eb26363f6e85&ws_ab_test=searchweb0_0,searchweb201602_7,searchweb201603_55)

You will get 1 megabit.  My project runs your GPU on an Cyclone EP3C55, so you know it will work, though you will need to use Quartus, I think V16 or below, though you will need to check the supported versions.  I know Quartus V12 & programs chips fine in Win10.

You have enough IO for a 24bit DAC or HDMI transmitter (Look for a DDR interface 12 wire HDMI transmitter to still save IOs), enough more for a direct IO pin HDMI transmitter, and audio DAC and with 40k gates, you can make a hardware accelerated drawing engine, accelerated memory Flash card interface & add an 8 bit DDR2 ram chip.  (Careful here, you want the IO bank and it's voltage to be on one of the faster banks + on a separate voltage supply, but you can run it tops at 200MHz in DDR meaning 400Mb/sec.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 10, 2020, 12:18:41 pm
Also be careful of the larger Cyclone IV in the 144 pin package.  You loose some IOs since more IOs are changed into VCCint/core and GND pins as they are needed to power the larger core.

As for the CycloneIII, use an adjustable regulator for the core VCCint.  If you run the IC a little high at their max 1.25v, or 1.3v, you can push the C8 to run a single DDR2/3 ram chip to 500MHz without error.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 10, 2020, 12:42:43 pm

I'm going to stick with Cyclone IV's for the moment as I have the dev environment set up for them - the above board will either use an EP4CE10 or CE15 FPGA, so the RAM will jump to 51 or 77KB respectively (and logic gate numbers increase respectively), but the package remains an easy-to-solder LQFP-144, minimising risk of problems/cost whilst I learn how to solder BGAs.  ;)
Those memory figures are wrong.
Try 40 kilobytes for CE10 and 48 kilobytes for CE15.  Based on design, you can only sub-divide huge chunks of ram into dividends of 8 kilobytes, or smaller ones into 1/2/4/8 kilobytes.  You can test compile to check.  My suggested 240pin Cyclone III give you 120 kilobytes, + double the IOs + more than double the logic cells of the CE15.  With another 1 kilobyte for the palette, and another 1x2 kilobytes to cache the DDR memory.  Another 1x2 kilobytes to cache the flash ram card.  (This means a 320x240@256 color background with colored text and sprites with 15 MAGGIE layers before you even incorporate the 16 megabyte DDR2 ram chip)

Read the data sheet and learn what an M9K block is.  Also, since your memory allocation is using blocks divided into 16 bits instead of 18 bits, you loose some flexibility in memory allocation and you cannot use all the bits at your disposal.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 10, 2020, 04:14:19 pm
For the future, the Lattice chip has 6x6 more pins than this chip Louis Rossmann is repairing in this video.
...
The secret here is the cleaning tinning of the pads and all that flux which helps transport the heat.
And a new PCB would be 100x cleaner than that water damaged mac.

He makes it look really easy actually - I guess with an SMT stencil and some decent flux, a BGA FPGA could be easier than an LQFP...

Do not got to the 30$ lattice chip, that one has it's solder balls at 0.5mm instead of 0.8mm.  But, if you do got that route and have your PCB manufacturer place the BGA for you, you will have 4megabits of graphics memory.

I'd have to be selling these things or crowd-funding the project if I was going to fund the cost for having a manufacturer place the BGA for me, it seems.  :o

You have enough IO for a 24bit DAC...

Yes, I'm just waiting on a DAC in the post to test my design on a PCB that will plug into the existing dev board and replace the 12-bit DAC.  I've built a 24-bit DAC into the new GPU board.

I'm going to stick with Cyclone IV's for the moment as I have the dev environment set up for them - the above board will either use an EP4CE10 or CE15 FPGA, so the RAM will jump to 51 or 77KB respectively (and logic gate numbers increase respectively), but the package remains an easy-to-solder LQFP-144, minimising risk of problems/cost whilst I learn how to solder BGAs.  ;)
Those memory figures are wrong.
Try 40 kilobytes for CE10 and 48 kilobytes for CE15.  Based on design, you can only sub-divide huge chunks of ram into dividends of 8 kilobytes, or smaller ones into 1/2/4/8 kilobytes.  You can test compile to check.  My suggested 240pin Cyclone III give you 120 kilobytes, + double the IOs + more than double the logic cells of the CE15.  With another 1 kilobyte for the palette, and another 1x2 kilobytes to cache the DDR memory.  Another 1x2 kilobytes to cache the flash ram card.

Read the data sheet and learn what an M9K block is.  Also, since your memory allocation is using blocks divided into 16 bits instead of 18 bits, you loose some flexibility in memory allocation and you cannot use all the bits at your disposal.

:wtf: I knew they were ball-park figures, but didn't realise I was that far out...  :(  Will go look at the Cyclone III more closely - or may just have to jump straight to the Lattice then, taking the BGA leap in one go... I take it an FPGA wouldn't be hot-air solderable in BGA format, unlike the smaller chip in the video you linked?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 10, 2020, 04:39:32 pm
:wtf: I knew they were ball-park figures, but didn't realise I was that far out...  :(  Will go look at the Cyclone III more closely - or may just have to jump straight to the Lattice then, taking the BGA leap in one go... I take it an FPGA wouldn't be hot-air solderable in BGA format, unlike the smaller chip in the video you linked?
In the video, the BGA was only 0.6mm smaller than the Lattice BGA.  What you saw was equivalent to a 100 pin BGA, 0.8mm.  The Lattice part is 256 pin.  (10x10 VS 16x16 balls)  Hot air with a ton of flux so the BGA floats when heated allowing it to self-center will solder easy.  The larger 4mb Lattice part with more IOs is actually a smaller IC since the ball pitch is 0.5mm.  That one I would leave to someone with superior gear to mount.

The Cyclone III is a normal QFP making life easy to solder and patch in an emergency where you can lift a pin.  You also get enough IOs to make 1 or 2 IO banks 2.5v for the DDR memory while leaving the other IO banks at 3.3v.  However, be warned, for the VCCint/core, make sure you have a 2 amp regulator since it can draw power if you fill up the IC completely with logic and max out the clock speed.  Same goes for the larger Cyclone IV chips.  This is why you loose IO pins on the larger Cyclone IV chips as those pins get changed into VCCint power pins to supply the core.

I would use the TI DVI transmitter listed earlier, and also add a second HDMI connector directly connected to IO pins to try out a soft serializer core which you may develop before going to a Lattice FPGA since you might be able to get rid of the TI DVI transmitter IC.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 11, 2020, 01:08:42 pm
In the video, the BGA was only 0.6mm smaller than the Lattice BGA.  What you saw was equivalent to a 100 pin BGA, 0.8mm.  The Lattice part is 256 pin.  (10x10 VS 16x16 balls)  Hot air with a ton of flux so the BGA floats when heated allowing it to self-center will solder easy.

Fair enough - seems I don't even need to worry about a hot plate or reflow oven then?  That would make the setup a lot cheaper.

The Cyclone III is a normal QFP making life easy to solder and patch in an emergency where you can lift a pin.  You also get enough IOs to make 1 or 2 IO banks 2.5v for the DDR memory while leaving the other IO banks at 3.3v.  However, be warned, for the VCCint/core, make sure you have a 2 amp regulator since it can draw power if you fill up the IC completely with logic and max out the clock speed.  Same goes for the larger Cyclone IV chips.  This is why you loose IO pins on the larger Cyclone IV chips as those pins get changed into VCCint power pins to supply the core.

Those Cyclone IIIs sound better than the IVs...?  Which seems ironic due to their numbering...?

I would use the TI DVI transmitter listed earlier, and also add a second HDMI connector directly connected to IO pins to try out a soft serializer core which you may develop before going to a Lattice FPGA since you might be able to get rid of the TI DVI transmitter IC.

Okay, the TFP410 (http://www.ti.com/lit/ds/symlink/tfp410.pdf)?  Are there any reference designs floating around in the ether for that chip at all?  I'm Googling for ideas as I write this reply, but not finding any obvious tips.

As for the second HDMI connector - there's going to be preferential (high-speed IO) pins to connect it to on the FPGA, right?  I'm going to have to switch to the Cyclone III or Lattice FPGA for these as I don't have the spare IO on the Cyclone IV CE10 (no point using the CE15 really, as it's more expensive, still limited on RAM and less IO).

@jhpadjustable - don't know if you're still following this discussion, but if so, what considerations do I need to make regarding IO pins so that I can use the new 'v1' GPU card to develop audio output on it?  Would make absolute sense to include an audio driver of some description (or just reserve a couple of pins connected to a header) so that I at least have the option of developing the audio side in the FPGA.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 11, 2020, 01:33:26 pm

Those Cyclone IIIs sound better than the IVs...?  Which seems ironic due to their numbering...?

Only the CycloneIV GX series offer a few different embedded hardware above the CycloneIII.  Otherwise, the III is identical to the IV which you are using in every respect, other than the 240pin QFP has been dropped for BGA packages only.

Read all you DVI transmitter datasheets... Also read the IO pins and their advanced uses in intel's manuals to know which IOs to use for ram & regular bus interface applications.  Read about audio DACs and how many IOs you need to operate them if you want sound.  TI has an absurd amount of info on audio DACs with different capabilities and prices.  Also, the DVI transmitters operate exactly like a video DAC, except you do not need to worry about driving the H&V sync down a video cable.  Also, the DVI transmitter can drive an HDMI connector as it is backwards compatible.  Also, the DVI transmitter may support multiplexed digital video meaning you send 12 bits, the upper 12 on a high clock, the lower 12 on a low clock meaning only 16 IOs in total are used instead of 28.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 08:15:02 am
Hi @nockieboy, I hope you are progressing well.  Do you have schematics for us to look at and Gerbers yet?

I hope you purchased a few of those Cyclone IIIs.  As is usual here at EEVblog, when a good deal with a good project is listed, like a huge 100$ FPGA for 35$, in a hand solder-able QFP, the stock is now sold out.  You would need to purchase something like 1K pieces or an entire production run direct from Intel to get that price.

Do you have anything new to show us on the Z80 software driving the GPU?

Remember, the part number is 'EP3C40Q240C8N'
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2020, 10:08:07 am
Hi @nockieboy, I hope you are progressing well.  Do you have schematics for us to look at and Gerbers yet?

Unfortunately, progress has been pretty slow as work is getting progressively busier as the month wears on.  :scared:  Coincidentally, I have just finished an initial PCB design in the last couple of days though; schematics and PCB designs attached.  Would appreciate any feedback on them - especially if there's any problems or mistakes!  I'm not an electrical engineer and have no training, so I've tried my best to copy the schematic for the dev board where I can (rightly or wrongly) and add-in the bits and pieces I need.  I'm waiting on a couple of ADV7125s to arrive in the post so that I can test the 'video out' part of the circuit before committing the entire design to PCB.

I don't want bad design of the PCB to hinder later development of things like the keyboard interface, sound or SD card interface and what I've attached here is a first draft.  One thing I haven't done with the design is look at which signals go to which pins - a lot of what is connected where, and in which order, has been dictated by the board design and FPGA orientation to get a successful routing completed.  I need to review those connections and make sure it will work as intended.

I hope you purchased a few of those Cyclone IIIs.  As is usual here at EEVblog, when a good deal with a good project is listed, like a huge 100$ FPGA for 35$, in a hand solder-able QFP, the stock is now sold out.  You would need to purchase something like 1K pieces or an entire production run direct from Intel to get that price.

I haven't purchased any Cyclone III's just yet - my budget is restrictive at best (remember, I'm doing this purely as a hobby) and my confidence in building one of these PCBs and getting it right first time matches that, so I'm taking smaller, slower steps initially and designing for a Cyclone IV EP4CE10.  Once I'm happy that I've got the design considerations down for that and a working build (and can get rid of the dev board and mess of wires off my desk!), I'll either switch straight to a Lattice build if my design skills are up to the task and I'm feeling brave, or see about getting a Cyclone III.  ;)

Parts are ordered for the first build - I haven't ordered the PCB yet (good thing as I hadn't thought you might want to check it out!) but they tend to get delivered a lot quicker than the parts do; seems that the parts come on the back of a tuk tuk or something from China. ;D

Do you have anything new to show us on the Z80 software driving the GPU?

Other than the DMI monitor (some screenshots I've posted previously), there's nothing new really to show at the moment - I'm about to start working on the video driver for CP/M as soon as I get a day free to make a start on it, once that's done there'll be more to see.  :)

Quick question though - how did you get the Z80 image converted for the GPU?  Did you use stock software and something to save it in the required format, or write a converter yourself?  I'm using paint.net (https://www.getpaint.net/index.html) rather than Photoshop.

The other important thing I want to start testing shortly is the PS2 interface - need to get that up and running and sending chars to the Z80 via interrupts before I order the PCB, just so I'm happy the circuit will work.  With the FPGA using 3.3v, and needing to pull the 5v interrupt line low when required, I'm using a transistor to do that - hopefully that will work, but I've yet to set up a test.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 12:09:40 pm
Go for the cheapest version of the ADV7125 DAC, the 50MHz version, though the TI THS8136PHP is cheaper, faster and higher quality, but you need to run the IO and a bank on the FPGA at 1.8v, though, no voltage reference.
https://www.mouser.com/ProductDetail/Texas-Instruments/THS8136PHP?qs=sGAEpiMZZMswix2y39yldVRXhfgYHmM93ATDG4%252BVYYs%3D (https://www.mouser.com/ProductDetail/Texas-Instruments/THS8136PHP?qs=sGAEpiMZZMswix2y39yldVRXhfgYHmM93ATDG4%252BVYYs%3D)
vs
https://www.mouser.com/ProductDetail/Analog-Devices/ADV7125KSTZ50?qs=sGAEpiMZZMswix2y39yldfRSUiTQKynFVgceQfpCL2c%3D (https://www.mouser.com/ProductDetail/Analog-Devices/ADV7125KSTZ50?qs=sGAEpiMZZMswix2y39yldfRSUiTQKynFVgceQfpCL2c%3D)

Why are you clocking the DAC from your oscillator.  You should be using an output from the FPGA, preferably, one of the dedicated PLL output pins.  Use the second PLL CLK output if you have the reference oscillator on CLK1 input.

Why haven't you wired the 'blank' signal on the DAC to the video enable out.  It would help and also is necessary if you change the DAC for the DVI transmitter.

Things you can use the FPGA dedicated CLK inputs for:
clock oscillator <must be on a dedicated clock input for PLL to function  at high quality>
z80 clk input
Z80 buss controls, IE RD WR MREQ M1 INTA, IORQ, so long as all the buss controls are on the dedicated clock inputs.
reset
serial port RXD

I'm trusting you FPGA IO pins and part number.  Remember the EP4CE10E22C8N may have a few different IO pins than the EP4CE6E22C8N, typically a few less IOs changed into VCCint and GNDint.


What about the unused IOs on the SD-Card reader.

For the next revision, note that going straight to BGA means you cannot make a mistakes as you wont have access to pins to lift.

What size are your VIAs on your PCB.  are you sure any fab house can handle that in cheap PCB mode?  I know it's not a problem with higher quality expensive PCBs and if you are already using fine VIAs, you might as well go to a 4 layer PCB as it will be only a few dollars more from some China PCB manufacturers.

Are your power traces thin little traces like the data lines?


Your AMS1117-1.2 is ok for the EP4CE10E22C8N and you should expect it to get warm since it is linear with an almost 4v drop and a potential 0.25w VCCint load when switching your core to 15 layers.  This means around 208ma draw on a 800ma regulator.  With a 3.8v drop from the 5v supply = around 0.8 watts of dissipated waste heat.  (I'm assuming worst case with your current design).

Where is your 3.3v regulator?

You are going to get noise/ripples on you analog output with that ground layout and positioning of resistors.
Also, ADV7125 has an internal voltage reference mode.
With the ADV7125, also make sure the analog 5V is well filtered and isolated from the rest of your 5v design.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2020, 01:29:59 pm
Go for the cheapest version of the ADV7125 DAC, the 50MHz version, though the TI THS8136PHP is cheaper, faster and higher quality, but you need to run the IO and a bank on the FPGA at 1.8v, though, no voltage reference.

Yes, I've gone for the 50 MHz version.

Why are you clocking the DAC from your oscillator.  You should be using an output from the FPGA, preferably, one of the dedicated PLL output pins.  Use the second PLL CLK output if you have the reference oscillator on CLK1 input.

Erm...  ::)  I guess because it's a 50 MHz clock and the DAC is 50 MHz, it seemed like a good idea at the time?  I take it using CLK7, 6, or 4 wouldn't be an issue?  It would make routing easier?

Why haven't you wired the 'blank' signal on the DAC to the video enable out.  It would help and also is necessary if you change the DAC for the DVI transmitter.

No particular reason, other than I guess I thought it wasn't needed.  Have added it in then.  :-+

Things you can use the FPGA dedicated CLK inputs for:
clock oscillator <must be on a dedicated clock input for PLL to function  at high quality>
z80 clk input
Z80 buss controls, IE RD WR MREQ M1 INTA, IORQ, so long as all the buss controls are on the dedicated clock inputs.
reset
serial port RXD

I'm trusting you FPGA IO pins and part number.  Remember the EP4CE10E22C8N may have a few different IO pins than the EP4CE6E22C8N, typically a few less IOs changed into VCCint and GNDint.

Well, I've yet to go through and confirm that the pins are all okay.  The realisation that the reference design I've been working from is for the CE6 version has caused me to go dig up a reference for a CE10 version - I'll go through the pins when I get a chance.


What about the unused IOs on the SD-Card reader.

Well, I was getting short of IOs so it seemed a 1-bit connection was the best idea - again, based off of example schematics I'd found elsewhere...

What size are your VIAs on your PCB.  are you sure any fab house can handle that in cheap PCB mode?  I know it's not a problem with higher quality expensive PCBs and if you are already using fine VIAs, you might as well go to a 4 layer PCB as it will be only a few dollars more from some China PCB manufacturers.

Ah, well spotted.  They're 10mil vias (20mil overall) - I've just checked with JLCPCB and it appears I can go that small on a multi-layer PCB, but not on a 2-layer PCB.  :(

Are your power traces thin little traces like the data lines?

Most traces are 8mil, or 12mil for the 5v lines, with 6mil minimum spacing for all?  I guess with the power requirements of the EP4CE10, I'll need wider traces on ALL the power lines?

Where is your 3.3v regulator?

That's off-board, on another card in the stack along with the 5v regulator.  I guess I could do with adding a cap or two to that supply as it comes onto the card.

You are going to get noise/ripples on you analog output with that ground layout and positioning of resistors.
Also, ADV7125 has an internal voltage reference mode.
With the ADV7125, also make sure the analog 5V is well filtered and isolated from the rest of your 5v design.

I'm into new territory here. :o How do I need to improve the ground layout?  Are there any guides or tutorials on this sort of thing?  So I don't need the AD1580 voltage reference?  I'll go see what I can learn about power supply filtering and isolation..  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 02:02:02 pm
Go for the cheapest version of the ADV7125 DAC, the 50MHz version, though the TI THS8136PHP is cheaper, faster and higher quality, but you need to run the IO and a bank on the FPGA at 1.8v, though, no voltage reference.

Yes, I've gone for the 50 MHz version.

Why are you clocking the DAC from your oscillator.  You should be using an output from the FPGA, preferably, one of the dedicated PLL output pins.  Use the second PLL CLK output if you have the reference oscillator on CLK1 input.

Erm...  ::)  I guess because it's a 50 MHz clock and the DAC is 50 MHz, it seemed like a good idea at the time?  I take it using CLK7, 6, or 4 wouldn't be an issue?  It would make routing easier?
The dac CLK needs to be the pixel clk, not the 50MHz clk.
You cannot use the FPGA dedicated CLK inputs as an output to drive the DAC clk input.  They are inputs only.  Read the Intel datasheet and find out which output are connected to a PLL clock output.
Quote
Why haven't you wired the 'blank' signal on the DAC to the video enable out.  It would help and also is necessary if you change the DAC for the DVI transmitter.

No particular reason, other than I guess I thought it wasn't needed.  Have added it in then.  :-+

Things you can use the FPGA dedicated CLK inputs for:
clock oscillator <must be on a dedicated clock input for PLL to function  at high quality>
z80 clk input
Z80 buss controls, IE RD WR MREQ M1 INTA, IORQ, so long as all the buss controls are on the dedicated clock inputs.
reset
serial port RXD

I'm trusting you FPGA IO pins and part number.  Remember the EP4CE10E22C8N may have a few different IO pins than the EP4CE6E22C8N, typically a few less IOs changed into VCCint and GNDint.

Well, I've yet to go through and confirm that the pins are all okay.  The realisation that the reference design I've been working from is for the CE6 version has caused me to go dig up a reference for a CE10 version - I'll go through the pins when I get a chance.


What about the unused IOs on the SD-Card reader.

Well, I was getting short of IOs so it seemed a 1-bit connection was the best idea - again, based off of example schematics I'd found elsewhere...

What size are your VIAs on your PCB.  are you sure any fab house can handle that in cheap PCB mode?  I know it's not a problem with higher quality expensive PCBs and if you are already using fine VIAs, you might as well go to a 4 layer PCB as it will be only a few dollars more from some China PCB manufacturers.

Ah, well spotted.  They're 10mil vias (20mil overall) - I've just checked with JLCPCB and it appears I can go that small on a multi-layer PCB, but not on a 2-layer PCB.  :(

Are your power traces thin little traces like the data lines?

Most traces are 8mil, or 12mil for the 5v lines, with 6mil minimum spacing for all?  I guess with the power requirements of the EP4CE10, I'll need wider traces on ALL the power lines?
You should only use the 6 mil spacing between traces-traces and pads.  You should have something like 10 or 12 mil spacing for everything else like polygon fills.
5V and 3.3V & 1.2v, if not filled should be at least 50mil for the most part.  Make sure you have no weak points and don't pass through single vias, or any at all.
Quote
Where is your 3.3v regulator?

That's off-board, on another card in the stack along with the 5v regulator.  I guess I could do with adding a cap or two to that supply as it comes onto the card.

You are going to get noise/ripples on you analog output with that ground layout and positioning of resistors.
Also, ADV7125 has an internal voltage reference mode.
With the ADV7125, also make sure the analog 5V is well filtered and isolated from the rest of your 5v design.

I'm into new territory here. :o How do I need to improve the ground layout?  Are there any guides or tutorials on this sort of thing?  So I don't need the AD1580 voltage reference?  I'll go see what I can learn about power supply filtering and isolation..  ???
Your ground around the VGA connector and dac and 75 ohm load resistors is broken up and not solid.  It routs as a large open object which connects at some different GND points at the outer edges.  Also, your 5v feeding the DAC is your digital 5v.  You need an analog 5v.  A separate 5v from it's own dedicated 5v regulator whose GND is referenced right at the DAC's analog GND and VGA connector's GND return pins for the R&G&B wires.  Make sure you feed the DAC's 5v regulator with 9v to 12v through a series RC or RLC filter whose filter termination attaches to the DAC's analog GND.

Read the dac data sheet, it tells you how to operate the DAC using it's internal voltage reference.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2020, 05:01:09 pm
You should only use the 6 mil spacing between traces-traces and pads.  You should have something like 10 or 12 mil spacing for everything else like polygon fills.
5V and 3.3V & 1.2v, if not filled should be at least 50mil for the most part.  Make sure you have no weak points and don't pass through single vias, or any at all.

Righto, will sort that on the next revision. Vias are unavoidable on a 2-layer board.  Might have a look at what the cost of a 4-layer board would be. :-\

If I'm going multi-layer, it'll be for the first time ever.  Are there any particular considerations I need to bare in mind? Should I separate the power and ground planes with the signal plane (or not), for example?

Also, ADV7125 has an internal voltage reference mode.
With the ADV7125, also make sure the analog 5V is well filtered and isolated from the rest of your 5v design.

Your ground around the VGA connector and dac and 75 ohm load resistors is broken up and not solid.  It routs as a large open object which connects at some different GND points at the outer edges.  Also, your 5v feeding the DAC is your digital 5v.  You need an analog 5v.  A separate 5v from it's own dedicated 5v regulator whose GND is referenced right at the DAC's analog GND and VGA connector's GND return pins for the R&G&B wires.  Make sure you feed the DAC's 5v regulator with 9v to 12v through a series RC or RLC filter whose filter termination attaches to the DAC's analog GND.

Read the dac data sheet, it tells you how to operate the DAC using it's internal voltage reference.

I'm a little confused by the data sheet, to be honest.  It states there's an internal reference mode, but then states that the Vref pin should be connected up as per the application schematic (figure 12, page 15 of the datasheet), where it shows an external reference being used and makes no mention of how to enable the internal reference mode.  All I can surmise is that the diode and resistor should be removed and a capacitor (value unknown) placed in series with Vaa feeding the Vref pin?

Also, the 5V supply is direct from the USB port in this instance.  Or it could be from a 5V regulator if a 9-18V power supply is used.  Creating an analogue 5V supply is not going to be easy and will require modifications and a new version to an existing card that handles the power supply for the computer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 05:09:24 pm
Also, the 5V supply is direct from the USB port in this instance.  Or it could be from a 5V regulator if a 9-18V power supply is used.  Creating an analogue 5V supply is not going to be easy and will require modifications and a new version to an existing card that handles the power supply for the computer.
USB5v powering an analog 5v device... :(
Give me some time to think of something.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 05:16:40 pm
You should only use the 6 mil spacing between traces-traces and pads.  You should have something like 10 or 12 mil spacing for everything else like polygon fills.
5V and 3.3V & 1.2v, if not filled should be at least 50mil for the most part.  Make sure you have no weak points and don't pass through single vias, or any at all.

Righto, will sort that on the next revision. Vias are unavoidable on a 2-layer board.  Might have a look at what the cost of a 4-layer board would be. :-\

If I'm going multi-layer, it'll be for the first time ever.  Are there any particular considerations I need to bare in mind? Should I separate the power and ground planes with the signal plane (or not), for example?

Your going to need to make the bottom almost all GND and thick VCC/VCCint/VCCa.  You will need multiple parallel vias for the power traces.  Coming from the regulators, use 50mil, but you may shrink them to 20 mils approaching the FPGA and other ICs, as long as the decoupling caps are next to a large filled GND plane.  Don't bother filling the top with a GND plane, it will just make you be sloppy about placing the GND and this allows you to focus on layout and IO pin selection.

You may take a few liberties with the 245 buffers, but with your layout, you probably wont need to.

Your design is simple enough to go with 2 layer, just need to do things a little smarter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2020, 05:23:19 pm
Also, the 5V supply is direct from the USB port in this instance.  Or it could be from a 5V regulator if a 9-18V power supply is used.  Creating an analogue 5V supply is not going to be easy and will require modifications and a new version to an existing card that handles the power supply for the computer.
USB5v powering an analog 5v device... :(
Give me some time to think of something.

Let me add that the USB power supply is NOT a permanent thing.  All this time the Microcom has been slaved to a host PC so I can see its output and talk to it via a serial console.  With the addition of a video card and PS2 keyboard, it won't need to be connected to a host computer any more and so its usual method of receiving power will be via a 12V source (wall wart?).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 06:43:46 pm
Also, the 5V supply is direct from the USB port in this instance.  Or it could be from a 5V regulator if a 9-18V power supply is used.  Creating an analogue 5V supply is not going to be easy and will require modifications and a new version to an existing card that handles the power supply for the computer.
USB5v powering an analog 5v device... :(
Give me some time to think of something.
Let me add that the USB power supply is NOT a permanent thing.  All this time the Microcom has been slaved to a host PC so I can see its output and talk to it via a serial console.  With the addition of a video card and PS2 keyboard, it won't need to be connected to a host computer any more and so its usual method of receiving power will be via a 12V source (wall wart?).

I read the ADV7125 data sheet, it specifically says the dac can operate with a Vaa at 3.3v on page 4 of 17.  Use a dedicated 3.3v 150-350ma regulator powered from 5v with the input filter I mentioned.  This will allow you to filter your 5v supply to a clean 3.3v for the analog video out.

For the v-ref, as an output, just place the cap, no resistor.  But, I would place dummy pads for the resistor and reference diode since you may just leave them unpopulated.

Here is the cheapest ADV7125:
https://www.chip1stop.com/view/dispDetail/DispDetail?lang=en&cont=USA&partId=AD01-0052199&mpn=ADV7125KSTZ50&keyword=adv7125 (https://www.chip1stop.com/view/dispDetail/DispDetail?lang=en&cont=USA&partId=AD01-0052199&mpn=ADV7125KSTZ50&keyword=adv7125)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2020, 07:09:20 pm
I read the ADV7125 data sheet, it specifically says the dac can operate with a Vaa at 3.3v on page 4 of 17.  Use a dedicated 3.3v 150-350ma regulator powered from 5v with the input filter I mentioned.  This will allow you to filter your 5v supply to a clean 3.3v for the analog video out.

For the v-ref, as an output, just place the cap, no resistor.  But, I would place dummy pads for the resistor and reference diode since you may just leave them unpopulated.

 :-+ Sounds like a plan.

Here is the cheapest ADV7125:
https://www.chip1stop.com/view/dispDetail/DispDetail?lang=en&cont=USA&partId=AD01-0052199&mpn=ADV7125KSTZ50&keyword=adv7125 (https://www.chip1stop.com/view/dispDetail/DispDetail?lang=en&cont=USA&partId=AD01-0052199&mpn=ADV7125KSTZ50&keyword=adv7125)

I ordered mine here: https://www.aliexpress.com/item/4000433708668.html?spm=a2g0s.9042311.0.0.27424c4dqtzxLQ (https://www.aliexpress.com/item/4000433708668.html?spm=a2g0s.9042311.0.0.27424c4dqtzxLQ)

..but I notice it's a 240MHz part.  Should be okay though running at 50 MHz?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 07:17:11 pm

..but I notice it's a 240MHz part.  Should be okay though running at 50 MHz?  ???

? Your pixel clock is 25MHz, not 50.  Your need to clock the DAC at 25MHz to match your pixel clock speed.  The 240 is the upper limit.
Also, those at Aliexpress, what does the chip look like.  Though they might be fake, or 50Mhz relabeled at 250, they are a simple enough component which should still work fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2020, 07:22:52 pm
? Your pixel clock is 25MHz, not 50.  Your need to clock the DAC at 25MHz to match your pixel clock speed.

Yep, you got me.  I should stop trying to do two things at once.  ;)

The 240 is the upper limit.
Also, those at Aliexpress, what does the chip look like.  Though they might be fake, or 50Mhz relabeled at 250, they are a simple enough component which should still work fine.

That's okay then.  Yes, it's always a concern about getting fake components, my luck will run out at some point...  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2020, 11:13:29 pm
Ok, here are the actual limits of each intel FPGA as I compiled your project with these chips:
Code: [Select]
-----------------------------------
EP4CE6E22C8
NUM_LAYERS = 7
ADDR_SIZE = 15
NUM_WORDS = 24576

Logic cells = 95% full
Remaining 1kbyte blocks = 5.
-----------------------------------
EP4CE10E22C8
NUM_LAYERS = 13
ADDR_SIZE = 16
NUM_WORDS = 40960

Logic cells = 96% full
Remaining 1kbyte blocks = 5.
-----------------------------------
EP4CE15E22C8
NUM_LAYERS = 15
ADDR_SIZE = 16
NUM_WORDS = 53248

Logic cells = 75% full
Remaining 1kbyte blocks = 3.
-----------------------------------
EP4CE40F23C8N OR EP3C40Q240C8N
NUM_LAYERS = 15
ADDR_SIZE = 17
NUM_WORDS = 122880

Logic cells = 30% full
Remaining 1kbyte blocks = 5.
-----------------------------------

Num_words is the bytes of available GPU display ram, + another 1024 for the palette.
Num_layers is the available display windows/sprites.  By now, you know what that means...

I was wrong about the 'EP4CE15E22C8', you actually make it to 53.248kb instead of 48kb.
The cyclone III makes it to 122.88kb + space and IO pins for a 128mb or 1gb DDR2 Dram + another 3 MAGGIE layers for the Dram's contents (18 total MAGGIEs), but, your Z80 has so little address space that the 1gb may be too much.

Since you are using the slowest -C8 versions, and, you need a C7, or even a -C6 for the higher densities, I recommend replacing the 1.2v regulator for an adjustable one and adjust it for 1.35v.  This will make a C8 perform somewhere inbetween a C7 and C6 which would be perfect.  Though, my GPU design, there are only a few critical address paths in the FPGA, so it still wont get warm or draw too much current over driving the VCCint to 1.35v.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 18, 2020, 12:41:21 am
Wow, Aliexpress has this EP4CE55F23C8N:
https://www.aliexpress.com/item/4000565235137.html?spm=a2g0o.productlist.0.0.6f4070d8TJDFSw&algo_pvid=32026952-2ec8-4c29-8482-f604669bd0df&algo_expid=32026952-2ec8-4c29-8482-f604669bd0df-10&btsid=81dd9ffb-1486-42b3-a4ca-3047c798def0&ws_ab_test=searchweb0_0,searchweb201602_7,searchweb201603_55 (https://www.aliexpress.com/item/4000565235137.html?spm=a2g0o.productlist.0.0.6f4070d8TJDFSw&algo_pvid=32026952-2ec8-4c29-8482-f604669bd0df&algo_expid=32026952-2ec8-4c29-8482-f604669bd0df-10&btsid=81dd9ffb-1486-42b3-a4ca-3047c798def0&ws_ab_test=searchweb0_0,searchweb201602_7,searchweb201603_55)

At 2.3 megabit, that's slightly larger than the 1.9 megabit Lattice part.  Though, the 16$ lattice part is coming from reputable sources like Digikey and Mouser and you are guaranteed a legitimate part.  Digikey lists the EP4CE55F23C8N at $115 usd, so that 18$ Aliexpress price sounds too fishy.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 18, 2020, 01:02:10 am
 Put in the extra effort and use at least the 'EP4CE15E22C8' fpga.  You get all 15 maggie layers, and enough free logic gates to add sprite collision detection or/maybe and semi-translucency between all layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 18, 2020, 06:08:54 pm
Ok, here are the actual limits of each intel FPGA as I compiled your project with these chips:
Code: [Select]
-----------------------------------
EP4CE6E22C8
NUM_LAYERS = 7
ADDR_SIZE = 15
NUM_WORDS = 24576

Logic cells = 95% full
Remaining 1kbyte blocks = 5.
-----------------------------------
EP4CE10E22C8
NUM_LAYERS = 13
ADDR_SIZE = 16
NUM_WORDS = 40960

Logic cells = 96% full
Remaining 1kbyte blocks = 5.
-----------------------------------
EP4CE15E22C8
NUM_LAYERS = 15
ADDR_SIZE = 16
NUM_WORDS = 53248

Logic cells = 75% full
Remaining 1kbyte blocks = 3.
-----------------------------------
EP4CE40F23C8N OR EP3C40Q240C8N
NUM_LAYERS = 15
ADDR_SIZE = 17
NUM_WORDS = 122880

Logic cells = 30% full
Remaining 1kbyte blocks = 5.
-----------------------------------

Num_words is the bytes of available GPU display ram, + another 1024 for the palette.
Num_layers is the available display windows/sprites.  By now, you know what that means...

You know, the CE10 isn't looking that bad an upgrade at all.  Get's me another 6 layers, almost doubling the sprite count over the CE6.

I was wrong about the 'EP4CE15E22C8', you actually make it to 53.248kb instead of 48kb.
The cyclone III makes it to 122.88kb + space and IO pins for a 128mb or 1gb DDR2 Dram + another 3 MAGGIE layers for the Dram's contents (18 total MAGGIEs), but, your Z80 has so little address space that the 1gb may be too much.

Would be easy enough to page the 1gb into the 512KB 'window' available to the Z80, if I could find a use for all that RAM...

Since you are using the slowest -C8 versions, and, you need a C7, or even a -C6 for the higher densities, I recommend replacing the 1.2v regulator for an adjustable one and adjust it for 1.35v.  This will make a C8 perform somewhere inbetween a C7 and C6 which would be perfect.  Though, my GPU design, there are only a few critical address paths in the FPGA, so it still wont get warm or draw too much current over driving the VCCint to 1.35v.

Righto, so scrub the 1.2v regulator and replace with an adjustable set to 1.35v.  Also, add in a 3.3v 'analogue' sourced from the 5v for the ADV7125.  Am I right in thinking the 'analogue' 3.3v source is just a well-filtered, but otherwise identical, source to the existing 3.3v in the Microcom, but dedicated to the ADV7125 and sharing a ground with it?  The ground will still have to meet up with the primary ground on the system at some point?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 18, 2020, 06:20:51 pm
Put in the extra effort and use at least the 'EP4CE15E22C8' fpga.  You get all 15 maggie layers, and enough free logic gates to add sprite collision detection or/maybe and semi-translucency between all layers.

Hmm.. okay, have ordered one - will perfect the board design for the CE10 when I get a chance and then re-do it from the CE15.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 18, 2020, 06:28:20 pm
Put in the extra effort and use at least the 'EP4CE15E22C8' fpga.  You get all 15 maggie layers, and enough free logic gates to add sprite collision detection or/maybe and semi-translucency between all layers.

Hmm.. okay, have ordered one - will perfect the board design for the CE10 when I get a chance and then re-do it from the CE15.
Did you read Intel's data sheet and look at the pin planner for the CE15?  Make sure you have enough IOs.
Using the dedicated clock inputs the way I mentioned will give you 6 new free IOs, but, I think that with the CE15, you loose 6 IO since they change into power supply pins.

Also, re layout the DAC so it's analog out face the VGA connector directly, with proper GND return traces for the VGA connector's analog RGB GND return signals.  Also wire the 75ohm resistors properly within that return path.  Read my PCB design notes a few pages up.  The DAC draws so little current that you can use a simple RC filter for it's 3.3v regulator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 18, 2020, 10:35:42 pm
Did you read Intel's data sheet and look at the pin planner for the CE15?  Make sure you have enough IOs.
Using the dedicated clock inputs the way I mentioned will give you 6 new free IOs, but, I think that with the CE15, you loose 6 IO since they change into power supply pins.

Looks like you lose 10 IOs - I can't absorb that loss on the board, even using the clock inputs as you've suggested, without losing the SD card interface. I'll stick with the CE10 for the moment and see if I can get that working and make use of the SD interface with that.  You queried the interface method to the SD socket previously - is there a better way I can connect it up to utilise the remaining handful of IOs I have on the CE10?

Also, re layout the DAC so it's analog out face the VGA connector directly, with proper GND return traces for the VGA connector's analog RGB GND return signals.  Also wire the 75ohm resistors properly within that return path.  Read my PCB design notes a few pages up.  The DAC draws so little current that you can use a simple RC filter for it's 3.3v regulator.

Okay, will give that a try.  I have a couple of days off after tomorrow, hopefully can get the PCB re-organised then.  I guess if I'm moving the DAC to sit above the VGA socket, the resistors will be closer anyway, but I'm not 100% on what 'properly' entails. ???  Is it just maintaining a solid ground plane all around the resistors and VGA socket or do I need to consider anything else as well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 18, 2020, 10:39:52 pm
Did you read Intel's data sheet and look at the pin planner for the CE15?  Make sure you have enough IOs.
Using the dedicated clock inputs the way I mentioned will give you 6 new free IOs, but, I think that with the CE15, you loose 6 IO since they change into power supply pins.

Looks like you lose 10 IOs - I can't absorb that loss on the board, even using the clock inputs as you've suggested, without losing the SD card interface. I'll stick with the CE10 for the moment and see if I can get that working and make use of the SD interface with that.  You queried the interface method to the SD socket previously - is there a better way I can connect it up to utilise the remaining handful of IOs I have on the CE10?

Run the DAC at 18 bit.   You get 6 additional IOs + the other 6 on the dedicated clock inputs.
Your maximum palette has only 6 bits on the green anyways with 5 bit on the blue & red.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 19, 2020, 02:47:19 pm
Here is a home made Lattice LFE5U-45 board, but, made with the 381 pin BGA.  The advantage using the 384 BGA is you can use the Lattice LFE5U-45 1.9megabit, or the LFE5U-85 3.7megabit interchangeably.  It's done in Kicad and the boards are home assembled.

https://www.youtube.com/watch?v=-rBTqxgmfaM (https://www.youtube.com/watch?v=-rBTqxgmfaM)

Kicad project files: https://github.com/gregdavill/ButterStick (https://github.com/gregdavill/ButterStick)

Example daughter board:

https://www.youtube.com/watch?v=WNOm_esUVsw (https://www.youtube.com/watch?v=WNOm_esUVsw)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on January 19, 2020, 05:21:45 pm
Here is a home made Lattice LFE5U-45 board, but, made with the 381 pin BGA.

Nice project!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 19, 2020, 05:27:38 pm
Here is a home made Lattice LFE5U-45 board, but, made with the 381 pin BGA.

Nice project!
Just so we are clear, it is not my project.  But the presenter illustrates how easy it is to mount and bake a 0.8mm BGA using a stencil and solder paste.  And how if you watch him, the initial error in alignment, and centering of the BGA is not a problem.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 20, 2020, 12:18:42 pm
Okay, here's the latest on the power supplies for the FPGA.  3.3VA is the supply for the DAC - you say it needs some sort of filter on the output - mentioned either RC or RLC.  I don't know enough about this stuff to decide which to use and what values I'd need.  Any suggestions welcome.  :-+

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2020, 01:45:12 pm
RC filter the 5v input to the DAC's 3.3v regulator.
10 ohm, 0805, or 1206 for safety and 10uf should do.
Remember positioning and layout of the analog end...

Note that there are chokes and filters better suited for this, but your dac only draws 70ma max and a large enough resistor and cap are as cheap and dumb as it gets.

You can always use the same LC filters which you are using for the FPGA PLL analog supply.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2020, 02:06:21 pm
Okay, here's the latest on the power supplies for the FPGA.  3.3VA is the supply for the DAC - you say it needs some sort of filter on the output - mentioned either RC or RLC.  I don't know enough about this stuff to decide which to use and what values I'd need.  Any suggestions welcome.  :-+
The RC filter feeds the power into the regulator so that the regulator wont transmit high frequency ripple through it and the output will always be 3.3v, even with a voltage drop across the resistor.
You are using an analog regulator, so with no high frequency ripple entering the 3.3v regulator, the output should be clean as the regulator should be grounded next to the DAC itself.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2020, 05:03:13 pm
RC filter the 5v input to the DAC's 3.3v regulator.
10 ohm, 0805, or 1206 for safety and 10uf should do.
To do things right, you can always replace the resistor with the correct 0805/1206 ferrite bead or inductor.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 20, 2020, 05:11:37 pm
To do things right, you can always replace the resistor with the correct 0805/1206 ferrite bead or inductor.

Okay, so a 10 ohm ferrite bead can replace the resistor, or what value would I need for an inductor equivalent?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 20, 2020, 05:24:20 pm
[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2020, 06:16:54 pm
To do things right, you can always replace the resistor with the correct 0805/1206 ferrite bead or inductor.

Okay, so a 10 ohm ferrite bead can replace the resistor, or what value would I need for an inductor equivalent?
Until you can find the spectrum of the noise on your 5v supply, you cannot exactly tell.  The 10 ohm is a blanket low pass filter.  Though, voltage noise feeding the regulator input below a certain frequency begins to be rejected by the regulator electronics itself and you can tune or choose a ferrite to choke out all frequencies above that range.

What you have is ok.  When you build the PCB, all you need is to do is make an all white screen and make sure the regulator input is at least 4.2v approximately.  If not, just shrink the 10 ohm to 5 ohm.

The advantage of a ferrite is that it may have a DC resistance below 5 ohm, or even below 1 ohm, but as the frequency noise in your 5v supply increases, the series resistance increases dramatically according to the ferrite's datasheet chart blocking that signal from penetrating through.

Look up ferrite datasheets for these charts and look up your regulator's supply rejection ratio VS frequency to see where you want your ferrite to actually be at a really high resistance.

Change your 10uf to 100nf since it is non-polarized and add a 10uf in parallel.  You need both as the 10uf filters a lower frequency band white the 100nf/0.1uf cleans up the higher frequencies.

Also set the core VCCint to 1.3v.  1.35 is overkill and you want a touch of safety margin as each regulator and resistor precision may have a bit of error.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 20, 2020, 07:59:58 pm
Okay, here's the power supplies for the FPGA:

[attachimg=1]

On a slight tangent, taking 6 IOs (2 LSBs from each colour channel) will just about make up for the loss of 10 IOs on the CE15.  With the addition of the BLANK signal and the DAC CLK output, I don't have any free IOs on the CE10.  So if I move the key command signals (can't do all of them - non-critical signals like IORQ and RESET will have to go to normal IOs) to the FPGA's dedicated clock inputs, that will free up 5 IOs, plus the 6 from the colour output will give me 11 - so it'll be close, but I should be able to cater for the CE15.

Have attached latest schematic for info - still have yet to confirm that all the IO connections are valid and will work as intended.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2020, 10:29:24 pm
I am just curious about the 2 pll analog GNDs going through those 2 ferrite beads.  I have never done that in my designs and I have not seen that elsewhere.  If your bottom layer is mostly a GND plane under the FPGA, you shouldn't need it.  However, can you show me a link to a third party design which uses it as personally I though something like this might actually create problems under some circumstances.  The ferrite on the +2.5v for the PLL is correct.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2020, 11:55:50 pm
Have attached latest schematic for info - still have yet to confirm that all the IO connections are valid and will work as intended.

You only have 3 GND pins on your system expansion headers.  It is optimum to have 1 GND pin for every IO data pin for best results.  However, with your design's low frequency and low power, 4:1 or 5:1 should be fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 21, 2020, 08:33:23 am
I am just curious about the 2 pll analog GNDs going through those 2 ferrite beads.  I have never done that in my designs and I have not seen that elsewhere.  If your bottom layer is mostly a GND plane under the FPGA, you shouldn't need it.  However, can you show me a link to a third party design which uses it as personally I though something like this might actually create problems under some circumstances.  The ferrite on the +2.5v for the PLL is correct.

I've just copied the design from the EasyFPGA dev board schematics for the board I'm currently using - I figured it would be a good place to start from, considering the dev board seems to work fine.  :-//

Dev board schematic attached below.  Of course, I don't know if this is a 1:1 of the actual, physical dev board I'm using - I found it on the net by searching for the dev board name, but the part numbers match up.  It looks as though the ferrite beads on the physical board are actually just links - they look like SMD resistors (black) with a '0' on them, so 0R links.  Looks like no ferrite beads were used.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 21, 2020, 12:26:13 pm
Latest 2-layer PCB design with changes made to position of the DAC, number of colour bits to the DAC, etc. (I've dropped the two LSBs from each channel).

Has taken me an hour or two to get component positioning/orientation in a way that allows a successful auto-route.  Still had to wire two of the power feeds to the FPGA manually.

I haven't bothered working on ground planes yet - I thought I'd seek some feedback on the positioning of the DAC and those pull-down resistors for R, G and B before I start stressing about ground plane placement.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 21, 2020, 06:05:41 pm
For DAC_CLK (the pixel clock output from the FPGA) I've got two PLL output pins I can use, according to the pin manager in Quartus for the EP4CE10; one for PLL1 and one for PLL2.  The PLL2 output is preferable as it's closest to the DAC (it's currently used by R4 in the red channel to the DAC) - but, and this may be a stupid question - how do I know if PLL2 is used and, if not, how would I force Quartus to use it or will the router manage that by itself when it sees I've connected the clk output from the PLL to a PLL2 output? ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 21, 2020, 07:28:17 pm
For DAC_CLK (the pixel clock output from the FPGA) I've got two PLL output pins I can use, according to the pin manager in Quartus for the EP4CE10; one for PLL1 and one for PLL2.  The PLL2 output is preferable as it's closest to the DAC (it's currently used by R4 in the red channel to the DAC) - but, and this may be a stupid question - how do I know if PLL2 is used and, if not, how would I force Quartus to use it or will the router manage that by itself when it sees I've connected the clk output from the PLL to a PLL2 output? ???
If you System clock in is on PLL#1's dedicated clock input, ie 50MHz, use PLL#2.  This way, currently, if you have a nice multiple output clock, ie 25Mhz, 125MHz &250 Mhz current clocks, Quartus will automatically connect PLL#1 to #2 to generate the PLL output.  If you wan to use a SMPTE compatible 480p, IE 27Mhz pixel, 135Mhz core, 270Mhz core ram, You can make PLL #1 in Quartus convert 50MHz to 270MHz, then use PLL#1 to drive PLL#2 to generate the nice required multiples 27,135,270MHz.

So yes, connect the DAC's CLK input to PLL #2's output as it offers your best flexible path.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 21, 2020, 09:32:12 pm
Latest 2-layer PCB design with changes made to position of the DAC, number of colour bits to the DAC, etc. (I've dropped the two LSBs from each channel).

Has taken me an hour or two to get component positioning/orientation in a way that allows a successful auto-route.  Still had to wire two of the power feeds to the FPGA manually.

I haven't bothered working on ground planes yet - I thought I'd seek some feedback on the positioning of the DAC and those pull-down resistors for R, G and B before I start stressing about ground plane placement.
Ohh boy, are you auto routing and auto placing this?

Move the VGA connector to the right a little.

Make the DAC at 90 degrees so that the analog out faces the VGA plug.
Make the DAC's 75 ohm resistors and dac wiring straight to the VGA plug.  Make the proper VGA plug's Analog R&G&B  GND return pin paths feed on the top through/wired to the other side of the 75 ohms and to the DAC's R&G&B negative signals.  Place as many of the decoupling caps on top to the sides of these signals.  Also, you should be using 0603 parts, or if your hands are steady enough,  go for 0402 for these DAC components so everything is in a straight line.

Under the dac, bottom layer, a fill GND should be used throughout.    Use 2 adjacent VIAs for every GND connection to the top layer.

For a 2 layer board, this should make a really good analog signal for your frequency range.

Remember, match red's return GND signal path with red's 75 ohm resistor, then to the dac's inverted red GNS input.  You do not want a signal reflection crosstalk across your video outputs since you didn't match GNDs.  The GND plane feeding the VGA connector's GND pins will be good enough for your bandwidth.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 21, 2020, 10:42:11 pm
Ohh boy, are you auto routing and auto placing this?

Is there any other way when things start getting complicated? ???

I've manually placed all the components, but I am auto-routing otherwise it'd take me days to do the board manually?  Is there a better way, then?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 21, 2020, 11:37:33 pm
Ohh boy, are you auto routing and auto placing this?

Is there any other way when things start getting complicated? ???

I've manually placed all the components, but I am auto-routing otherwise it'd take me days to do the board manually?  Is there a better way, then?  :-//
LOL, see my attached 100% manual routed 8 layer board...

I expect you to at least route the crucial analog traces and Power and GND thick traces and force multiple vias there.
You may route the rest automatically, however, your "puny" 2 layer PCB is a 30 minute manual job.

Look at the total stats on my all manual routed attached .pdf.
[attachimg=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 22, 2020, 09:33:32 am
LOL, see my attached 100% manual routed 8 layer board...

I expect you to at least route the crucial analog traces and Power and GND thick traces and force multiple vias there.
You may route the rest automatically, however, your "puny" 2 layer PCB is a 30 minute manual job.

Look at the total stats on my all manual routed attached .pdf.
(Attachment Link)

[attachimg=1]

You may route the rest automatically, however, your "puny" 2 layer PCB is a 30 minute manual job.

It may be a 30-minute job for a professional like yourself, but remember my experience with electronics is pretty minimal at best.  I've only got this far on the desire to learn and stubbornness bordering on stupidity.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 22, 2020, 11:26:38 am
Move the VGA connector to the right a little.

Make the DAC at 90 degrees so that the analog out faces the VGA plug.
Make the DAC's 75 ohm resistors and dac wiring straight to the VGA plug.  Make the proper VGA plug's Analog R&G&B  GND return pin paths feed on the top through/wired to the other side of the 75 ohms and to the DAC's R&G&B negative signals.  Place as many of the decoupling caps on top to the sides of these signals.  Also, you should be using 0603 parts, or if your hands are steady enough,  go for 0402 for these DAC components so everything is in a straight line.

Under the dac, bottom layer, a fill GND should be used throughout.    Use 2 adjacent VIAs for every GND connection to the top layer.

For a 2 layer board, this should make a really good analog signal for your frequency range.

Remember, match red's return GND signal path with red's 75 ohm resistor, then to the dac's inverted red GNS input.  You do not want a signal reflection crosstalk across your video outputs since you didn't match GNDs.  The GND plane feeding the VGA connector's GND pins will be good enough for your bandwidth.

Made a start on the above - here's progress so far. Perhaps getting a little concerned about GND continuity, but not much I can do with that unless I start breaking signals or power lines out onto the bottom layer.

Close-up of the DAC area with a little more detail:

[attach=1]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 22, 2020, 01:36:15 pm
Excellent...

Push up C1, it is too close to the VGA plug.

Move up R2 and C2 closer to R1, lower U2 below C2.

You should now have a clear path for the Vaa on the top layer from regulator to all Vaa points since each GND should have their own vias by each component pad to the bottom layer.

Rotate the 3.3v regulator 90 deg. with it's caps allowing you to move the dac and vga plug a little further to the right so the have a little clearance from the fpga.

***********  Remember, the GND via for C5 and C3 should have their own via positioned closer to the DAC.  Those GND points should not have any other wires going out of them to the digital FPGA GND pins, or any other GND signals for the dac should not branch out to the fpga.


Everything else should work great.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 22, 2020, 04:39:13 pm
Okay, here's the latest.  The blue area is the ground plane on the bottom layer.  Don't worry about the ratlines indicating I should connect up to FB3 and C47 underneath - I'm ignoring those and will probably amend the schematic to use a unique ground connection for the DAC components so I won't have to worry about the auto-router (if I ever use it again! :o) connecting up the DAC ground to digital ground.

My only question is - where do I connect up the DAC ground plane? The nearest ground pin on the system header is at the top left of the 40-pin header next to the DAC.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 22, 2020, 05:05:42 pm
Okay, here's the latest.  The blue area is the ground plane on the bottom layer.  Don't worry about the ratlines indicating I should connect up to FB3 and C47 underneath - I'm ignoring those and will probably amend the schematic to use a unique ground connection for the DAC components so I won't have to worry about the auto-router (if I ever use it again! :o) connecting up the DAC ground to digital ground.

My only question is - where do I connect up the DAC ground plane? The nearest ground pin on the system header is at the top left of the 40-pin header next to the DAC.

(Attachment Link)

Pretty good.
Are your via's drill hole size large enough?
The 2 GND vias on the right of the dac are too close to the pins.  move those vias under the dac where you have space.  Same for the 2 GND vias at the top of the DAC.

You do not require a unique GND for your dac.  You do not require a ferrite bead for the FPGA PLL GND as well if you fill the bottom layer with a good GND.  Your bottom layer should be 95% GND fill for everything with a few opening voids for occasional power and signal traces.  It is just important that by the dac and it's regulator, that this GND section is 1 solid chunk without any voids for other traces.  What you have is good.

Note that a larger via server the equivalent to 2-3 of the finest possible vias.

Fill the Vaa between the right side of the DAC and U13 regulator and VGA plug so that the VaA trace is thick between C1 and the rest of the DAC.  make sure all your polygon clearances are something like 12mil, not 8 mil.  Too much copper fill close to pads make it hard to solder and are a continuous possible short point around drill holes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 22, 2020, 05:55:55 pm
Arrrg, 1 thing, rotate your entire 3.3v regulator section by 180 degrees...
Keep it's reference GNDs points as close to the DAC as possible and only allow in the dirty 5v at the outer edge of the design...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 22, 2020, 06:13:40 pm
Are your via's drill hole size large enough?

They're all 12mil/24mil - standard size for EasyEDA (which I'm using to design the board) and JLCPCB's requirements.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 22, 2020, 08:48:58 pm
Okay, latest update.  Just trying to manually route all the other lines now... and I'm starting to think I'll swap the 373s from the lower address lines for 245s, they'll make routing much easier even though I'll never need the ability to change the direction of the buffer.

[attach=1]

Oh, I also noticed that I'd missed the HS and VS signals from the FPGA out!  I was wondering why I wasn't seeing ratlines from HS_IN and VS_IN on the line driver chip...  so that's eaten up another 2 IOs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 22, 2020, 09:13:46 pm
Well, if you have a problem with the VGA output quality, it will now be a software or VGA cable issue...

As for your 74HC logic, make the VCC & GND traces to the caps thick, like you have doe already for a few of them.
Remember that you do not need to wire GND-GND on each 74HC IC, just add 2 vias along the thick GND trace as it will meet with the GND flood fill on the bottom of the PCB.

As for the VCC, look for the most convenient path.  This may also be partially along the bottom edge of the PCB, coming to the top layer just by the first ICs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 23, 2020, 06:25:13 pm
 :phew:

Here's the PCB design - all manually routed.  I must admit, there's a certain sense of achievement in doing it yourself - plus much finer control over trace widths for power supplies etc.  :-+

I get the feeling I've learned a lot from this exercise.  ;D

 :=\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 23, 2020, 06:56:08 pm
:phew:

Here's the PCB design - all manually routed.  I must admit, there's a certain sense of achievement in doing it yourself - plus much finer control over trace widths for power supplies etc.  :-+

I get the feeling I've learned a lot from this exercise.  ;D

 :=\
Nice.    :clap:   :-+

Amazing job for a first timer!!!

Now, I understand the difficulty in achieving this 2 layer design with all the limitations.  Since I cant see net names, I only see 2 little things to consider.

FB4 is receiving power through a trace going through an IC pads and vias.  I'm not sure about the bottom cap next to how C10 is wired.  Try removing the FB3 and FB4 from your schematic.  You will simplify a few GND connections and remove a few caps in your design that way maybe allowing a better path for FB4's Vpll.

Hang on a sec, something seems wrong with the Vpll and VCCint, are some of those shorted, or, on the wrong pins?
Can you show me a printout/screenshot with net names on the FPGA pins?
As well as net names on the other components?



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 23, 2020, 08:23:50 pm
Hmm.. have PM'd you to see about giving you direct access to the project.  In the meantime, here's a breakdown of the design (one layer per page). Don't know if that will be useful?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 23, 2020, 09:20:03 pm
The GND path under the FPGA and by the programming connectors is a little chopped up and can be easily fixed.  But, I want to look at the net names first as the Vpll and Vcore/int looks funny to me...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 24, 2020, 06:07:50 pm
Okay, here's the latest on the schematic and PCB.  DRC completed with one error - the 5V line going up to R19 was only 10mil wide when the design rules called for 18mil, so I've widened that and there's no errors now.  I also moved the TCK trace up a little to hug around the NCONFIG via a little closer and make the underside look a little neater near the top.  :)

All I have to do now is wait for parts to arrive and order the PCB, once I'm absolutely happy I've got the right SD card socket (for some reason I'm finding it hard to get a matching part/footprint combination) and crystal oscillator package for the 50 MHz clock source.

 :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 24, 2020, 06:48:42 pm
DRC completed with one error - the 5V line going up to R19 was only 10mil wide when the design rules called for 18mil,
:scared: 18MIL!!!
WTF, those pullups are 10kohm.  a 4 mil trace would have been overkill.

Anyways, take a look at the attached image, the trace circled in green it too wide for the pad.  Make it 12 mil.
[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 24, 2020, 09:23:12 pm
If you decide to go with the CycloneIII on your next PCB, add this ram chip:

https://www.digikey.com/product-detail/en/cypress-semiconductor-corp/S70KS1281DPBHV020/2015-S70KS1281DPBHV020-ND/9955180 (https://www.digikey.com/product-detail/en/cypress-semiconductor-corp/S70KS1281DPBHV020/2015-S70KS1281DPBHV020-ND/9955180)

You only need 12 IOs & 1 PLL balanced Pos/Neg pair output set to 1.8v running at the core clock memory speed.  You'll get the full 16 megabytes MAGGIE can address on this 1 chip, though, you will need to mask out first 128kb for the onboard FPGA ram and you will may need to add a wait state when the Z80 reads this ram unless you are smart about the programming.  No DDR ram controller, just shift out an address and data, and wait for a response.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 24, 2020, 11:34:57 pm
DRC completed with one error - the 5V line going up to R19 was only 10mil wide when the design rules called for 18mil,
:scared: 18MIL!!!
WTF, those pullups are 10kohm.  a 4 mil trace would have been overkill.

Anyways, take a look at the attached image, the trace circled in green it too wide for the pad.  Make it 12 mil.
(Attachment Link)

 :-// It didn't like the 10mil trace - I think because it was the only one on the board that was less than the 18mil minimum for the 5V net.

Have sorted that wayward trace on the FPGA too - thanks for spotting that.  :-+

If you decide to go with the CycloneIII on your next PCB, add this ram chip:

https://www.digikey.com/product-detail/en/cypress-semiconductor-corp/S70KS1281DPBHV020/2015-S70KS1281DPBHV020-ND/9955180 (https://www.digikey.com/product-detail/en/cypress-semiconductor-corp/S70KS1281DPBHV020/2015-S70KS1281DPBHV020-ND/9955180)

You only need 12 IOs & 1 PLL balanced Pos/Neg pair output set to 1.8v running at the core clock memory speed.  You'll get the full 16 megabytes MAGGIE can address on this 1 chip, though, you will need to mask out first 128kb for the onboard FPGA ram and you will may need to add a wait state when the Z80 reads this ram unless you are smart about the programming.  No DDR ram controller, just shift out an address and data, and wait for a response.

I like the look of that.  Could be a good (inexpensive) introduction to BGA soldering for me...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2020, 12:10:46 am
If you decide to go with the CycloneIII on your next PCB, add this ram chip:

https://www.digikey.com/product-detail/en/cypress-semiconductor-corp/S70KS1281DPBHV020/2015-S70KS1281DPBHV020-ND/9955180 (https://www.digikey.com/product-detail/en/cypress-semiconductor-corp/S70KS1281DPBHV020/2015-S70KS1281DPBHV020-ND/9955180)

You only need 12 IOs & 1 PLL balanced Pos/Neg pair output set to 1.8v running at the core clock memory speed.  You'll get the full 16 megabytes MAGGIE can address on this 1 chip, though, you will need to mask out first 128kb for the onboard FPGA ram and you will may need to add a wait state when the Z80 reads this ram unless you are smart about the programming.  No DDR ram controller, just shift out an address and data, and wait for a response.

I like the look of that.  Could be a good (inexpensive) introduction to BGA soldering for me...
That 1mm pitch BGA and the 240 pin QFP is your only solution for a 2 layer PCB with ram and no DRAM controller to engineer.  Every other option requires 4 layers and the lattice requires 10 or 8 mil vias because of it's density.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2020, 10:43:46 am
That 1mm pitch BGA and the 240 pin QFP is your only solution for a 2 layer PCB with ram and no DRAM controller to engineer.  Every other option requires 4 layers and the lattice requires 10 or 8 mil vias because of it's density.

I'd be happy to give that a try.  Once I've got a working v1, seems like the Cyclone 3 would be a worthwhile step up - it's significantly bigger than the CE4 chips though and will leave me with some routing headaches, I suspect, to cram it all into the form factor I'm working with.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2020, 03:34:59 pm
That 1mm pitch BGA and the 240 pin QFP is your only solution for a 2 layer PCB with ram and no DRAM controller to engineer.  Every other option requires 4 layers and the lattice requires 10 or 8 mil vias because of it's density.

I'd be happy to give that a try.  Once I've got a working v1, seems like the Cyclone 3 would be a worthwhile step up - it's significantly bigger than the CE4 chips though and will leave me with some routing headaches, I suspect, to cram it all into the form factor I'm working with.
No it wont.  All those extra IO means mostly single file traces next to each port.  With a lot of blank IO pins.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2020, 04:25:08 pm
The EP4CE10E22C8N arrived today - I notice it has a ground pad underneath the body of the chip, which the part doesn't have in EasyEDA.  I've checked the Intel literature and yes, the EP4CE10E22 DOES have a ground pad and it's supposed to be connected to GND, so I'll need to update the PCB design with this.

Here's what's got me thinking, though - how do I solder that central pad under the chip to GND?  I suppose I could place a few large vias there and use a hot air gun to heat the PCB up from the underside? Any suggestions?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2020, 06:28:45 pm
You can fake place a GND pad for the open copper area.  (IE, create a new custom home made SMD component with 1 pad connected to GND.)  A number of vias to GND within the pad around the perimeter will also be needed.  But, I recommend searching for the correct footprint type as it a standard and such a component will have the proper paste stencil.

As for soldering, hot air will do, baking is better but I know you are hot properly setup for that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2020, 07:21:37 pm
Okay, well it looks like the pad in the footprint I'm using is a little larger than the actual ground pad on the IC, and I'd just finished the attached update to the PCB before I read your post about putting vias around the edge - hopefully this will be alright?  I've moved the 2.5 line on the bottom side down, so it goes around the edge of the centre of U1 and there's now a nice ground plane under U1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2020, 07:54:50 pm
Okay, well it looks like the pad in the footprint I'm using is a little larger than the actual ground pad on the IC, and I'd just finished the attached update to the PCB before I read your post about putting vias around the edge - hopefully this will be alright?  I've moved the 2.5 line on the bottom side down, so it goes around the edge of the centre of U1 and there's now a nice ground plane under U1.
Everything looks good.
You still haven't considered the additional GND connections on the edge connectors which I mentioned earlier.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2020, 10:34:24 pm
Okay, well it looks like the pad in the footprint I'm using is a little larger than the actual ground pad on the IC, and I'd just finished the attached update to the PCB before I read your post about putting vias around the edge - hopefully this will be alright?  I've moved the 2.5 line on the bottom side down, so it goes around the edge of the centre of U1 and there's now a nice ground plane under U1.
Is it just me, or, do the pads on your new footprint appear to be small?

Make a high quality 1:1 paper print of both versions of the PCB and make sure you can solder the FPGA in place by placing a FPGA on top and looking that there is exposed copper both under the pins + a little extra outside of the pins.  Without that little extra, you wont be able to do a clean proper solder with an iron.

Make sure your print copy doe not contain the extra mask around the IC pads, just the copper underneath.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2020, 11:33:01 pm
Okay, well it looks like the pad in the footprint I'm using is a little larger than the actual ground pad on the IC, and I'd just finished the attached update to the PCB before I read your post about putting vias around the edge - hopefully this will be alright?  I've moved the 2.5 line on the bottom side down, so it goes around the edge of the centre of U1 and there's now a nice ground plane under U1.
Is it just me, or, do the pads on your new footprint appear to be small?

No, it's not just you.  I was concerned about that myself - it seems the footprint I selected for the chip wasn't precisely correct.  I'd chosen a TQFP-144 package footprint, as it was the only one I could find at the time with a ground pad under the chip.  It turns out that the pads are smaller, too - I've since done some more hunting (I'm no expert with EasyEDA and creating new symbols) and found an EQFP-144 package which is the real deal and matches the chip much more precisely in terms of the ground pad underneath.  It also comes with a grid of vias already and pads that match the original.

 :phew:

Next step is to see about fitting the CE15 into this design for the backwards compatibility...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2020, 11:05:35 am
Question:  Does it matter much if signal lines don't cross each other at right-angles?

Previously, whilst making my auto-routed PCBs I'd made for my CPU, memory, CompactFlash and power/serial cards, I've been a bit OCD about making sure signals on different layers cross each other at 90-degree angles to minimise cross-talk.  I don't even know where I got that idea from - or if it's even a thing I need to worry about. :-//

Just thought I'd ask and put that demon to bed once and for all.  >:D

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2020, 12:13:38 pm
You still haven't considered the additional GND connections on the edge connectors which I mentioned earlier.

There's not a lot I can do about those unless/until I redesign the entire computer and its system bus.  Those headers were designed over two years ago, before I knew anything about multiple grounds etc.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2020, 02:53:26 pm
Question:  Does it matter much if signal lines don't cross each other at right-angles?

Previously, whilst making my auto-routed PCBs I'd made for my CPU, memory, CompactFlash and power/serial cards, I've been a bit OCD about making sure signals on different layers cross each other at 90-degree angles to minimise cross-talk.  I don't even know where I got that idea from - or if it's even a thing I need to worry about. :-//

Just thought I'd ask and put that demon to bed once and for all.  >:D

(Attachment Link)
Too low frequency/power design to worry bout.  Long parallel trace above and below is a larger problem.

90 degree turns on a thin trace is also a problem as they are a weak etching point.  (You have 1 below a resistor by the PS2 keyboard connector on the top layer.)

Also, you have so many unused IOs on those connectors, you cannot add just 2-3 GNDs on each side?


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2020, 04:30:10 pm
90 degree turns on a thin trace is also a problem as they are a weak etching point.  (You have 1 below a resistor by the PS2 keyboard connector on the top layer.)

Ah, missed that one - but yes, was aware of the no-right-angles rule (although I wasn't sure why - now I know!)  ;D

Also, you have so many unused IOs on those connectors, you cannot add just 2-3 GNDs on each side?

They're not used for this card (only the pins that are used have net labels in this design), but they are pretty much all used elsewhere on other boards.  There's a couple I could re-purpose as GNDs, but would have to bodge them into the same GND pins as I'm using currently when they get to the 'utility' card that handles the power supply.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2020, 08:21:45 pm
Can't seem to find a solution to this issue I'm having.

I'm trying to return a value from a parameter array, defined as below:

Code: [Select]
parameter int BANK_ID[16] = '{9,3,71,80,85,0,255,255,255,255,255,255,255,255,255,255}; // The BANK_ID data to return
... based upon the address being read, like below:

Code: [Select]
Z80_rData[7:0] <= BANK_ID[addr_hold[3:0]]; // Return the appropriate value
addr_hold is an 8-bit register, addr_hold[7:0], consisting of the lowest 8-bits of a memory address.

I'm getting this error, though:

Error (10687): SystemVerilog error at z80_bridge.sv(115): indexing addr_hold returns an aggregate value

I can't seem to bottom out the meaning of this error or how to fix it.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 27, 2020, 12:33:38 am

Code: [Select]
parameter int BANK_ID[16] = '{9,3,71,80,85,0,255,255,255,255,255,255,255,255,255,255}; // The BANK_ID data to return
Code: [Select]
Z80_rData[7:0] <= BANK_ID[addr_hold[3:0]][7:0]; // Return the appropriate value
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 27, 2020, 08:21:50 am

Code: [Select]
parameter int BANK_ID[16] = '{9,3,71,80,85,0,255,255,255,255,255,255,255,255,255,255}; // The BANK_ID data to return

Code: [Select]
Z80_rData[7:0] <= BANK_ID[addr_hold[3:0]][7:0]; // Return the appropriate value

The one thing I didn't try - specifying the width of BANK_ID.  ::)  I was thinking the problem was with addr_hold itself..

... but it returns the same error again.  :(

Full code:

Code: [Select]
module Z80_bridge (

   // input
   input wire  reset,            // GPU reset signal
   input wire  GPU_CLK,          // GPU clock (125 MHz)
   input wire  Z80_CLK,          // Microcom clock signal (8 MHz)
   input wire  Z80_M1n,          // Z80 M1 - active LOW
   input wire  Z80_MREQn,        // Z80 MREQ - active LOW
   input wire  Z80_WRn,          // Z80 WR - active LOW
   input wire  Z80_RDn,          // Z80 RD - active LOW
   input wire  [21:0] Z80_addr,  // Microcom 22-bit address bus
   input wire  [7:0]  Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
   input wire  [7:0]  gpu_rData,
   input wire  gpu_rd_rdy,       // one-shot signal from mux that data is ready
input wire  sel_pclk,         // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
   input wire  sel_nclk,         // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
input wire PS2_RDY, // goes HIGH when data is ready from PS2 keyboard on PS2_DAT
input wire [7:0] PS2_DAT, // data from keyboard
input wire Z80_IORQ, // Z80 IORQ - active LOW
input wire Z80_IEI, // if HIGH, Z80_bridge can request interrupt immediately
   
   // output
   output reg  Z80_245data_dir,  // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
   output reg  [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
   output reg  Z80_rData_ena,    // flag HIGH to write data back to Z80
   output reg  Z80_245_oe,       // OE for 245 level translator *** ACTIVE LOW ***
   output reg  gpu_wr_ena,       // flag HIGH for 1 clock when writing to GPU RAM
   output reg  gpu_rd_req,       // flag HIGH for 1 clock when reading from GPU RAM
   output reg  [19:0] gpu_addr,  // connect to Z80_addr in vid_osd_generator to address GPU RAM
   output reg  [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
output reg Z80_INT_REQ, // flag HIGH to signal to host for an interrupt request
output reg Z80_IEO // flagged LOW when GPU is requesting an interrupt
   
);

// TODO:
//
// 1) Respond with appropriate data to any requests from Microcom ROM identification routines
//
// 2) Implement PS2 keyboard interface and interrupt handling (INTACK occurs when M1 goes LOW, then IORQ goes LOW, ends when both go HIGH)
//

parameter MEMORY_RANGE  = 3'b010; // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter MEM_SIZE_BITS = 15;    // Specifies maximum address size for the GPU RAM (anything above this returns $FF)
parameter BANK_RESPONSE = 1; // 1 - respond to reads at BANK_ID_ADDR with appropriate data, 0 - ignore reads to that address
parameter BANK_ID_ADDR = 17'b10111111111111111; // Address to respond to BANK_ID queries with data (lowest 4 bits left off)

parameter byte BANK_ID[16] = '{9,3,71,80,85,0,255,255,255,255,255,255,255,255,255,255}; // The BANK_ID data to return

wire Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, mem_window, last_Z80_WR2, last_Z80_WR3, last_Z80_RD2, last_Z80_RD3, bank_id_access;
reg addr_hold[7:0];

assign Z80_clk_pos    = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg    =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig   = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign Z80_mreq       = ~Z80_MREQn && Z80_M1n;  // Define a bus memory access state
assign Z80_write      = ~Z80_WRn;               // write transaction
assign Z80_read       = ~Z80_RDn;               // read transaction

// Only allow RD/WR to valid GPU RAM space
assign Write_GPU_RAM  =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
//assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read  && mem_valid_range; // Define the beginning of a Z80 read request of GPU Ram.

// Allow RD/WR to entire 512KB memory window
//assign Write_GPU_RAM  =  mem_window && Z80_mreq && Z80_write; // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read; // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

   gpu_addr         <=  Z80_addr[18:0];                        // Latch address bus onto GPU address bus
   mem_valid_range  <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS);  // Define GPU addressable memory space
   mem_window       <= (Z80_addr[21:19] == MEMORY_RANGE);      // Define an active memory range (this decides which socket the GPU replaces)
bank_id_access   <= (Z80_addr[21:4]  == BANK_ID_ADDR); // Define access to BANK_ID area

   if (Write_GPU_RAM) begin

      Z80_245data_dir  <= 1'b1;       // Set 245 DIR to FPGA
      Z80_rData_ena    <= 1'b0;       // Set FPGA pins to input (should be by default)
      Z80_245_oe       <= 1'b0;       // Enable 245 output
      gpu_wdata        <= Z80_wData;  // Latch data bus onto GPU data bus

   end

   if (Read_GPU_RAM) begin

      Z80_245data_dir  <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe       <= 1'b0;       // Enable 245 output
      Z80_rData_ena    <= 1'b1;       // Set bidir pins to output
addr_hold   <= Z80_addr[7:0];

   end else begin

      Z80_245data_dir  <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena    <= 1'b0;       // Re-set bidir pins to input

   end

   if (gpu_rd_rdy) begin

      if (mem_valid_range) begin

Z80_rData[7:0] <= gpu_rData[7:0];  // Latch the GPU RAM read into the output register for the Z80

end else begin

if (BANK_RESPONSE && bank_id_access) begin

Z80_rData[7:0] <= BANK_ID[addr_hold[3:0]][7:0]; // Return the appropriate value

end else begin

Z80_rData[7:0] <= 8'b11111111; // return $FF if addressed byte is outside the GPU's upper RAM limit

end

end

   end
   
   Z80_clk_delay  <= Z80_CLK;          // find the rising clock edge

   last_Z80_WR    <= Write_GPU_RAM;
   last_Z80_WR2   <= last_Z80_WR;
   last_Z80_WR3   <= last_Z80_WR2;

   last_Z80_RD    <= Read_GPU_RAM;
   last_Z80_RD2   <= last_Z80_RD;
   last_Z80_RD3   <= last_Z80_RD2;

   gpu_wr_ena     <= Write_GPU_RAM && ~last_Z80_WR2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
   gpu_rd_req     <= Read_GPU_RAM  && ~last_Z80_RD2 ; // Pulse the read request only once at the beginning of a read cycle.
   
end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 27, 2020, 06:59:00 pm
Why arent you using :

Code: [Select]
Z80_rData[7:0] <= BANK_ID[Z80_addr[3:0]]; // Return the appropriate value
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 27, 2020, 07:01:27 pm
Why arent you using :

Code: [Select]
Z80_rData[7:0] <= BANK_ID[Z80_addr[3:0]]; // Return the appropriate value

I seem to recall having problems using Z80_addr previously.  The bit of code that assigns the value to Z80_rData executes a couple of clock cycles later, after Z80_addr has been 'captured'.  I'm operating under the assumption that the address may have changed between the read being initiated and the value being returned to the data bus.  Thinking about it, however, this was back when we were having timing troubles with the whole Z80_bridge, so maybe I'm labouring under a false assumption...  :-//

It still doesn't compile, though - even though it successfully compiles symbol files...  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 27, 2020, 07:09:29 pm
Why arent you using :

Code: [Select]
Z80_rData[7:0] <= BANK_ID[Z80_addr[3:0]]; // Return the appropriate value

I seem to recall having problems using Z80_addr previously.  The bit of code that assigns the value to Z80_rData executes a couple of clock cycles later, after Z80_addr has been 'captured'.  I'm operating under the assumption that the address may have changed between the read being initiated and the value being returned to the data bus.  Thinking about it, however, this was back when we were having timing troubles with the whole Z80_bridge, so maybe I'm labouring under a false assumption...  :-//

It still doesn't compile, though - even though it successfully compiles symbol files...  ???
Yes it does compile.  I checked...  Showing your problem lies somewhere else, like with the line:
---------------------------------
reg addr_hold[7:0];
---------------------------------

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 27, 2020, 07:33:06 pm
Yes it does compile.  I checked...  Showing your problem lies somewhere else, like with the line:
---------------------------------
reg addr_hold[7:0];
---------------------------------

 |O

Project compiles now.  Silly mistake on my part, as usual..  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2020, 10:51:18 am
Okay, I seem to have another head-scratcher.  :o

I'm working on the PS2 keyboard interface.  I figured it would be easier to test using IO polling initially, rather than the whole interrupt setup as there are more unknowns there.  So the Z80 would be polling the GPU regularly to see if there is a character (or keycode) in the PS2 interface.  To do this, the GPU needs to intercept IO from the host - for the Z80, this is when IORQ and RD go LOW together, much like a memory cycle (but with IORQ instead of MREQ).

Here's the timing diagram for an IO cycle straight from the Z80 datasheet:

[attachimg=1]

It's pretty much identical to a memory cycle, except the Z80 automatically inserts 1 WAIT state into the cycle to give whatever is being addressed time to get its ducks in order. How generous.

So, I've set about modifying the Z80_bridge module to intercept IO cycles targeting a user-specified IO address ($F0 in this case), only looking at the lower half of the address bus as (officially, at least) the Z80 only uses the lower half of the address bus for IO addressing.  Yes, I know about IN A,(C)/OUT (C),A placing the full BC register on the address bus, just in case anyone is thinking about that.

Anyhow, should be simple, right?  I should be able to use the same process as for the memory read cycle in Z80_bridge?

Seems not.  I'm sometimes getting the right value back, but more often than not just getting $78 returned, which is effectively a null return on my system.

I've tried varying the delay between the IORQ cycle being detected, 'arming' the 245 in the right direction and putting the data on the bus, but a 2 cycle delay is a logical minimum to allow the 245 to change direction before driving the data bus, as proven with the previous memory cycle work.

I've tried adding a delay at the end of the IORQ cycle, despite the Z80 datasheets stating zero hold time is required after IORQ/RD goes HIGH at the end of the cycle.

With the code in its current state, I'm rarely getting the desired value returned (should get $AA returned for a valid IO read).

So I'm wondering if there's something stupid I've done in the code that is causing this issue?  It's fairly likely, after all.  :-[

I've also tried to break down the various functions within the always block to make it more readable (for me, anyway!)

I appreciate this sort of issue is a tough one to pin down if it's hardware-related, but I suspect it could be an issue with my HDL or the way I'm trying to do it.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2020, 10:52:19 am
It won't let me post the code AND an in-line image at the same time...  |O

Code: [Select]
module Z80_bridge (

   // input
   input wire  reset,            // GPU reset signal
   input wire  GPU_CLK,          // GPU clock (125 MHz)
   input wire  Z80_CLK,          // Microcom clock signal (8 MHz)
   input wire  Z80_M1n,          // Z80 M1 - active LOW
   input wire  Z80_MREQn,        // Z80 MREQ - active LOW
   input wire  Z80_WRn,          // Z80 WR - active LOW
   input wire  Z80_RDn,          // Z80 RD - active LOW
   input wire  [21:0] Z80_addr,  // Microcom 22-bit address bus
   input wire  [7:0]  Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
   input wire  [7:0]  gpu_rData,
   input wire  gpu_rd_rdy,       // one-shot signal from mux that data is ready
   input wire  sel_pclk,         // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
   input wire  sel_nclk,         // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
   input wire  PS2_RDY,          // goes HIGH when data is ready from PS2 keyboard on PS2_DAT
   input wire  [7:0] PS2_DAT,    // data from keyboard
   input wire  Z80_IORQn,        // Z80 IORQ - active LOW
   input wire  Z80_IEI,          // if HIGH, Z80_bridge can request interrupt immediately
   
   // output
   output reg  Z80_245data_dir,  // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
   output reg  [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
   output reg  Z80_rData_ena,    // flag HIGH to write data back to Z80
   output reg  Z80_245_oe,       // OE for 245 level translator *** ACTIVE LOW ***
   output reg  gpu_wr_ena,       // flag HIGH for 1 clock when writing to GPU RAM
   output reg  gpu_rd_req,       // flag HIGH for 1 clock when reading from GPU RAM
   output reg  [19:0] gpu_addr,  // connect to Z80_addr in vid_osd_generator to address GPU RAM
   output reg  [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
   output reg  Z80_INT_REQ,      // flag HIGH to signal to host for an interrupt request
   output reg  Z80_IEO           // flag HIGH when GPU is requesting an interrupt to pull IEO LOW
   
);

// TODO:
//
// 1) Implement PS2 keyboard interface and IO-polled / interrupt handling
//

parameter MEMORY_RANGE  = 3'b010;      // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter MEM_SIZE_BITS = 15;          // Specifies maximum address size for the GPU RAM (anything above this returns $FF)
parameter BANK_RESPONSE = 1;           // 1 - respond to reads at BANK_ID_ADDR with appropriate data, 0 - ignore reads to that address
parameter BANK_ID_ADDR  = 17'b10111111111111111;      // Address to respond to BANK_ID queries with data (lowest 4 bits left off)

parameter int BANK_ID[16] = '{9,3,71,80,85,32,69,80,52,67,69,54,0,255,255,255};  // The BANK_ID data to return

wire Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, mem_window, last_Z80_WR2, last_Z80_WR3, last_Z80_RD2, last_Z80_RD3, bank_id_access;


// ********************** PS2 Keyboard interface stuff **********************
//
parameter int INT_TYP  = 0;            // 0 = polled (IO), 1 = interrupt
parameter byte INT_VEC = 'h30;         // INTerrupt VECtor to be passed to host in event of an interrupt acknowledge
parameter int IO_DATA  = 240;          // IO address for keyboard polling
parameter int IO_CTRL  = 241;          // IO address for keyboard status
parameter int IO_HOLD  = 2;            // CLK cycles to hold IO data on bus after end of Z80 cycle

wire PS2_READY, IO_DATA_RQ, IO_STAT_RQ, INTA_start, INTA_end, Z80_INTACK;

reg [7:0] PS2_CHAR;
reg PS2_prev, INTACK_prev, IO_DATA_prev, IO_STAT_prev;
reg [4:0] INT_DELAY;
reg [4:0] IO_245_DLY;      // Delay to allow 245 to change direction before putting data onto bus
//reg [6:0] dly_io = 7'b0;
reg IO_hold_clk = 1'b0;       // used to hold the IO cycle a little longer past the end of the real cycle

assign PS2_READY     = PS2_RDY && ~PS2_prev;                                  // HIGH for 1 CLK when valid data is available on PS2_DAT
assign IO_DATA_RQ    = ~Z80_IORQn && (IO_DATA == Z80_addr[7:0]) & ~Z80_RDn;   // HIGH when host is reading data via appropriate IO address
assign IO_STAT_RQ    = ~Z80_IORQn && (IO_CTRL == Z80_addr[7:0]) & ~Z80_RDn;   // HIGH when host is reading status via appropriate IO address

assign Z80_INTACK    = INT_TYP && ~Z80_M1n && ~Z80_IORQn;                     // HIGH when host is acknowledging interrupt
assign INTA_start    = INT_TYP && Z80_INT_REQ && Z80_INTACK && ~INTACK_prev;  // HIGH for 1 CLK when interrupt acknowledge detected
assign INTA_end      = INT_TYP && Z80_INT_REQ && ~Z80_INTACK && INTACK_prev;  // HIGH for 1 CLK when interrupt acknowledge ends
//
// ********************************************************************

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign Z80_mreq      = ~Z80_MREQn && Z80_M1n;   // Define a bus memory access state
assign Z80_write     = ~Z80_WRn;                // write transaction
assign Z80_read      = ~Z80_RDn;                // read transaction

// Only allow RD/WR to valid GPU RAM space
assign Write_GPU_RAM  =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
//assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read  && mem_valid_range; // Define the beginning of a Z80 read request of GPU Ram.

// Allow RD/WR to entire 512KB memory window
//assign Write_GPU_RAM  =  mem_window && Z80_mreq && Z80_write;   // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

   gpu_addr             <=  Z80_addr[18:0];                       // Latch address bus onto GPU address bus
   mem_valid_range      <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
   mem_window           <= (Z80_addr[21:19] == MEMORY_RANGE);     // Define an active memory range (this decides which socket the GPU replaces)
   bank_id_access       <= (Z80_addr[21:4]  == BANK_ID_ADDR);     // Define access to BANK_ID area

   if (PS2_READY) begin       // valid data on PS2_DAT
     
      PS2_CHAR          <= PS2_DAT; // Latch the character into Ps2_char register
     
      // Check IEI here to make sure we can request an interrupt
     
      if (INT_TYP) begin
         Z80_INT_REQ    <= 1'b1;    // Fire off an INTerrupt REQuest
         Z80_IEO        <= 1'b1;    // Pull IEO LOW to prevent anything downstream from requesting interrupts
      end
     
   end
   
   if (Write_GPU_RAM) begin   // *** WRITING TO GPU RAM
     
      Z80_245data_dir   <= 1'b1;       // Set 245 DIR to FPGA
      Z80_rData_ena     <= 1'b0;       // Set FPGA pins to input (should be by default)
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      gpu_wdata         <= Z80_wData;  // Latch data bus onto GPU data bus
     
   end
   
   if (Read_GPU_RAM) begin    // *** READING FROM GPU RAM
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
     
   end
   
   if (INT_TYP && INT_DELAY[2]) begin  // *** RESPONDING TO INTERRUPT ACKNOWLEDGE
     
      Z80_rData[7:0]    <= INT_VEC;    // Put INT_VEC onto data bus after delay to allow 245 to get itself sorted
     
   end

   if (INTA_start) begin      // *** Valid INTerrupt ACKnowledge detected
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
      INT_DELAY[0]      <= 1'b1;       // Start delay timer
     
   end
   else if (INTA_end) begin   // *** End of valid INTerrupt cycle
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      Z80_INT_REQ       <= 1'b0;       // Cancel INTerrupt REQuest
      Z80_IEO           <= 1'b0;       // Allow downstream interrupt requests again
     
   end

   if (gpu_rd_rdy) begin
     
      if (mem_valid_range) begin
         
         Z80_rData[7:0] <= gpu_rData[7:0];  // Latch the GPU RAM read into the output register for the Z80
         
      end else begin
         
         if (BANK_RESPONSE && bank_id_access) begin
           
            Z80_rData[7:0] <= BANK_ID[Z80_addr[3:0]]; // Return the appropriate value
           
         end else begin
           
            Z80_rData[7:0] <= 8'b11111111;   // return $FF if addressed byte is outside the GPU's upper RAM limit
           
         end
         
      end
     
   end
   
   // *** START of IO cycle requesting PS2_CHAR byte
   if (~INT_TYP && IO_DATA_RQ && ~IO_DATA_prev) begin
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
      IO_245_DLY[0]     <= 1'b1;       // Start delay timer before putting data on bus
      IO_hold_clk       <= 1'b1;       // Enable IO hold
     
   end
   
   // *** RESPONDING TO IO READ
   if (~INT_TYP && IO_DATA_RQ && IO_245_DLY[2]) begin
     
      //Z80_rData[7:0]     <= PS2_CHAR;   // Put PS2_CHAR onto data bus after delay to allow 245 to get itself sorted
      Z80_rData[7:0]    <= 'hAA;       // Put static value on bus to test
     
   end
   
   // *** END of IO cycle
   if (~INT_TYP && ~IO_DATA_RQ && IO_DATA_prev) begin
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      PS2_CHAR          <= 8'b0;       // Reset PS_CHAR value
      //dly_io[0]          <= 1'b1;       // Trigger IO shutoff delay
      IO_hold_clk       <= 1'b0;       // Release IO hold
     
   end
   
   // *** DELAYED END of IO cycle
   /*if (~INT_TYP && IO_hold_clk && dly_io[IO_HOLD]) begin
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      PS2_CHAR          <= 8'b0;       // Reset PS_CHAR value
      IO_hold_clk       <= 1'b0;       // Release IO hold
     
   end*/
   
   //
   // *** IF NO INTERRUPT, MEMORY OR IO READ OPERATIONS ARE ONGOING, ENFORCE DATA BUS DEFAULTS ***
   //
   if ((~INT_TYP || ~Z80_INT_REQ) && ~Read_GPU_RAM && ~IO_hold_clk) begin
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      Z80_IEO           <= ~Z80_IEI;   // Pass-through Interrupt Enable flag from upstream devices
     
   end
   
   //
   // *** FLAG & SIGNAL MAINTENANCE ***
   //
   
   // CLOCK EDGE DETECT
   Z80_clk_delay  <= Z80_CLK;

   // WRITE EDGE DETECT
   last_Z80_WR    <= Write_GPU_RAM;
   last_Z80_WR2   <= last_Z80_WR;
   last_Z80_WR3   <= last_Z80_WR2;

   // READ PROCESSING
   last_Z80_RD    <= Read_GPU_RAM;
   last_Z80_RD2   <= last_Z80_RD;
   last_Z80_RD3   <= last_Z80_RD2;
   
   // IO EDGE DETECT & PIPELINE
   IO_DATA_prev   <= IO_DATA_RQ;
   IO_STAT_prev   <= IO_STAT_RQ;
   IO_245_DLY[4:1]<= IO_245_DLY[3:0];
   //dly_io[6:1]     <= dly_io[5:0];
   
   // INTERRUPT EDGE DETECT & PIPELINE
   INTACK_prev    <= Z80_INTACK;
   INT_DELAY[4:1] <= INT_DELAY[3:0];
   
   // PS2 KEYBOARD EDGE DETECT
   PS2_prev       <= PS2_RDY;

   // GPU RAM FLAGS
   gpu_wr_ena     <= Write_GPU_RAM && ~last_Z80_WR2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
   gpu_rd_req     <= Read_GPU_RAM  && ~last_Z80_RD2 ; // Pulse the read request only once at the beginning of a read cycle.
   
end

// **********************************************************************************************************

endmodule

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2020, 12:13:49 pm
Okay, I've made an improvement.  ;D

I'm now getting mostly the intended value back, but it's still not 100%.

[attachimg=1]

Now I'm getting an error in 1 in 7 results, approximately.  I've just cleaned up some of the IF... conditionals and completely removed any delay holding data on the bus after the end of the IORQ cycle.  Code in next post.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2020, 12:14:21 pm
Code: [Select]
module Z80_bridge (

   // input
   input wire  reset,            // GPU reset signal
   input wire  GPU_CLK,          // GPU clock (125 MHz)
   input wire  Z80_CLK,          // Microcom clock signal (8 MHz)
   input wire  Z80_M1n,          // Z80 M1 - active LOW
   input wire  Z80_MREQn,        // Z80 MREQ - active LOW
   input wire  Z80_WRn,          // Z80 WR - active LOW
   input wire  Z80_RDn,          // Z80 RD - active LOW
   input wire  [21:0] Z80_addr,  // Microcom 22-bit address bus
   input wire  [7:0]  Z80_wData, // Z80 DATA bus to pass incoming data to GPU RAM
   input wire  [7:0]  gpu_rData,
   input wire  gpu_rd_rdy,       // one-shot signal from mux that data is ready
   input wire  sel_pclk,         // make HIGH to trigger the Z80 bus on the positive edge of Z80_CLK
   input wire  sel_nclk,         // make LOW  to trigger the Z80 bus on the negative edge of Z80_CLK
   input wire  PS2_RDY,          // goes HIGH when data is ready from PS2 keyboard on PS2_DAT
   input wire  [7:0] PS2_DAT,    // data from keyboard
   input wire  Z80_IORQn,        // Z80 IORQ - active LOW
   input wire  Z80_IEI,          // if HIGH, Z80_bridge can request interrupt immediately
   
   // output
   output reg  Z80_245data_dir,  // control level converter direction for data flow - HIGH = A -> B (toward FPGA)
   output reg  [7:0]  Z80_rData, // Z80 DATA bus to return data from GPU RAM to Z80
   output reg  Z80_rData_ena,    // flag HIGH to write data back to Z80
   output reg  Z80_245_oe,       // OE for 245 level translator *** ACTIVE LOW ***
   output reg  gpu_wr_ena,       // flag HIGH for 1 clock when writing to GPU RAM
   output reg  gpu_rd_req,       // flag HIGH for 1 clock when reading from GPU RAM
   output reg  [19:0] gpu_addr,  // connect to Z80_addr in vid_osd_generator to address GPU RAM
   output reg  [7:0]  gpu_wdata, // 8-bit data bus to GPU RAM in vid_osd_generator
   output reg  Z80_INT_REQ,      // flag HIGH to signal to host for an interrupt request
   output reg  Z80_IEO           // flag HIGH when GPU is requesting an interrupt to pull IEO LOW
   
);

// TODO:
//
// 1) Implement PS2 keyboard interface and IO-polled / interrupt handling
//

parameter MEMORY_RANGE  = 3'b010;      // Z80_addr[21:19] == 3'b010 targets the 512KB 'window' at 0x100000-0x17FFFF (Socket 3 on the Microcom)
parameter MEM_SIZE_BITS = 15;          // Specifies maximum address size for the GPU RAM (anything above this returns $FF)
parameter BANK_RESPONSE = 1;           // 1 - respond to reads at BANK_ID_ADDR with appropriate data, 0 - ignore reads to that address
parameter BANK_ID_ADDR  = 17'b10111111111111111;      // Address to respond to BANK_ID queries with data (lowest 4 bits left off)

parameter int BANK_ID[16] = '{9,3,71,80,85,32,69,80,52,67,69,54,0,255,255,255};  // The BANK_ID data to return

wire Z80_mreq, Z80_write, Z80_read, Write_GPU_RAM;
wire Read_GPU_RAM;
wire Z80_clk_pos,Z80_clk_neg,Z80_clk_trig;

reg Z80_clk_delay, last_Z80_WR, last_Z80_RD, mem_valid_range, mem_window, last_Z80_WR2, last_Z80_WR3, last_Z80_RD2, last_Z80_RD3, bank_id_access;


// ********************** PS2 Keyboard interface stuff **********************
//
parameter int INT_TYP  = 0;            // 0 = polled (IO), 1 = interrupt
parameter byte INT_VEC = 'h30;         // INTerrupt VECtor to be passed to host in event of an interrupt acknowledge
parameter int IO_DATA  = 240;          // IO address for keyboard polling
parameter int IO_CTRL  = 241;          // IO address for keyboard status
parameter int IO_HOLD  = 2;            // CLK cycles to hold IO data on bus after end of Z80 cycle

wire PS2_READY, IO_DATA_RQ, IO_STAT_RQ, INTA_start, INTA_end, Z80_INTACK;

reg [7:0] PS2_CHAR;
reg PS2_prev, INTACK_prev, IO_DATA_prev, IO_STAT_prev;
reg [4:0] INT_DELAY;
reg [4:0] IO_245_DLY;      // Delay to allow 245 to change direction before putting data onto bus
//reg [6:0] dly_io = 7'b0;
reg IO_hold_clk = 1'b0;       // used to hold the IO cycle a little longer past the end of the real cycle

assign PS2_READY     = PS2_RDY && ~PS2_prev;                                  // HIGH for 1 CLK when valid data is available on PS2_DAT
assign IO_DATA_RQ    = ~Z80_IORQn && (IO_DATA == Z80_addr[7:0]) & ~Z80_RDn;   // HIGH when host is reading data via appropriate IO address
assign IO_STAT_RQ    = ~Z80_IORQn && (IO_CTRL == Z80_addr[7:0]) & ~Z80_RDn;   // HIGH when host is reading status via appropriate IO address

assign Z80_INTACK    = INT_TYP && ~Z80_M1n && ~Z80_IORQn;                     // HIGH when host is acknowledging interrupt
assign INTA_start    = INT_TYP && Z80_INT_REQ && Z80_INTACK && ~INTACK_prev;  // HIGH for 1 CLK when interrupt acknowledge detected
assign INTA_end      = INT_TYP && Z80_INT_REQ && ~Z80_INTACK && INTACK_prev;  // HIGH for 1 CLK when interrupt acknowledge ends
//
// ********************************************************************

assign Z80_clk_pos   = ~Z80_clk_delay &&  Z80_CLK;
assign Z80_clk_neg   =  Z80_clk_delay && ~Z80_CLK;
assign Z80_clk_trig  = (Z80_clk_pos && sel_pclk) || (Z80_clk_neg && ~sel_nclk);

assign Z80_mreq      = ~Z80_MREQn && Z80_M1n;   // Define a bus memory access state
assign Z80_write     = ~Z80_WRn;                // write transaction
assign Z80_read      = ~Z80_RDn;                // read transaction

// Only allow RD/WR to valid GPU RAM space
assign Write_GPU_RAM  =  mem_window && Z80_mreq && Z80_write && mem_valid_range; // Define a GPU Write action - only write to address within GPU RAM bounds
//assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read  && mem_valid_range; // Define the beginning of a Z80 read request of GPU Ram.

// Allow RD/WR to entire 512KB memory window
//assign Write_GPU_RAM  =  mem_window && Z80_mreq && Z80_write;   // Define a GPU Write action - only write to address within GPU RAM bounds
assign Read_GPU_RAM   =  mem_window && Z80_mreq && Z80_read;   // Define the beginning of a Z80 read request of GPU Ram.

// **********************************************************************************************************

always @ (posedge GPU_CLK) begin

   gpu_addr             <=  Z80_addr[18:0];                       // Latch address bus onto GPU address bus
   mem_valid_range      <= (Z80_addr[18:0]  <  2**MEM_SIZE_BITS); // Define GPU addressable memory space
   mem_window           <= (Z80_addr[21:19] == MEMORY_RANGE);     // Define an active memory range (this decides which socket the GPU replaces)
   bank_id_access       <= (Z80_addr[21:4]  == BANK_ID_ADDR);     // Define access to BANK_ID area

   if (PS2_READY) begin       // valid data on PS2_DAT
     
      PS2_CHAR          <= PS2_DAT; // Latch the character into Ps2_char register
     
      // Check IEI here to make sure we can request an interrupt
     
      if (INT_TYP) begin
         Z80_INT_REQ    <= 1'b1;    // Fire off an INTerrupt REQuest
         Z80_IEO        <= 1'b1;    // Pull IEO LOW to prevent anything downstream from requesting interrupts
      end
     
   end
   
   if (Write_GPU_RAM) begin   // *** WRITING TO GPU RAM
     
      Z80_245data_dir   <= 1'b1;       // Set 245 DIR to FPGA
      Z80_rData_ena     <= 1'b0;       // Set FPGA pins to input (should be by default)
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      gpu_wdata         <= Z80_wData;  // Latch data bus onto GPU data bus
     
   end
   
   if (Read_GPU_RAM) begin    // *** READING FROM GPU RAM
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
     
   end
   
   if (INT_TYP && INT_DELAY[2]) begin  // *** RESPONDING TO INTERRUPT ACKNOWLEDGE
     
      Z80_rData[7:0]    <= INT_VEC;    // Put INT_VEC onto data bus after delay to allow 245 to get itself sorted
     
   end

   if (INTA_start) begin      // *** Valid INTerrupt ACKnowledge detected
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
      INT_DELAY[0]      <= 1'b1;       // Start delay timer
     
   end
   else if (INTA_end) begin   // *** End of valid INTerrupt cycle
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      Z80_INT_REQ       <= 1'b0;       // Cancel INTerrupt REQuest
      Z80_IEO           <= 1'b0;       // Allow downstream interrupt requests again
     
   end

   if (gpu_rd_rdy) begin
     
      if (mem_valid_range) begin
         
         Z80_rData[7:0] <= gpu_rData[7:0];  // Latch the GPU RAM read into the output register for the Z80
         
      end else begin
         
         if (BANK_RESPONSE && bank_id_access) begin
           
            Z80_rData[7:0] <= BANK_ID[Z80_addr[3:0]]; // Return the appropriate value
           
         end else begin
           
            Z80_rData[7:0] <= 8'b11111111;   // return $FF if addressed byte is outside the GPU's upper RAM limit
           
         end
         
      end
     
   end
   
   // *** START of IO cycle requesting PS2_CHAR byte
   if (IO_DATA_RQ && ~IO_DATA_prev) begin
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
      IO_245_DLY[0]     <= 1'b1;       // Start delay timer before putting data on bus
      //IO_hold_clk       <= 1'b1;       // Enable IO hold
     
   end
   
   // *** RESPONDING TO IO READ
   if (IO_DATA_RQ && IO_245_DLY[2]) begin
     
      //Z80_rData[7:0]     <= PS2_CHAR;   // Put PS2_CHAR onto data bus after delay to allow 245 to get itself sorted
      Z80_rData[7:0]    <= 'hAA;       // Put static value on bus to test
     
   end
   
   // *** END of IO cycle
   if (~IO_DATA_RQ && IO_DATA_prev) begin
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      PS2_CHAR          <= 8'b0;       // Reset PS_CHAR value
      //dly_io[0]          <= 1'b1;       // Trigger IO shutoff delay
      //IO_hold_clk       <= 1'b0;       // Release IO hold
     
   end
   
   // *** DELAYED END of IO cycle
   /*if (~INT_TYP && IO_hold_clk && dly_io[IO_HOLD]) begin
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      PS2_CHAR          <= 8'b0;       // Reset PS_CHAR value
      IO_hold_clk       <= 1'b0;       // Release IO hold
     
   end*/
   
   //
   // *** IF NO INTERRUPT, MEMORY OR IO READ OPERATIONS ARE ONGOING, ENFORCE DATA BUS DEFAULTS ***
   //
   if (~Z80_INT_REQ && ~Read_GPU_RAM && ~IO_DATA_RQ) begin
     
      Z80_245data_dir   <= 1'b1;       // Set 245 dir toward FPGA
      Z80_rData_ena     <= 1'b0;       // Re-set bidir pins to input
      Z80_IEO           <= ~Z80_IEI;   // Pass-through Interrupt Enable flag from upstream devices
     
   end
   
   //
   // *** FLAG & SIGNAL MAINTENANCE ***
   //
   
   // CLOCK EDGE DETECT
   Z80_clk_delay  <= Z80_CLK;

   // WRITE EDGE DETECT
   last_Z80_WR    <= Write_GPU_RAM;
   last_Z80_WR2   <= last_Z80_WR;
   last_Z80_WR3   <= last_Z80_WR2;

   // READ PROCESSING
   last_Z80_RD    <= Read_GPU_RAM;
   last_Z80_RD2   <= last_Z80_RD;
   last_Z80_RD3   <= last_Z80_RD2;
   
   // IO EDGE DETECT & PIPELINE
   IO_DATA_prev   <= IO_DATA_RQ;
   IO_STAT_prev   <= IO_STAT_RQ;
   IO_245_DLY[4:1]<= IO_245_DLY[3:0];
   //dly_io[6:1]     <= dly_io[5:0];
   
   // INTERRUPT EDGE DETECT & PIPELINE
   INTACK_prev    <= Z80_INTACK;
   INT_DELAY[4:1] <= INT_DELAY[3:0];
   
   // PS2 KEYBOARD EDGE DETECT
   PS2_prev       <= PS2_RDY;

   // GPU RAM FLAGS
   gpu_wr_ena     <= Write_GPU_RAM && ~last_Z80_WR2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
   gpu_rd_req     <= Read_GPU_RAM  && ~last_Z80_RD2 ; // Pulse the read request only once at the beginning of a read cycle.
   
end

// **********************************************************************************************************

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2020, 12:35:20 pm
^-^ So I seem to have sorted it myself, though I'm not sure why.  I've removed all the terms from the IF... conditionals checking for IO cycle start, data release, end with wires that do the comparisons, as that was the only difference I could see between my IO conditionals and the memory ones.

So:

Code: [Select]
IF (IO_DATA_REQ && ~IO_DATA_prev) begin

has now changed to (only relevant lines shown - obviously the WIRE assignment doesn't appear in the ALWAYS block!):

Code: [Select]
assign IO_DATA_ST = IO_DATA_RQ && ~IO_DATA_prev; // HIGH for 1 CLK when valid IO_DATA cycle starts

if (IO_DATA_ST) begin

Now I seem to be getting reliable values returned every time.  If anyone can explain why, I'd like to know what the difference is!  :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 25, 2020, 02:46:13 am
So, has anything new progressed?

Or, are you on covid - save all your pennies/spend all of your time with the family lockdown?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 25, 2020, 10:15:26 am
So, has anything new progressed?

Or, are you on covid - save all your pennies/spend all of your time with the family lockdown?

Hey!

Well, no news to report in terms of features or software developments (other than getting CP/M drivers working nicely so I can use all the various programs there with proper screen output).  Yes, lockdown has been in force here since mid-March, which has affected our post and sanity, but I got all the parts together to make the video card in the last few days, so I'm incrementally building it and testing as I go to make sure there's no problems.  Amazingly, the cheap EP4CE10's I got from China actually appear to be EP4CE10's...  :phew:

I have it running the GPU HDL, communicating nicely with the rs232_debugger software and playing tunes on the buzzer/speaker via a single IO.  I soldered the 245's onto the board last night to connect the FPGA up to the Z80's bus to see if I could read the GPU's RAM from the Z80, but all I'm getting is $7E's where I should be getting the first page of video RAM.  I didn't have time to take it any further last night, but whilst sleeping(!) wondered if it's because the test system I'm using is running at 4 MHz instead of 8?  Don't know if that would mess with the z80_bridge timings at all and cause the Z80 to miss the data the FPGA is putting back onto the data bus?

Anyhow, I'm going to look at that today if I get the chance - switch the uCOM over to 8 MHz and test it again, and if that still doesn't work then I'll test all the connections between the FPGA chip itself and the address & control buses to see if there's any bad connections preventing the FPGA detecting RD/WRs to it.  Will update as soon as I can with developments.  :-+

EDIT:
No - bumping the system clock up to 8 MHz makes no difference.  I'm able to turn on/off the sound output via an OUT command to the appropriate IO port, so it would appear the lower (A0-A7) part of the address bus and data bus is working properly, but it seems to me that getting no data back when trying to read the GPU RAM could be an issue with the middle/upper addresses not getting through properly.  Will continue looking at these.

EDIT 2:
The Z80 is able to write data to the GPU RAM - I've been POKE-ing values to the GPU RAM and can see the changes in the RS232_debugger, but the Z80 cannot read the values back - all I'm getting back is $7E, which is what I get when there's no chip in the socket where the memory address resides.  Could this be a timing issue?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 26, 2020, 04:13:15 am

EDIT 2:
The Z80 is able to write data to the GPU RAM - I've been POKE-ing values to the GPU RAM and can see the changes in the RS232_debugger, but the Z80 cannot read the values back - all I'm getting back is $7E, which is what I get when there's no chip in the socket where the memory address resides.  Could this be a timing issue?

1. Check with a magnifying glass your soldering.
2. Check with ohm meter for continuity on the OE and DIR lines of the 245s.
3. Go with an ohm meter and make sure your IO buffer's OE/DIR aren't shorted to adjacent pins on the FPGA, or shorted to GND/VCC.
4. Double check the schematic by pin number to the Quartus pinout file since I think we moved some IOs to adapt to the PCB layout.
5.  Verify that the new IOs on the larger CycloneIV are valid free IO.  (You only need to concern yourself with the OE and DIR signals for the 245s as the write function works.
6.  Make sure during pin number swapping, you didn't accidentally label/number the OE and DIR controls coming out of the FPGA backwards.

This type of possible problem is normal with a first time brand new PCB.

Lastly, you will need to scope the 245's OE/DIR as the 'Chinese Cyclone' may have a damaged IO pin.  Make sure the signal has a good 3v high and 0v low.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 26, 2020, 10:40:11 am
1. Check with a magnifying glass your soldering.
2. Check with ohm meter for continuity on the OE and DIR lines of the 245s.
3. Go with an ohm meter and make sure your IO buffer's OE/DIR aren't shorted to adjacent pins on the FPGA, or shorted to GND/VCC.
4. Double check the schematic by pin number to the Quartus pinout file since I think we moved some IOs to adapt to the PCB layout.

Have done these already - there's no issues with continuity between the FPGA and 245 for OE or DIR signals, no shorts that I can find.

5.  Verify that the new IOs on the larger CycloneIV are valid free IO.  (You only need to concern yourself with the OE and DIR signals for the 245s as the write function works.

Hmm.. well they appear to be valid IO according to the Pin Planner.  Where else do I need to look to check these?  I'm wading through datasheets and handbooks...

6.  Make sure during pin number swapping, you didn't accidentally label/number the OE and DIR controls coming out of the FPGA backwards.

Have checked and double-checked this, all is good.

This type of possible problem is normal with a first time brand new PCB.

That's reassuring, but it's still frustrating!

Lastly, you will need to scope the 245's OE/DIR as the 'Chinese Cyclone' may have a damaged IO pin.  Make sure the signal has a good 3v high and 0v low.

Yes, so this is the next thing - will require some setup with my logic analyser and I'll check it with that first.  My scope won't touch this sort of issue unless I specifically write some HDL to repeatedly switch the DIR pin at a frequency that the scope can see and allow me to get a stable trace on the screen.

I've included the latest version of the project in a zip below in case it's useful.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 26, 2020, 11:12:07 am
Hang on...

Code: [Select]
   if (Write_GPU_RAM) begin   // *** WRITING TO GPU RAM
     
      Z80_245data_dir   <= 1'b1;       // Set 245 DIR to FPGA
      Z80_rData_ena     <= 1'b0;       // Set FPGA pins to input (should be by default)
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      gpu_wdata         <= Z80_wData;  // Latch data bus onto GPU data bus
     
   end
   
   if (Read_GPU_RAM) begin    // *** READING FROM GPU RAM
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
     
   end

Above code is from z80_bridge.sv.

For a GPU RAM WRITE from the Z80, it's setting Z80_245data_dir HIGH.  That's setting the 245 to A>B direction.  This is fine for the prototype, because I've got the Z80 data bus on the A side, HOWEVER on the PCB I've got the FPGA on the A side.  :palm:

So if I'm reading it right, Z80_245data_dir is being set to the opposite value of what is required.  Amazing that I was able to write data to the GPU RAM at all...  :wtf:  Unless the 245's DIR pin never goes HIGH at all, in which case it won't matter what value Z80_245data_dir is set to, it'll always be sending data TO the FPGA.

I've reversed the values for Z80_245data_dir in the HDL to accommodate the change in layout of the PCB, but still not able to read anything from GPU RAM.  Strangely, I'm able to write to GPU RAM (and I can see the uCOM's bootstrap setting up the GPU for text display mode) but any block copies (using LDIR) just seem to write 0xB0 to every address, rather than 0x00 or any other value.

EDIT: Updated Z80_bridge.sv attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: lintweaker on April 27, 2020, 11:49:36 am
Oh, yes. Those level converters with DIR can make things a lot harder...
It took me months to get a Z80 to read stuff back from peripherals living in the FPGA. After going back to the basics (simple LED with status readback) I've managed to get it working.
I am using TI SN74LVC8T245DWR or SN74LVC8T245PWRs as level converters with the 5V Z80 stuff on the 'B' side.

Did you put your project on github? I am interested in using it.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 27, 2020, 12:24:50 pm
Did you put your project on github? I am interested in using it.

Yes - here it is: https://github.com/nockieboy/gpu (https://github.com/nockieboy/gpu)  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: lintweaker on April 27, 2020, 01:42:43 pm
Yes - here it is: https://github.com/nockieboy/gpu (https://github.com/nockieboy/gpu)  :)
Thanks!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 28, 2020, 02:29:30 am
Hang on...

Code: [Select]
   if (Write_GPU_RAM) begin   // *** WRITING TO GPU RAM
     
      Z80_245data_dir   <= 1'b1;       // Set 245 DIR to FPGA
      Z80_rData_ena     <= 1'b0;       // Set FPGA pins to input (should be by default)
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      gpu_wdata         <= Z80_wData;  // Latch data bus onto GPU data bus
     
   end
   
   if (Read_GPU_RAM) begin    // *** READING FROM GPU RAM
     
      Z80_245data_dir   <= 1'b0;       // Set 245 DIR TO Z80
      Z80_245_oe        <= 1'b0;       // Enable 245 output
      Z80_rData_ena     <= 1'b1;       // Set bidir pins to output
     
   end

Above code is from z80_bridge.sv.

For a GPU RAM WRITE from the Z80, it's setting Z80_245data_dir HIGH.  That's setting the 245 to A>B direction.  This is fine for the prototype, because I've got the Z80 data bus on the A side, HOWEVER on the PCB I've got the FPGA on the A side.  :palm:

So if I'm reading it right, Z80_245data_dir is being set to the opposite value of what is required.  Amazing that I was able to write data to the GPU RAM at all...  :wtf:  Unless the 245's DIR pin never goes HIGH at all, in which case it won't matter what value Z80_245data_dir is set to, it'll always be sending data TO the FPGA.

I've reversed the values for Z80_245data_dir in the HDL to accommodate the change in layout of the PCB, but still not able to read anything from GPU RAM.  Strangely, I'm able to write to GPU RAM (and I can see the uCOM's bootstrap setting up the GPU for text display mode) but any block copies (using LDIR) just seem to write 0xB0 to every address, rather than 0x00 or any other value.

EDIT: Updated Z80_bridge.sv attached.
Have your tried completely rolling back the version of the interface, way back to 1.0 where we didn't have the interrupt or PS2 keyboard interface...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 28, 2020, 08:49:34 am
Have your tried completely rolling back the version of the interface, way back to 1.0 where we didn't have the interrupt or PS2 keyboard interface...

Not yet, but I'm pretty confident the PS2 (and by extension the interrupt request) sections of HDL in the Z80_bridge aren't interfering with anything else.  There is no PS2 HDL to handle and read the PS2 input (there's no PS2 connector on the board at the moment), but I've attached a GND to the PS2_RDY input on the Z80_bridge just to be sure - but even if it did float HIGH, it wouldn't do anything except read PS2_DAT into a register anyway, ready to be read by an IO RD from the Z80.

I'm fairly convinced it's a bad IO on the FPGA.  I've done my best to try and get some data from the 245_DIR line between pin 143 on the FPGA and pin 1 on the 74LVC245, but I'm finding attaching a logic analyser probe impossible - I need four or five arms to hold everything in place and operate the PC at the same time.

What I did do was a very tight loop of test code:

Code: [Select]
6000   LD HL,0C000H  ; Translates to GPU RAM address 0x0000
6003   LD A,(HL)     ; Read a byte from GPU RAM into the accumulator
6004   LD A,(HL)
6005   LD A,(HL)
6006   LD A,(HL)
6007   LD A,(HL)
6008   JP 6003       ; Jump back and read again

Basically, it gets the Z80 to read an address in GPU RAM (pointed to by HL) several times and loop back to read it again constantly.  Without looking at the clock timings for the individual commands I was using, I'd say it would be fair to estimate that the 245_DIR line should have been HIGH for anything between 20-40% of the time in that loop (disclaimer: wild guess from top of my head, but supported by some logic).  As all I could reliably connect to the 245's pin 1 was my multimeter, I would have expected to see something like 1V maybe, displayed as an average on the meter if it was working properly.

At rest (i.e. no GPU RAM access by the Z80), the pin read around 40mV.  Whilst the test loop was running, it read 49-60mV, sometimes jumping to around 200mV, but it didn't seem to like being measured and I could hear some faint static from the speaker briefly, then it locked up entirely.  I'm fairly confident that the test was sensitive enough to pick up if the line was going HIGH as it should do when the Z80 read the GPU RAM, but there was little sign of that.  Very strange behaviour.

Naturally, I'd prefer to get the logic analyser to record 245_DIR during a GPU RAM RD transaction, but I just can't seem to get a logic probe to contact securely with pin 1 of the TSSOP.  Might try soldering a wire to it later and try again.

My last step is a little extreme, so I'm holding off doing it until I'm happy I've exhausted all attempts with the logic analyser and I've had the time to dig out the oscilloscope and set it up (again, I need five arms and plenty of time to do that).  Basically, I'll cut the 245_DIR trace and connect a spare FPGA IO (I have a couple) to the 245 with some wire-wrap, if need be.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2020, 02:18:04 pm
So it was a dead/faulty IO pin on the FPGA.  :phew:  I cut the line from pin 143 to the data 245's DIR pin and bodged a connection between a spare IO on the FPGA (pin 7) and the DIR pin, updated the HDL with the new pin assignment and hey presto! It works - I can read the GPU RAM now.  ;D

Now for the next step - build the VGA output section and hope that all works as intended!  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 01, 2020, 12:12:10 am

EDIT 2:
The Z80 is able to write data to the GPU RAM - I've been POKE-ing values to the GPU RAM and can see the changes in the RS232_debugger, but the Z80 cannot read the values back - all I'm getting back is $7E, which is what I get when there's no chip in the socket where the memory address resides.  Could this be a timing issue?

1. Check with a magnifying glass your soldering.
2. Check with ohm meter for continuity on the OE and DIR lines of the 245s.
3. Go with an ohm meter and make sure your IO buffer's OE/DIR aren't shorted to adjacent pins on the FPGA, or shorted to GND/VCC.
4. Double check the schematic by pin number to the Quartus pinout file since I think we moved some IOs to adapt to the PCB layout.
5.  Verify that the new IOs on the larger CycloneIV are valid free IO.  (You only need to concern yourself with the OE and DIR signals for the 245s as the write function works.
6.  Make sure during pin number swapping, you didn't accidentally label/number the OE and DIR controls coming out of the FPGA backwards.

This type of possible problem is normal with a first time brand new PCB.

Lastly, you will need to scope the 245's OE/DIR as the 'Chinese Cyclone' may have a damaged IO pin.  Make sure the signal has a good 3v high and 0v low.
:-DD Heheheh, it's always the last thing...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 01, 2020, 09:04:24 am
:-DD Heheheh, it's always the last thing...

 ;)

And there's always another thing...   :-\ I completed the VGA section last night and switched on, blank screen (no signal).  Now I haven't had much time to look into the issue, but I noticed after a quick look at the HDL last night that there was no BLANK output from the GPU to the DAC (but the line is there on the PCB), so I quickly added an output in HDL linked to Vcc and tried again - still no output.

So here's my to-do list - feel free to chip in with any other suggestions - that I'll try to work through over the weekend. Listed in order of ease of testing (I have no easy/reliable way to get my logic analyser connected to the FPGA pins):

1) Check Quartus HDL for errors/incorrect pin allocations (done this - this is how I spotted the missing BLANK output)
2) Check for bad soldering
3) Check BLANK line for 3.3V on PCB
4) Check good 3.3VA to U13 (DAC)
5) Check U6 for good 5V supply and test for HSYNC and VSYNC signals
6) Check U3 outputs (via R7-R9 for ease of access) for R, G and B signals
7) Check R/G/B lines from FPGA
8 ) ... not wanting to jinx it, but consider possibility there's a few more bad IOs on this FPGA ...  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 01, 2020, 09:49:13 am
BLANK output from the GPU to the DAC (but the line is there on the PCB), so I quickly added an output in HDL linked to Vcc and tried again - still no output.

Doesn't Blank = VCC mean 'Blank' as in black, as in no picture?

Don't we have an 'active' video output which would just need to be inverted to feed this signal?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 01, 2020, 10:08:17 am
Doesn't Blank = VCC mean 'Blank' as in black, as in no picture?

The way I read the datasheet, I thought it meant no image if BLANK was not at Vcc?

[attachimg=1]

Don't we have an 'active' video output which would just need to be inverted to feed this signal?

Errrr.... possibly - would that be the vid_de_out (vde at the pin) output from vid_out_stencil???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 03, 2020, 10:05:43 am
It appears there's no hs and no vs coming out of the FPGA.  I couldn't pick up any blue signals on blue[5] or blue [2] when I tested them.  As I'm using my logic analyser, connected via a Dupont lead with a pin stuck in the end to connect to one of my multimeter's leads so I can use the sharp point on the end to single out the FPGA pins I want to test, it's a shaky method but I'm consistently getting a pixel_clk signal (sort of - my logic analyser won't measure a frequency that high, but I'm getting a signal as best it can manage) and BLANK is HIGH.

Could there be something I've missed in the HDL that is stopping hs/vs output?  I'll test the rest of the colour channels later, taking a break for a bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 03, 2020, 05:28:06 pm
What does the scope say?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 16, 2020, 10:19:52 am
Quick update, as nothing has really progressed.  The scope didn't provide any meaningful data (to me, anyway) - looks like the IOs are dead on the first FPGA and a second I put together is completely dead.

I've given up on the project for the moment while I wait for some low-temperature solder to arrive.  I have a concern that I may have cooked the last FPGA as I tried soldering it with a hot air gun from the top, instead of from underneath via the... vias... and not having an IR temp gun meant I had no idea how hot I was making the chip, so I figure the wait for some low-temp solder would be worth it and should mean I can solder the exposed ground pad underneath the chip without roasting the chip.  Obviously I use normal solder for the pins - I'm quite happy I can do them without causing much hassle to the chip.

I've got two of these FPGAs sourced from AliExpress left - if I can get better results soldering them using the low-temp paste (but they still don't work fully) then I'll know they're a bad batch and it's not my caveman soldering skills.  Sourcing an FPGA from a legitimate seller is about 6x more expensive, though, so I want to make sure my soldering is up to the task before I start literally burning through cash.  I'll get an IR temp gun before I start on a legitimate FPGA build...

TLDR: going on hiatus for a while - waiting for materials - before attempting another build.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on May 16, 2020, 03:35:43 pm
Take a look at the project in my signature. It's open source (so you can modify it if you want to adapt it to your project by adding/removing peripherals, or using some other connector as the 0.1" one on the board is not really suitable for anything high-speed), it supports rather beefy FPGAs (up to Spartan-7 S50 with 76.8K logic cells and 90 36Kbit BRAM cells), there is up to 256 MBytes of DDR2 memory with 16bit bus running at 333 MHz (so theoretical maximum bandwidth is 333 * 2 * 16 = 10656 Mbit/s), and there is an HDMI output port. But most importantly, it's tested and known to work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 16, 2020, 10:15:28 pm
Quick update, as nothing has really progressed.  The scope didn't provide any meaningful data (to me, anyway) - looks like the IOs are dead on the first FPGA and a second I put together is completely dead.

I've given up on the project for the moment while I wait for some low-temperature solder to arrive.  I have a concern that I may have cooked the last FPGA as I tried soldering it with a hot air gun from the top, instead of from underneath via the... vias... and not having an IR temp gun meant I had no idea how hot I was making the chip, so I figure the wait for some low-temp solder would be worth it and should mean I can solder the exposed ground pad underneath the chip without roasting the chip.  Obviously I use normal solder for the pins - I'm quite happy I can do them without causing much hassle to the chip.

I've got two of these FPGAs sourced from AliExpress left - if I can get better results soldering them using the low-temp paste (but they still don't work fully) then I'll know they're a bad batch and it's not my caveman soldering skills.  Sourcing an FPGA from a legitimate seller is about 6x more expensive, though, so I want to make sure my soldering is up to the task before I start literally burning through cash.  I'll get an IR temp gun before I start on a legitimate FPGA build...

TLDR: going on hiatus for a while - waiting for materials - before attempting another build.  ::)
Heat burning a 144pin TQFP when just drag soldering the pins is tough to do.

1 IO dead, ok, maybe static electric discharge or Chinese junk.
1 bank of IOs dead, maybe an IO bank's VCCIO or GNDIO isn't soldered down or making contact.

If you see the DAC getting a clock & syncs & random data, but no picture, maybe a Chinese fake DAC ic.

You should have paid the extra 20% an purchased the read McCoys from the links I've provided when we did the price comparisons earlier and be guarantee good ICs.  (Note that I realize I also provided Aliexpress links for some FPGAs and I did warn of the possibilities of problems when purchasing from there)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 17, 2020, 03:25:02 am
How about a detailed hi-res photograph of your assembled PCB.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 11:09:50 am
Heat burning a 144pin TQFP when just drag soldering the pins is tough to do.

Agreed - and I'm confident enough in my soldering skills to not be slightly worried about this particular risk.

Using the hot air gun, however, I'm not so sure about.  I've ordered an IR temperature gun - I can't really hot-air solder a chip as large as a QFP-144 where I can't see the solder melting on the ground pad and expect to keep it even vaguely close to any kind of soldering profile. 

You should have paid the extra 20% an purchased the read McCoys from the links I've provided when we did the price comparisons earlier and be guarantee good ICs.  (Note that I realize I also provided Aliexpress links for some FPGAs and I did warn of the possibilities of problems when purchasing from there)

I was always going to go for the cheapest FPGAs I could source initially as I had no confidence in my ability to be able to solder them (the 'hardest' I'd done before was the odd TSSOP, I hadn't gone smaller than 0805 for passives and I have no specialist or expensive equipment), so don't worry about the advice you gave me - it was good.

I'm happy that soldering a QFP-144 isn't actually that difficult now, even with the exposed ground pad, aside from my concerns with possibly overheating the chip - but I'm taking steps to prevent that now by getting the IR temp gun.  There's still no guarantee that's the issue - but I may as well deal with the obvious issues as well as the less obvious ones.

I've taken some pics with my phone - can't say they're much use, but I'll attach them anyway.  I've been using a x10 loupe magnifying glass for all my SMD soldering anyway, so I've inspected the board as best I can and can't see any bad connections on the FPGA.  The next step is to check all the power pins at the FPGA to make sure power is getting through.

Some of the resistor values are approximations (85R instead of 75R on the RGB outputs, for example), and I think I found X1 to be the fiddliest thing to solder of the lot (I used solder paste and hot air gun for it), but it's outputting a 50 MHz clock as far as I can tell (the FPGA works in terms of talking to the Z80 and operating the buzzer, anyway).

I'll attach the other four images in following posts, due to attachment size limitations.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 11:12:09 am
This image shows the side of the FPGA closest to the video DAC.  The hs/vs booster (74HCT541) is just visible in the bottom left of the image and VGA socket at the bottom of the image.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 11:14:09 am
90 degrees counter-clockwise from previous image, showing the FPGA side on the data and control bus input side.  The jumper lead is the bodge I made when I realised the data bus's 245_DIR IO pin wasn't working, so switched to an alternate IO pin on the FPGA.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 11:15:55 am
Another 90 degrees counter-clockwise, looking at the side of the FPGA that connects to the clock source, serial port and AS/JTAG ports.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 11:17:37 am
Finally, another 90 degrees counter-clockwise from previous post, showing side of FPGA that handles the system's address bus, from A0-X21.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: cruff on May 17, 2020, 01:20:18 pm
It looks like there are solder bridges on chip U3 on the upper side in the image.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 01:32:58 pm
It looks like there are solder bridges on chip U3 on the upper side in the image.

Yes, they're supposed to be there.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 17, 2020, 05:58:52 pm
Ok,
Have you ever drag soldered pins?
Do you have extra flux?
Do you have solder wick?

I've attached at least 2 lifted pins, the VCCA pll and VCCIO for the DAC and I think some of the Z80 port.

Things are iffy, I bet other pins are also just barely touching cold solder joints.

Also, having a lifted VCCIO may be damaging to powering up the FPGA, but from what I see, properly cleaning things up may make this PCB work fine.
[attach=1]
[attach=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 07:01:17 pm
Have you ever drag soldered pins?
Do you have extra flux?
Do you have solder wick?

Yes to all those.  I have sticky/waxy (applied with a tooth pick), liquid (applied with a brush) and jelly-like (applied from a syringe) flux.  I've been using solder wick on the FPGA - you can probably see where the white solder mask has been removed on a few traces with some overzealous wicking...  And drag soldering is something I've learned on this FPGA and the one before it...

I've attached at least 2 lifted pins, the VCCA pll and VCCIO for the DAC and I think some of the Z80 port.

...but I'm happy there's no bad connections to the FPGA - I've checked and re-checked all the FPGA pins' connections to the PCB with a loupe and multimeter - I can confirm that ALL the 3.3V input pins to the FPGA are receiving 3.3V (well, 3.2V actually...  ???)

The 1.3V regulator is pumping out some heat, though - it felt quite hot to the touch whilst I was testing some of the FPGA pins, so here's some voltage readings from the tabs on the AMS1117s:  :-DMM
Things are iffy, I bet other pins are also just barely touching cold solder joints.

Also, having a lifted VCCIO may be damaging to powering up the FPGA, but from what I see, properly cleaning things up may make this PCB work fine.

Short of testing every single pin on the FPGA, which I think I might just have to do, I'm pretty confident of ALL the FPGA connections to the PCB (including the exposed ground pad underneath).  The photos I've taken aren't the best quality - I'd need a digital microscope that can take stills really, so the pins you think look lifted or cold-soldered are actually fine if viewed with the light source from a different angle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on May 17, 2020, 07:48:07 pm
The 1.3V regulator is pumping out some heat, though - it felt quite hot to the touch whilst I was testing some of the FPGA pins
That's why almost all FPGA boards I've seen use buck converters for the core voltage. Some larger devices can consume a lot of current on that rail, so using linear converters is impractical because they would generate a serious amount of heat.
Also - why 1.3V? If my memory serves me Cyclone-4's Vccint is 1.2 V nominal ±0.05 V, or 1.0 V ± 0.03 V, so 1.3 V would certainly be out of spec.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 08:25:43 pm
Also - why 1.3V? If my memory serves me Cyclone-4's Vccint is 1.2 V nominal ±0.05 V, or 1.0 V ± 0.03 V, so 1.3 V would certainly be out of spec.

This was recommended by BrianHG:

Since you are using the slowest -C8 versions, and, you need a C7, or even a -C6 for the higher densities, I recommend replacing the 1.2v regulator for an adjustable one and adjust it for 1.35v.  This will make a C8 perform somewhere inbetween a C7 and C6 which would be perfect.  Though, my GPU design, there are only a few critical address paths in the FPGA, so it still wont get warm or draw too much current over driving the VCCint to 1.35v.

Having checked the datasheet in more detail, you're quite right, it does appear to be out of spec, especially as the voltage coming out is actually slightly higher than the 1.3V required in the design.

I doubt that dropping the voltage to 1.2V will affect the performance in any material way (unless BrianHG can shed some more light on that) as the prototype version on the FPGA dev board runs fine with a 1.2V supply.  Interestingly, that's a linear supply as well.  Will have to check the temp on that part next time around.

Likewise, I can't see how 1.3V instead of 1.2V on Vccint is going to stop the IO at the DAC side from working, when everything else seems fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on May 17, 2020, 09:22:47 pm
Having checked the datasheet in more detail, you're quite right, it does appear to be out of spec, especially as the voltage coming out is actually slightly higher than the 1.3V required in the design.
Overclocking 101 - before you overclock anything you always establish that device you're about to run out of spec works in spec. As going out of spec is always a lottery. There is a reason the specs are what they are, if Antel would be certain that their devices will have higher performance than they are at 1.3 V, they would certainly market this a a feature. For example, on Xilinx side there are certain FPGAs which are individually tested in production and have embedded VID code telling which voltage they can be ran at to get the most out of them.

Likewise, I can't see how 1.3V instead of 1.2V on Vccint is going to stop the IO at the DAC side from working, when everything else seems fine.
Once you're out of spec, you're in terra incognita, and anything can happen. For all we know, FPGA might be now half brain-dead and outputting a mains voltage on its pins just for the hell of it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 17, 2020, 10:01:51 pm
Likewise, I can't see how 1.3V instead of 1.2V on Vccint is going to stop the IO at the DAC side from working, when everything else seems fine.
Once you're out of spec, you're in terra incognita, and anything can happen. For all we know, FPGA might be now half brain-dead and outputting a mains voltage on its pins just for the hell of it.

Fair point, I guess I'll have to set the 1.3V output to 1.2V then before I do anything else.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 17, 2020, 10:55:32 pm
1.2v is fine for your design.  The overclock is way too small to need any boosting.  I mentioned it as a last result.
The way I designed the core, errors from overclocking would only represent glitches in the core memory, however, since you confirmed that the Z80 reads and writes to the core memory with the RS232 Debugger, this isn't where your problem lies.
(Only the core dualport ram is running at 250MHz (Of the 240MHz limit reported by Quartus) with an AB-mux switch.  And only around 8 signals are out of slack by less than 0.1ns. Everything else runs at 125MHz and report all in the green by a good margin.)

Did you check that the syncs are coming out of the right pins of the VGA connector?

Are you sending +5V to pin 9 on the VGA connector so that the monitor +Vsense pin knows it is being connected to a turned on video card? Never mind, your old development board doesn't have it.
Also, pins 5,6,7,8 and 10 should be grounded.

Can I see the latest schematic and pcb prints, the white PCB you showed me doesn't match what is posted on here on the forum.  Some Vias don't line up or are missing.

That darn white soldermask doesn't allow you to see anything.

Did your scope show a proper HS and VS coming out of the VGA connector, when connected to a monitor?  This should at least turn on the monitor.

What was the frequency of the CLK output to the DAC?

Can I have a copy of your latest Quartus project?  Your GitHub has only single files and I will not download all the files individually 1 by one.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 18, 2020, 08:16:02 am
1.2v is fine for your design.  The overclock is way too small to need any boosting.  I mentioned it as a last result.
The way I designed the core, errors from overclocking would only represent glitches in the core memory, however, since you confirmed that the Z80 reads and writes to the core memory with the RS232 Debugger, this isn't where your problem lies.
(Only the core dualport ram is running at 250MHz (Of the 240MHz limit reported by Quartus) with an AB-mux switch.  And only around 8 signals are out of slack by less than 0.1ns. Everything else runs at 125MHz and report all in the green by a good margin.)

Okay, no problem, I'll either replace the ADJ with a 1.2V regulator or adjust the resistors to drop the voltage to 1.2V.  Have updated the schematic as well (though not the copy I'm attaching in this post).

Did you check that the syncs are coming out of the right pins of the VGA connector?

I've checked with my logic analyser, which picked up no signals whatsoever.  I've yet to get the oscilloscope set up - unfortunately I haven't had the time or space to dig it out and get it set up, have been too busy with work, but will try to do some testing with it and get some results soon.

Are you sending +5V to pin 9 on the VGA connector so that the monitor +Vsense pin knows it is being connected to a turned on video card? Never mind, your old development board doesn't have it.
Also, pins 5,6,7,8 and 10 should be grounded.

No, but I've added that into the schematic for the next iteration of the board.  I note that a couple of pins in the VGA standard are for an I2C connection to a ROM in the monitor?  Presumably to identify the monitor and get resolutions etc?  My uCOM has I2C, so I'm wondering if it would be worth connecting it up to the VGA port as well.  Might be something to look at later.

Did your scope show a proper HS and VS coming out of the VGA connector, when connected to a monitor?  This should at least turn on the monitor.

No, there's nothing coming out of the VGA connector at all as far as I can tell - with the caveat that I haven't yet got the oscilloscope on it.  I've checked these signals back to the FPGA and there's nothing coming out of the FPGA, so it's not (necessarily) the DAC or hs/vs driver (U6).

What was the frequency of the CLK output to the DAC?

I have no test equipment that can measure a 50MHz signal.  My scope is only 20MHz and it's as old as the hills. The best I can do is jury-rig a couple of FFs and divide the clock by 8 or 16 to measure it on my logic analyser or oscilloscope, with all the associated extra wiring and bad connections that brings with it.  I'm actually waiting on some PCBs and parts to make up a proper clock divider.

Can I have a copy of your latest Quartus project?  Your GitHub has only single files and I will not download all the files individually 1 by one.

All attached below.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 18, 2020, 09:14:30 am
Unless the board is held in reset by the reset input, a sync must come out as that sync generator section is hard wired logic.

As for the clock, it is 25Mhz, and a 20MHz analog scope should see it as a sine wave.  If we have it at 50MHz, it would be a shriveled sine wave.

You have a few more questionable soldering GNDIO and VCCIO and VCCINT around the sync lines and the port on the photo you provided which was true-white / bottom left side.

Your meter may still read these as connections since there are multiple VCC & GND connection inside the FPGA, but don't let that fool you, with a small 144pin package, every VCC/GND still needs a physical good connection otherwise funny things happen as seen on other homemade PCB FPGA threads here at EEVblog.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: obiwanjacobi on May 22, 2020, 06:11:31 am
Not read the 40 pages preceding this - but it might be an idea to make the simplest 'hello world' code and start testing the basics and work up from there. Sounds like you need to establish what is working and what is not at a basic level.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 22, 2020, 06:31:05 am
Not read the 40 pages preceding this - but it might be an idea to make the simplest 'hello world' code and start testing the basics and work up from there. Sounds like you need to establish what is working and what is not at a basic level.
The code is good.  nockieboy got it fully functional on a dev board with a good CycloneIV on it.  He has poor soldering joints on his home made board and bought his CycloneIV from a questionable source, as he already discovered that it has 1 confirmed dead IO pin.  Other than a voltmeter, his old analog scopes hasn't been able to tell him much other than all the IO feeding the DAC are dead.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 29, 2020, 06:50:22 pm
Yeah, nothing further to add - the oscilloscope is showing all the IO are dead for the RGB and HS/VS outputs.  I'm just waiting on some low temp solder, an IR temperature gun and I'll order a good FPGA from a reputable source before trying again.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 29, 2020, 10:12:34 pm
I would still 'drag' solder all the pins on the sides I mentioned.
In fact, with normal leaded solder, I would blob solder the pins, then, using solder wick, wick us the excess.

You have nothing to loose at this point.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on May 30, 2020, 12:15:20 am
I would still 'drag' solder all the pins on the sides I mentioned.
In fact, with normal leaded solder, I would blob solder the pins, then, using solder wick, wick us the excess.

You have nothing to loose at this point.
Or add a crap ton of tacky gel flux, and then go with a molten solder "ball" across all pins. Flux will prevent bridges, while excess solder will ensure good wetting.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 30, 2020, 05:55:31 am
What the results of drag soldering should look like with normal solder: 

https://www.youtube.com/watch?v=nyele3CIs-U (https://www.youtube.com/watch?v=nyele3CIs-U)

Take a look at 4:15.  This is what your soldering should look like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: obiwanjacobi on May 30, 2020, 07:13:38 am
I remember that when I first tried soldering SMD, I found it easier to get good (enough) results with simply using a small soldering tip and carefully touching up on each pin individually. My point: you don't have to drag-solder.

You DO need lots of flux and use very little solder.
Also be careful with using wick - better to prevent that by using very little solder.

[2c]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on May 30, 2020, 03:15:08 pm
Gel flux helps a lot.

I for one usually don't "drag solder". I usually rather solder a few pins at a time with either a bevel or chisel tip (depending on pitch and accessibility), essentially "dragging" along the pins being soldered rather than dragging along the side of the package. Takes maybe a little more time, but it's still fast and tends to make fewer bridges. YMMV.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 30, 2020, 06:09:23 pm
I had been using a wedge tip with a tiny blob of solder on the end and lots of waxy flux.  Had got it so that I could do a whole side of the 144-pin FPGA with no bridges, or a couple if I was unlucky.  I did try drag soldering, but found it just seemed to bridge the entire set of pins, no matter how much flux I used.

As soon as the IR thermometer arrives, I'll try another of the cheap FPGAs (I have two left) and see how they go.  I'm probably completely wrong, but I feel that I may have been overheating the chips when I was hot-air soldering the central exposed ground pad on the last couple of attempts.  I do that first, then I go round the FPGA soldering its pins using the methods above.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 14, 2020, 03:46:35 pm
Okay, so I might have found out why the RGB and HS/VS outputs of the FPGA are 'dead'...  :palm:

[attachimg=1]

I hadn't included an inverter on the Z80's RESET input to the FPGA.  RESET on the Z80 is active low, this is obviously in opposition to the workings of the FPGA's positive logic, meaning the video circuit was constantly in a state of reset and not outputting ANY colour signals or video sync signals.  I've added the inverter as shown above in the red circle, and I can now get good, clear HS and VS signals from my latest board.  (I say latest, it's the third board I've built so far - the first being the only other working one, but with the bad IO on the data buffer.)  So I'll get the rest of the video circuit built on this latest card and give it a test.

Still, it's been good practice soldering these TQFP-144s.  This latest board is looking much neater.  :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2020, 02:01:42 pm
Have just uploaded the new HDL to the first board I'd made (the one with the alternate GPIO used for the data direction on the Z80 interface to bypass the bad IO pin) and it's working perfectly.  Image is stable, all the colours are there, everything seems to be working fine.  :phew: :-+

[attachimg=1]

[attachimg=3]

The second board I made seems to be dropping bit 0 on the data bus, so there's probably a bad IO on pin 142 for that board.  I haven't got around to building the DAC and VGA output part of that board yet.

The third board (version 2 PCB with AS/JTAG connectors spaced further apart, spare IO pins exposed as pads on the PCB and another spare GPIO wired to an LED) is working just fine so far, but I've yet to solder the DAC onto the PCB.  It's outputting HS and VS fine, though.

[attachimg=2]

So I'd call that a successful project!  ;D

I've thanked you previously, but I'll do it again - thanks for your help BrianHG and everyone else who has chipped in with info and suggestions.  It's all very much appreciated.  :-+

Once I'm happy with my HDL code additions (for the LED and audio output for testing), I'll update the github repo with the latest version of the project.

I'm waiting on some PS2 keyboard connectors - when they arrive, I can start on working on keyboard integration into the project.  That'll make my computer fully stand-alone, so it's a major milestone for me.  After that/while I'm waiting on the post, I'm starting to look into integrating an AY-3-8910 or YM2149 (old 80's sound chips) into the FPGA, somehow.  I have spare IO to drive a stereo output, it's just a case of adapting what little I can find out there to work on my EP4CE10.  I'm also giving some thought to how I'm going to give the Z80 access to an SD card via the FPGA too.

Oh, and of course continue working on the software side for the video output.  I'm tempted to start investigating the graphics modes on the FPGA/MAGGIEs and develop some graphics functions (PLOT, LINE, CIRCLE etc) in software - but I'm wondering if they could be done in hardware somehow, too?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 15, 2020, 02:34:00 pm
Congratulations!
I'm waiting on some PS2 keyboard connectors - when they arrive, I can start on working on keyboard integration into the project.  That'll make my computer fully stand-alone, so it's a major milestone for me.  After that/while I'm waiting on the post, I'm starting to look into integrating an AY-3-8910 or YM2149 (old 80's sound chips) into the FPGA, somehow.  I have spare IO to drive a stereo output, it's just a case of adapting what little I can find out there to work on my EP4CE10.  I'm also giving some thought to how I'm going to give the Z80 access to an SD card via the FPGA too.
If you have documentation describing how it works, I would just implement it inside FPGA too (sound chips of that era were very simple - just a bunch of various waveform generators and a mixer to mix them together), and add an I2S DAC to actually output sound. This will also open a possibility of outputting high-quality audio too (like waveform players, which present in some audio chips of that era or maybe a bit more recent), as all I2S DACs support at least 44.1 kHz/16bit format (this used to be called "CD quality" as that's the format used on audio CDs, of course they support lower bitrates too). I2S bus is also extremely pin-efficient, requiring only 3 pins (bit clock, left/right signal and a serial data line), and it doesn't require particularly high frequencies too (unless you want to output audiophool-grade signals at insane bitrates, even though most people would never hear the difference).

Also - have you considered placing it all on a single PCB once you ensure your prototype works?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2020, 03:14:52 pm
Congratulations!

Thanks asmi!  ;D

If you have documentation describing how it works, I would just implement it inside FPGA too

Yes, that's the idea.  Currently I'm using less than 50% of the logic and RAM in the EP4CE10, although I'll increase the number of MAGGIEs and RAM exposed to the host system shortly, I'm intending on keeping some spare space for the PS2 keyboard interface and whatever I can implement to make some noise.  Ideally, I'd like to emulate the AY-3-8910 (or YM2149 - same thing, basically) so that I won't have to change any of the chiptune software I have in CP/M (aside from port numbers in the 'driver').

(sound chips of that era were very simple - just a bunch of various waveform generators and a mixer to mix them together), and add an I2S DAC to actually output sound. This will also open a possibility of outputting high-quality audio too (like waveform players, which present in some audio chips of that era or maybe a bit more recent), as all I2S DACs support at least 44.1 kHz/16bit format (this used to be called "CD quality" as that's the format used on audio CDs, of course they support lower bitrates too). I2S bus is also extremely pin-efficient, requiring only 3 pins (bit clock, left/right signal and a serial data line), and it doesn't require particularly high frequencies too (unless you want to output audiophool-grade signals at insane bitrates, even though most people would never hear the difference).

I'm definitely no audiophool - in fact I'm pretty much tone deaf. ;)  Whilst the idea of CD-quality output is nice, it's not essential - I'm working with an 8-bit processor and am looking to recreate audio capabilities of its era, generally (though any improvement would be great; I'm obviously not too concerned about being period-accurate, otherwise I wouldn't be using an FPGA in the first place!)  ;)

Also - have you considered placing it all on a single PCB once you ensure your prototype works?

It'd be an expensive PCB and besides, I've made it to be as modular as possible.  What you see in the previous post is a stack of five cards, from bottom to top:
You can add another memory card to up the memory to 4 MB, add other interface/IO cards etc, but as a bare minimum you just need the power, cpu and memory card to have a working system and can expand it as you see fit.  In future I'll likely be adding more cards to the mix - different CPU's, for example - with a Motorola 68010 being a clear destination on my mental roadmap.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 15, 2020, 03:40:40 pm
Congratulations!

Too bad that over a few months gone to waste on an inverted reset input signal.  :palm:

At least the RS232 debugger wasn't tied into a reset and still functioned, otherwise with nothing working at all, who knows what you would have done with what would have been almost a totally dead FPGA...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 15, 2020, 03:52:28 pm
I'm definitely no audiophool - in fact I'm pretty much tone deaf. ;)  Whilst the idea of CD-quality output is nice, it's not essential - I'm working with an 8-bit processor and am looking to recreate audio capabilities of its era, generally (though any improvement would be great; I'm obviously not too concerned about being period-accurate, otherwise I wouldn't be using an FPGA in the first place!)  ;)
That's fine - you can work with 8 bit data internally, and upconvert data to 16 bits (or even to 24 bits) right before sending it off to DAC - basically you left-align the data by adding 0x00 to the right (equivalent to logical left-shift by 8 ). Since the I2S is a serial bus, it doesn't cost you any more pins and no FPGA resources because I2S protocol itself requires sending quite a bit of "nothingness" for padding purposes.

Come of think of it, I also wonder when (historically) DMA became a thing in computers, because playing waveforms off storage it real time is going to consume quite a bit of CPU time. My memory is rather fuzzy on that I was born in 84, so most of pre-IBM PC stuff went before I got into computers ::)

It'd be an expensive PCB and besides, I've made it to be as modular as possible.  What you see in the previous post is a stack of five cards, from bottom to top:
I just think that having a single board (or more sensible modularity a-la computer motherboard with main board and extensions as opposed to "sandwitch-style") looks better, but it may be just me ^-^
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2020, 04:33:23 pm
Congratulations!

Too bad that over a few months gone to waste on an inverted reset input signal.  :palm:

Thanks!  Yep, well, at least I'm not working to any kind of deadline.  It's just something I'm doing to pass the time, and it's certainly doing that!  ::) ;D  Funny how I instantly doubted my soldering and the hardware before checking the software more thoroughly.  Can't even remember why I was looking at the reset circuit and noticed the problem with the Z80's reset line.  :-//

At least the RS232 debugger wasn't tied into a reset and still functioned, otherwise with nothing working at all, who knows what you would have done with what would have been almost a totally dead FPGA...

Well, I was able to operate the speaker via IO port writes from the Z80, and read/write the GPU RAM, so I knew the FPGA wasn't totally dead, but I'd have ordered more FPGAs (from expensive but reputable sources), doubted my soldering skills even more and eventually given up, probably.  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2020, 04:46:03 pm
Come of think of it, I also wonder when (historically) DMA became a thing in computers, because playing waveforms off storage it real time is going to consume quite a bit of CPU time. My memory is rather fuzzy on that I was born in 84, so most of pre-IBM PC stuff went before I got into computers ::)

Oooh I won't be playing waveforms or anything like that - at least not in the way you're thinking.  Before DMA and IBM-style sound cards, in the realm of 8-bit computers in the early 80's, a dedicated sound chip was used and data sent to it on a byte-by-byte basis with instructions on volume, pitch, duration etc.  It was still CPU-intensive and I think the commands/data to the sound chip were usually updated during the blanking interval at the end of each frame (I'm no expert though, so don't quote me).

I just think that having a single board (or more sensible modularity a-la computer motherboard with main board and extensions as opposed to "sandwitch-style") looks better, but it may be just me ^-^

The decision to go the route I've gone with the stacking headers boiled down to some VERY early (and uninformed) decisions I made when moving from breadboard to PCB a year or two back.  When I started, I knew next to nothing about electronics, PCBs and all the essential skills you need to design and build this kind of project.  Stacking headers seemed the most cost-effective and easy way to get the project working, given my skills and knowledge with electronics at the time.  Now, however, being more experienced in everything from electronics to soldering to PCB design, I'll likely change the format completely when I move on to a 16-bit system for my next project, but that's still a long way off yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 15, 2020, 08:15:28 pm
Congratulations! I haven't participated in the thread, but I have followed. Great job!!!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 16, 2020, 12:25:03 am
@nockieboy, how's the DAC's quality?

     There was one thing about the data and clock feeding the DAC's digital inputs which I didn't consider when setting the output pins because of the slow 25MHz speed.

     If you see any pixel glitches, or, when you finally create a 'grey' ramp test pattern with each shade of grey being at least 4 pixels wide, if there are any fine vertical stripes between any 2 grey shade bars, inverting the DAC's CLK output pin will solve the problem.

     (This is due to driving the data lines and the CLK output both from D-flipflops outputs and we may be violating the setup&hold time for the DAC's digital inputs as all the transitions are right at the same time as the rising edge of the clock.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 16, 2020, 12:40:01 am
Oh, and of course continue working on the software side for the video output.  I'm tempted to start investigating the graphics modes on the FPGA/MAGGIEs and develop some graphics functions (PLOT, LINE, CIRCLE etc) in software - but I'm wondering if they could be done in hardware somehow, too?

Yes.  You would create a command port address where the Z80 can feed a small FIFO input which would have something like a 16-64 commands x 64 bits (16-64 commands x 8 word x 8bits each).  Something like a 8bit function, pen FG/BG color & fill color, start x,y, end x,y coordinates + a third set of x/y coordinates if you want to make a triangle filling engine.

On the other side of the command FIFO, you would have your sequencer which would read a 64 bit command from the fifo whenever it is not empty, you will loop the start and end coordinates in the drawing pattern & write to a free memory port since you have 15 read/write ports running at 25MHz.  This would sacrifice 1 maggie channel as it would become a hardware accelerated pixel plotting channel.

1 more memory channels will be needed if you want to accelerate copy & paste graphics memory.  Something like a software sprite, or accelerated graphical paintbrush or fonts.

Those 15 ports gives you some cool capabilities, not to mention that you can use this engine to feed the main Z80 port as well allowing a drawing engine which can fill up to 125 million pixels a second instead of 25 million pixels a second.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 09:03:31 am
@nockieboy, how's the DAC's quality?

     There was one thing about the data and clock feeding the DAC's digital inputs which I didn't consider when setting the output pins because of the slow 25MHz speed.

     If you see any pixel glitches, or, when you finally create a 'grey' ramp test pattern with each shade of grey being at least 4 pixels wide, if there are any fine vertical stripes between any 2 grey shade bars, inverting the DAC's CLK output pin will solve the problem.

     (This is due to driving the data lines and the CLK output both from D-flipflops outputs and we may be violating the setup&hold time for the DAC's digital inputs as all the transitions are right at the same time as the rising edge of the clock.)

Hmm.. well, I haven't noticed any graphical glitches or stripes as you've described - the image looks good.  As you point out, though, I haven't set up a greyscale pattern yet and I'm just going by what I can see on the image of the Z80 you created.

I've got some experimenting and learning to do now that I have a stable system to play with (the original prototype suffered greatly from all those wire connections between the uCOM and the level converters on a breadboard, then to the FPGA dev board itself - it was getting more miss than hit as time went by) - I need to refresh my memory on the various MAGGIE colour modes and get a greyscale test image set up.

Quick question - what did you use to create the image of the Z80 chip?  Is there some format option or settings I can use to save an image in a suitable format to dump into the GPU's RAM?


Oh, and of course continue working on the software side for the video output.  I'm tempted to start investigating the graphics modes on the FPGA/MAGGIEs and develop some graphics functions (PLOT, LINE, CIRCLE etc) in software - but I'm wondering if they could be done in hardware somehow, too?

Yes.  You would create a command port address where the Z80 can feed a small FIFO input which would have something like a 16-64 commands x 64 bits (16-64 commands x 8 word x 8bits each).  Something like a 8bit function, pen FG/BG color & fill color, start x,y, end x,y coordinates + a third set of x/y coordinates if you want to make a triangle filling engine.

Now this is where you're going to lose me very quickly again. :o  So the FIFO would be 16-64 commands deep with each command having space for up to 8 bytes?

On the other side of the command FIFO, you would have your sequencer which would read a 64 bit command from the fifo whenever it is not empty, you will loop the start and end coordinates in the drawing pattern & write to a free memory port since you have 15 read/write ports running at 25MHz.  This would sacrifice 1 maggie channel as it would become a hardware accelerated pixel plotting channel.

Okay, so 1 MAGGIE used for hardware accelerated pixel plotting, writing the output from the sequencer into RAM.

1 more memory channels will be needed if you want to accelerate copy & paste graphics memory.  Something like a software sprite, or accelerated graphical paintbrush or fonts.

A blitter (http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0119.html), basically?

Those 15 ports gives you some cool capabilities, not to mention that you can use this engine to feed the main Z80 port as well allowing a drawing engine which can fill up to 125 million pixels a second instead of 25 million pixels a second.

Okay, I feel I did pretty well up to this last sentence.  :o  Feed the main Z80 port? :-//  Even at 25 million pixels a second, isn't that a minimum framerate of over 80 fps at 640x480?  That isn't too shabby.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 11:31:14 am
Hmm.. think I have an issue with bit 1 of the green channel?

[attachimg=1]

Not a great picture, but there should be two more black squares to the left of the visible purple ones.  All should be shades of grey.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 16, 2020, 11:33:41 am
When I say fifo on a Z80 port, I mean a memory address you may choose which allows the Z80 to write to the fifo.
You would also provide a 'fifo' full flag for the Z80.

The fifo actually isn't necessary, but it will allow your Z80 to post multiple drawing commands while the other side of the fifo which seeds the sequencer pixel plotter is busy working plotting pixels.

As for the commands, I would prefer an 8 or 16 bit word system.  1 byte control, 1 byte data.
On your sequencer side (the thing which reads and follows the commands in the FIFO and draws the lines) , your commands would be something like:

set coordinate x1 high byte.
set coordinate x1 low byte.
set coordinate y1 high byte.
set coordinate y1 low byte.
set coordinate x2 high byte.
set coordinate x2 low byte.
set coordinate y2 high byte.
set coordinate y2 low byte.
set foreground color
set background color
set drawing color depth
set graphics destination ram coordinates high byte
set graphics destination ram coordinates low byte
set graphics raster width size
set graphics screen width limit
set graphics screen height limit
run line
run circle
run circle filled
run rectangle
run rectangle filled
run triangle
run triangle filled
run/stop/reset geometry engine (this 1 command may be on it's own dedicated port with immediate action regardless of the FIFO's state.)

That's already 24 commands.
For accelerated graphics, I would pre-compile your graphics generating list and feed the fifo in a straight manner.
I would also double buffer the geometry settings so you may draw new shapes while only updating only the required coordinate changes instead of re-filling all the settings every time.

As for the BW Z80 graphic I made, I loaded and cropped the image into Paint-Shop-Pro 6.
Then made it black and white.
Then saved it as a 'RAW' image data making it 8 bit per pixel, IE: 1 byte per pixel, no header in the file.
Then passed that 'RAW' file through my home-made basic program which can squeeze the image down to 4 bits, 2 bits or 1 bit.
(Obviously, for 8 bit, you don't need any conversion from the 'RAW' format.  Also, if you switch your palette to a MAC default 256 colored palette, using (PSE) Adobe Photoshop Elements 9, that paint software will generate an 8bit  256 color image matching the MAC palette so you may insert full color scan.  The MAC 256 color palette is pretty good for faces and most other photos as the Adobe Photoshop will dither the results to look like a few thousand colors.)

I've attached my bitplane converter.
Note that the 256 output mode actually divides the 256 gray shade image down to 16 shades of grey and places that image on palette color 16 through 32.  (This has nothing to do with the Photoshop true 256 full color image which doesn't need any processing, all you need for that it to adjust your palette to match Photoshop's Palette converter's settings)

Photoshop 24bit color to Paletted image converter: Go to 'Image / Mode / Indexed Color'.  You will also most likely try to google the file format it uses to load and save a palette to convert to you GPU palette generator.  Also, dont forget that your GPU can hold 2 different palettes simultaneously as well as sub 16/4/2 color chunks of both palettes selected for each MAGGIE window.

[attach=2]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 16, 2020, 11:47:17 am
Hmm.. think I have an issue with bit 1 of the green channel?

(Attachment Link)

Not a great picture, but there should be two more black squares to the left of the visible purple ones.  All should be shades of grey.
Check for short/adjacent short/open/dead IO pin.
Chick IO pin table.
Check palette data.

Remember, when using the 4444 palette, you can only have 4bits red,green,blue.
When using the 565 palette, you only have 5 bits red and blue, but only 6 bits green.
I don't remember how we wired the LSB bits in the code, but they may have been tied to the MSB bits to allow full contrast color.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 16, 2020, 12:31:32 pm
Okay, I feel I did pretty well up to this last sentence.  :o  Feed the main Z80 port? :-//  Even at 25 million pixels a second, isn't that a minimum framerate of over 80 fps at 640x480?  That isn't too shabby.

Ooopsie, I forgot you are using bitplanes.  This means to write a pixel, you must read it's data, modify only the bits you are interested in changing, then write that data out.  That is unless we implement the bit-for-bit write mask feature which is available in Intel's dual-port ram megafunction.

This will be up to you.  As for the Z80 port, just use the RS232 debugger channel and you can then write 75 million pixels a second, or around 25 million read-modify-write pixel drawing commands.  This way you will not use up any MAGGIE channels.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 12:52:27 pm
Ooopsie, I forgot you are using bitplanes.  This means to write a pixel, you must read it's data, modify only the bits you are interested in changing, then write that data out.  That is unless we implement the bit-for-bit write mask feature which is available in Intel's dual-port ram megafunction.

This will be up to you.  As for the Z80 port, just use the RS232 debugger channel and you can then write 75 million pixels a second, or around 25 million read-modify-write pixel drawing commands.  This way you will not use up any MAGGIE channels.

I have no idea what the benefits or drawbacks are of using either system, other than the bit-for-bit write mask feature sounds like it could speed things up a little, not that speed is an issue?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 16, 2020, 02:04:11 pm
When I say fifo on a Z80 port, I mean a memory address you may choose which allows the Z80 to write to the fifo.
You would also provide a 'fifo' full flag for the Z80.

The fifo actually isn't necessary, but it will allow your Z80 to post multiple drawing commands while the other side of the fifo which seeds the sequencer pixel plotter is busy working plotting pixels.

As for the commands, I would prefer an 8 or 16 bit word system.  1 byte control, 1 byte data.
On your sequencer side (the thing which reads and follows the commands in the FIFO and draws the lines) , your commands would be something like:
Maybe it would be better to do it "the modern way" (how modern video cards do it) - CPU can create however many "command lists" in video memory it wants/needs, and then there is a GPU register which specifies the address of the current command list, and the way it works is that video core only reads it's value once in the beginning of a frame and executes it to the end before it reads the register again. This way a list switchover is guaranteed to be consistent, CPU can take it's time to create a new command list asynchronously from video core, and a video core can also prefetch entire command list from video memory into some kind of queue to improve core's performance.

If you guys have some spare time for reading, I highly recommend to read this blog series about how modern video cards and Graphics API work: https://fgiesen.wordpress.com/2011/07/09/a-trip-through-the-graphics-pipeline-2011-index/ Even if it won't be directly applicable to this project, it's still a very interesting reading, and can give you some ideas for your own designs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 16, 2020, 03:33:29 pm
Maybe it would be better to do it "the modern way" (how modern video cards do it) - CPU can create however many "command lists" in video memory it wants/needs, and then there is a GPU register which specifies the address of the current command list,

     Until nockieboy adds DRAM to his GPU or goes to the 4megabit Lattice FPGA (preferably doing both simultaneously during the upgrade), I recommended a 1 to 2 kilobyte fifo since his GPU ram is very limited while his Z80 ram is huge.  It's just a strategy to minimize wasting the core graphics memory.  (With the Cyclone IV ram allocated as large as possible for the video core, there are a spare 2-4 kilobytes of ram which cannot be allocated as that 1 huge chunk, so, this additional fifo/graphics command buffer will end up in those and will actually have 0 penalty on the bulk graphics ram anyways.)

     When I say fifo, well it could just be a ram block with address pointer.  Or, this address pointer just feeds one of his 15 read ports.  With added 16 megabytes dram buffer, which would probably add another 7 MAGGIE ports + 1 Z80 R/W port, the fifo may be replaced with reading directly from one of those DRAM channels while the core memory MAGGIE channels will end up being used as sprite/texture data while the bulk DRAM will contain the full background graphics.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 04:27:15 pm
Maybe it would be better to do it "the modern way" (how modern video cards do it) - CPU can create however many "command lists" in video memory it wants/needs, and then there is a GPU register which specifies the address of the current command list,

     Until nockieboy adds DRAM to his GPU or goes to the 4megabit Lattice FPGA (preferably doing both simultaneously during the upgrade), I recommended a 1 to 2 kilobyte fifo since his GPU ram is very limited while his Z80 ram is huge.

I don't seem to be able to get a reasonably-priced Lattice dev board from anywhere - unless anyone here can point me in the direction of one around the £30 / $40 USD mark that I haven't been able to find?

But yes, the next step is to start looking at the Lattice chips and building a board with one of those on it.  In fact my success on my first attempt with this video card (delay finding the HDL bug aside) and asmi's blog (http://thingselectronic.blogspot.ca/) has almost inspired me to make the jump to BGA - I guess hot air-soldering one isn't impossible?  May as well add a DRAM while I'm at it.

It's just a strategy to minimize wasting the core graphics memory.  (With the Cyclone IV ram allocated as large as possible for the video core, there are a spare 2-4 kilobytes of ram which cannot be allocated as that 1 huge chunk, so, this additional fifo/graphics command buffer will end up in those and will actually have 0 penalty on the bulk graphics ram anyways.)

Yes, I'm making use of the RAM all the way up to 32KB now (leaving the 1KB for the palette at the top, still) - for some reason I've probably forgotten, NUM_WORDS was set to 24,575 (0x5FFF).  With 10 MAGGIEs, I'm at 74% of total logic elements.  The EP4CE10 has another 12KB or so, but I can't make use of it without messing with the RAM HDL and getting waaay out of my depth very quickly, so other uses for that RAM would be welcome.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 16, 2020, 04:36:59 pm
     Until nockieboy adds DRAM to his GPU or goes to the 4megabit Lattice FPGA (preferably doing both simultaneously during the upgrade), I recommended a 1 to 2 kilobyte fifo since his GPU ram is very limited while his Z80 ram is huge.  It's just a strategy to minimize wasting the core graphics memory.  (With the Cyclone IV ram allocated as large as possible for the video core, there are a spare 2-4 kilobytes of ram which cannot be allocated as that 1 huge chunk, so, this additional fifo/graphics command buffer will end up in those and will actually have 0 penalty on the bulk graphics ram anyways.)
The big advantage of using command lists is that it completely decouples GPU performance from CPU, allowing you to scale them independent of each other. And I don't think they will consume all that much memory, unless you're going to do something really insane like per-pixel drawing (which is always going to be much slower than using primitives).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on June 16, 2020, 04:39:21 pm
I don't seem to be able to get a reasonably-priced Lattice dev board from anywhere - unless anyone here can point me in the direction of one around the £30 / $40 USD mark that I haven't been able to find?

I suppose you're looking for some ECP5 dev board? You'll have a hard time finding one in this price range. The MachXO2/3 boards are around $25, but those FPGAs are probably largely "underpowered" for your requirements?

The official ECP5 eval board is $99.99. Certainly more expensive than your target price, but I couldn't find anything cheaper based on an ECP5. https://www.latticestore.com/products/tabid/417/categoryid/59/productid/122774/default.aspx (https://www.latticestore.com/products/tabid/417/categoryid/59/productid/122774/default.aspx)

There is this open-source project: https://gregdavill.github.io/OrangeCrab/ (https://gregdavill.github.io/OrangeCrab/)
but: very few IOs broken out, and no ready-made board that I know of.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 16, 2020, 04:46:11 pm
Yes, I'm making use of the RAM all the way up to 32KB now (leaving the 1KB for the palette at the top, still) - for some reason I've probably forgotten, NUM_WORDS was set to 24,575 (0x5FFF).  With 10 MAGGIEs, I'm at 74% of total logic elements.  The EP4CE10 has another 12KB or so, but I can't make use of it without messing with the RAM HDL and getting waaay out of my depth very quickly, so other uses for that RAM would be welcome.
You're making your own board, right? So what stops you from adding an SRAM/SDRAM chip on it, or HyperRAM chip if your IO pin budget doesn't allow for the former (HyperRAM only uses 12 IO pins and has 64Mbit capacity running up to 100 MHz DDR for 3V and 166 MHz for 1.8V version)? Of those, SRAM is the easiest to implement a controller for (it's literally "place address out, read out the data on the next cycle"), followed by HyperRAM (because it "looks" like PSRAM meaning refresh is taken care of internally, and protocol is very simple, though it has quite a bit of latency from initiating command until first byte out).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 04:55:40 pm
I suppose you're looking for some ECP5 dev board? You'll have a hard time finding one in this price range. The MachXO2/3 boards are around $25, but those FPGAs are probably largely "underpowered" for your requirements?

The official ECP5 eval board is $99.99. Certainly more expensive than your target price, but I couldn't find anything cheaper based on an ECP5. https://www.latticestore.com/products/tabid/417/categoryid/59/productid/122774/default.aspx (https://www.latticestore.com/products/tabid/417/categoryid/59/productid/122774/default.aspx)

Ah, that's okay then, I was just worried I was missing something somewhere.  Will have to wait a while to get one of those - I think trying to build a video card based on a Lattice FPGA may be a little fraught with problems, but then again I'm not sure what a dev board will do for me.  I've got the HDL, might need to tweak it some for the Lattice environment, all I need really is to get one onto a board so I can program it.

Is the toolchain similar to Altera's?

You're making your own board, right? So what stops you from adding an SRAM/SDRAM chip on it, or HyperRAM chip if your IO pin budget doesn't allow for the former (HyperRAM only uses 12 IO pins and has 64Mbit capacity running up to 100 MHz DDR for 3V and 166 MHz for 1.8V version)? Of those, SRAM is the easiest to implement a controller for (it's literally "place address out, read out the data on the next cycle"), followed by HyperRAM (because it "looks" like PSRAM meaning refresh is taken care of internally, and protocol is very simple, though it has quite a bit of latency from initiating command until first byte out).

Yes, have made my own board - pictured previously.  The biggest problem stopping me from adding SRAM/SDRAM is the lack of free IO.  I've got literally 4 IO pins left free - I can stretch that to 7 if I drop the SD card that I want to include.  This is one of the reasons I'm probably using this platform as a stepping stone to BGA, but I get panicky if I think about that too much at the moment.  :scared: ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on June 16, 2020, 05:04:02 pm
I suppose you're looking for some ECP5 dev board? You'll have a hard time finding one in this price range. The MachXO2/3 boards are around $25, but those FPGAs are probably largely "underpowered" for your requirements?

The official ECP5 eval board is $99.99. Certainly more expensive than your target price, but I couldn't find anything cheaper based on an ECP5. https://www.latticestore.com/products/tabid/417/categoryid/59/productid/122774/default.aspx (https://www.latticestore.com/products/tabid/417/categoryid/59/productid/122774/default.aspx)

Ah, that's okay then, I was just worried I was missing something somewhere.  Will have to wait a while to get one of those - I think trying to build a video card based on a Lattice FPGA may be a little fraught with problems, but then again I'm not sure what a dev board will do for me.  I've got the HDL, might need to tweak it some for the Lattice environment, all I need really is to get one onto a board so I can program it.

This basic dev board doesn't have SDRAM or DDR RAM so, that might be a problem for you (unless the amount of block RAM is sufficient.) There are other Lattice ECP5 dev boards, just take a look, one of them probably has that.

Is the toolchain similar to Altera's?

I have never really used Altera's tools much, so I can't really comment. But Lattice Diamond is reasonable and easy to use. I rather like it.
Speaking of Diamond, the ECP5 series is actually not supported by the free version, so you'll need an extra license. Lattice dev boards come with a free license (limited to the ECP5 model there is on the board IIRC), but if you don't buy a Lattice dev board, you'll probably have to buy a license. I have no clue about the current pricing. A few years back, it was $99/year, but it may have changed!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 16, 2020, 05:39:32 pm
This is one of the reasons I'm probably using this platform as a stepping stone to BGA, but I get panicky if I think about that too much at the moment.  :scared: ;D
You will come to that eventually, like I did, and so did many others. At least now you've successfully passed the first stage  - "who the f*ck needs so many pins???" - and started to understand exactly why having more pins is good, not bad ;)
Like I said a million times before, your best bet is to give it a try. Begin from the cheapest FPGA in BGA package you can find, design a simple breakout with nothing on it except the bare minimum required to program the chip + some LEDs. My very first FPGA board used the cheapest 7 series chip I could find (at the time it was A15), once I got that working, I felt much more at ease working with more expensive parts. Now I don't shy away from placing $100+ BGAs on my boards.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 16, 2020, 06:15:24 pm
BGA - I guess hot air-soldering one isn't impossible?

Sure is. The balls are made of solder, so all you need is a little bit of flux which you put on the board. Put it on and start heating. When it moves, pock it gently to make sure it's sitting well, count to 5, then remove the heat slowly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 06:41:58 pm
Speaking of Diamond, the ECP5 series is actually not supported by the free version, so you'll need an extra license. Lattice dev boards come with a free license (limited to the ECP5 model there is on the board IIRC), but if you don't buy a Lattice dev board, you'll probably have to buy a license. I have no clue about the current pricing. A few years back, it was $99/year, but it may have changed!

Ah, the licence may be a deal breaker for me. :'(  I'm not building this with making profits in mind, it's a personal project and having to pay a yearly fee so I can use an IDE to program FPGAs sort of flies in the face of my desire to keep this hobby as a hobby.

Mind you, if I'm looking to step up to BGAs, then the options open up further for other makes of FPGA as well.  I could just get an EP4CE10 (or upgrade slightly to the CE15 or beyond) in a BGA package and have access to lots more IO that will let me add an SDRAM etc.

So adding SDRAM would be a definite benefit then?

This is one of the reasons I'm probably using this platform as a stepping stone to BGA, but I get panicky if I think about that too much at the moment.  :scared: ;D
You will come to that eventually, like I did, and so did many others. At least now you've successfully passed the first stage  - "who the f*ck needs so many pins???" - and started to understand exactly why having more pins is good, not bad ;)

That is so true.  I had no idea about FPGAs before I started this thread - literally none at all - and now I'm struggling with the limited IO on my FPGA - and that's just interfacing it to an 8-bit microprocessor and VGA video output with a couple of extra addons (SD card, PS/2, LED, speaker).

I'm quite enjoying learning about them and using them, though.  Whilst a lot of these discussions about various components of the video driver are going over my head, I'm also learning so much and loving the versatility of FPGAs.  But now I'm feeling the need.... for moar IOs!  ;D

Like I said a million times before, your best bet is to give it a try. Begin from the cheapest FPGA in BGA package you can find, design a simple breakout with nothing on it except the bare minimum required to program the chip + some LEDs. My very first FPGA board used the cheapest 7 series chip I could find (at the time it was A15), once I got that working, I felt much more at ease working with more expensive parts. Now I don't shy away from placing $100+ BGAs on my boards.

I've spent a little time reading your blog today and I must say it's giving me a little confidence to go and try and make a BGA-based card.  I don't have a reflow oven like you, but I have a cheap hot air gun, lots of flux, some low-temp lead-free solder (now), and a desire to give it a try, so I think I'll take your advice and see what I can do.

Had a quick look for some BGA FPGA packages I could start out on - found this as the cheapest option:

LCMXO2 (https://www.mouser.co.uk/ProductDetail/Lattice/LCMXO2-256HC-4UMG64C?qs=aG4jnN2UxMUhCNE6rpggwg%3D%3D) - a Lattice MachXO2?  I'd rather stick with Intel/Altera as I'm familiar with the toolchain now, but the cheapest EPx FPGA I can find is over £15 for an EP4CE6 (https://www.mouser.co.uk/ProductDetail/Intel-Altera/EP4CE6U14I7N) from Mouser, or £18 for two EP4CE10F17s (https://www.aliexpress.com/item/32830183164.html?) from AliExpress.

Those EP4CE10F17s from AliExpress are 256-pin FineLine BGA packages... I've had a quick look to see what their dimensions are, looks like a 1mm pitch??  I'm guessing JLCPCB would be fine with that.

I'm also going to have to go to 4-layer PCB fab as well, I'm guessing?

BGA - I guess hot air-soldering one isn't impossible?

Sure is. The balls are made of solder, so all you need is a little bit of flux which you put on the board. Put it on and start heating. When it moves, pock it gently to make sure it's sitting well, count to 5, then remove the heat slowly.

Thanks NorthGuy.  :-+  I guess I just need to give it a go and build my confidence by doing it with smaller, cheaper packages first like asmi has suggested.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 16, 2020, 07:14:13 pm
Ah, the licence may be a deal breaker for me. :'(  I'm not building this with making profits in mind, it's a personal project and having to pay a yearly fee so I can use an IDE to program FPGAs sort of flies in the face of my desire to keep this hobby as a hobby.
That is one reason I've chosen Xilinx from the get go - they provide a lot of useful stuff for free, as well as give access to a lot of devices, including some really beefy ones like Artix-200 with 200k gates.

Mind you, if I'm looking to step up to BGAs, then the options open up further for other makes of FPGA as well.  I could just get an EP4CE10 (or upgrade slightly to the CE15 or beyond) in a BGA package and have access to lots more IO that will let me add an SDRAM etc.
One thing you need to note is that FPGA lines usually consist of several pin-compatible device subfamilies with different densities, so you can install larger device on your board if smaller isn't enough without board respin (or the other way around), if you designed your board to support the largest device is this pin-compatible subfamily from the get go (usually this means using DC-DC converters capable of providing enough current for the largest device). This is why you can take my Spartan-7 board and install any device in that package, and it will work. There are some gotchas with this approach, but in general it works just fine.

So adding SDRAM would be a definite benefit then?
Having something is always better than not having it :) But you still got to watch out to not run out of pins - BGAs do have more pins, but you will run out of them just as well ;D

I've spent a little time reading your blog today and I must say it's giving me a little confidence to go and try and make a BGA-based card.  I don't have a reflow oven like you, but I have a cheap hot air gun, lots of flux, some low-temp lead-free solder (now), and a desire to give it a try, so I think I'll take your advice and see what I can do.
Thanks, I wish I would have more time to post stuff there, I got a lot to say, but no time to actually write it up and prepare all related materials (like pictures and stuff).

Those EP4CE10F17s from AliExpress are 256-pin FineLine BGA packages... I've had a quick look to see what their dimensions are, looks like a 1mm pitch??  I'm guessing JLCPCB would be fine with that.
I would recommend you to be careful with those aliexpress chips, especially in the beginning as it's somewhat of a lottery and there is a chance to receive a dud. Imagine that you soldered your first BGA FPGA on, and it's not working. Why? Is it because you screwed something up in schematics, or it's a soldering failure (I'm yet to encounter one, but it is always a possibility), or your FPGA is a dud? How do you figure out which one it is?
This is why I'd suggest you to skip morning coffee for few days (or some beers for one Friday, since you're in UK ;D), and buy a known-good chip. At least this will all but eliminate one possibility. But be prepared for schematic/layout screw ups - it happens even to the best of us who should know better, and for me my first revision of any project almost never even gets to assembly, as I find some fatal flaw either while waiting for the boards to get manufactured and delivered, or during some basic testing of newly arrived boards.

I'm also going to have to go to 4-layer PCB fab as well, I'm guessing?
Yes, that would be a start. You can do quite a bit with 4 layer boards nowadays, with more and more manufacturers allowing for ever narrower traces without paying through the nose.

Thanks NorthGuy.  :-+  I guess I just need to give it a go and build my confidence by doing it with smaller, cheaper packages first like asmi has suggested.
If you don't mind working with older FPGAs, you can try getting your hands on some FBGAs with leaded solder balls instead of usual lead-free stuff. Yes, you can still find them even on Digikey, here is one example: https://www.digikey.com/products/en?keywords=XC6SLX25-2FT256I (https://www.digikey.com/products/en?keywords=XC6SLX25-2FT256I)
Also make sure you place your BGA devices far enough apart from other parts to make hot air gun assembly easier as you won't have to worry about blowing some nearby parts off board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 16, 2020, 07:16:56 pm
the cheapest EPx FPGA I can find is over £15 for an EP4CE6 (https://www.mouser.co.uk/ProductDetail/Intel-Altera/EP4CE6U14I7N) from Mouser, or £18 for two EP4CE10F17s (https://www.aliexpress.com/item/32830183164.html?) from AliExpress.

XC7S6-1FTGB196C is less than US $15 from Mouser.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 16, 2020, 07:50:14 pm
I would recommend you to be careful with those aliexpress chips, especially in the beginning as it's somewhat of a lottery and there is a chance to receive a dud. Imagine that you soldered your first BGA FPGA on, and it's not working. Why? Is it because you screwed something up in schematics, or it's a soldering failure (I'm yet to encounter one, but it is always a possibility), or your FPGA is a dud? How do you figure out which one it is?

Already been there with the current batch of EP4CE10 TQFP-144's I got from there.  Thing is, I intentionally got them from AliExpress knowing (or suspecting) that they may not be fully functional, but I did it because I needed practice soldering TQFP packages - I'd never done anything like that before, especially not with the exposed ground pad underneath.  Now I'm happy I can solder them reliably, the next batch I would get would be from somewhere like Mouser or Digikey.  So far, the success rate for the 3 FPGAs from AliExpress are 2 with a single dud IO, 1 working just fine.  But I'll update that once I get the third card fully built (though it's working fine so far).

This is why I'd suggest you to skip morning coffee for few days (or some beers for one Friday, since you're in UK ;D), and buy a known-good chip. At least this will all but eliminate one possibility. But be prepared for schematic/layout screw ups - it happens even to the best of us who should know better, and for me my first revision of any project almost never even gets to assembly, as I find some fatal flaw either while waiting for the boards to get manufactured and delivered, or during some basic testing of newly arrived boards.

Running my schematics and PCB design past you guys here seems to have ironed out most of the critical errors - the only issue I've found with the PCB so far is that I think I messed up the PS/2 socket wiring, but everything else is just fine.   :)

If you don't mind working with older FPGAs, you can try getting your hands on some FBGAs with leaded solder balls instead of usual lead-free stuff. Yes, you can still find them even on Digikey, here is one example: https://www.digikey.com/products/en?keywords=XC6SLX25-2FT256I (https://www.digikey.com/products/en?keywords=XC6SLX25-2FT256I)
Also make sure you place your BGA devices far enough apart from other parts to make hot air gun assembly easier as you won't have to worry about blowing some nearby parts off board.

So what are the issues with lead-free stuff?  Are all the newer BGA FPGAs with lead-free solder balls?  In theory (and from what I remember of your blog!!) then an ENIG finish on the PCB would give better soldering results if I have lead-free BGA balls?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 16, 2020, 08:17:54 pm
Already been there with the current batch of EP4CE10 TQFP-144's I got from there.  Thing is, I intentionally got them from AliExpress knowing (or suspecting) that they may not be fully functional, but I did it because I needed practice soldering TQFP packages - I'd never done anything like that before, especially not with the exposed ground pad underneath.  Now I'm happy I can solder them reliably, the next batch I would get would be from somewhere like Mouser or Digikey.  So far, the success rate for the 3 FPGAs from AliExpress are 2 with a single dud IO, 1 working just fine.  But I'll update that once I get the third card fully built (though it's working fine so far).
You're talking about logic, while I'm talking about perception. Your very first try would better be a success as it would provide insane morale boost, so even if you will see a failure down the road, it won't be that big of a deal.

Running my schematics and PCB design past you guys here seems to have ironed out most of the critical errors - the only issue I've found with the PCB so far is that I think I messed up the PS/2 socket wiring, but everything else is just fine.   :)
Unfortunately since I focus pretty much exclusively on Xilinx 7 series devices, I can't help much with other devices. That's why I was kind of nudging you towards these devices, as I know them fairly well so I can say something actually useful and helpful ::) Specialization has some bad sides as well as some good ones.

So what are the issues with lead-free stuff?  Are all the newer BGA FPGAs with lead-free solder balls?  In theory (and from what I remember of your blog!!) then an ENIG finish on the PCB would give better soldering results if I have lead-free BGA balls?
Most modern chips are lead-free. But to be honest, I tried pretty much all combinations (LF balls with leaded paste, LF balls/LF paste, HASL/HALFSL/ENIG), and all worked OK. I still recommend ENIG because it provides flat surfaces and protects pads for a long time from corrosion. ENIG is compatible with both leaded and LF solder, infact I'd argue leaded solder provides stronger bond.
The reason I suggested using BGA with leaded balls is because they melt at lower temperature, so it's easier to solder using hot-air gun (for ovens it doesn't matter at much).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 17, 2020, 10:46:01 am
You're talking about logic, while I'm talking about perception. Your very first try would better be a success as it would provide insane morale boost, so even if you will see a failure down the road, it won't be that big of a deal.

True, fair point.  Well, it seems if I want to practice on an FPGA that is in the same family as the Intel/Altera ones I've been using, I'm looking to spend about $12 each on BGA packages (obviously excluding PCB fab costs too).  I don't mind too much learning another toolchain (I actually have an unused Spartan FPGA board on a shelf and the programmer to go with it), so do you have any recommendations on a cheaper option I can practice with?

Most modern chips are lead-free. But to be honest, I tried pretty much all combinations (LF balls with leaded paste, LF balls/LF paste, HASL/HALFSL/ENIG), and all worked OK. I still recommend ENIG because it provides flat surfaces and protects pads for a long time from corrosion. ENIG is compatible with both leaded and LF solder, infact I'd argue leaded solder provides stronger bond.
The reason I suggested using BGA with leaded balls is because they melt at lower temperature, so it's easier to solder using hot-air gun (for ovens it doesn't matter at much).

Ah okay, I hadn't thought there'd be a difference in melting point, but that's logical.  Do you need additional solder (i.e. a solder mask) for BGAs, or can you just drop one onto a PCB (tacked in place with some sticky flux), and heat it up?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 17, 2020, 03:04:33 pm
True, fair point.  Well, it seems if I want to practice on an FPGA that is in the same family as the Intel/Altera ones I've been using, I'm looking to spend about $12 each on BGA packages (obviously excluding PCB fab costs too).  I don't mind too much learning another toolchain (I actually have an unused Spartan FPGA board on a shelf and the programmer to go with it), so do you have any recommendations on a cheaper option I can practice with?
Like I said, the only practical experience I have is with 7 series devices because quite frankly they cover pretty much entire range of my immediate and potential near-to-midterm needs, allowing designs from very simple glue logic at the small end all the way to 933 MHz DDR3 memory and 10+ Gpbs transceivers for pretty much any modern hi-speed interconnect I can think of from HDMI/DVI to PCI Express 3.0 and 10G Ethernet.
That said, if you want to practice BGA soldering (not necessarily FPGAs), buy a bunch of QSPI flash chips in BGA-24 package (for example this (https://www.digikey.ca/en/products/detail/cypress-semiconductor-corp/S25FL116K0XBHI030/4914896)), get an FTDI's 3.3V MPSSE cable (or any 3.3V microcontroller you have which has an SPI port available), design a small breakout (this chip can be broken out on regular 2 layer board), and get on with your practice! Once you solder the chip down, you can use SPI master device (be in an MCU, or MPSSE cable) to verify that soldering was a success and you can communicate with the chip.

Ah okay, I hadn't thought there'd be a difference in melting point, but that's logical.  Do you need additional solder (i.e. a solder mask) for BGAs, or can you just drop one onto a PCB (tacked in place with some sticky flux), and heat it up?
Solder and solder mask are two different things, the purpose of the latter is to prevent former from getting into places where it isn't supposed to go :)
If you use a hot air gun and ENIG (or any other flat) finish, you can go either way with or without additional paste on BGA pads, if using something like HASL, then you don't need to use solder paste as HASL already IS a solder :) With ENIG, advantage of soldering with solder paste on pads is that after soldering the device is sitting higher off board, which, for example, makes washing off remaining flux residue as well as small solder droplets (these quite often form in the oven) from under the package easier.
So I'd recommend sticking to ENIG, and not adding solder paste onto BGA pads before soldering unless you have a stencil and print solder onto entire board at once. Just add a good amount of tacky flux, and go for it. One thing - as flux heats up it loses viscosity and becomes more liquid, so if you put a bit too much of it, the part may shift a little (not a problem at all for reasonable pitch BGAs say 0.6+mm, but can be a big problem for microBGAs with <0.5mm pitch). As for package alignment - as you may or may not know, molten solder has very high surface tension (easy way to see it is to progressively add solder onto soldering iron tip - you will see that you can add A LOT before it drips, and the reason such big ball still hangs onto the tip is the surface tension), so BGAs tend to self-align if misalignment is less than half of the ball pitch, but if it's more, they can self-align into the wrong pads (off by 1), so you need to make sure misalignment doesn't exceed pitch/2 (again, this is typically not a problem for 1 and 0.8 mm pitch devices which you likely will be working with).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 17, 2020, 03:43:59 pm
Ah okay, I hadn't thought there'd be a difference in melting point, but that's logical.  Do you need additional solder (i.e. a solder mask) for BGAs, or can you just drop one onto a PCB (tacked in place with some sticky flux), and heat it up?

Since you do not have good control over placement when you do this manually, you're risking smashing the solder paste and perhaps short something inside (although a chance of this is not that big). Thus, it looks more reliable to me not to use any solder paste, only flux. This lets you move the FPGA freely and thus you can achieve better placement prior to heating.

When you don't use solder paste, it is more important to have a flat surface. I've never used anything but ENIG, so I cannot comment on other surfaces.

The amount of solder added by the solder paste is small compared to the amount of solder in the balls, so it doesn't affect the quality of the connection much, for prototyping anyway.

Don't use too much flux, or it may start bubbling and bubbles will start escaping from under FPGA lifiting it up which may screw up the alignment.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 17, 2020, 04:16:19 pm
That said, if you want to practice BGA soldering (not necessarily FPGAs), buy a bunch of QSPI flash chips in BGA-24 package (for example this (https://www.digikey.ca/en/products/detail/cypress-semiconductor-corp/S25FL116K0XBHI030/4914896)), get an FTDI's 3.3V MPSSE cable (or any 3.3V microcontroller you have which has an SPI port available), design a small breakout (this chip can be broken out on regular 2 layer board), and get on with your practice! Once you solder the chip down, you can use SPI master device (be in an MCU, or MPSSE cable) to verify that soldering was a success and you can communicate with the chip.

Righto, will take a look at those QSPIs, they sound like a good way to practice.  :-+

Ah okay, I hadn't thought there'd be a difference in melting point, but that's logical.  Do you need additional solder (i.e. a solder mask) for BGAs, or can you just drop one onto a PCB (tacked in place with some sticky flux), and heat it up?
Solder and solder mask are two different things, the purpose of the latter is to prevent former from getting into places where it isn't supposed to go :)

Well done, you spotted my deliberate mistake.  ;D  Of course I meant an SMT stencil.  ;)

If you use a hot air gun and ENIG (or any other flat) finish, you can go either way with or without additional paste on BGA pads, if using something like HASL, then you don't need to use solder paste as HASL already IS a solder :)

I've been using HASL all along so far - haven't really had enough there to solder anything to it without requiring additional solder, though.  I think I had one TSSOP pin actually tack down with no additional solder, but it needed some more before I was happy with the electrical connection.  I suppose what little is there would help a BGA ball to melt/attach, though.

With ENIG, advantage of soldering with solder paste on pads is that after soldering the device is sitting higher off board, which, for example, makes washing off remaining flux residue as well as small solder droplets (these quite often form in the oven) from under the package easier.
So I'd recommend sticking to ENIG, and not adding solder paste onto BGA pads before soldering unless you have a stencil and print solder onto entire board at once. Just add a good amount of tacky flux, and go for it. One thing - as flux heats up it loses viscosity and becomes more liquid, so if you put a bit too much of it, the part may shift a little (not a problem at all for reasonable pitch BGAs say 0.6+mm, but can be a big problem for microBGAs with <0.5mm pitch). As for package alignment - as you may or may not know, molten solder has very high surface tension (easy way to see it is to progressively add solder onto soldering iron tip - you will see that you can add A LOT before it drips, and the reason such big ball still hangs onto the tip is the surface tension), so BGAs tend to self-align if misalignment is less than half of the ball pitch, but if it's more, they can self-align into the wrong pads (off by 1), so you need to make sure misalignment doesn't exceed pitch/2 (again, this is typically not a problem for 1 and 0.8 mm pitch devices which you likely will be working with).

Yes, I'm intending to start with 1mm pitch BGAs.  Aware of the self-alignment due to surface tension - have found it very useful when soldering the 3225 oscillator to the video card. All sounds very promising - I'm eager to get started, now! :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 24, 2020, 02:43:49 pm
My second video board is up and running with 10 MAGGIEs currently, no dead IOs found so far, nice clean grey scale bar show all RGB outputs are working:

[attachimg=1]

The picture isn't great - my phone has a potato camera - but all 15 shades are visible (there's two blacks).  Working on the PS/2 interface now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 25, 2020, 01:39:14 pm
Okay, more of a general electronics question now.

I've noticed that the 1.2V regulator (AMS1117-1.2) is getting very hot - around 60 degrees Celsius (140 degrees Fahrenheit) which I'm attributing to that fact it's running from a 5V source rather than the amount of current being drawn by the FPGA (it's all running fine from a USB cable).

I've been working on a v.2 board design for a little while, incorporating improvements to the power routing (widening traces where possible) and so on and I've changed the power to the AMS1117-1.2 from 5V to the 3.3V source,  believing (rightly or wrongly - let me know!) that dropping from 3.3V to 1.2V should create less thermal load than from 5V.

Is that right?  Will I have other problems (not enough power in the 1.2V rail, for example) though if I do this?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: JagV12 on June 25, 2020, 01:55:27 pm
AMS1117 is a 'linear voltage regulator' which means that its power dissipation is (Vin - Vout)*Iin. So, the lower the input voltage, the better as long as drop out voltage is above 1.3V. This means the minimum input voltage should be 2.5V for a 1.2V regulator. 3.3V should then be OK
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 25, 2020, 02:17:03 pm
Or do it the proper way - replace linear regulator with switched-mode buck converter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 25, 2020, 04:33:09 pm
Or do it the proper way - replace linear regulator with switched-mode buck converter.
Right now, lowering the regulator's source to 3.3v will be borderline for your EP4CE10E22C8N.  If you spend the 1$ extra and go to the larger EP4CE15E22C8N (Yes, there is a 1 dollar price difference to get 50% more logic gates), you will need to go to the switched-mode buck converter as the larger core draws will draw more current as soon as you increase the 10 maggie layers in Quartus to 15 layers.

Make sure the regulator is set to 1.2v out.  Using it you default 1.3v causes an excessive amount of current draw from the Cyclone core.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 25, 2020, 04:54:30 pm
Right now, lowering the regulator's source to 3.3v will be borderline for your EP4CE10E22C8N.  If you spend the 1$ extra and go to the larger EP4CE15E22C8N (Yes, there is a 1 dollar price difference to get 50% more logic gates), you will need to go to the switched-mode buck converter as the larger core draws will draw more current as soon as you increase the 10 maggie layers in Quartus to 15 layers.

Hmm.. the only issue with the EP4CE15 is that it doesn't have the required IO pins for my project (it drops from 91 to 81 IO pins).  To use a more powerful FPGA I'll need to switch to a BGA package as we've been discussing recently, in which case I'm looking to go to the EP4CE22 which has an increase in RAM as well and will require a complete redesign of the PCB.  I'm in the initial stages of creating the schematic for it, but I'm all ears for suggestions on how to improve any aspect of the design, including the power supply.  So switch-mode buck converters on the 1.2V AND 2.5V?  Will I need to beef up the 3.3V supply too or is that just used for the IO?

Make sure the regulator is set to 1.2v out.  Using it you default 1.3v causes an excessive amount of current draw from the Cyclone core.

My first video card had the regulator set to 1.3V, but I've since changed it to 1.2V and the second video card is a straight 1.2V regulator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 25, 2020, 05:30:29 pm
Right now, lowering the regulator's source to 3.3v will be borderline for your EP4CE10E22C8N.  If you spend the 1$ extra and go to the larger EP4CE15E22C8N (Yes, there is a 1 dollar price difference to get 50% more logic gates), you will need to go to the switched-mode buck converter as the larger core draws will draw more current as soon as you increase the 10 maggie layers in Quartus to 15 layers.
The thing to watch out for with bucks is Vout ripple. I skimmed through Cyclone IV datasheet but couldn't find any specs for it. For reference Spartan-7/Artix-7 have requirement of <50 mVpp @20MHz BW, which is very generous and is rather easy to achieve with multiple MLCC caps at the output. Most modern-ish buck ICs are designed to work with MLCCs (which are unique due to their ultra-low ESR), but some older devices will be unstable.
As for specific devices, my favorite low-ish current buck is TLV62130, which accepts up to 17 V (so I can use 9-12-15 V walwarts, which I'm sure we all accumulated aplienty of from all kinds of electronic devices bought over years), is fairly cheap and can output up to 3 A of current. Right now I'm evaluating AOZ2151 IC, which accepts up to 28 V (so I can use up to 20 V rail coming from USB-C PD directly), provides up to 4 A of current, and is more precise (1.5% over PVT vs 2.5% for TLV62130), while still being cheap. Both are available in QFN-ish packages, and so ground plane can be used as heatsink (super important when you have several such devices close by, as they collectively can generate quite a bit of heat).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 25, 2020, 06:31:23 pm
The thing to watch out for with bucks is Vout ripple. I skimmed through Cyclone IV datasheet but couldn't find any specs for it. For reference Spartan-7/Artix-7 have requirement of <50 mVpp @20MHz BW, which is very generous and is rather easy to achieve with multiple MLCC caps at the output. Most modern-ish buck ICs are designed to work with MLCCs (which are unique due to their ultra-low ESR), but some older devices will be unstable.
As for specific devices, my favorite low-ish current buck is TLV62130, which accepts up to 17 V (so I can use 9-12-15 V walwarts, which I'm sure we all accumulated aplienty of from all kinds of electronic devices bought over years), is fairly cheap and can output up to 3 A of current. Right now I'm evaluating AOZ2151 IC, which accepts up to 28 V (so I can use up to 20 V rail coming from USB-C PD directly), provides up to 4 A of current, and is more precise (1.5% over PVT vs 2.5% for TLV62130), while still being cheap. Both are available in QFN-ish packages, and so ground plane can be used as heatsink (super important when you have several such devices close by, as they collectively can generate quite a bit of heat).

Okay, so it looks like I'm going to have to review my power supply if I'm going to go to a larger BGA FPGA.

My system has a 5V primary power rail powering everything, which is sourced from either the USB cable providing the serial connection with my desktop PC or a wall-wart DC input via a 7805.  An AMS1117 provides the 3.3V rail from the 5V supply.  The system as a whole currently pulls about 0.04A according to an imprecise USB voltage measuring tool I've just tried on it.

I based the FPGA design on a schematic for the dev board I was using to prototype the video card - so the power rails are identical to the ones in my dev board.  I've hunted down a schematic for a dev board using the EP4CE22F17 as well (the DE0-Nano (https://wiki.ntb.ch/infoportal/_media/fpga/boards/de0_nano/de0-nano-schematic.pdf)) and was intending to use that as a reference when designing the supporting circuits and power supplies.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 25, 2020, 07:10:47 pm
I based the FPGA design on a schematic for the dev board I was using to prototype the video card - so the power rails are identical to the ones in my dev board.  I've hunted down a schematic for a dev board using the EP4CE22F17 as well (the DE0-Nano (https://wiki.ntb.ch/infoportal/_media/fpga/boards/de0_nano/de0-nano-schematic.pdf)) and was intending to use that as a reference when designing the supporting circuits and power supplies.
That schematics has 1.5 A LDO for the Vccint rail :palm:
See attachment for the schematic of the buck that you need (taken straight out of device datasheet). As you can see, there are only 3 extra components compared to typical LDO implementation - one 3.3 nF cap to set up soft start (can be omitted if you don't particularly care about slowing down startup), 100K resistor for "power good" signal (again optional, can leave unconnected if you aren't going to use this signal) and inductor, so really only inductor is mandatory. Everything else (input/output caps, Vout setting resistor divider) is the same for buck and LDO. This circuit will give you 90+% efficiency almost across entire range output current when powered by 5 V, and so it probably won't be even warm at full 3 A current.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 25, 2020, 07:28:08 pm
If you are going BGA, maybe taking a look at the Lattice 15$ fpga with 2 megabits ram may be useful.

I would also add 2x of the 'S70KS1281DPBHV020' 16 megabyte ram chips, each on their own 10/11 wire buss while only sharing their differential PLL clock outputs.  This would allow 2 separate banks of operation.  Though, you will need to wire 1 IO bank at 1.8v to get the full 250MHz speed of your core PLL clock.

At 2.15$ a chip, not as cheap as strict DDR ram, but it has a built in ram controller.  And Maggie can only address 16 megabytes anyways, maybe 32 megabytes with some modding.

Unfortunately, the good price of the 'S70KS1281DPBHV020'  is like that because it is being discontinued.  You need to go with the smaller 8 megabyte newer 'S27KS0642GABHI030' at 4.35$.  You need to wire 2 of them on 1 bus with separate CS# to match the S70K....  But in this configuration, during the 'additional latency', if setup properly, you can run 2 of these in a dual bank mode.

These are normal DDR2 rams and are much more available and cheaper per MB, but you need a DDR2 controller:
W9725G6KB-25
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 25, 2020, 10:37:12 pm
Look at what I found, DIY reballing.  You will need a dummy stencil for reballing, solder paste & a hot air gun, bu here is someone doing it: (Begins at 5:45) (IE, you can now remove and re-position/mount a failed mounted BGA IC again and again.)

https://www.youtube.com/watch?v=8a5Uvj5ibWI (https://www.youtube.com/watch?v=8a5Uvj5ibWI)

Since these stencils are cheap, then it is worth it if you have everything else:
Reballing Stencil (https://www.aliexpress.com/item/32555671822.html?spm=a2g0o.detail.1000060.1.37305c742Pcq9y&gps-id=pcDetailBottomMoreThisSeller&scm=1007.13339.146401.0&scm_id=1007.13339.146401.0&scm-url=1007.13339.146401.0&pvid=e89234c4-c868-4b53-a821-f3f8ee687201&_t=gps-id:pcDetailBottomMoreThisSeller,scm-url:1007.13339.146401.0,pvid:e89234c4-c868-4b53-a821-f3f8ee687201,tpp_buckets:668%230%23177981%235_668%23808%233772%23903_668%23888%233325%231_668%232846%238114%23773_668%232717%237560%23281_668%233164%239976%23623)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 26, 2020, 01:27:49 am
Look at what I found, DIY reballing.  You will need a dummy stencil for reballing, solder paste & a hot air gun, bu here is someone doing it: (Begins at 5:45) (IE, you can now remove and re-position/mount a failed mounted BGA IC again and again.)
I've been working with BGAs for over 3 years now, and I have never had a soldering issue, and so never had to reball anything. But I only use chips purchased via official channels, so I'm not sure how things would go if I were to buy them off aliexpress et al.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 26, 2020, 02:06:54 am
If you are going BGA, maybe taking a look at the Lattice 15$ fpga with 2 megabits ram may be useful.
Lattice devices suck in a sense that they usually come in small pitch packages. And zero free IPs - you're on your own. If he changes vendor, he might as well go Xilinx as they are the best anyways.

I would also add 2x of the 'S70KS1281DPBHV020' 16 megabyte ram chips, each on their own 10/11 wire buss while only sharing their differential PLL clock outputs.  This would allow 2 separate banks of operation.  Though, you will need to wire 1 IO bank at 1.8v to get the full 250MHz speed of your core PLL clock.

Unfortunately, the good price of the 'S70KS1281DPBHV020'  is like that because it is being discontinued.  You need to go with the smaller 8 megabyte newer 'S27KS0642GABHI030' at 4.35$.  You need to wire 2 of them on 1 bus with separate CS# to match the S70K....  But in this configuration, during the 'additional latency', if setup properly, you can run 2 of these in a dual bank mode.
You need to use 1.8 V Vccio and differential clock to get 166 MHz (or 200 MHz on newest HyperRAM 2 devices), at 3 V they only go up to 100 MHz. But the interface is DDR, so you get two transfers per clock. One thing that suck abouts them (aside from smallish capacity of only 8 Mbytes per die) is the latency is rather high, especially for dual-die ones (S70 series), so you will need to make sure your application takes advantage of their long burst ability in order to amortize initial latency. I actually have a simple FPGA devboard with a couple of these memory chips in parallel (this was my very first Xilinx FPGA devboard BTW!), and I found that single-die devices can work with singular latency most of the time, which is good if your access pattern is more random and you don't want to completely pipeline memory access for double-latency. Cool thing about using static double-latency though is that it allows to easily place multiple memory devices in parallel and get double (or more) bandwidth this way.

These are normal DDR2 rams and are much more available and cheaper per MB, but you need a DDR2 controller:
W9725G6KB-25
Again, the question here is of tradeoff between simplicity, capacity and bandwidth. If you need capacity and bandwidth, you need to use DDR3(L) memory because they provide highest capacity and bandwidth for price (MT41J128M16JT-125 is about 4.5$ and has capacity of 256 MBytes with 16bit data bus running up to 800 MHz!).
If he only needs like 1 Mbytes or less, I'd use regular SRAM as it's the simplest solution in terms of controller implementation, as well as it provides the smallest latency possible, so it's the best for truly random access.
As a middle ground, I would recommend looking at SDRAM or LPDDR1 modules - they provide between 16 and 256 MBytes of capacity, while still having rather small access latency. Also - Micron provides free simulation models for all of it's memory modules (from SDRAM all the way to DDR4), so designing controller is much easier because you can actually run full end-to-end simulations to check that controller works like it should. And these models are provides in full source code, so you can figure out some finer points in modules functionality in case datasheet is unclear on something.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 26, 2020, 09:06:55 am
Look at what I found, DIY reballing.  You will need a dummy stencil for reballing, solder paste & a hot air gun, bu here is someone doing it: (Begins at 5:45) (IE, you can now remove and re-position/mount a failed mounted BGA IC again and again.)

Good find.  :-+  That makes me more confident in giving it a try - if I do mess up for whatever reason, it isn't a complete lost cause and I could recover the BGA to try again. Nice.  :)

If you are going BGA, maybe taking a look at the Lattice 15$ fpga with 2 megabits ram may be useful.

I seem to recall us talking about the Lattice recently and discovering there could be licensing issues?  $99 a year for the IDE is beyond my meagre hobby budget.  If we're going the route of external RAM though, the internal RAM (or lack of) won't be an issue.

I would also add 2x of the 'S70KS1281DPBHV020' 16 megabyte ram chips, each on their own 10/11 wire buss while only sharing their differential PLL clock outputs.  This would allow 2 separate banks of operation.  Though, you will need to wire 1 IO bank at 1.8v to get the full 250MHz speed of your core PLL clock.

At 2.15$ a chip, not as cheap as strict DDR ram, but it has a built in ram controller.  And Maggie can only address 16 megabytes anyways, maybe 32 megabytes with some modding.

Unfortunately, the good price of the 'S70KS1281DPBHV020'  is like that because it is being discontinued.  You need to go with the smaller 8 megabyte newer 'S27KS0642GABHI030' at 4.35$.  You need to wire 2 of them on 1 bus with separate CS# to match the S70K....  But in this configuration, during the 'additional latency', if setup properly, you can run 2 of these in a dual bank mode.

These are normal DDR2 rams and are much more available and cheaper per MB, but you need a DDR2 controller:
W9725G6KB-25

Okay, well moving to BGA does mean I can add some external memory which is a big bonus (even if it's just SDRAM) - I'm assuming then that all the video RAM could be moved out to the external memory and there'd no longer be an issue with the limited size of RAM inside the FPGA?  Didn't you mention there'd be speed issues / complexity in the interface previously?

Remember that I don't need masses of RAM.  I'd be perfectly happy with 512 KB to fill the hole in the system memory that the FPGA creates, but I understand that with extra MBs I could get higher screen resolutions?  There's also the potential to build the MMU into the FPGA and remove the need for a memory card in my system altogether - all the system RAM could be hosted on the FPGA card.

The other proviso with all this is that I haven't a clue what I'm doing.  I've gotten this far on the goodwill of this forum and masses of support from BrianHG, but this next step to BGA and using external SDRAM/DDR/whatever seems like a pretty big step for me (though I'm sure it's dead easy for you guys experienced with this stuff) and I'd need guidance and instruction to get it right (esp. with the HDL).  I don't want to make a nuisance of myself.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 26, 2020, 02:30:44 pm
DRAM consists of two-dimensional arrays of very small capacitors. The capacitors are feeble, and need lots of special care.

Reading is done one row at a time. The row is read from the matrix into a buffer. The capacitors are so small that the read destroys the charges and memory is lost. Therefore, it is necessary to write the buffer back, even if its content doesn't change. The reading process is called "Activation". Write back is called "Precharge".

Now imagine you want to read something, but a different row is activated. This row now has to be precharged, new row activated and then your read performed. This produces substantial latency. So, truly random access is not very fast.

Worse yet, the capacitors lose charge over time. The content of a capacitor survives only tens of ms. Therefore, you must activate every row and discharge it every so often, or you'll lose the memory. This is called "Refresh". The memory chip may keep track of refreshes and maintain the counter which row must be refreshed next, so you only need to sent it a refresh commands every so often and it will refresh a rows at a time. The chip automatically cycles through all the rows making sure all are refreshed. With others, you may need to supply the address of the row being refreshed. If you suddenly decide to read something during refresh, your latency suffers - you now need to want until the end of refresh, then activate your row, then read. If you activate each and every row regularly (as may be the case with video buffer), you do not need refreshes.

The memory consists of one or more banks, each with its own memory array and IO buffer, all connected in parallel. You need to select which bank you read/write, but the operations which do not need IO (such as activations, precharges, and refreshes) can be done by every bank independently. Your controller must take care of every bank. All this requires certain complexity in the controller. Your choice is to either use a stock controller or write your own which is designed specifically for video buffer.

Or, you can take SRAM, which doesn't require any of that and has fixed latency (around 10 ns). The problem is it's many times more expensive than DRAM.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 26, 2020, 04:33:58 pm
Okay, well moving to BGA does mean I can add some external memory which is a big bonus (even if it's just SDRAM) - I'm assuming then that all the video RAM could be moved out to the external memory and there'd no longer be an issue with the limited size of RAM inside the FPGA?  Didn't you mention there'd be speed issues / complexity in the interface previously?

Remember that I don't need masses of RAM.  I'd be perfectly happy with 512 KB to fill the hole in the system memory that the FPGA creates, but I understand that with extra MBs I could get higher screen resolutions?  There's also the potential to build the MMU into the FPGA and remove the need for a memory card in my system altogether - all the system RAM could be hosted on the FPGA card.

The other proviso with all this is that I haven't a clue what I'm doing.  I've gotten this far on the goodwill of this forum and masses of support from BrianHG, but this next step to BGA and using external SDRAM/DDR/whatever seems like a pretty big step for me (though I'm sure it's dead easy for you guys experienced with this stuff) and I'd need guidance and instruction to get it right (esp. with the HDL).  I don't want to make a nuisance of myself.

8 or 16 bit SDRAM and DDR1/2/3 Ram will be too slow for the MAGGIE system other than having 1-2 dumber linear MAGGIE background graphics layers.  All tile/font/sprite images will need to be stored in the FPGA + you will need an extra 1-2kb FPGA cache to stream the DRAM video.

To replace the core and storing everything in DRAM, you would need 1GHz 32bit DDR3 controller which is beyond the CycloneIV.  You would also have to use all of the core ram to create a smart read ahead cache since DDR ram reads bytes in bursts where you need only single bytes from.  The development cycle to accomplish this is beyond our time and scope.

Hence, with the DDR ram, you will only get 2 raster MAGGIE layers which may pass raster video through, or each feed 1 of the 15 core MAGGIE layers to address tiles/fonts/sprites stored in the core ram.  The other 50% access time of the DDR ram will be for the Z80 and pixel drawing engine.

Now, I say 16 megabytes since the address pointer in the MAGGIE is currently 24 bits, ie 16 megabyte pointer.  I do not know about the Z80 paging capabilities, but, if you are limited to 512kb, including graphics memory, there are other smaller 512kb static rams which are still 2-4$, but have much faster row access times which may have less of a driver interface issue and a smaller ras/cas penalties and no sequential burst requirements.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 26, 2020, 04:54:34 pm
8 or 16 bit SDRAM and DDR1/2/3 Ram will be too slow for the MAGGIE system other than having 1-2 dumber linear MAGGIE background graphics layers.  All tile/font/sprite images will need to be stored in the FPGA + you will need an extra 1-2kb FPGA cache to stream the DRAM video.

To replace the core and storing everything in DRAM, you would need 1GHz 32bit DDR3 controller which is beyond the CycloneIV.  You would also have to use all of the core ram to create a smart read ahead cache since DDR ram reads bytes in bursts where you need only single bytes from.  The development cycle to accomplish this is beyond our time and scope.
You've got to be kidding! 16 bit DDR3 even running at 400 MHz gives you enough bandwidth to stream and double-buffer (meaning you read and write in parallel) a 1080p/32bpp/60Hz video stream in real time with some bandwidth to spare! And this video card has a resolution of what? 640x480/8bpp/60Hz? You should be able to push at least 50 these streams in parallel with no problems whatsoever!

But if you for some bizzare reason need more, what stops you from implementing wider bus, up to 64bit SODIMM?

Something doesn't sound right here.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 26, 2020, 06:05:16 pm
8 or 16 bit SDRAM and DDR1/2/3 Ram will be too slow for the MAGGIE system other than having 1-2 dumber linear MAGGIE background graphics layers.  All tile/font/sprite images will need to be stored in the FPGA + you will need an extra 1-2kb FPGA cache to stream the DRAM video.

To replace the core and storing everything in DRAM, you would need 1GHz 32bit DDR3 controller which is beyond the CycloneIV.  You would also have to use all of the core ram to create a smart read ahead cache since DDR ram reads bytes in bursts where you need only single bytes from.  The development cycle to accomplish this is beyond our time and scope.
You've got to be kidding! 16 bit DDR3 running at 400 MHz gives you enough bandwidth to stream and double-buffer (meaning you read and write in parallel) a 1080p/32bpp/60Hz video stream in real time with some bandwidth to spare! And this video card has a resolution of what? 640x480/8bpp/60Hz? You should be able to push at least 50 these streams in parallel with no problems whatsoever!

But if you for some bizzare reason need more, what stops you from implementing wider bus, up to 64bit SODIMM?

Something doesn't sound right here.
Your figures are correct for 'bandwidth to stream' IE sequential burst-efficient access, 2 pictures simultaneously...

   You haven't followed the project, the MAGGIE system has 16 translucent video window layers (16 pictures), 16 bits each, at 25 million pixels a second.  HOWEVER, each MAGGIE layer can tell the next adjacent MAGGIE layer to address individual 16 bit pixels from anywhere else in ram on a pixel/pixel basis, no sequential multiple pixel reads, hence the realtime pixel zooming and skipping feature.

   All this means is that exactly like a said, running a single 125MHz or 250MHz DDR2/3 ram chip at 16 bits.  Since you cannot address single bytes/words and have those redirect to a point elsewhere in ram without waiting for a ras/cas/4-8 clk burst/terminate cycle, all being said and done, an over 35ns turnaround for each random byte access, you cannot achieve the 25MHz pixel speed * 15 pixels which sit on-top of each pixel, each which may randomly point to anywhere else in ram for an associated font/tile which can be also 16bits/pixel or pointer to another font/tile.

   However, just having 2 sequential 16bit/pixel raster layers with a small pixel cache is doable with a simple ram controller, + having another graphics geometry engine random read/write access port plus another port with 0 (ZERO) wait state at Z80 speed weaved in will be feasible with some simple HDL code.

Squeezing out the Drams approximate full 750MB/sec is doable with 16 random access ports, only half of them somewhat sequential can be done, all read ahead in time to generate each 16 layer finished pixel, however I want nockieboy to be able to finish the project.

Now, if 512kb is a limit on the Z80, maybe nockieboy should consider ZBT-SRAM.  It has access exactly like a static ram chip, but when swapping from reading to writing and back, the ram chip will have 0 wait states, or Zero Bus Turnaround.  A 250Mhz ZBT sram, 256K x 18bit (512 kilobytes).  The ram controller HDL code is non-existent other than a latch and IO pins set to the tightest timing tolerances.  Now the memory density is less, but it will perform almost identical to a core signle-port ram operating at 250MHz and 0 coding experience is needed.

For some reason, the 256kx18bit 200MHz is a cheap sweet spot for ZBT ram at 2$ each (maybe obsolete).
ZBT 250Mhz = $8.40.
Sync SRAM 250MHz = $5.53.  I need to read more on this as the interface is a little more complex as the first read/write can take 2 cycles.


I would say if the Z80 can access more than 2 megabytes, go for a single 16bit ddr ram chip.  If it can only access 512kb, a more expensive but more HDL friendly solution would be the ZBT ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 26, 2020, 07:54:13 pm
Now, if 512kb is a limit on the Z80, maybe nockieboy should consider ZBT-SRAM.  It has access exactly like a static ram chip, but when swapping from reading to writing and back, the ram chip will have 0 wait states, or Zero Bus Turnaround.

Aren't all asynchronous SRAM chips like that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 26, 2020, 08:12:26 pm
I would say if the Z80 can access more than 2 megabytes, go for a single 16bit ddr ram chip.  If it can only access 512kb, a more expensive but more HDL friendly solution would be the ZBT ram.

My Z80 system can address 4 MB of memory (in 16 KB banks) with the current MMU I have.  As luck would have it, that equates to 8 sockets on two memory PCBs (with each taking up to a maximum 512 KB chip).  The second PCB is optional, so with one PCB you've got 2 MB.  For sheer ease of interfacing the FPGA to the Z80's memory space, it inserts its core memory into the 512 KB 'window' that the 3rd socket would otherwise occupy (the first having to be RAM and the fourth needing to be the ROM OS).  So if I have a video card on the system, the 3rd memory socket has to be empty.  Currently, in place of the 512 KB of memory that could have been a chip in the 3rd socket, instead it is the 32 KB of core RAM the FPGA makes accessible to the Z80.

[attachimg=1]

There's nothing stopping me using a 16 MB chip on the video card and allowing the FPGA to handle memory management and give the Z80 access to all of that RAM.  I've just been talking about 512 KB not as a hard limit, but merely to make up the 512 KB that could have been in the 3rd socket instead of the FPGA.  All RAM on the system is SRAM and I've got no objection to using SRAM on the FPGA instead of DRAM, considering its benefits with this design's random memory access characteristics.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 26, 2020, 09:12:41 pm
There's nothing stopping me using a 16 MB chip on the video card and allowing the FPGA to handle memory management and give the Z80 access to all of that RAM.  I've just been talking about 512 KB not as a hard limit, but merely to make up the 512 KB that could have been in the 3rd socket instead of the FPGA.  All RAM on the system is SRAM and I've got no objection to using SRAM on the FPGA instead of DRAM, considering its benefits with this design's random memory access characteristics.

16MB SRAM would be more expensive. The cheapest I can see on DigiKey (2 x 64Mb chips) is $40. That is compared to $2 for a DRAM chip.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 26, 2020, 09:35:04 pm
Now, if 512kb is a limit on the Z80, maybe nockieboy should consider ZBT-SRAM.  It has access exactly like a static ram chip, but when swapping from reading to writing and back, the ram chip will have 0 wait states, or Zero Bus Turnaround.

Aren't all asynchronous SRAM chips like that?
SRAM and Synchronous SRAM are 2 different things.  Pure SRAM, IE no clock interface, comes in a number of sizes and speeds, like 70ns, 35ns, 15ns... As the speed goes up, the price and size increases.

The Synchronous SRAM comes in 2 variants, the normal and ZBT.  These rams have a clock and cleanly latch the address and data on the rising edge, or for the data, on both clock edges for the DDR variant.  The advantage of the Synchronous types is clocks up to 250 MHz for SDR, 400MHz DDR (800MHz data), and a cheaper price or larger size.  The non ZBT variant relies on 1 additional clock cycle when switching from a read to a write as the latched 'Write Enable' control which is clocked requires that 1 additional clock for the data line drivers to switch direction.

(Now we are talking only 1 chip, 512 kilobytes, his Z80's memory window size.  If nockieboy wants more ram, he'll go with DDR Ram)

Example:
https://www.rocelec.com/part/IDTIDT71V3558S200PFG?utm_medium=buyNow&utm_source=findChips (https://www.rocelec.com/part/IDTIDT71V3558S200PFG?utm_medium=buyNow&utm_source=findChips)
200MHz sync ZBT SRAM - 71V3558S200 datasheet - https://www.idt.com/document/dst/71v3556-58ssa-data-sheet (https://www.idt.com/document/dst/71v3556-58ssa-data-sheet)
(This one operates identically to a Quartus Memory IP block, but, external as it has a fixed pipeline delay of 2.  Since writes are also on a delayed pipeline of 2, there is no turn-around time for switching between write and read on the command input as 2 clocks later, you would have the IO direction swap & write data ready to go inside the FPGA.)

https://www.arrow.com/en/products/is61nlp25618a-200tqli/integrated-silicon-solution-inc?utm_term=backorder&utm_campaign=arrow_findchips_2019&utm_currency=&utm_medium=aggregator&utm_source=findchips&utm_content=inv_listing (https://www.arrow.com/en/products/is61nlp25618a-200tqli/integrated-silicon-solution-inc?utm_term=backorder&utm_campaign=arrow_findchips_2019&utm_currency=&utm_medium=aggregator&utm_source=findchips&utm_content=inv_listing)
200MHz sync SRAM - IS61NLP25618A-200TQLI datasheet http://www.issi.com/WW/pdf/61-64LPS_VPS12832EC-12836EC-25618EC.pdf (http://www.issi.com/WW/pdf/61-64LPS_VPS12832EC-12836EC-25618EC.pdf)
(This one when sending a write, the write data is taken immediately.  But when reading, the read comes in on the next clock.  So, when switching from the previous read, then going to a write, you need to wait that additional clock for the last read to be returned to you before swapping the IO direction to make an immediate write.  ZBT type sram doesn't have this issue and is easy-peasy to interface with as yo never need to add that 1 clock delay/pause.)

Normal SRAM, well, $1.20 for 256Kx16/18, but, 10ns access time.  And there are still write penalties in the timing diagrams as some models have a 15-20ns write cycle time while still claiming 10ns access.  You would want the 10 write cycle, 10ns access version for full 100MHz support.
(This one is simple, but, too slow operating at half speed, or even less.  But, it's great for battery retention memory.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on June 27, 2020, 12:32:00 am
Write back is called "Precharge".
That's not quite right -- "precharge" refers to charging the bit lines coming in to the sense amplifiers up to 1/2 Vcc in preparation for reading a row. Writing back is called "refresh" (and kind of happens as a side effect of reading -- this Wikipedia article explains it quite well: https://en.wikipedia.org/wiki/Dynamic_random-access_memory (https://en.wikipedia.org/wiki/Dynamic_random-access_memory)).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 27, 2020, 01:08:24 am
Write back is called "Precharge".
That's not quite right -- "precharge" refers to charging the bit lines coming in to the sense amplifiers up to 1/2 Vcc in preparation for reading a row. Writing back is called "refresh" (and kind of happens as a side effect of reading -- this Wikipedia article explains it quite well: https://en.wikipedia.org/wiki/Dynamic_random-access_memory (https://en.wikipedia.org/wiki/Dynamic_random-access_memory)).

This makes sense. I always wondered why such a strange choice of the word.

At any rate, from the controller viewpoint, you activate the row, work with it, then when you're done you issue the precharge command, at which point your data are written back and the row is deactivated. Apparently it also precharges amplifiers. Between activate and precharge commands, you can exchange the data with the buffer - read or write. The refresh command refers to maintenance refreshes which must not happen between activate and precharge commands. These refreshes are reads followed by writes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 28, 2020, 11:30:05 am
Okay, I can work on the BGA design whilst I do other stuff - in the meantime, what to get started on next with the HDL side?  The graphics accelerator?  How is this going to work (in a mid-level overview sort of way)?

BrianHG mentioned previously a list of commands/functions that the module would perform and I have a basic checklist myself, like CIRCLE, LINE, FILL, etc and even perhaps basic sprite collision - how would this be implemented and where do I start?  :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 28, 2020, 03:28:31 pm
BrianHG mentioned previously a list of commands/functions that the module would perform and I have a basic checklist myself, like CIRCLE, LINE, FILL, etc and even perhaps basic sprite collision - how would this be implemented and where do I start?  :scared:
If you want to start with a geometry engine, then:
Begin with writing your code written in basic.
Try to get as many of the functions possible done with the same 2 for loops.  IE (x & y) counter.
Try to make the drawng codes always draw from left to right as your ram is 16 bit which may be as many as 16 pixels per word.
Start this far.  Make sure the final output resembles addressing screen memory from a pointer, not X&Y pointers.

Then we optimize a bit.
Then we make a verilog equivilant.

Now, because of memory constraints, even though another said no, I do recommend the 'FIFO command plotting drawing port'.  This doesn't mean you will stick with this, all it means is that lateron, you will get rid of the first command FIFO and replace it with a programmable loop sequence counter pointing into system graphics memory to fetch the commands automatically (which would probably still feed fill this FIFO anyways  ;) ).

Now when I say basic, I mean use the 'Free Basic' compiler which I used for the RS232_Debugger.  It takes less than a second to compile and opening a graphics screen is 1 line command which emulating a dumb point placement is also 1 command.  You may use a 'C' compiler for windows to create your code, but, for this type of code fiddling around, you wont have such play-ability.  Also, you might end up coding too well and create code which will be more difficult to translate to verilog.

For the 'FIFO' port, the basic emulation code should read a file which contains the stream the Z80 would be sending to generate the graphics.

As we go further, you will need to add thing like screen base memory, limit X&Y coordinates so your commands don't end up erasing out of screen memory.  You also need to store the pixel bit-plane mode drawing type so the final section knows how to fill the ram.

The final part, written in verilog, pixel writer, takes the plotted memory coordinates and edits the ram's contents.  Because of the biplane system, you will need to read-modify-write each byte coming in.  In this small sequencer, you will want a smart 1 byte cache which will read a byte if needed, and edit contents.  It will not write the byte until it receives the next pixel write since it may be the same memory address as in that cache.  If so, it will re-edit the cache.  If not, it will write the current cache and read the next pixel byte to be edited.  (Now I know we talked about single bit masking for writing bitplane data, however, this may work inside the FPGA, however, if you want external DRAM or SRAM, we can only narrow this down to 8 bits.  So might as well put in the effort and do the cache for universal compatibility.)

I think I said enough for you to begin thinking....

As for every control listed above, I would probably engineer 2 banks of controls for 2 the drawing engine since you can display multiple graphics modes simultaneously on the screen, refilling all that data with 2 different window modes going on might offer an advantage.  This doesn't mean program it that way to begin with, just make allowances when storing all the control registers to hold the 2 banks.  The other choice is 2 distinct drawing engines taking up more FPGA resources.

As for compiling graphics command data.  I do have a universal configurable compiler I created for another project which can build 16 bit opcodes functions with data to create your 'FIFO' port file, however, you would be expected to create a Z80 driven controller of your own in the future.

A lot to think about...

-------------------------------------------------------------------------------------------
Sprite collision is handled inside the pixel-mixer just before the palette since part of the code already exists to discern  if a pixel is solid or not and which once is drawn on-top of one-another.  As for software rendered sprites in the Geometry engine, that will be located in the 'pixel writer which takes the plotted memory coordinates and edits the ram's contents.'  Another reason the read-modify-write pixel drawing command has additional use above simple blind writes into memory which contains 'bit' for 'bit' write enables to access individual bit-planes.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 28, 2020, 05:20:22 pm
If you want to start with a geometry engine, then:
Begin with writing your code written in basic.
Try to get as many of the functions possible done with the same 2 for loops.  IE (x & y) counter.
Try to make the drawng codes always draw from left to right as your ram is 16 bit which may be as many as 16 pixels per word.
Start this far.  Make sure the final output resembles addressing screen memory from a pointer, not X&Y pointers.

Right, leave it with me.  I'll see what I can do.

Also, you might end up coding too well and create code which will be more difficult to translate to verilog.

There's little chance of me coding it too well!  :-DD

For the 'FIFO' port, the basic emulation code should read a file which contains the stream the Z80 would be sending to generate the graphics.

Okay, so I'll write a Free Basic program with the basic draw functions and get it to read a file with a list of commands and process them accordingly.  That's absolutely more than enough for me to be getting started with!  Just got to squeeze some time in to familiarise myself with Free Basic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 28, 2020, 07:16:00 pm
Almost done making a setup freebasic and a compiler for generating a drawing.binary file.
Give me a few more hours.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 28, 2020, 10:47:49 pm
Here you go: 'geo.zip'.

Contents:
Command Prompt - Just a dos shell.  Nice big fat font...
c.bat            - Compiles 'Geo.bas'
geo.bas        - GPU geometry engine simulator/tester written in 'FreeBasic'
palette.bin    - Has your GPU palette so the simulator knows the color palette when drawing

fwasm.exe    - My assembly universal compiler, PIC-ASM16/18 mnemonic compliant, used to convert the 'Drawing.asm' into a binary 'drawing.bin'
instr.txt        - Used by fwasm.exe to define the opcode and operand structure to compile the 'drawing.asm'.  You will add to this file as you add GPU geometry commands.

Drawing.asm - An assembly code written similar to PIC-ASM16/18 mnemonic with a few test plotting commands
Drawing.lst   - Generated by my fwasm.exe, contains the compiled results, opcodes, memory addresses and errors
Drawing.bin  - Contains the fwasm.exe compiler binary which can be run using the geo.exe
Drawinf.mif   - the Drawing.bin in .mif format, less the 8 byte header.

geo.exe        - The compiled executable GPU geometry engine simulator which reads and executes the compiled 'Drawing.bin' file.  It's programmed to pause for a key-press after every plot command.  Once 'Drawing.bin' is finished, you will need to press the 'ESC' key to quit the program.

I've only setup a basic few things (yes it functions!), you will need to do a lot more.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 02:18:26 am
     Note that if you do not like the current fixed 16bit instruction format, there is still time to go with an 8bit op-code method which compresses the unused bits and removes commands as 1 command may be used to load multiple settings and perform functions.

     It doesn't make much a difference in the end other than saving a few bytes of ram per operation while making the verilog a little more complex.  Fancy repeat commands or fancy sequencing of functions will no longer be possible.  Corrupt commands creating infinite loops or a crash of the sequencer will now also become possible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 08:50:20 am
Have completed the line function.  Will finish the circle function later tonight.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 08:52:03 am
     Note that if you do not like the current fixed 16bit instruction format, there is still time to go with an 8bit op-code method which compresses the unused bits and removes commands as 1 command may be used to load multiple settings and perform functions.

     It doesn't make much a difference in the end other than saving a few bytes of ram per operation while making the verilog a little more complex.  Fancy repeat commands or fancy sequencing of functions will no longer be possible.  Corrupt commands creating infinite loops or a crash of the sequencer will now also become possible.

Think I'll stick with the 16-bit format.  Less downsides and any loss of speed manipulating 16-bit instructions on an 8-bit processor will be more than made up for by having hardware-accelerated drawing anyway.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 09:31:44 am
Have completed the line function.  Will finish the circle function later tonight.  :-+
I fixed 2 sets of errors.
On lines 101 through 104, the srcmem has the wrong '#'  for the x'#' and y'#'.
Also, I wrote little and big endian in the REMarks backwards.

Now for the line algorithm.
Ok, for the screen limits, what we will do in the verilog/code is just skip the PSet/write to pixel ram if the coordinates fall outside the screen limits.  This will allow for geometry to go slightly outside the screen area, yet not be corrupted.  Yes the code will still be generating draw commands, but will ignore the pixel writes.

Now, is everything in your line algorithm 'integer' math?
Can you visualize it in verilog like almost everything else I have already written.

I believe this is another line generator written using ints only as reference.  It's basically the same thing written in C: https://www.eevblog.com/forum/microcontrollers/any-simple-blitter-around-(looking-for-fpga-design)/msg1803284/#msg1803284 (https://www.eevblog.com/forum/microcontrollers/any-simple-blitter-around-(looking-for-fpga-design)/msg1803284/#msg1803284)
Except is it as minimal as it gets and uses fixed point 16.16 mathematics.  Well, I guess we can get away with 12.12 in verilog with the 125Mhz fmax.

After the circle, we will build this module in verilog where the input is a 16 bit data input port with enable & CTS output.  And a 12bit x, 12 bit y, 8 bit color, write pixel enable output & we will simulate it in Quartus.

The actual write pixel will be a second verilog module which will compute the memory address from the coordinates, then do a read / modify / write from GPU ram.  It will have a similar CTS (clear to send) output and an inputs to receive the first geometry unit's coordinates.

Between all these modules, we will tie them together with FIFO, using the full and empty and shift inputs flags for the CTS and data ready inputs to cache and sequence everything, though, except for large flood fills, I doubt the Z80 will ever fill out more than 2 or 3 commands before the geometry unit has finished.

Later, we will improve the pixel memory writer to have a pixel copy function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 11:14:44 am
Now for the line algorithm...

Now, is everything in your line algorithm 'integer' math?
Can you visualize it in verilog like almost everything else I have already written.

Errr... no?  :o

I believe this is another line generator written using ints only as reference... Except is it as minimal as it gets and uses fixed point 16.16 mathematics.  Well, I guess we can get away with 12.12 in verilog with the 125Mhz fmax.

Attached is the updated Geo.bas, with a new line function based on the linked code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 11:30:43 am
Now, that line generator code can easily be written in verilog.

When doing the circle, it will look pretty similar.

We will skip a filled circle and a filled triangle in place of starting the first part of the verilog simulation.

  I want to modify the filled triangle to a 4 sided filled polygon.  Where the triangle will be a 4 sided polygon with 2 sets of coordinates being identical. The idea is to make 1 function perform 2 shapes.  Then, perhaps make that function plot only the outer edges performing the un-filled variants of the shapes.  All that changes is when you call the different shapes, it will just pass the appropriate x'#' and y'#' into the polygon engine with a fill on or off.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 11:51:14 am
Oh, and a circle, filled or unfilled is just the 4 sided polygon with the 4 points generating a bezier curve.

With that 4 sided polygon, you can now make rotated rectangles, triangles & ovals, filled and unfilled completing a very functional geometry engine.

There are some old Amiga 100% polygon rendered game which you would now be able to run at 640x480 60fps on a Z80 where as the Amiga could only do 15fps at 320x200.

It would have been nice to play this buttery smooth and sharp at the time:
https://www.youtube.com/watch?v=wjMf_bEfqIc (https://www.youtube.com/watch?v=wjMf_bEfqIc)

Maybe we should re-thing the 12 bit coordinates and go for 24 bit with a scaling and rotating transformation multipliers for the geometry engine, with Z coordinates and you will have a simple 3D rendering engine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 01:03:45 pm

If you are going BGA, maybe taking a look at the Lattice 15$ fpga with 2 megabits ram may be useful.

I seem to recall us talking about the Lattice recently and discovering there could be licensing issues?  $99 a year for the IDE is beyond my meagre hobby budget.  If we're going the route of external RAM though, the internal RAM (or lack of) won't be an issue.


Licensing?
https://www.latticesemi.com/en/Products/DesignSoftwareAndIP/FPGAandLDS/LatticeDiamond#_FD13D8A25CBB47BD83F143E5B55DBC75 (https://www.latticesemi.com/en/Products/DesignSoftwareAndIP/FPGAandLDS/LatticeDiamond#_FD13D8A25CBB47BD83F143E5B55DBC75)

Under the 'ECP5U', it has a tick 'Free License'.  It's the 'ECP5UM & ECP5UM5G' which require the license, however, I don't think you are placing a 50$ FPGA on your Z80 GPU.

Everything else you have written on your own.
Too bad, but a cheap eval board would really help.

Maybe I might take a look at their Lattice Diamond FPGA design software.

You still need to choose what type of memory you might want for your GPU.

Note that the FPGA internal ram is required for the tile/font texture memory.  The external extended memory, DDR or Hyperbus RAM can only be used for background raster graphics display ram or tile layout ram unless you use the ZBT sram.  With ZBT SRAM, the external memory can do everything like the internal FPGA ram, except, it will only have access to 3 MAGGIES if you run it at 125MHz, 4 MAGGIES if you run it at 150MHZ, 6 MAGGIES at the max 200MHz.  This does not take away from the internal possible 15 MAGGIES, it would be added to them.  Subtract 1 MAGGIE if you want the pixel copy/blitter command to run at 2x speed.  You only need this if you want to display something like 100 large software sprites onscreen 30 frames per second.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 01:37:19 pm
Aargh. Having trouble with the Free Basic syntax now.  I've got (what I think is) the circle function in there, but I can't test it as I can't seem to successfully add a 'radius' parameter to the func_plot function.  Just getting loads of errors.  Attached current code at bottom. :(

Oh, and a circle, filled or unfilled is just the 4 sided polygon with the 4 points generating a bezier curve.

 ???

With that 4 sided polygon, you can now make rotated rectangles, triangles & ovals, filled and unfilled completing a very functional geometry engine.

From the circle function?  :o

There are some old Amiga 100% polygon rendered game which you would now be able to run at 640x480 60fps on a Z80 where as the Amiga could only do 15fps at 320x200.

 ;D ;D ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 02:21:08 pm
Ok, I've updated the circle with the right command structure.

You were supposed to use the x0,y0 for the center, and the x1,y1 would be the x&y radius.

Now, I know that having 8 plotted points  is optimum since calculating the arc is considered processing intensive, but, inside the FPGA, with your architecture, the actual pixel writing is at the same speed or slower than the mathematics.

What I was thinking was running 4 curved line generators in a row, which each created an arc.  The top left, top right, bottom left, bottom right of the circle.  The reason behind this is when we will create a filled circle, the center of the circle is a right angle triangle filled to the edge of that generated line.

The reason behind this is if we move the left and right coordinates off the center axis and move the top and bottom coordinates off the Y axis, we can generate that oval with any rotation.

Start with drawing only the top left quadrant arc of the circle, using X0&Y0 as the circle's center, but use the X1&Y1 to stretch out the arc being generated.

The update I've attached just corrects your code, corrects the drawing.asm and instr.txt.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 29, 2020, 02:21:13 pm
Under the 'ECP5U', it has a tick 'Free License'.  It's the 'ECP5UM & ECP5UM5G' which require the license, however, I don't think you are placing a 50$ FPGA on your Z80 GPU.
So it's a full 16x16 BGA matrix with 0.8 mm pitch... 0.8 mm pitch does not leave enough space to fit two traces between pads, so you can only breakout 2 rows on a top layer, 2 more on a next layer (as there are no vias), and only 1 on subsequent (because they will need to go between vias). I've assembled a full pinout matrix diagram for caBGA-256 (as it seems Lattice couldn't be bothered to), and it is 5 IO rows deep. That means you can't fully break it out on 2 signal layers (4 layer board) - you will need 3 signal layers and so 6 layer board.
You can try using a fab that offers 75 um traces - this way you will be able to fit 2 traces between pads on a top layer and so breakout 3 full rows. If that fab can also do 0.4 mm pad vias (or smaller), this will allow breaking out another 3 rows on a next layer, and 2 rows on any subsequent layers. All of that will dramatically reduce the total amount of layers, making 4 layer board absolutely feasible.
Or you can pick a different part that is available in 1 mm pitch BGA, this will mean even 0.1 mm traces will be more than enough to fully breakout a matrix on 4 layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 02:27:41 pm
Under the 'ECP5U', it has a tick 'Free License'.  It's the 'ECP5UM & ECP5UM5G' which require the license, however, I don't think you are placing a 50$ FPGA on your Z80 GPU.
So it's a full 16x16 BGA matrix with 0.8 mm pitch... 0.8 mm pitch does not leave enough space to fit two traces between pads, so you can only breakout 2 rows on a top layer, 2 more on a next layer (as there are no vias), and only 1 on subsequent (because they will need to go between vias). I've assembled a full pinout matrix diagram for caBGA-256 (as it seems Lattice couldn't be bothered to), and it is 5 IO rows deep. That means you can't fully break it out on 2 signal layers (4 layer board) - you will need 3 signal layers and so 6 layer board.
You can try using a fab that offers 75 um traces - this way you will be able to fit 2 traces between pads on a top layer and so breakout 3 full rows. If that fab can also do 0.4 mm pad vias (or smaller), this will allow breaking out another 3 rows on a next layer, and 2 rows on any subsequent layers. All of that will dramatically reduce the total amount of layers, making 4 layer board absolutely feasible.
Or you can pick a different part that is available in 1 mm pitch BGA, this will mean even 0.1 mm traces will be more than enough to fully breakout a matrix on 4 layers.
With a 2 layer board, and 1 trace between 2 pads, he would have access to at least 90 IOs with no VIAs.
The via drill would still need to be small enough to do the VCC and GND.
For a few additional signals above the 90, only a few though, I would reserve them for slow signals where you could afford to snake them around the power which would all need to come in from 1 side or 2 sides of the FPGA.
He could get away with another 20 IOs viaed from top to bottom layer still leaving room for VCC/GND.

A 4 layer board would give him a lot of freedom.
The nice thing about the ZBT ram is that it runs at 3.3v removing an IO supply voltage required by HyperBus ram or DDR2 ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 02:46:14 pm
The nice thing about the ZBT ram is that it runs at 3.3v removing an IO supply voltage required by HyperBus ram or DDR2 ram.

ZBT RAM is looking more and more appealing, and I don't think the cost will be a barrier either with the amounts I'd be using.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 29, 2020, 02:46:51 pm
With a 2 layer board, and 1 trace between 2 pads, he would have access to at least 90 IOs with no VIAs.
The via drill would still need to be small enough to do the VCC and GND.
For a few additional signals above the 90, only a few though, I would reserve them for slow signals where you could afford to snake them around the power which would all need to come in from 1 side or 2 sides of the FPGA.
Wasn't the whole point of going to BGA is to use (a lot) more IO pins? Using only 90 is such ridiculous waste.

A 4 layer board would give him a lot of freedom.
I don't quite see "a lot of freedom". You still can't have a full breakout, unless you go for 75 um traces, or pick a different part in 1 mm pitch package. 4 layer board still only gives you 2 signal layers, same as 2 layer board.

The nice thing about the ZBT ram is that it runs at 3.3v removing an IO supply voltage required by HyperBus ram or DDR2 ram.
That mostly doesn't matter, because Vccio pins are mostly adjacent to the IO bank they serve, so you can easily place a planelet on a power layer. You will need to sacrifice a few hi-speed pins (use them only for slow signals as they won't have a reference plane directly below/above them) in order to bring in Vccint and Vccaux rails to the middle of the matrix though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 03:17:26 pm
Now, I know that having 8 plotted points  is optimum since calculating the arc is considered processing intensive, but, inside the FPGA, with your architecture, the actual pixel writing is at the same speed or slower than the mathematics.

What I was thinking was running 4 curved line generators in a row, which each created an arc.  The top left, top right, bottom left, bottom right of the circle.  The reason behind this is when we will create a filled circle, the center of the circle is a right angle triangle filled to the edge of that generated line.

The reason behind this is if we move the left and right coordinates off the center axis and move the top and bottom coordinates off the Y axis, we can generate that oval with any rotation.

Start with drawing only the top left quadrant arc of the circle, using X0&Y0 as the circle's center, but use the X1&Y1 to stretch out the arc being generated.

So instead of drawing all 8 octants, you only want 2 to be drawn for the top-left quadrant of the 'circle'?  Won't this just require removing 6 of the 8 draw_pixel calls in the displayBresenhmCircle() function, or is there more to this?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 03:22:03 pm
With a 2 layer board, and 1 trace between 2 pads, he would have access to at least 90 IOs with no VIAs.
The via drill would still need to be small enough to do the VCC and GND.
For a few additional signals above the 90, only a few though, I would reserve them for slow signals where you could afford to snake them around the power which would all need to come in from 1 side or 2 sides of the FPGA.
Wasn't the whole point of going to BGA is to use (a lot) more IO pins? Using only 90 is such ridiculous waste.
Originally, it was the 15$ price each for a core with 2 megabits ram.

He currently has 90 IO on his Cyclone IV.  He would want at least another 44 IOs for 1 or 2 ZBT SRAMs, a few less for DDR2 operating at a lower IO voltage, or, 13 IOs for the Hyperbus Ram, with that IO bank operating at a lower voltage.

He would want 6 IOs to drive a CD Quality stereo audio DAC.
He would want another 4 IOs to improve his SD card interface to support parallel 4 bit mode.
Another 12 IOs to directly drive a HDMI port.  (Though, it can be a replacement for the current Video DAC.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 03:27:42 pm
geo.zip attached with top-left quadrant arc drawing.  I've commented-out the circle function call and diverted it to the arc function, so it'll work with the existing drawing.bin.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 03:31:15 pm
Originally, it was the 15$ price each for a core with 4 megabits ram.

He currently has 90 IO on his Cyclone IV.  He would want at least another 44 IOs for 1 or 2 ZBT SRAMs, a few less for DDR2 operating at a lower IO voltage, or, 13 IOs for the Hyperbus Ram, with that IO bank operating at a lower voltage.

He would want 6 IOs to drive a CD Quality stereo audio DAC.
He would want another 4 IOs to improve his SD card interface to support parallel 4 bit mode.
Another 12 IOs to directly drive a HDMI port.  (Though, it can be a replacement for the current Video DAC.)

Yes, this is accurate, plus another 10 IOs max to fill out the buffer (level converter) direction controls for the command and address buses as well, so that I have the option of being able to run the whole show from the FPGA with a soft-core CPU if I (or anyone else) wanted to go that route.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 03:46:09 pm
geo.zip attached with top-left quadrant arc drawing.  I've commented-out the circle function call and diverted it to the arc function, so it'll work with the existing drawing.bin.

Ok, I think what I asked for was wrong.  What I'm looking for is Bresenham's Ellipse.  Remember, we don't want to make 2 codes in the FPGA for circles and ellipses.  When you call a circle, the Verilog will just copy and use the X1 coordinate as the X&Y radius while calling the ellipse.  When you want an ellipse, the same ellipse will be called using the separate X&Y figures stored in X1&Y1.  However, this will not allow you to rotate the ellipse.  The calculation speed in the FPGA for the ellipse will be just as fast as the optimized circle algorithm.
 
After this, we have the filled ellipse.

The triangle which calls 3 lines.
Filled triangle which calls 3 lines, while plotting a line from 1 coordinate of the rendering line.

I'm not sure what else you would like, but next we go to the Geometry_xy_plotter.sv and simulate.
Then will come Geometry_pixel_writer.sv and simulate on it's own.
The merge the 2 together and simulate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 04:18:33 pm
Ok, I think what I asked for was wrong.  What I'm looking for is Bresenham's Ellipse.  Remember, we don't want to make 2 codes in the FPGA for circles and ellipses.  When you call a circle, the Verilog will just copy and use the X1 coordinate as the X&Y radius while calling the ellipse.  When you want an ellipse, the same ellipse will be called using the separate X&Y figures stored in X1&Y1.  However, this will not allow you to rotate the ellipse.  The calculation speed in the FPGA for the ellipse will be just as fast as the optimized circle algorithm.

Ah, my bad - thought it was too easy.  ::)


I'm not sure what else you would like, but next we go to the Geometry_xy_plotter.sv and simulate.

What else do I need?  Plot, line, circle/arc and polygon (and their filled variants) are all I can think of, unless you have other suggestions?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 29, 2020, 04:28:50 pm
Remember, we don't want to make 2 codes in the FPGA for circles and ellipses.  When you call a circle, the Verilog will just copy and use the X1 coordinate as the X&Y radius while calling the ellipse.  When you want an ellipse, the same ellipse will be called using the separate X&Y figures stored in X1&Y1.  However, this will not allow you to rotate the ellipse.  The calculation speed in the FPGA for the ellipse will be just as fast as the optimized circle algorithm.

May I suggest. You can create just a simple drawer which draws an arbitrary curve given three points. Such curves can then be used to draw any sort of lines - straight, circles, ellipses, true-type fonts etc. Then you can organize everything into a pipeline:

drawing commands (circle, line etc.) ---> FIFO ---> parser which dissects shapes into simple curves ---> FIFO --> curve drawer ->

This way you need only a single drawing algorithm and save some logic. Later you can add other drawers, such as area fillers or blitters in parallel with the curve drawer, each with its own FIFO queue from the parser.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 29, 2020, 04:48:04 pm
Hmm.. I have to call it on this ellipse business.   :palm:

Should be easy in theory - I should be able to tweak the circle function to do it, but I'm having trouble finding anything reliable on ellipses that I can translate to Free Basic, and the function I've got isn't working because... well, I can't get it to work.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 04:52:38 pm
Remember, we don't want to make 2 codes in the FPGA for circles and ellipses.  When you call a circle, the Verilog will just copy and use the X1 coordinate as the X&Y radius while calling the ellipse.  When you want an ellipse, the same ellipse will be called using the separate X&Y figures stored in X1&Y1.  However, this will not allow you to rotate the ellipse.  The calculation speed in the FPGA for the ellipse will be just as fast as the optimized circle algorithm.

May I suggest. You can create just a simple drawer which draws an arbitrary curve given three points. Such curves can then be used to draw any sort of lines - straight, circles, ellipses, true-type fonts etc. Then you can organize everything into a pipeline:

drawing commands (circle, line etc.) ---> FIFO ---> parser which dissects shapes into simple curves ---> FIFO --> curve drawer ->

This way you need only a single drawing algorithm and save some logic. Later you can add other drawers, such as area fillers or blitters in parallel with the curve drawer, each with its own FIFO queue from the parser.
Yes, this is what I am looking for, as a circle just has those 3 points set to the canter coordinates, +/- the radius as a perfect circle.  With a curved line algorithm, with the 4 source coordinates being use as 4 center quadrant points on a circle, you can draw the ellipse rotated to any angle.

I believe think it is called a 'Rational Bézier curve'.

For simple circle & ellipse, the all integer 'Bresenham's Ellipse' algorithm is fine.
It also comes in the filled variant as well, though the filled variant is nothing more than a horizontal for X loop to draw from left half to right half of the circle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 29, 2020, 04:55:49 pm
Yes, this is accurate, plus another 10 IOs max to fill out the buffer (level converter) direction controls for the command and address buses as well, so that I have the option of being able to run the whole show from the FPGA with a soft-core CPU if I (or anyone else) wanted to go that route.
Looks like whoever designed their pinouts was on something serious. Check out the pinout diagram of their 381 pin package in attachment. To me that matrix looks easier to break out than 256 ball one. Even Lattice themselves showing an example pinout of that package with only 4 layers, 4 mil traces and 7 mil drills (that might be a problem).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 06:19:30 pm
Hmm.. I have to call it on this ellipse business.   :palm:

Should be easy in theory - I should be able to tweak the circle function to do it, but I'm having trouble finding anything reliable on ellipses that I can translate to Free Basic, and the function I've got isn't working because... well, I can't get it to work.  :-//

Ok, hang on.  Look here for notes on drawing an ellipse inside a rectangle: http://members.chello.at/easyfilter/bresenham.html (http://members.chello.at/easyfilter/bresenham.html)

Too bad that algorithm uses floats.  But, it is easy to modify if you want to fill the ellipse by adding a for x loop when drawing between the left and right side.

I need to look a little more tonight when I wake up.
For now, star a new dummy Quartus project to simulate the Geometry_xy_plotter.sv.
Code: [Select]
You will need inputs:
clk        // system clock
reset      // force reset
cmd_ready  // load the 16 bit data command
cmd_data[15:0] // data bus
draw_busy      // when high, the pixel writer is busy, so the geometry plotter will pause before sending any new pixels

You will need outputs:

load_cmd       //  output high when ready to receive the next cmd_data[15:0] input

draw_cmd_rdy   //  Pulsed high when the data on the draw_cmd[35:0] is ready to send to the pixel writer module.
draw_cmd[35:0] //  bits [35:32] hold an aux function number 0 through 15.
               //  When AUX=0,  do nothing
               //  When AUX=1,  write pixel,                             bits 31:24 hold the color bits 23:12 hold the Y coordinates, 11:0 hold the X coordinates
               //  When AUX=2,  write pixel with color 0 mask,           bits 31:24 hold the color bits 23:12 hold the Y coordinates, 11:0 hold the X coordinates
               //  When AUX=3,  write from read pixel,                   bits 31:24 ignored        bits 23:12 hold the Y coordinates, 11:0 hold the X coordinates
               //  When AUX=4,  write from read pixel with color 0 mask, bits 31:24 ignored        bits 23:12 hold the Y coordinates, 11:0 hold the X coordinates
               //  When AUX=6,  read source pixel,                       bits 31:24 ignored,       bits 23:12 hold the Y coordinates, 11:0 hold the X coordinates
               //  When AUX=7,  Set Truecolor pixel color                bits 31:24 8 bit alpha blend mixe value, bits 23:0  hold RGB 24 bit color.
               //                                                        Use function Aux3/4 to draw this color, only works if the destination is set to 16 bit true-color mode

               //  When AUX=14, set destination mem address,  bits 31:24 hold the bitplane mode and bits 23:0 hold the destination base memory addres for write pixel.
               //  When AUX=15, set source mem address,       bits 31:24 hold the bitplane mode and bits 23:0 hold the source base memory address for read source pixel.

When copying, yes, having a different bitplane mode for source and destination will work as the pixel writer will have basic conversion logic.
Can you think of anything else?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 06:43:05 pm
Yes, this is accurate, plus another 10 IOs max to fill out the buffer (level converter) direction controls for the command and address buses as well, so that I have the option of being able to run the whole show from the FPGA with a soft-core CPU if I (or anyone else) wanted to go that route.
Looks like whoever designed their pinouts was on something serious. Check out the pinout diagram of their 381 pin package in attachment. To me that matrix looks easier to break out than 256 ball one. Even Lattice themselves showing an example pinout of that package with only 4 layers, 4 mil traces and 7 mil drills (that might be a problem).
:scared:  WTF????????????!?!?!!?!?!!?!?!?!?!?!?!!?!?!?
That's some scary shit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 29, 2020, 07:27:33 pm
:scared:  WTF????????????!?!?!!?!?!!?!?!?!?!?!?!!?!?!?
That's some scary shit.

I think I figured it out. That big-ass ground section at the bottom is where SERDESes would be bonded out in UM devices. So it kind of make sense. Now I'm actually curious if it's possible to fully break it out using JLCPCB's 4 layer process (3.5 mil traces, 0.2/0.4 mm drills). Their example uses 4 mil traces and 7 mil drills (no via pad size is given).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 11:27:47 pm
I figure you are asking what low end JLPCB/PCBWay manufacturing constraint metrics you may get away with a 0.8mm BGA.  See attached photo for what I use.  It boils down to a 7.9mil drill, 15.8mil via (better read & properly set in Metric), 4mil trace between BGA pads, 6 mil trace for PWR/GRND, 17.7mil BGA pad.

Photo has metric unit scale listed:
[attach=1]

If you are going to copy, use the Metric figures as they are exact.  If I remember, JLPCB considers the vias as 8mil drill just squeezing into their lower tier PCB fab.  Also, that IC has Deep Color HDMI inputs an I had no problem with it's LVDS.  Still inspect PCBs before assembly.  When receiving 12 PCBs from an order of 10pcbs, 2 pcbs has slight drill alignment error.  They were still functional, but, the other 10 had dead center drilling.

To begin placement, I place the BGA on a 0.4mm metric grid (well, I work with 0.1mm electrical grid), then paint a complete grid of VIAs offset at 45 degree by 0.4x0.4mm.  Add a grid copy of top layer tracks at 45 degrees to all VIAs pointing outward from the center of the IC.  Then work my way backwards by erasing vias & tracks which are not needed.  I also group resize the top PWR&GND tracks from 4mil to 6 mil.  Then finish fanning out the top layer, then going to the bottom layer.

For power decoupling caps, I use 0402s (imperial) compact footprint on the bottom layer with 0.45mm (17.7mil) tracks across the PWR vias.  The 0402 allows for 1 4mil data trace in-between the pads.

Here is the bottom layer.  It's a little messed up as this IC has 6 separate power supplies voltages (PVDD, CVDD, TVDD, AVDD, DVDD, DVDDIO & GND), but this was a 6 layer PCB.
[attach=2]
The FPGA should be much neater with fewer caps and only 2 or 3 supply volatages.
Those caps will most likely sit in a square in under the inner most row of IOs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 29, 2020, 11:46:56 pm
Oooops, forgot the clearance rules, see below:

[attach=1]

Basically, 4mil between tracks, 10mil for power plane and polygon fills.
Once again, use the Metric figures in my attached photo.

With a 4 layer board, and the LEF5U45 caBGA-256, you wont be able to route around 30 IOs of the available 197 resulting in 167 available routed IOs.  With a 6 layer PCB, you will have access to every IO.

You might reclaim some of those final difficult to route 30 IOs with a few short traces on the GND polygon layer, but they will go through additional vias, so use them for signals in the 25MHz and below range.  I would usually place the bprom configuration & reset signals here.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 01:19:10 am
With a 4 layer board, and the LEF5U45/85 caBGA-256, you wont be able to route around 30 IOs of the available 197 resulting in 167 available routed IOs.  With a 6 layer PCB, you will have access to every IO.
No, I'm more interested in caBGA-381 as it seems to me that it's possible to fully break it out on 4 layer board.

You might reclaim some of those final difficult to route 30 IOs with a few short traces on the GND polygon layer, but they will go through additional vias, so use them for signals in the 25MHz and below range.  I would usually place the bprom configuration & reset signals here.
The fab I usually use can do 3/3 mil (75um) tracks and 0.15/0.3 mm vias (and the quality of their boards is a whole new level compared to the likes of JLCPCB who tries to cut every corner in the process to shave off another cent off production cost, even if quality suffers), so for me 2 tracks between pads/vias is not a problem, but I'm genuinely intrigued by their higher pin count packages (caBGA-554 and 756) because they are not full matrices and seems to be designed for low layer count boards, while providing a ton of IO pins. If I am to take Lattice word on it, they promise full breakout of 756 ball package (365 user IO!) on just 2 signal layers! I can't think of any other FPGA which would allow such a feat. Too bad the fabric in those devices is about two times slower than in 7 series, otherwise it would be one hell of a device!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 02:08:52 am
The fab I usually use can do 3/3 mil (75um) tracks and 0.15/0.3 mm vias (and the quality of their boards is a whole new level compared to the likes of JLCPCB who tries to cut every corner in the process to shave off another cent off production cost, even if quality suffers).
Now, for this project, nockieboy wants the cheapest functional PCB which will be quickest time to anyone as it is an open-source project where online users will most likely default their orders to JLPCB/PCBway.  Make no mistake, for some of my mass production designs, we have below 2 mil trace with lazer drill vias and 22GB/s LVDS.  I do not use JLPCB for this work.  My recommendations offer a sweet spot for these cheap fab houses while still trying to route as many of the BGA IOs as possible with 4 layers.

Yes, with a finer FAB, you can push this to a 2 layer board, but you wont really save on FAB cost until you mass produce PCBs.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 02:40:43 am
Now, for this project, nockieboy wants the cheapest functional PCB which will be quickest time to anyone as it is an open-source project where online users will most likely default their orders to JLPCB/PCBway.  Make no mistake, for some of my mass production designs, we have below 2 mil trace with lazer drill vias and 22GB/s LVDS.  I do not use JLPCB for this work.  My recommendations offer a sweet spot for these cheap fab houses while still trying to route as many of the BGA IOs as possible with 4 layers.
The fab I use is not that much more expensive than JLCPCB. So I'm not talking about some kind of high-end fab, just the one which cares about quality. And I (and my clients) certainly appreciate that and are prepared to pay a bit of premium.

Yes, with a finer FAB, you can push this to a 2 layer board, but you wont really save on FAB cost until you mass produce PCBs.
2 layer board is going to be garbage because of signal integrity no matter what.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 02:55:09 am
LOL, a 4 megabyte (36 megabit) ZBT ram for 15$.  Too bad you need to purchase 800 of them.
https://www.verical.com/pd/integrated-silicon-solution-sram-IS61NVF102436B-6-5TQL-TR-1194781?utm_campaign=verical_findchips_2019&utm_currency=&utm_medium=aggregator&utm_source=findchips&utm_content=inv_listing (https://www.verical.com/pd/integrated-silicon-solution-sram-IS61NVF102436B-6-5TQL-TR-1194781?utm_campaign=verical_findchips_2019&utm_currency=&utm_medium=aggregator&utm_source=findchips&utm_content=inv_listing)

That would be every ounce of the Z80's accessible 4 megabytes all directly addressable picture, program and blitter sprite memory, though with 133Mhz speed, you are talking 3 MAGGIES which can access 4 megabytes, 4 MAGGIES with a little more effort and Z80 & Geometry engine with a potential 75MHz Z80 0 wait-state access.  And you would still have access to the 15 other MAGGIES channels as well which would have around 192kb for their address range.  The 3-4 ZBT MAGGIES can still drive the 15 FPGA MAGGIES and vice-versa.  You would have a hell of a lot of room for audio now as well.  Well worth placing in the FPGA an accelerated multichannel MP3 decoder/encoder on top of the FM synthesizer for the audio so you can playback mix in compressed high quality sound effects for games.

Here is a 2 megabytes ZBT, 16$ for 1, however, this one supports 200MHz: (7 MAGGIES)
https://www.mouser.com/ProductDetail/ISSI/IS61NLP51236B-200TQLI?utm_term=IS61NLP51236&qs=rnuWwpjhhVu7EtaUBW4FOg%3D%3D&utm_campaign=IS61NLP51236B-200TQLI&utm_medium=aggregator&utm_source=findchips&utm_content=ISSI (https://www.mouser.com/ProductDetail/ISSI/IS61NLP51236B-200TQLI?utm_term=IS61NLP51236&qs=rnuWwpjhhVu7EtaUBW4FOg%3D%3D&utm_campaign=IS61NLP51236B-200TQLI&utm_medium=aggregator&utm_source=findchips&utm_content=ISSI)

These guys require 32 bits for the data bus, not 16.  But, they are more available than the 18bit versions.

2 Megabyte, 18 bit version, fewer available: (7 MAGGIES, you can always place 2 of them for 4 megabytes)
https://www.mouser.com/ProductDetail/ISSI/IS61NLP102418B-200TQLI?utm_term=IS61NLP102418&qs=UxK%2FDTs6dB6rHPCxdOLQcw%3D%3D&utm_campaign=IS61NLP102418B-200TQLI&utm_medium=aggregator&utm_source=findchips&utm_content=ISSI (https://www.mouser.com/ProductDetail/ISSI/IS61NLP102418B-200TQLI?utm_term=IS61NLP102418&qs=UxK%2FDTs6dB6rHPCxdOLQcw%3D%3D&utm_campaign=IS61NLP102418B-200TQLI&utm_medium=aggregator&utm_source=findchips&utm_content=ISSI)

In quantity, the 2 megabyte versions go below 10$.

Even Micron makes the 2 megabyte ZBT Srams (36 bit version):
https://www.rocelec.com/part/CYPMCNMT55L512Y32PT-6?utm_medium=buyNow&utm_source=findChips (https://www.rocelec.com/part/CYPMCNMT55L512Y32PT-6?utm_medium=buyNow&utm_source=findChips)
18 bit version:
https://www.rocelec.com/part/CYPMCNMT55L1MY18PT-6?utm_medium=buyNow&utm_source=findChips (https://www.rocelec.com/part/CYPMCNMT55L1MY18PT-6?utm_medium=buyNow&utm_source=findChips)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 03:23:04 am
LOL, a 4 megabyte (36 megabit) ZBT ram for 15$.  Too bad you need to purchase 800 of them.
I think you guys will need to modify your video core to work with longer latency memory. Modern videocards use GDDR6 memory which have hundreds of cycles-long latency, and that doesn't stop video cores to saturate these interfaces despite insane bandwidth(which nowadays is measured in 100's of gigabytes per second) afforded by these interfaces. One thing to think about - video card resources don't have to be stored in video memory as flat contiguous chunks of memory, but can have any structure which facilitates algorithms utilized by the core.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 03:43:33 am
I need to read up on GSI Technologies '18Mb Pipelined and Flow Through Synchronous NBT SRAM'.  They are more available, a bit cheaper and supposed to have a mode similar to ZBT as well as up to 333MHz speed, though, your 15$ FPGA has a 200MHz limit on the IOs in SDR, bit in DDR maybe with a proper layout, you will achieve 11-12 MAGGIES on all 2 megabytes.

36Mb Pipelined and Flow Through Synchronous NBT SRAM at 200MHz is available at under 27$ for 1 while the 18Mb versions are around 14$ for 1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 04:09:19 am
LOL, a 4 megabyte (36 megabit) ZBT ram for 15$.  Too bad you need to purchase 800 of them.
I think you guys will need to modify your video core to work with longer latency memory. Modern videocards use GDDR6 memory which have hundreds of cycles-long latency, and that doesn't stop video cores to saturate these interfaces despite insane bandwidth(which nowadays is measured in 100's of gigabytes per second) afforded by these interfaces. One thing to think about - video card resources don't have to be stored in video memory as flat contiguous chunks of memory, but can have any structure which facilitates algorithms utilized by the core.
     Those cards have megabytes of smart cache just for their ram controller on their GPU die.  All sprites and overlays are now software rendered and stored in separate chunks of ram.  Now if we were to redesign the GPU for all software rendering windows form multiple source ram images to a destination screen display ram, with a software configurable rendering display manager, with a full instruction set for the GPU to perform all these tasks with a software stack, yes.  With 1 beginner developer, a few years from now, we will have re-engineered a semi modern obsolete 2D video card accelerator.  A lot of tricks were designed in to give him hardware video windows or sprties (the MAGGIES) which can be configured anyway what-so-ever with multiple palette chunks assigned to each layer, each one with different bits/color and different resolutions.  And there is only a little bit of code left to add to get hardware pixel collision through each layer identifying if any 2 pixels which don't contain the transparent color 0 sit on top of each other.  It has really been designed to be something like the ultimate 8bit CPU gaming display engine where complete character animations and background scrolls can be achieved only by updating 4-8 bytes per display element & reading 2 bytes per display element/layer to determine 16 possible collisions.

nockieboy just wants to tie in something and go.  I think the 2-4$ 512kb ram chip is fine for an 8 bit 8MHz Z80 while it requires 0 verilog coding experience to get it to work.

Remember, most old Z80 type 8bit personal computers only has to worry about 320x240 at 15Khz (140ns per pixel), 1 bit color per pixel, 160x240 at 4 colors in graphics mode.  Maybe 16 colors in text mode.  This GPU does 15 parallel superimposed windows at 640x480 @ 32Khz x 16 bits per pixel, or 8 bits palette color, with 0 wait states on the Z80 access, plus now a hardware accelerated geometry engine with blitter copy on a 15$fpga.  If I wanted only 1 screen with 640x480 @ 1 bit color, or 16 color text like nockieboy's original spec, or even just a graphics 32 bit color 640x480 with a geometry engine, yes, a single dram chip would be easy with the dumbest dram controller you could think of.  But it wouldn't have some of the goodies of of the old days 8-bit microcomputer style graphics, but now with full color and hi-res output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 06:17:41 am
Those cards have megabytes of smart cache just for their ram controller on their GPU die.  All sprites and overlays are now software rendered and stored in separate chunks of ram. 
These cards also render billions of triangles per second. So let's scale it back by a factor of 1000 - can you render millions of triangles per second with kilobytes of "smart" cache (whatever that is)?

Now if we were to redesign the GPU for all software rendering windows form multiple source ram images to a destination screen display ram, with a software configurable rendering display manager, with a full instruction set for the GPU to perform all these tasks with a software stack, yes.  With 1 beginner developer, a few years from now, we will have re-engineered a semi modern obsolete 2D video card accelerator.  A lot of tricks were designed in to give him hardware video windows or sprties (the MAGGIES) which can be configured anyway what-so-ever with multiple palette chunks assigned to each layer, each one with different bits/color and different resolutions.  And there is only a little bit of code left to add to get hardware pixel collision through each layer identifying if any 2 pixels which don't contain the transparent color 0 sit on top of each other.  It has really been designed to be something like the ultimate 8bit CPU gaming display engine where complete character animations and background scrolls can be achieved only by updating 4-8 bytes per display element & reading 2 bytes per display element/layer to determine 16 possible collisions.
That is a lot of hand-waving. Let's consider facts - now you have a fully obsolete 2D video card accelerator. So devising just "semi-obsolete" will be a big step ahead ;) And no, I don't think it will take years. And even if it will - who cares, as long as it's fun to work on? ;) I, for one, would follow such a project really closely, and would find a way to contribute, because I have great interest in the the subject of 2D/3D rendering using modern approaches, even if they are implemented on a much smaller scale than what modern video cards can do. I'm not interested in using ancient techniques though. I have some experience developing 3D engines using 3D GFX APIs, so I have some knowledge on a subject, though of course it's mostly on the software side, which is why I have keen interest in what's going on on HW side of these APIs.

nockieboy just wants to tie in something and go. 
I can't read his mind, but I think this thread is a proof positive that that is absolutely not his intention. The way I see it, it's a typical hobby project where process is just as important as result, so once you achieve some goal, you invent another one, move the goal post and continue going. Infact if my memory serves me most of features you listed above were not in the original list of requirements, so they were added on the go, which again, is perfectly fine for a "permanently in-progress" hobby project.

I think the 2-4$ 512kb ram chip is fine for an 8 bit 8MHz Z80 while it requires 0 verilog coding experience to get it to work.
That is a classic manifestation of sunk cost fallacy. When your solution becomes inadequate to the task at hand, you don't design crutches for it, instead you re-engineer it so it becomes adequate, and if that doesn't work - you throw it away and start from the ground up. The fact that you need an expensive memory to scale your solution up from measly 640x480 is a proof that existing solution is hitting the wall, and needs to be either significantly re-engineered, or just thrown away and re-designed using a different approach which would scale better.

Remember, most old Z80 type 8bit personal computers only has to worry about 320x240 at 15Khz (140ns per pixel), 1 bit color per pixel, 160x240 at 4 colors in graphics mode.  Maybe 16 colors in text mode.  This GPU does 15 parallel superimposed windows at 640x480 @ 32Khz x 16 bits per pixel, or 8 bits palette color, with 0 wait states on the Z80 access, plus now a hardware accelerated geometry engine with blitter copy on a 15$fpga.  If I wanted only 1 screen with 640x480 @ 1 bit color, or 16 color text like nockieboy's original spec, or even just a graphics 32 bit color 640x480 with a geometry engine, yes, a single dram chip would be easy with the dumbest dram controller you could think of.  But it wouldn't have some of the goodies of of the old days 8-bit microcomputer style graphics, but now with full color and hi-res output.
That ship sailed a loooooong time ago in case you hadn't noticed, as Z80 systems did not have even remotely anything like what you have now. In fact if it's anything like my hobby projects, I absolutely wouldn't be surprised if tomorrow nockieboy comes around and says "you know what - that Z80 thingy is becoming too much of a limitation, so let's get rid of it and replace it with some 32 bit CPU, like RISC-V!" :) This kind of evolution is completely normal, and there is no need to hang on to existing solutions, and long as the process is still fun for those involved. At the end of the day, hobby projects are all about fun first and foremost. I don't think using this Z80 system is nearly as much fun as designing it :D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 07:37:55 am
@asmi, I think you are going off the deep end here.  If you want a 2D/3D accelerated GPU, you may start a thread on the subject and I will contribute.  A decade ago I touched on the subject matter and there is a lot to do and setup just to draw 100 million triangle a second, seeing that each triangle will need to be filled, each having potentially say an average of 4000 pixels each with some intelligence like read ahead cache and omitting hidden triangles beneath others still requires a degree of planning and design.

This project started with a wish to have 640x480 with 1 bit color, or 320x240 by 16 colors.  being a beginner project for nockieboy, we played around with a sync generator, then a 1 bit font and text.  Then, with what a small FPGA could do, we created a standardized method to address a few layers of video.  If nockieboy wants to abandon this project and begin anew with a simple 32 bit, large ram page flip-able display GPU, no MAGGIE, but a GPU accelerated programable core that renders a double buffered display from a stings of stored geometry data structures all on it's own like a modern video card, he is free to do so.  (Not to mention he will need to create his own compiler to construct the geometric code running in the video card)  Remember, his current cpu upgrade wishes is to add support for a 2-4MHz 6502, not a 100Mhz 486, hence the thread title 'FPGA VGA Controller for 8-bit computer'.

Now hooking DDRam to the current design is doable and still can offer everything that comes with large memory, and the limitations are minor as the existing core still offers additional internal ram for effects layers, but, it will take some time to get it right unless I program the whole thing myself.  I am offering trade-offs solutions and options as my free time is shrinking and nockieboy will have to do all the new development on his own.

Quote
"smart" cache (whatever that is)?
Smart cache reads ahead, does branch prediction, holds extra content which will be used after plotting a line or row, or simple write-back for writing into same memory space before sending it back to ram.  In fact, our 'pixel writer' coming after the geometry unit will have a smart cache, except it is only 2 words long for the pixel reader and 2 words long for the pixel writer.  It will speed up any horizontal drawn lines and all fills up to 8 fold.  Most of our objects are only drawing 1 byte, or even parts of a byte written one after the other and 1 word can contain up to 16 pixels.  The 2 word cache will allow these type of reads and writes to be done multiple times immediately and only offload the data to or from the ram once a new completely different word of memory is required.  With DDR2/3 or Hyperbus RAM, these 2 words would be extended to the burst size X 2, so, 16 - 32 bytes each.  Still doable with a a lot more more work.

There is obviously more to this to improve design and efficiency.  I guess this is why CPUs have a L1 cache, then a L2 cache, then a L3 cache, then system memory.

However, there is one thing I can agree upon.  If nockieboy wants the engineering headache, place 2 independently wired Hyperbus Rams for 32/64 megabytes.  It will take a lot longer to get it to function, but he will have a ton of memory space whether he makes the memory interface efficient and extra fast or basically good enough to function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 30, 2020, 10:58:30 am
Ok, hang on.  Look here for notes on drawing an ellipse inside a rectangle: http://members.chello.at/easyfilter/bresenham.html (http://members.chello.at/easyfilter/bresenham.html)

Too bad that algorithm uses floats.  But, it is easy to modify if you want to fill the ellipse by adding a for x loop when drawing between the left and right side.

I like that site, wish I'd found that earlier! :)  Have attached latest Geo.bas and compiled drawing.bin to show the working ellipse function.

I need to look a little more tonight when I wake up.
For now, star a new dummy Quartus project to simulate the Geometry_xy_plotter.sv.
...
When copying, yes, having a different bitplane mode for source and destination will work as the pixel writer will have basic conversion logic.

Okay, test project started in Quartus II with the inputs/outputs you've specified.  Nothing really to show yet, but I've attached geometry_xy_plotter.sv for info.

Can you think of anything else?

I'm hoping that's not a trick question, because right now I can't think of anything else.  ???

EDIT: Just a thought, but what about a general FILL function?  Specify a point coordinate and a colour and off it goes, filling in all pixels of the colour at the point coordinate with the new colour, until bounded by other colours?  Or would that be too far?

I guess as an alternate to this, I'm thinking about a filled polygon function?  Perhaps based off of the filled square, but being able to specify all four corner positions?


I need to read up on GSI Technologies '18Mb Pipelined and Flow Through Synchronous NBT SRAM'.  They are more available, a bit cheaper and supposed to have a mode similar to ZBT as well as up to 333MHz speed, though, your 15$ FPGA has a 200MHz limit on the IOs in SDR, bit in DDR maybe with a proper layout, you will achieve 11-12 MAGGIES on all 2 megabytes.

36Mb Pipelined and Flow Through Synchronous NBT SRAM at 200MHz is available at under 27$ for 1 while the 18Mb versions are around 14$ for 1.

I know you guys have discussed this all already whilst I've been sleeping, but (for this project at least) $27 (or even $14) for a RAM chip is a bit expensive and I'd need to be convinced of the benefits before pulling the trigger on that.

nockieboy just wants to tie in something and go.  I think the 2-4$ 512kb ram chip is fine for an 8 bit 8MHz Z80 while it requires 0 verilog coding experience to get it to work.

Sounds good to me. Don't forget that I already consider the design and assembly of this card to be pretty advanced for a beginner - minimising the number of (relatively) expensive components that could be difficult to solder seems like a good strategy.


nockieboy just wants to tie in something and go. 
I can't read his mind, but I think this thread is a proof positive that that is absolutely not his intention. The way I see it, it's a typical hobby project where process is just as important as result, so once you achieve some goal, you invent another one, move the goal post and continue going. Infact if my memory serves me most of features you listed above were not in the original list of requirements, so they were added on the go, which again, is perfectly fine for a "permanently in-progress" hobby project.

To some degree you're right, asmi, but I do have a specific goal in mind and I outlined that near the start of this thread.  In more general terms, I wanted to free my little DIY computer from the host PC, breaking away from the serial console and giving it its own video output and keyboard interface so I could use it as a standalone system.  I don't recall if I ever admitted this, but my holistic aim was to be able to create a computer, from scratch, that I could plug into the living-room TV and play Pong (or my home-coded version of it) with the family.  That was my gold-standard end goal.

Now, technically I could write Pong for it at the moment and that would be that, but you're right in that it's a typical hobby project and I have become quite addicted to the process as much as the end result.  Feature creep is a very significant factor, as is learning about this world of technicalities and skills I never, ever, thought I'd wind up learning about and developing.  Originally the design for my computer was all through-hole components.  I'm now soldering TSSOPs, 0603 passives and QFP-144s without breaking a sweat and seriously planning for the move to BGA.  I'm not an electronics engineer.  I'm not a programmer.  I have no formal education in either domain.  But I do like to learn - and if I can build something fun and practical whilst I'm doing that, so long as the 'next step' isn't insurmountable, then I'll always want to push further as long as you kind folks are willing to put up with my ignorance and stupidity.  :)


Remember, his current cpu upgrade wishes is to add support for a 2-4MHz 6502, not a 100Mhz 486, hence the thread title 'FPGA VGA Controller for 8-bit computer'.

Err.. a 6502 isn't an upgrade from a Z80, it's more of a downgrade.  Just sayin'. ;)  There is a chance in the future that I'll move up to the 16-bit Motorola 68010 as I have one sitting in a box somewhere, but that's still a way off.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 30, 2020, 11:36:42 am
Have just added filled ellipses.  Updated Geo.bas, Drawing.asm and drawing.bin below.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 03:47:12 pm
Have just added filled ellipses.  Updated Geo.bas, Drawing.asm and drawing.bin below.
Nice.  Optimize converting the longs to ints like the line drawing algorithm shouldn't be a problem.

We were missing a few controls, so I added in the geo.bas: (Full files attached below.)
Code: [Select]
if func1<8 then
REM *************************************************************
REM **** Set 24 bit screen memory registers ************
REM *************************************************************
if func2=127 and func3=0   then destmem = x0*4096 + y0: Rem set 24 bit destination screen memory pointer for plotting
if func2=127 and func3=1   then destmem = x1*4096 + y1: Rem set 24 bit destination screen memory pointer for plotting
if func2=127 and func3=2   then destmem = x2*4096 + y2: Rem set 24 bit destination screen memory pointer for plotting
if func2=127 and func3=3   then destmem = x3*4096 + y3: Rem set 24 bit destination screen memory pointer for plotting
if func2=127 and func3=4   then srcmem  = x0*4096 + y0: Rem set 24 bit source screen memory pointer for blitter copy
if func2=127 and func3=5   then srcmem  = x1*4096 + y1: Rem set 24 bit source screen memory pointer for blitter copy
if func2=127 and func3=6   then srcmem  = x2*4096 + y2: Rem set 24 bit source screen memory pointer for blitter copy
if func2=127 and func3=7   then srcmem  = x3*4096 + y3: Rem set 24 bit source screen memory pointer for blitter copy

if func2=127 and func3=8   then destmem = x0*4096 + y0:srcmem  = x1*4096 + y1: Rem both source and destination pointers for blitter copy
if func2=127 and func3=9   then destmem = x1*4096 + y1:srcmem  = x0*4096 + y0: Rem both source and destination pointers for blitter copy
if func2=127 and func3=10  then destmem = x2*4096 + y2:srcmem  = x3*4096 + y3: Rem both source and destination pointers for blitter copy
if func2=127 and func3=11  then destmem = x3*4096 + y3:srcmem  = x2*4096 + y2: Rem both source and destination pointers for blitter copy

if func2=127 and func3=12  then dest_width   = x2  : Rem Sets the number of bytes per horizontal line in the destination raster
if func2=127 and func3=13  then src_width    = y2  : Rem Sets the number of bytes per horizontal line in the destination raster
if func2=127 and func3=14  then dest_width   = x3  : Rem Sets the number of bytes per horizontal line in the destination raster
if func2=127 and func3=15  then src_width    = y3  : Rem Sets the number of bytes per horizontal line in the destination raster

REM *************************************************************
REM **** Set screen width and height limits ************
REM *************************************************************

if func2=126 and func3=0  then max_x = x0: max_y = y0 : REM set the maximum width and height of the screen
if func2=126 and func3=1  then max_x = x1: max_y = y1 : REM set the maximum width and height of the screen
if func2=126 and func3=2  then max_x = x2: max_y = y2 : REM set the maximum width and height of the screen
if func2=126 and func3=3  then max_x = x3: max_y = y3 : REM set the maximum width and height of the screen

if func2=126 and func3=16 then draw_collision = 0     : REM Clear the pixel drawing collision counter
if func2=126 and func3=17 then blit_collision = 0     : REM Clear the blitter copy pixel collision counter

And the additions to the 'geometry_xy_plotter.sv':
Code: [Select]
module geometry_xy_plotter (

    input clk,              // System clock
    input reset,            // Force reset
    input cmd_ready,        // 16-bit data command ready signal
    input cmd_data[15:0],   // 16-bit data command bus
    input draw_busy,        // HIGH when pixel writer is busy, so geometry plotter will pause before sending any new pixels
   
    output load_cmd,        // HIGH when ready to receive next cmd_data[15:0] input
    output draw_cmd_rdy,    // Pulsed HIGH when data on draw_cmd[15:0] is ready to send to the pixel writer module
    output draw_cmd[35:0],  // Bits [35:32] hold AUX function number 0-15:
                            //  AUX=0  : Do nothing
                            //  AUX=1  : Write pixel,                             : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
                            //  AUX=2  : Write pixel with color 0 mask,           : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
                            //  AUX=3  : Write from read pixel,                   : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
                            //  AUX=4  : Write from read pixel with color 0 mask, : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
                            //  AUX=6  : Read source pixel,                       : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
                            //  AUX=7  : Set Truecolor pixel color                : 31:24 8 bit alpha blend mix value : bits 23:0 hold RGB 24 bit color
                            //                                                    Use function Aux3/4 to draw this color, only works if the destination is set to 16 bit true-color mode

                            //  AUX=10 ; Resets the Write Pixel collision counter
                            //  AUX=11 ; Resets the Write from read pixel collision counter
                            //  AUX=12 : Set destination raster width in bytes    : 15:0 holds destination raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
                            //  AUX=13 : Set source raster width in bytes,        : 15:0 holds source raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
                            //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
                            //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel

    output Write_col[7:0],  // An 8 bit saturation counter which counts the number of pixel write collisions
    output Copy_col[7:0],   // An 8 bit saturation counter which counts the number of blit write from read pixel write collisions
    output idle             // an output which goes high when the geometry plotter is finished and is doing nothing
);

Now I think you are ready to begin coding the 'geometry_xy_plotter.sv'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 04:42:28 pm
EDIT: Just a thought, but what about a general FILL function?  Specify a point coordinate and a colour and off it goes, filling in all pixels of the colour at the point coordinate with the new colour, until bounded by other colours?  Or would that be too far?
You only call the function twice in a row...
EG,


Code: [Select]
; *************************************************************************************
; ** Draw a filled ellipse (250,250)-(300,350) with palette color 9
; *************************************************************************************
set_x 0,d'175' ; set x0 register to 250 - The ellipse's top-left X position
set_y 0,d'175' ; set y0 register to 250 - The ellipse's top-left Y position
set_x 1,d'300' ; set x1 register to 300 - The ellipse's bottom-right X position
set_y 1,d'350' ; set y1 register to 350 - The ellipse's bottom-right Y position
plot_circle_fill d'9' ; plot a filled ellipse with palette color 9
        plot_circle d'15'         ; plot the outline of the same ellipse with palette color 15

Remember, my commands holding their screen coordinates were optimized to do this sort of thing.
You may make such a command in your Z80 graphics driver, but, it would just execute the above code.
The Geometry unit will draw between 25 million all the way up to 125 million pixels a second.  It wont break a sweat drawing the extra few pixels surrounding the edge of an ellipse, or rectangle a second time.

Give it a test in geo.bas.
Now, truly begin the 'geometry_xy_plotter.sv'.  Start with being able to load it's internal storage registers with the command input port.

Use the maggie.sv and rs232_DEBUGGER.v to get an idea of how to associate/assign labels from the source command & how to store those labels into the memory registers.  The labels and registers should be almost identical to the geo.bas labels.  Except for the x# & y#, make them 2 dimensional 12 bit registers for ease of design.  (I should have done that anyways within geo.bas.  Sorry, my bad.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 05:12:14 pm
@asmi, I think you are going off the deep end here.  If you want a 2D/3D accelerated GPU, you may start a thread on the subject and I will contribute.  A decade ago I touched on the subject matter and there is a lot to do and setup just to draw 100 million triangle a second, seeing that each triangle will need to be filled, each having potentially say an average of 4000 pixels each with some intelligence like read ahead cache and omitting hidden triangles beneath others still requires a degree of planning and design.
I will do so at some point, but first I need to figure out what kind of hardware will I need, and design and build such HW. I do have quite a bit of boards with HDMI out, but they all need to overclock FPGA in order to get 1080p out, with that I plan to design a board with DisplayPort out so that I will be free to output just about any resolution I want or need, and it can also output sound at the same time (which might become useful at some point). I know GPU cores require crazy amounts of memory bandwidth, but the best I can do while keeping costs reasonable is 400 MHz DDR3, the question is if it's better to have a single wide interface, or several smaller ones. The latter approach allows for some cool tricks - like taking advantage of large capacity by cloning the same resource (say texture) into all memory devices, and effectively getting ability to have multi-port read access to several different memory locations at once.

However, there is one thing I can agree upon.  If nockieboy wants the engineering headache, place 2 independently wired Hyperbus Rams for 32/64 megabytes.  It will take a lot longer to get it to function, but he will have a ton of memory space whether he makes the memory interface efficient and extra fast or basically good enough to function.
If I were him, I'd go for DDR3 as it's a general purpose memory, and so learning how to work with it will be useful in other projects in the future, while HyperRAMs are pretty specialist parts and only suitable in limited scenarios. Or implement a two-tier memory architecture by connecting relatively small (but fast) SRAM chip and DDR3 at the same time, so SRAM can be used as off-chip cache for much larger DDR3 memory array.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 06:01:39 pm
If I were him, I'd go for DDR3 as it's a general purpose memory, and so learning how to work with it will be useful in other projects in the future, while HyperRAMs are pretty specialist parts and only suitable in limited scenarios. Or implement a two-tier memory architecture by connecting relatively small (but fast) SRAM chip and DDR3 at the same time, so SRAM can be used as off-chip cache for much larger DDR3 memory array.
It took me almost a 2 months full time to get DDR3/2 working perfectly for my scaler.  However, let it be known that I designed that ram controller from scratch, it has 8 asynchronous read and 8 asynchronous write ports (with adaptive priority) with read request post in advance commands and write cache on each channel and it had to be as compact and efficient as possible operating on the slowest CycloneIII with 128bits where Altera's had the DQS port limit on a CcycloneIII at 96 bits on the higher speed upper and lower IO banks.  This doe not include reading every single nuance of the FPGA data sheet and DDR2/3 datasheets to make sure I made 0 errors in wiring the devices and that I would achieve the clocking goals before the design was complete.

Now I do not see this project requiring such bandwidth or such a complex design but unless nockieboy were to use an off the shelf DDR3 controller and carefully read the LFE5U's DDR3 ram implementation guide, he will get stuck.  The DDR3 will eat up 2 IO banks on his FPGA due to operating at a lower voltage.  I would use a 1GB reduced latency DDR3 as the price is only around 1$ more than the regular one but the memory controller will have a little less latency.  Maybe 2 of them for 32 bits is allowed by the LFE5U's within 2 adjacent higher speed IO banks.  The slowest LFE5U45-6 at 15$ can run the ram at tops 312MHz, or, 624MTPS.  (Can DDR3 be run that slow?) This is not too bad that a 1080p requires a continuous stream of 150 million pixels a second with a 32 bit ram bus, or 300MHz for a 16 bit ram bus.  The LFE5U without hardware serdes will just squeeze out 720p, actually the -7 variant wouldn't have a problem as well as increase the DDR3 clk speed.  That video mode cuts the 150Mhz @ 32 bit bandwidth requirement into 75Mhz.

     If I started from day one making a GPU with the 15$ LFE5U, I would target 720P with 1 or 2 1gb DDR3s.  Run a 32 bit (ARGB) true-color display and make everything else drawn by a geometry engine every frame with optional edge anti-aliasing using the 'A' alpha channel when drawing the graphics.  The memory space with full true color would mean full accelerated anti-aliased tiles/fonts/rendering including soft edge since there is an 8 bit translucency stencil alpha channel.  But, an 8 bit CPU would never really be able to take advantage of the horse power under the hood.  However, there is also enough room for a softcore 32bit - 68K type of cpu or simple arm-risc which can be placed inside the LFE5U as well as a 64 channel full MIDI wavetable audio system with accelerated DCT for compressed audio streams.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 06:28:58 pm
It took me almost a 2 months full time to get DDR3/2 working perfectly for my scaler.  However, let it be known that I designed that ram controller from scratch, it has 8 asynchronous read and 8 asynchronous write ports (with adaptive priority) with read request post in advance commands and write cache on each channel and it had to be as compact and efficient as possible operating on the slowest CycloneIII with 128bits where Altera's had the DQS port limit on a CcycloneIII at 96 bits on the higher speed upper and lower IO banks.  This doe not include reading every single nuance of the FPGA data sheet and DDR2/3 datasheets to make sure I made 0 errors in wiring the devices and that I would achieve the clocking goals before the design was complete.
Again, this depends on the goal. If the goal indeed is to make it work somehow and call it a day - then yea, do the bare minimum to get it going, and call it good. However if the goal is to learn how to work with the most "commodity" memory available with the aim to use this knowledge and experience in the future projects - then this is a great opportunity to do so.

Now I do not see this project requiring such bandwidth or such a complex design but unless nockieboy were to use an off the shelf DDR3 controller and carefully read the LFE5U's DDR3 ram implementation guide, he will get stuck.  The DDR3 will eat up 2 IO banks on his FPGA due to operating at a lower voltage.  I would use a 1GB reduced latency DDR3 as the price is only around 1$ more than the regular one but the memory controller will have a little less latency.  Maybe 2 of them for 32 bits is allowed by the LFE5U's within 2 adjacent higher speed IO banks.  The slowest LFE5U45-6 at 15$ can run the ram at tops 312MHz, or, 624MTPS.  (Can DDR3 be run that slow?) This is not too bad that a 1080p requires a continuous stream of 150 million pixels a second with a 32 bit ram bus, or 300MHz for a 16 bit ram bus.  The LFE5U without hardware serdes will just squeeze out 720p, actually the -7 variant wouldn't have a problem.  That mode cuts the 150Mhz requirement into 75Mhz.
I just checked Micron 2 Git datasheet, and the minimum frequency is set at 303 MHz, unless DLL is disabled - in this case it can be as low as 128 kHz (yes, you read it right - kilohertz!) - it mentions 7800 ns as max clock period.

If I started from day one making a GPU with the 15$ LFE5U, I would target 720P with 1 or 2 1gb DDR3s.  Run a 32 bit (ARGB) true-color display and make everything else drawn by a geometry engine every frame with optional edge anti-aliasing using the 'A' alpha channel when drawing the graphics.  The memory space and full true color wound mean full accelerated anti-aliased tiles/fonts/rendering including soft edge since there is an 8 bit translucency stencil alpha channel.  But, an 8 bit CPU would never really be able to take advantage of the horse power under the hood.  However, there is also enough room for a softcore 32bit - 68K type of cpu or simple arm-risc V which can be placed inside the LFE5U as well as a 64 channel full MIDI wavetable audio system.
This was part of the reason why I suggested implementing command lists that can be stored in video memory - this will completely decouple GPU performance from CPU, as latter can take it's merry time preparing next list while GPU works with existing one. This is how DirectX 11/12 API works. Those command lists can have external parameters, so that CPU can update things like object positions etc, without changing the actual command list. In DX parlance they are called constant buffers. CPU can update these buffers without changing command list, and then these are fed into the rendering pipeline automatically when command list references said buffer. All of that will make CPU performance almost non-factor, as pretty much all graphical stuff will be offloaded onto GPU.
Also I wonder if your existing core would be much simpler had it worked with full color objects and surfaces as opposed to packed-color ones, as I assume you will need additional HW to pack and unpack pixel information from data bytes stored in memory. While in case of full color this will be a trivial memory address calculation without any need to somehow transform data you get from memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on June 30, 2020, 07:51:30 pm
in this case it can be as low as 128 kHz (yes, you read it right - kilohertz!) - it mentions 7800 ns as max clock period.

You won't have enough time to refresh everything at that speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on June 30, 2020, 07:59:47 pm
You won't have enough time to refresh everything at that speed.
DLL disabled mode is not designed for operational use and none of characteristics are guaranteed. Quote from Micron's datasheet:
Quote
The DRAM is not tested to check—nor does Micron warrant compliance with—normal mode timings or functionality when the DLL is disabled. An attempt has been made to have the DRAM operate in the normal mode where reasonably possible when the DLL has been disabled; however, by industry standard, a few known exceptions are defined:
• ODT is not allowed to be used.
• The output data is no longer edge-aligned to the clock.
• CL and CWL can only be six clocks.
When the DLL is disabled, timing and functionality can vary from the normal operation specifications when the DLL is enabled (see DLL Disable Mode in Commands section of the data sheet for more information). Disabling the DLL also implies the need to change the clock frequency (see Input Clock Frequency Change section of the data sheet for details).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 09:18:56 pm
EDIT: Just a thought, but what about a general FILL function?  Specify a point coordinate and a colour and off it goes, filling in all pixels of the colour at the point coordinate with the new colour, until bounded by other colours?  Or would that be too far?
You only call the function twice in a row...
EG,


Code: [Select]
; *************************************************************************************
; ** Draw a filled ellipse (250,250)-(300,350) with palette color 9
; *************************************************************************************
set_x 0,d'175' ; set x0 register to 250 - The ellipse's top-left X position
set_y 0,d'175' ; set y0 register to 250 - The ellipse's top-left Y position
set_x 1,d'300' ; set x1 register to 300 - The ellipse's bottom-right X position
set_y 1,d'350' ; set y1 register to 350 - The ellipse's bottom-right Y position
plot_circle_fill d'9' ; plot a filled ellipse with palette color 9
        plot_circle d'15'         ; plot the outline of the same ellipse with palette color 15

Remember, my commands holding their screen coordinates were optimized to do this sort of thing.
You may make such a command in your Z80 graphics driver, but, it would just execute the above code.
The Geometry unit will draw between 25 million all the way up to 125 million pixels a second.  It wont break a sweat drawing the extra few pixels surrounding the edge of an ellipse, or rectangle a second time.

Give it a test in geo.bas.
Now, truly begin the 'geometry_xy_plotter.sv'.  Start with being able to load it's internal storage registers with the command input port.

 :palm: Sorry, my bad.  You meant a general 'Flood Fill', right?

     Ok, that would take a little feedback cooperation between the 'geometry_xy_plotter.sv' and 'pixel_writer', but I'm wondering how I could generate a cheap method where it can properly seek and fill around the corner of an onscreen object.

     A radiant style fill would be easy, but, on screen objects would be able to cast shadows which means it wouldn't be a true 'Flood Fill'.  If a shadow is cast, you would need to manually start an additional 'Flood Fill' in the void to complete the fill which may once again still contain additional voids.  If I can figure out an easy way to automatically drive the filling of the voids, you would have a really fast 'Flood Fill'.  Otherwise, the fill will need to be done in a much slower maze-seek algorithm.  (Much slower means filling something like 5 million pixels a second instead of 125 million a second.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 30, 2020, 09:31:24 pm
:palm: Sorry, my bad.  You meant a general 'Flood Fill', right?

Yes, that's the one.  Sorry, my terminology isn't necessarily up to the task - this is all new ground for me.

     Ok, that would take a little feedback cooperation between the 'geometry_xy_plotter.sv' and 'pixel_writer', but I'm wondering how I could generate a cheap method where it can properly seek and fill around the corner of an onscreen object.

     A radiant style fill would be easy, but, on screen objects would be able to cast shadows which means it wouldn't be a true 'Flood Fill'.  If a shadow is cast, you would need to manually start an additional 'Flood Fill' in the void to complete the fill which may once again still contain additional voids.  If I can figure out an easy way to automatically drive the filling of the voids, you would have a really fast 'Flood Fill'.  Otherwise, the fill will need to be done in a much slower maze-seek algorithm.  (Much slower means filling something like 5 million pixels a second instead of 125 million a second.)

Okay, well I kind of broke it into two separate things.  One was the original idea - the flood fill.  I have memories of doing these on my old Amstrad in whatever graphics programme I used to have and it would literally take tens of seconds, if not more for more complex shapes, to fill with a colour.  Having a hardware version of that would be useful - although perhaps with limited use-cases (the aforementioned graphics programme being the most obvious) - or old 'graphical adventures', where the picture for a key location would be built up in front of you as you read the descriptive text - again with some painfully slow flood fills.

The other idea that came out of it was polygons.  I think you mentioned being able to draw triangles or polygons with the ellipse function?  Being able to draw bespoke shapes with three, four or potentially more, vertices either as wireframe or filled would be VERY useful.  I know the line function can do the same thing with some additional work from the Z80, but being able to fill those shapes would be nice.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 09:42:01 pm
Also I wonder if your existing core would be much simpler had it worked with full color objects and surfaces as opposed to packed-color ones, as I assume you will need additional HW to pack and unpack pixel information from data bytes stored in memory. While in case of full color this will be a trivial memory address calculation without any need to somehow transform data you get from memory.
Yes, currently we have multiple different packed color modes and the pixel writer after the geometry unit has code to deal with it.  Yes, 32 bit only removes a lot of glut, but, remember DDR3 smallest burst has 8 words @ 32 bit for the optimum.  To make efficient use of the dram when reading and writing pixels, internally we would have a 8x32 = 256 bit bus which would look equivilant to a 1 bitplane image with an 8 bit memory bus.  Yes, it would be written out a little different, but it boils down to the same idea.  When reading or writing adjacent pixels, you do not want to sacrifice that minimum 4 cycle burst of the same DRAM memory address 8 times in a row with the write mask set for 1 individual byte every time.  Now you may have a DDR3 ram controller with a smart cache to manage this, but to properly weave your pixel plotting commands with reads for the screen refresh, you should organize your memory requests on the page burst boundary with the bottom CAS A0,A1,A2 all = 0.  Otherwise, there will end up having a few access penalties when as you cross a row address if the word alignment isn't on centered on the 8 byte burst.  In fact, once you have done this, everything, like geometry command arrays should all be padded and sit on an 8 word boundary.

The big difference is that we wouldn't have to worry about any other pixel formats.  And in the case of a 256 color paletted bitmap, there would be 1 function in the pixel writer to convert that bitmap to 32 bit in real time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2020, 09:53:13 pm
The other idea that came out of it was polygons.  I think you mentioned being able to draw triangles or polygons with the ellipse function?  Being able to draw bespoke shapes with three, four or potentially more, vertices either as wireframe or filled would be VERY useful.  I know the line function can do the same thing with some additional work from the Z80, but being able to fill those shapes would be nice.

Triangle and filled triangle, 4 sided polygon and filled 4 sided polygon will be added as they are basic functions for a 2D accelerator.  They are basically just 2 line functions running at once and tied together.  This is why I made the source X&Y coordinates have 4 points for up to 4 vertices.

Using the 'Line' function, with multiple coordinates to construct a closed shape, then flood fill that shape is easy.  Once the shape is completed, you would once again go back through all the 'points' in the object and do a radiant style fill 1 pixel toward the inside of the object.  Otherwise, you would just generate your object using multiple filled triangles just like any other 3D geometric generated image, or filled 4 sided polygons which are actually only 2 triangles with 1 matching face.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on July 01, 2020, 01:08:17 am
Yes, currently we have multiple different packed color modes and the pixel writer after the geometry unit has code to deal with it.  Yes, 32 bit only removes a lot of glut, but, remember DDR3 smallest burst has 8 words @ 32 bit for the optimum.  To make efficient use of the dram when reading and writing pixels, internally we would have a 8x32 = 256 bit bus which would look equivilant to a 1 bitplane image with an 8 bit memory bus.  Yes, it would be written out a little different, but it boils down to the same idea.  When reading or writing adjacent pixels, you do not want to sacrifice that minimum 4 cycle burst of the same DRAM memory address 8 times in a row with the write mask set for 1 individual byte every time.  Now you may have a DDR3 ram controller with a smart cache to manage this, but to properly weave your pixel plotting commands with reads for the screen refresh, you should organize your memory requests on the page burst boundary with the bottom CAS A0,A1,A2 all = 0.  Otherwise, there will end up having a few access penalties when as you cross a row address if the word alignment isn't on centered on the 8 byte burst.  In fact, once you have done this, everything, like geometry command arrays should all be padded and sit on an 8 word boundary.
Well - there is quite a bit you can do. For example, you can have a FIFO with 32 bit write port and whatever your memory interface width for a read port. Or you can split single x32 interface in two x16 ones, or four x8 (though that can get a bit wasteful in terms of pins needed for ADDR/CTRL lines). Or just duplicate your processing cores and process several pixels in parallel, so that you can write them all at the same time. Or some combination of above :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on July 01, 2020, 01:47:51 am
Otherwise, there will end up having a few access penalties when as you cross a row address

If your addressing scheme is such that the adjacent rows are in different banks, then crossing row boundaries will not pose any additional penalties.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 02:39:40 am
Otherwise, there will end up having a few access penalties when as you cross a row address

If your addressing scheme is such that the adjacent rows are in different banks, then crossing row boundaries will not pose any additional penalties.
You still cannot terminate mid burst without penalty.  With so much ram, word aligning all you data structures to sit evenly on a 8 word x whatever width bits boundary in the memory just shrinks down that problem.  For example, if you need to begin to read right at the end of the row, all addresses '1's, even though the ram will do it, the 8 word burst will just wrap around for the remaining 7 cycles after you get that first word you want, and the remainder of that burst will be wasted when what you want right after that initial last word is the next row right after.  Such word, and even double word alignment for data and code to even accelerate CPU copies began way, way, way back with 68020 and up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 01, 2020, 02:32:42 pm
Now, truly begin the 'geometry_xy_plotter.sv'.  Start with being able to load it's internal storage registers with the command input port.

Use the maggie.sv and rs232_DEBUGGER.v to get an idea of how to associate/assign labels from the source command & how to store those labels into the memory registers.  The labels and registers should be almost identical to the geo.bas labels.  Except for the x# & y#, make them 2 dimensional 12 bit registers for ease of design.  (I should have done that anyways within geo.bas.  Sorry, my bad.

I'd be lying if I said I knew what I was doing, so I've thrown some code at the Quartus project and I'm hoping what stuck is vaguely going in the right direction..  ???

Have got as far as the functions (I think) - not sure how to progress.  Anyway, take a look at the attached and let me know where I've gone wrong so far.  ::)

EDIT:
Updated code as I hadn't created registers for max_x, max_y or the two collision counters.  :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on July 01, 2020, 02:43:53 pm
For example, if you need to begin to read right at the end of the row, all addresses '1's, even though the ram will do it, the 8 word burst will just wrap around for the remaining 7 cycles after you get that first word you want, and the remainder of that burst will be wasted when what you want right after that initial last word is the next row right after.

You just read in whole bursts. If the start address is all ones, you don't align it so that it is the first bit in the burst. You align the bursts always the same. The content corresponding to the odd address with all '1' will be the last bit in the burst. Then you can cross row borders without problems. You can read something which spans several rows non-stop.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 04:01:52 pm
Now, truly begin the 'geometry_xy_plotter.sv'.  Start with being able to load it's internal storage registers with the command input port.

Use the maggie.sv and rs232_DEBUGGER.v to get an idea of how to associate/assign labels from the source command & how to store those labels into the memory registers.  The labels and registers should be almost identical to the geo.bas labels.  Except for the x# & y#, make them 2 dimensional 12 bit registers for ease of design.  (I should have done that anyways within geo.bas.  Sorry, my bad.

I'd be lying if I said I knew what I was doing, so I've thrown some code at the Quartus project and I'm hoping what stuck is vaguely going in the right direction..  ???

Have got as far as the functions (I think) - not sure how to progress.  Anyway, take a look at the attached and let me know where I've gone wrong so far.  ::)

EDIT:
Updated code as I hadn't created registers for max_x, max_y or the two collision counters.  :palm:

Ok, a little mistake on my part, these guys will be in the inside the memory pixel writer...  So they have to be removed.
Code: [Select]
    output Write_col[7:0],  // An 8 bit saturation counter which counts the number of pixel write collisions
    output Copy_col[7:0],   // An 8 bit saturation counter which counts the number of blit write from read pixel write collisions
    output idle             // An output which goes high when the geometry plotter is finished and is doing nothing

Next, your first 4 assigns need the destinations to have wires declared.

Next, this module's outputs are also wires (as well as the inputs).  (See maggie.sv for example.)

To begin with, make all your inputs and outputs on the ports 'wire'.  Look at maggie.sv to see how this is done.  You have the [x:y] on the wrong side of the names.

next make these 5 regs:
Code: [Select]
draw_cmd_func[3:0]
draw_cmd_data_color[7:0]
draw_cmd_data_word_Y[11:0]
draw_cmd_data_word_X[11:0]
draw_cmd_tx
Then I would assign the output port wire to them:
Code: [Select]
draw_cmd[35:32] = draw_cmd_func[3:0]
draw_cmd[31:24] = draw_cmd_data_color[7:0]
draw_cmd[23:12] = draw_cmd_data_word_Y[11:0]
draw_cmd[11:0]  = draw_cmd_data_word_X[11:0]
draw_cmd_rdy    = draw_cmd_tx

Make 16 localparams CMD_OUT_#choose a function name#  and make each = to the AUX# in my comments.

Then when sending a command, all you need to do is:
Code: [Select]
begin
 draw_cmd_func         <= CMD_OUT_#choose a function name#[3:0];
 draw_cmd_data_color   <= 'usually the draw color'
 draw_cmd_data_word_Y  <= 'usually Y coordinate'
 draw_cmd_data_word_X  <= 'usually  X coordinate'
 draw_cmd_tx           <= 1;
end ...
 else if no other new commands running draw_cmd_tx  <=0 ;

Basically, when sending a command, the 'draw_cmd' should have the right data and the 'draw_cmd_rdy' should go high same time.  The 'draw_cmd_rdy' may only be high for additional clocks if the next command going out is ready to go.
Basically when sending a command, make the draw_cmd_rdy =1, when doing nothing, or default state, make it =0.

I left out the things you should be able to work out on your own...

After this, compile in Quartus 9.1 on a schematic with inputs and outputs & try sending a few of the current completed commands and see if the output simulate right.

See attached 'geometry_xy_plotter.sv' where I tell you where and when you send out a command...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 01, 2020, 04:48:03 pm
Sorry, bit confused - how does draw_cmd[35:0] get populated with data?  draw_cmd_func, draw_cmd_data_color, draw_cmd_data_word_Y and draw_cmd_data_word_X don't get set anywhere?  I've obviously missed something...  ???

EDIT: Yes - I missed the last code paragraph in your reply.  Still not sure which X/Y coordinate gets set though?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 05:17:28 pm
Sorry, bit confused - how does draw_cmd[35:0] get populated with data?  draw_cmd_func, draw_cmd_data_color, draw_cmd_data_word_Y and draw_cmd_data_word_X don't get set anywhere?  I've obviously missed something...  ???

EDIT: Yes - I missed the last code paragraph in your reply.  Still not sure which X/Y coordinate gets set though?
Take a look at the assigns I added:
Code: [Select]
//************************************************
// Assign output port wires to internal registers
//************************************************
assign draw_cmd[35:32] = draw_cmd_func[3:0];
assign draw_cmd[31:24] = draw_cmd_data_color[7:0];
assign draw_cmd[23:12] = draw_cmd_data_word_Y[11:0];
assign draw_cmd[11:0]  = draw_cmd_data_word_X[11:0];
assign draw_cmd_rdy    = draw_cmd_tx;

Also, I changed your first 4 command names so they make modern sense.
I also added parameters to the reset collision counters so you may also set 1 to 4 transparent colors when counting collisions, and for when you write/paste a pixel with the mask function.

(See next post)
(back in 1.5hours)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 05:55:58 pm
Ok, I simplified the layout and and broke everything down to 2 case statements.  See attached code.

It would be nice to replace all the 8'd### with FUNC_IN_'name of function' and at the beginning of the code, make localparams for all the FUNC_IN_'name of function'.

You will need to change the geo.bas to reflect the new FUNC_IN_xxxx #s, and modify the 'instr.txt' file for the fwasm.exe compiler so it's commands reflect the new FUNC_IN_xxxx #s.

I'll be back in 1.5 hours...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 01, 2020, 06:25:22 pm
So I'm removing the func3 checks from Geo.bas entirely and instead checking func2 values, which need to match those in the Verilog file, right?

Did you include the code for 8'd127 in the extend_cmd case statement as an example of how the rest should go, or....?  Bit confused as Geo.bas uses x0 * 4096 + y0, but in the Verilog you've just assigned x[0] and y[0] directly to draw_cmd_data_word_X/Y.  Is that right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 07:20:54 pm
So I'm removing the func3 checks from Geo.bas entirely and instead checking func2 values, which need to match those in the Verilog file, right?

Did you include the code for 8'd127 in the extend_cmd case statement as an example of how the rest should go, or....?  Bit confused as Geo.bas uses x0 * 4096 + y0, but in the Verilog you've just assigned x[0] and y[0] directly to draw_cmd_data_word_X/Y.  Is that right?
Yes.  Its just that in the geo.bas, x&y should be swapped as Y holds the MSBs and X the LSBs.  I already got the right order in the .sv file for you.

Just look at the width of the assigned bits and where they end up.
I know in basic, I did it the *4096 for the MSBs and +(add) the LSBs.

Since the command input into this module is 16 bits wide, we need a method send a 24 bit address to the pixel writer.  The only way to do so is load 2 12 bit addresses into one of our temporary X&Y registers, then send those to the pixel writer.  Remember, the pixel writer has a 36bit command port, not 16 bit.

I allowed 12 bits to sent in 1 command by reserving commands 128 through 255, and using the lower 12 bits of the command to set the 8 available 12bit work registers.  Commands 0 through 127, IE command bit [7] being low, all perform 1 alternate function with the allowance for 1 additional byte stored in the first 8 bits of the command.


This means for the Z80 to send a command, it would need to send 2 adjacent bytes every time.
The 'geometry_xy_plotter.sv' takes in those 16 bit commands and will occasionally spit out 36bit commands to the next module containing the address generator which translates the mem address and x&y coordinates into a new mem address with the right offset pointing to the pixel, that unit will feed the memory writer which does a read/modify/write at the specified address, counting if there is a pixel collision.

After you complete this part and simulation of the geometry engine, we will add the first geometric shape, a box and a box fill.  When simulating that one, after issuing the command, the geo engine should spit a stream of CMD_OUT_PXWRI commands with x&y coordinates.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 01, 2020, 08:08:50 pm
Okaaay.. I think the code is up to date with what you've specified.  Have attached both the Verilog and Free Basic source below.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 09:02:18 pm
Ok, I touched up the geometry_xy_plotter.sv.
Read it carefully and make it work and simulate in Quartus.

Also, add an IF(reset) ... else ... right at the top to default all the registers.

I also added the geo_shape, geo_run, geo_mask, geo_fill registers, tied them into the case statement and made a separate section after the loading of a command, the area where we place the running geo units.  I also assigned the load_cmd output and commented on each reg's purpose.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 01, 2020, 09:33:07 pm
Ok, I touched up the geometry_xy_plotter.sv.
Read it carefully and make it work and simulate in Quartus.

Also, add an IF(reset) ... else ... right at the top to default all the registers.

I also added the geo_shape, geo_run, geo_mask, geo_fill registers, tied them into the case statement and made a separate section after the loading of a command, the area where we place the running geo units.  I also assigned the load_cmd output and commented on each reg's purpose.

You just need to attach the file.  ;)  Will take a look tomorrow.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 01, 2020, 11:06:43 pm
Ok, I've done the heavy lifting...

Here is the Quartus9.1 Simulation test bench:
[attachimg=1]

Here is a test simulation:
[attach=2]

And, I've attached the Quartus project.
Read the 'geometry_xy_plotter.sv' inside and see how I vastly simplified the case setup using the 'casez' command and using '?' for don't care bits on the commands.

Make sure you understand everything before continuing.  Next, you still need to add the 'reset' and test out a few of the current functioning commands in the simulation.

Ask questions!
Change my stimulus simulation inputs so that you at least fill an x&y coordinates in x0/y0, x1/y1.

Don't assume anything cause next, we will put in the 'draw_box' algorithm and watch it spit out a bunch of coordinates to plot.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 03:40:15 am
Ok, so I had time and got bored....  I figured coding would be better the snacking on junk food...

I've added the box & box_filled command, however, I deliberately did not make any comments on the function.
It will be your job to fill in the comments for each line & post them here so I can make sure you understand what's going on.

The code appears to simulate fine, with coordinates in all 4 directions.

You will also be responsible for testing the code in the simulator by manipulating the commands going into the geometry unit and deciphering the results.

Full Quartus project attached below.
(It so far compiles with an FMAX above your core 125MHz clock, though, we can run the geometry unit at 75MHz if ever needed.  It's only the memory pixel writer which we want running at 125MHz.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 10:15:54 am
I've added the box & box_filled command, however, I deliberately did not make any comments on the function.
It will be your job to fill in the comments for each line & post them here so I can make sure you understand what's going on.

Here you go:

Code: [Select]
case (geo_shape)    // run a selected geometric drawing engine

4'd1 : begin    // draw a filled rectangle

if ( geo_y != (y[1] + geo_ydir) ) begin             // Check for bottom (or top, depending on sign of geo_ydir) of rectangle reached
if ( geo_x != (x[1] + geo_xdir) ) begin         // Check for right (or left, depending on sign of geo_xdir) of rectangle reached
draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.
draw_cmd_tx          <= 1'b1;               // send command (have moved this after the X, Y setting for easy reading)

// Now increment (or decrement according to geo_xdir) geo_x to the next pixel.
// If geo_fill is HIGH, step to next X-position to fill the rectangle.
// If geo_x is at the end edge, step past it.
// If geo_y is at start or end (top or bottom edge), step to next X-position to draw the horizontal line.
if (geo_fill || geo_x == x[1] || geo_y == y[0] || geo_y == y[1] )   geo_x <= geo_x + geo_xdir;
// Otherwise, jump to end X-position to draw other edge for non-filled rectangle.
else                                                                geo_x <= x[1];

end else begin  // geo_x has passed vertical edge
draw_cmd_tx         <= 1'b0;                // do not send a draw cmd this cycle
geo_x               <= x[0];                // reset X to start X-position
geo_y               <= geo_y + geo_ydir;    // increment (or decrement) Y-position for next line
end
end else begin      // geo_y has passed horizontal edge
geo_run             <= 1'b0;                // stop geometry engine - shape completed
draw_cmd_tx         <= 1'b0;                // do not send a draw cmd this cycle
end

end // draw a filled rectangle

The code appears to simulate fine, with coordinates in all 4 directions.

You will also be responsible for testing the code in the simulator by manipulating the commands going into the geometry unit and deciphering the results.

I'm confused about how cmd_h (with a value of 12) creates a filled rectangle (or a value of 8 creates a non-filled rectangle) - or how any value is interpreted from cmd_h and cmd_l.  There's a few bit operations and splitting of the cmd bus going on that I'm having difficulty following.   :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 11:08:34 am
I'm confused about how cmd_h (with a value of 12) creates a filled rectangle (or a value of 8 creates a non-filled rectangle) - or how any value is interpreted from cmd_h and cmd_l.  There's a few bit operations and splitting of the cmd bus going on that I'm having difficulty following.   :o
I separated the command into _h and _l for legibility.  Take a look at lines 207 through 231 (in particular line 214 where I transpose the draw command number) this is where I setup all the controls for the geometry engine:
Code: [Select]
            8'b000????? : begin // this range of commands all begin drawing a shape.
                                // drawing commands begin here.  Keep the convention that:
                                // extend_cmd[0] = mask enable
                                // extend_cmd[1] = use the color in the copy/paste buffer.  This one is for drawing in true color mode.
                                // extend_cmd[2] = fill enable

                geo_shape[3]         <= 1'b0;           // geo shapes 0 through 7, geo shapes 8 through 15 are for copy & paste.
/*LINE 214*/      geo_shape[2:0]       <= command_in[5:3];// Set which one of shapes 0 through 7 should be drawn.  Shape 0 turns means nothing is being drawn
                geo_fill             <= command_in[2];
                geo_paste            <= command_in[1];  // used for drawing in true color 16 bit mode
                geo_mask             <= command_in[0];
                geo_run              <= 1'b1;           // a flag which signifies that a geometric shap drawing engine will begin drawing
                geo_color            <= command_data8;  // set the 8bit pen color.
               
                geo_sub_func1        <= 4'b0;           // for geometric engines which have multiple phases, reset the phase counter
                geo_sub_func2        <= 4'b0;           // for geometric engines which have 2 dimensional multiple phases, reset the phase counter
               
                // Initialize the geometry unit starting coordinates and direction so it can begin plotting immediately
                geo_x                <= x[0];           // initialize the beginning pixel location
                geo_y                <= y[0];           // initialize the beginning pixel location
                if ( x[1] < x[0] ) geo_xdir <= 12'd0-12'd1; // set the direction of the counter (negative x in this case)
                else               geo_xdir <= 12'd1;       // positive x direction
                if ( y[1] < y[0] ) geo_ydir <= 12'd0-12'd1; // negative y direction
                else               geo_ydir <= 12'd1;       // positive y direction
            end

Now, let's make a change (Read all the ***):
Code: [Select]
            8'b000????? : begin // this range of commands all begin drawing a shape.
                                // drawing commands begin here.  Keep the convention that:
                                // ***extend_cmd[3] = fill enable
                                // ***extend_cmd[4] = use the color in the copy/paste buffer.  This one is for drawing in true color mode.
                                // ***extend_cmd[5] = mask enable - when drawing, the mask colors will not be plotted as they are transparent
 
                geo_shape[3]         <= 1'b0;           // geo shapes 0 through 7, geo shapes 8 through 15 are for copy & paste.
/*LINE214*/     geo_shape[2:0]       <= command_in[2:0];// *** Set which one of shapes 0 through 7 should be drawn.  Shape 0 turns means nothing is being drawn
                geo_fill             <= command_in[3];  // *** Fill enable bit.
                geo_paste            <= command_in[4];  // *** used for drawing in true color 16 bit mode
                geo_mask             <= 1'b0;           // *** Mask disables when drawing raw geometry shapes
                geo_run              <= 1'b1;           // a flag which signifies that a geometric shap drawing engine will begin drawing
                geo_color            <= command_data8;  // set the 8bit pen color.
               
                geo_sub_func1        <= 4'b0;           // for geometric engines which have multiple phases, reset the phase counter
                geo_sub_func2        <= 4'b0;           // for geometric engines which have 2 dimensional multiple phases, reset the phase counter
               
                // Initialize the geometry unit starting coordinates and direction so it can begin plotting immediately
                geo_x                <= x[0];           // initialize the beginning pixel location
                geo_y                <= y[0];           // initialize the beginning pixel location
                if ( x[1] < x[0] ) geo_xdir <= 12'd0-12'd1; // set the direction of the counter (negative x in this case)
                else               geo_xdir <= 12'd1;       // positive x direction
                if ( y[1] < y[0] ) geo_ydir <= 12'd0-12'd1; // negative y direction
                else               geo_ydir <= 12'd1;       // positive y direction
            end

Change the .sv and simulate.  Tell me now what are the new 2 commands for drawing a box outline and filled box.  Simulate to make sure you got the figures correct.

This setup should make more sense...

Also make sure you verify that you understand how lines 101 & 102 work.  Why those 2 allow you to set all the x#&y# with 12 bit numbers, and why lines 107-108 & 115-116 send out all 4 of each as destination or source memory addresses.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 11:44:46 am
Change the .sv and simulate.  Tell me now what are the new 2 commands for drawing a box outline and filled box.  Simulate to make sure you got the figures correct.

Box outline = 0x01
Box filled    = 0x09

[attachimg=1]

This setup should make more sense...

Also make sure you verify that you understand how lines 101 & 102 work.  Why those 2 allow you to set all the x#&y# with 12 bit numbers, and why lines 107-108 & 115-116 send out all 4 of each as destination or source memory addresses.

 :-+ Sure does.

As for lines 101/102 - yes, happy with how they work.  Haven't encountered casez before, but certainly looks like a powerful and useful statement.  Clever coding as well, reducing all those previous case statements down to two lines to assign the 12-bit number to the appropriate x# and y#.  :clap:

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 12:10:08 pm
Ok, change line 244 to:

Code: [Select]
4'd2 : begin    // draw a filled rectangle
This will make the rectangle shape #2 and filled rectangle shape #10.

Now, add in the plotting section:
Code: [Select]
4'd1 : begin    // draw line from (x[0],y[0]) to (x[1],y[1])
.......
end //  draw line from x[0],y[0] to x[1],y[1]

Remember my trick when I construct the rectangle that the first point in the line has already been set by the time this algorithm has been called.  When turning on the CMD_OUT_PXWRI, that coordinate will be sent.  When incrementing the line location, that inc comes out on the next clock cycle which is why I increase the destination by 1 when testing to see if we reached the final pixel in the IF().

Note: The filled flag is ignored for a single line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 12:25:06 pm
Haven't encountered casez before, but certainly looks like a powerful and useful statement.  Clever coding as well, reducing all those previous case statements down to two lines to assign the 12-bit number to the appropriate x# and y#.  :clap:
As long as you understand that the '?' are don't care bits, and they can be spread out through the case#.
Also you understand that how I'm addressing the x&y array 0 through 3.  You will need to do something like this again when it comes to the pixel writer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 12:44:52 pm
So, single line drawing:

Code: [Select]
        4'd1 : begin    // draw line from (x[0],y[0]) to (x[1],y[1])
       
            if ((geo_y != (y[1] + geo_ydir) and (geo_x != x[1] + geo_xdir)) begin
       
                draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
                draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
                draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
                draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.
                draw_cmd_tx          <= 1'b1;               // send command (have moved this after the X, Y setting for easy reading)
               
                // increment x,y position
               
       
            end else begin  // end of line
           
                geo_run         <= 1'b0;
                draw_cmd_tx     <= 1'b0;
           
            end
       
        end // draw line

Got that far.  I need to create variables for dx, dy, errd and magic?  Where would be the best place for these?  I thought about assigning them in the same place as where geo_x and geo_y are given their starting values?  They may not be used for all the drawing functions, but it makes sense (to me at least)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 01:26:03 pm
Ok, the line algorithm has an extended setup, so you need to think of the code running in 2 hunks.

Back at the initialization section, at line 221-222, I prepared 2 variable to allow you to make such sequences just in case:
Code: [Select]
                geo_sub_func1        <= 4'b0;           // for geometric engines which have multiple phases, reset the phase counter
                geo_sub_func2        <= 4'b0;           // for geometric engines which have 2 dimensional multiple phases, reset the phase counter

Now, this is how you would start your line code:

Code: [Select]
  4'd1 : begin    // draw line from (x[0],y[0]) to (x[1],y[1])
       
case(geo_sub_func1) // During the draw line, we have multiple sub functions to call 1 at a time

4'd0 : begin  //(case sub_function=0)  **** Initialize line parameters

/*  do this setup function 0
    dx = x1 - x0
    dy = y1 - y0
*/
geo_sub_func1 <= 4'd1 ;  // switch over to the next function
end // (case sub_function=0)

4'd1 : begin  //(case sub_function=1)  **** Second Initialize line parameters
   
/*  Do this setup function next
   if (dx < 0) Then
        dx = -dx
        sx = -1
    Else
        sx = 1
    End If
   
    if (dy > 0) Then
        dy = -dy
        sy = 1
    Else
        sy = -1
    End If
*/

geo_sub_func1 <= 4'd2 ;  // switch over to the next function
end // (case sub_function=1)

4'd2 : begin  //(case sub_function=0)  **** Initialize line parameters

/*  do this setup function last
    magic = 0
    errd  = dx + dy
    x     = x0
    y     = y0
    is_done = FALSE ********* do not bother with is_done, use 'geo_run' instead.  It is already set and you clear it to break the function.
*/

geo_sub_func1 <= 4'd3 ;   // setup done, switch over to the next function, drawing the actual line
end // (case sub_function=2)



4'd3 : begin  //(case sub_function=3) Draw the line
            if ( (geo_y != (y[1] + geo_ydir)) && (geo_x != (x[1] + geo_xdir)) ) begin
       
                draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
                draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
                draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
                draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.
                draw_cmd_tx          <= 1'b1;               // send command (have moved this after the X, Y setting for easy reading)
               
                // increment x,y position
               
       
            end else begin  // end of line
           
                geo_run         <= 1'b0;
                draw_cmd_tx     <= 1'b0;
           
              end

end // (case sub_function=3) drawing the line.

endcase // ending case the multiple sub functions of draw line
       
        end // end of draw line

Now, this is a baby step that I broke down the basic code into ordered sequences which can be done in parallel.
You will need 'signed regs' for the dx,dy,errd,magic.

I coded it this way so you can see, test, and simulate what is happening an be sure of the results.  Step by step.  (Remember, in the simulation waveform, you can add internal hidden variables to the waveform view.  You can even add analog 'oscilloscope' view of any regs.  (I'm expecting a sine wave when plotting a circle))

However, with this setup, there are 3 additional system clocks going before the line begins to plot.  Once you can draw a line properly, you would want to shrink this down to 1 clock.  IE step 0 = setup, step 2 = drawing line.  Note that it is possible to do the variable setup instantly with an ugly big Boolean equation, but, for a Z80 at 20MHz, I don't think we need to worry about 1 clock at 125MHz.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 01:39:29 pm
Ah, I'd already started working on the setup before I read your last post.  Do we need sx and sy?  I was thinking I could use geo_xdir and geo_ydir for these?  I'd also obtained the absolute values for dx and dy like this:

Code: [Select]
dx              <= (x[1]>x[0]) ? (x[1]-x[0]) : (x[0]-x[1]); // get absolute size of delta-x
dy              <= (y[1]>y[0]) ? (y[1]-y[0]) : (y[0]-y[1]); // get absolute size of delta-y
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on July 02, 2020, 01:45:30 pm
Hey guys! Do you have full HDL sources for this project? I'm curious if it can be ported to Xilinx/Vivado and Lattice platforms without major changes. I noticed you are using schematics for the top level, but if my memory serves me (it's been a while since I used Quartus) it can generate an actually HDL file that reflects what's on schematic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 01:52:25 pm
Hey guys! Do you have full HDL sources for this project? I'm curious if it can be ported to Xilinx/Vivado and Lattice platforms without major changes. I noticed you are using schematics for the top level, but if my memory serves me (it's been a while since I used Quartus) it can generate an actually HDL file that reflects what's on schematic.

Full project is available here (https://github.com/nockieboy/gpu).  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on July 02, 2020, 02:29:06 pm
Full project is available here (https://github.com/nockieboy/gpu).  :)
Thanks!
I tried importing it to Vivado, and as I suspected top level HDL file is missing, and I don't have Quartus to see if I can generate it :(
Well it was worth the shot.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 02:36:07 pm
Full project is available here (https://github.com/nockieboy/gpu).  :)
Thanks!
I tried importing it to Vivado, and as I suspected top level HDL file is missing, and I don't have Quartus to see if I can generate it :(
Well it was worth the shot.

The top-level repo isn't actually a Quartus project - there's several Quartus projects in various folders.  EP4CE10 is the one to look in for the Quartus project, but you're right, there's no top level HDL file, just a design/schematic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on July 02, 2020, 02:41:26 pm
The top-level repo isn't actually a Quartus project - there's several Quartus projects in various folders.  EP4CE10 is the one to look in for the Quartus project, but you're right, there's no top level HDL file, just a design/schematic.
Yes I figured it out as I still remember what Quartus project looks like. Can you see if you can somehow generate HDL file from that schematic?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 02:53:11 pm
The top-level repo isn't actually a Quartus project - there's several Quartus projects in various folders.  EP4CE10 is the one to look in for the Quartus project, but you're right, there's no top level HDL file, just a design/schematic.
Yes I figured it out as I still remember what Quartus project looks like. Can you see if you can somehow generate HDL file from that schematic?

Hmmm.. it seems I can, but I'm getting errors from Quartus about illegal characters in the design file and illegal pins in the Verilog HDL.  I don't know if @BrianHG might have more luck or suggestions?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 02:58:22 pm
Here's my latest code for the line drawing (attached as file at bottom).

I can't get it to work properly, having tried a number of variations on the code.  geo_x seems to be incrementing/decrementing properly, but geo_y isn't after the first loop.  :-//

[attach=1]

Oh,  also had to modify the setup of geo_xdir and geo_ydir a little to account for horizontal and vertical lines (neutral x or y increments):

EDIT:
One problem seems to be that I got the sign wrong on calculating dy - should be:
Code: [Select]
dy              <= (y[0]>y[1]) ? (y[1]-y[0]) : (y[0]-y[1]); // get absolute size of delta-y
[attach=2]

Now geo_y is updating, but we're not reaching x[1]y[1] at the same time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 04:19:38 pm
Ok, if you take a look at the basic code, remember, these lines are happening forward 1 after the other:
Code: [Select]
      magic = errd shl 1
      if (magic > dy) Then
         errd += dy
         x    += sx
      End If
       
      if (magic < dx) Then
         errd += dx
         y    += sy
      End If

This means if you want to make the verilog equivalent, like the beginning startup, you will need to make a second sub 'geo_sub_func#2'.  Doing it this way, I bet you can get it to work, 1 ploted pixel would come out every 3 clock cycles.

If you want, attempt this strategy first.  I'm sure you will get it to work.  The real magic comes if you make a code which will plot a pixel every single clock cycle.  I've tested my magic functional code, I'll upload it if you give up.  For now, here is some light to send you in the right direction:

Code: [Select]
                    // increment x,y position
                    //magic       <= errd << 1; ************ Remember, this takes 1 clock cycle for magic to have the result
                    if ( (errd << 1) > dy) begin  // havind the '(errd << 1)' inside the if means it's checking the immediate number, not 1 clock delayed number

Note: Getting the rest is not as easy it may seem, but, the final result is fairly simple and should correctly plot a new pixel every single clock cycle.  The output should match the geo.bas.  (I attached one where I print the line coordinates on the screen.)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2020, 05:00:47 pm
Just in case you were wondering about my 'magic' code compared to geo.bas, with an uneven line, see sim here:
[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2020, 09:15:32 pm
No worries - will have to take a look at this tomorrow now, I've had an unexpectedly busy evening and not been able to even look at this!  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 08:45:04 am
Ok, if you take a look at the basic code, remember, these lines are happening forward 1 after the other:
Code: [Select]
      magic = errd shl 1
      if (magic > dy) Then
         errd += dy
         x    += sx
      End If
       
      if (magic < dx) Then
         errd += dx
         y    += sy
      End If

This means if you want to make the verilog equivalent, like the beginning startup, you will need to make a second sub 'geo_sub_func#2'.  Doing it this way, I bet you can get it to work, 1 ploted pixel would come out every 3 clock cycles.

Ah, of course, I'd forgotten that rather important feature of HDL...  :palm:

If you want, attempt this strategy first.  I'm sure you will get it to work.  The real magic comes if you make a code which will plot a pixel every single clock cycle.  I've tested my magic functional code, I'll upload it if you give up.  For now, here is some light to send you in the right direction:

Code: [Select]
                    // increment x,y position
                    //magic       <= errd << 1; ************ Remember, this takes 1 clock cycle for magic to have the result
                    if ( (errd << 1) > dy) begin  // havind the '(errd << 1)' inside the if means it's checking the immediate number, not 1 clock delayed number

Note: Getting the rest is not as easy it may seem, but, the final result is fairly simple and should correctly plot a new pixel every single clock cycle.  The output should match the geo.bas.  (I attached one where I print the line coordinates on the screen.)

Okay, have plugged away at this over several iterations now and am still getting exactly the same output in the simulation. :(

My code is below - I've tried to go for gold and get the single-cycle pixel output, but it's not working.  geo_y isn't incrementing at the correct rate and neither geo_x or geo_y are hitting x[1] or y[1] at the same time, causing the line to carry on forever.

Code: [Select]
4'd2 : begin

draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.
draw_cmd_tx          <= 1'b1;               // send command (have moved this after the X, Y setting for easy reading)

if (geo_x == x[1] && geo_y == y[1]) begin  // end of line
geo_run         <= 1'b0;
draw_cmd_tx     <= 1'b0;
end

// increment x,y position
if ((errd << 1) > dy) begin

errd    <= errd + dy;
geo_x   <= geo_x + geo_xdir;

if (((errd+dy)<<1) < dx) begin

errd    <= errd + dx;
geo_y   <= geo_y + geo_ydir;

end

end else if ((errd << 1) < dx) begin

errd    <= errd + dx;
geo_y   <= geo_y + geo_ydir;

end

end

I can't figure out how to get the increment x,y position block to execute in a single cycle.  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 08:48:26 am
Ah, hang on - GOT IT!  ;D

Those if...endifs require some lateral thought to convert to a fully parallel system like HDL.  :o

[attach=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 08:51:39 am
You arent plotting the last pixel....
This is my version:
Code: [Select]
                    // increment x,y position
                    //magic       <= errd << 1; ************ Remember, this takes 1 clock cycle for magic to have the result
                    if ( (errd << 1) > dy) begin  // havind the '(errd << 1)' inside the if means it's checking the immediate number, not 1 clock delayed number

geo_x   <= geo_x + geo_xdir;

if ( ((errd << 1) + dy) < dx)  begin
errd    <= errd + dy + dx;
geo_y   <= geo_y + geo_ydir;
end else errd    <= errd + dy;
 
                    end else if ( (errd << 1) < dx) begin
errd    <= errd + dx;
geo_y   <= geo_y + geo_ydir;
end
               
                end

You still need to plot the last pixel...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 08:53:45 am
You arent plotting the last pixel....

Yes, I've spotted that - just looking into it.

Is that going to need another geo_sub_func1 stage to execute the draw command for the last pixel?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 08:59:41 am
You arent plotting the last pixel....

Yes, I've spotted that - just looking into it.

Is that going to need another geo_sub_func1 stage to execute the draw command for the last pixel?

Try this:
Code: [Select]
                    if (geo_x == x[1] && geo_y == y[1]) begin  // end of line
                        //geo_run         <= 1'b0;
                        //draw_cmd_tx     <= 1'b0;
                        //geo_sub_func1     <= 4'd3;  // On the next clock, run the stop-drawing-line function.
                        geo_shape         <= 4'd0;  // On the next clock, end the stop-drawing-line function.
                    end
Code: [Select]
           default : begin
geo_run         <= 1'b0; // no valid drawing engine selected, so stop the geo_run flag.
draw_cmd_tx     <= 1'b0; // no valid drawing engine selected, so make sure draw_cmd_tx is disabled.
end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 09:00:25 am
Also simulate your line with an odd angle to make sure...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 09:10:06 am
Yeah, that seems to work just fine.  :-+

I noticed my code is slightly different to yours, though?
Code: [Select]
// increment x,y position
if ((errd << 1) > dy) begin
   
if (((errd+dy)<<1) < dx) begin

errd    <= errd + dx + dy;
geo_y   <= geo_y + geo_ydir;
geo_x   <= geo_x + geo_xdir;

end else begin

errd    <= errd + dy;
geo_x   <= geo_x + geo_xdir;

end

end else if ((errd << 1) < dx) begin

errd    <= errd + dx;
geo_y   <= geo_y + geo_ydir;

end

Hoping the differences are cosmetic.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 09:12:52 am
Never mind, it was cosmetic.  I hadn't streamlined the code and removed the unnecessary 'geo_x <= geo_x + geo_xdir' lines from the first nested if conditional.  Sorted now.

Have simulated with a variety of random values, negatives and positives, and all appear to work fine.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 09:14:57 am
Ok, next, the big fat circle...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 09:18:59 am
Never mind, it was cosmetic.  I hadn't streamlined the code and removed the unnecessary 'geo_x <= geo_x + geo_xdir' lines from the first nested if conditional.  Sorted now.

Have simulated with a variety of random values, negatives and positives, and all appear to work fine.  :-+

LOL, in you code:

            default : begin
           
                geo_run         <= 1'b0; // no valid drawing engine selected, so stop the geo_run flag.
                geo_run         <= 1'b0;  AGAIN??? ^Look Up^
                draw_cmd_tx     <= 1'b0;
               
            end

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 09:30:27 am
D'oh!  Good old copy-paste errors!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 09:59:16 am
Fixing the 'Data_mux' module bug.
If you remember, in the Z80_bridge, we had to make the read requests and write requests going into the data_mux 2 clock cycles fat before we could solve the Z80 R&W errors.
See here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2859700/#msg2859700 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2859700/#msg2859700)

Anyways, the problem had to be solved 'properly' for the geometry pixel writer.
Step 1, simulate the original 'data_mux' with single clock cycle pulsed read and write requests from both ports A&B.
[attach=1]
The green boxes and lines denote a read or write request, and the successful results.
The red boxes and lines denote a read or write request, but failure to execute a proper response.

Next, the re-write.  The new 'data_mux_v2' with the same simulation stimulus:
[attach=2]
As you can see, all the same read & write requests properly execute the desired proper response.  In fact, as an improvement, right at 230ns, I placed 2 consecutive read requests simultaneously on on both port inputs for a total of 4 consecutive reads.  The new data_mux_v2 now cached the 4 reads, interleaves the read addresses to the GPU ram and returns all 4 addressed data results to the correct port.
(You can sort of see why we had problems earlier.  And also how adding another port for the geometry pixel writer would have been a nightmare if I didn't patch this one up properly...)

Attached are the Quartus Simulation test benches for both the original and the new data_mux 2:1 ram port emulator.

@nockieboy, step 1, change the data_mux to the data_mux_v2 in your GPU project from my working simulat source code.  You will also need to add my 'fifo_3word_0_latency.sv' source code located in the simulation project to your GPU project as well.

Step 2, text the Z80 and RS232 interface.

If working, then go to step #3, change the Z80_bridge back the it's original intended mode of operation.

Step3, fix these lines in 'Z80_bridge.sv' so that the gpu_rd_req&wr_ena pulses are now 1 clock cycle wide like so:
Code: [Select]
   // GPU RAM FLAGS
   gpu_wr_ena     <= Write_GPU_RAM && ~last_Z80_WR; // (data_mux bug fixed, pulse for only 1 clock, not 2) 2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
   gpu_rd_req     <= Read_GPU_RAM  && ~last_Z80_RD; // (data_mux bug fixed, pulse for only 1 clock, not 2) 2 ; // Pulse the read request only once at the beginning of a read cycle.

And test the Z80 access + RS232 Debugger access.  Report results please.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 11:07:13 am
Okay, have done some testing with the new mux_v2 module.  Primarily, everything seems to work fine - however, my PS/2 keyboard no longer works properly.  After about the second keypress, the screen is filled with :) faces and then blanks.

Initially I thought the keyboard may be damaged, as I managed to drop it on the floor earlier ::), but a test using the old mux module showed it was working okay.  I'm still getting the odd duplication of some key presses which I've been meaning to look at, but on the whole it's usable.

This indicates there's still an issue with the IO read function in the z80_bridge, which is probably affected by the changes in the mux_v2 module, making it unusable.  I think I'm going to need help debugging that.  However, whilst testing with the serial console providing input to the system, I didn't experience any errors accessing or modifying GPU RAM.

EDIT:  I'm going to try again, but with the Stage 3 changes to the z80_bridge as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 11:22:44 am
No, doesn't seem to be working at all with the stage 3 modification.  The screen is badly corrupted, randomly each time I reset the system, so it looks like writes to the GPU RAM are being corrupted and it can't set up the display properly.  That's before I can even get to using the keyboard.  :-\

EDIT:  The RS232_debugger is reading and writing the GPU RAM fine, however.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 02:26:13 pm
Please try setting just the read to 1 pulse and the write enable back to 2 pulses to make sure the new reads 1 shot reads are ok.

If the single write present the bug, upload a copy of the latest version for me to take a look at.  This time around, I think we may be latching the Z80 data bus itself too early and I want to try something.

Also, please specify how the Z80 software keyboard is accessed.  I would like to know how it relates to 'writing' to GPU ram, and then how it relates to reading the GPU ram.  IE - when does the keyboard access use the 'gpu_wr_ena' and  'gpu_rd_req' flags.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 03:03:37 pm
Please try setting just the read to 1 pulse and the write enable back to 2 pulses to make sure the new reads 1 shot reads are ok.

Yes, that's working.

If the single write present the bug, upload a copy of the latest version for me to take a look at.  This time around, I think we may be latching the Z80 data bus itself too early and I want to try something.

No problem - latest z80_bridge.sv attached.

Also, please specify how the Z80 software keyboard is accessed.  I would like to know how it relates to 'writing' to GPU ram, and then how it relates to reading the GPU ram.  IE - when does the keyboard access use the 'gpu_wr_ena' and  'gpu_rd_req' flags.

Hmm.. well that's the thing, the keyboard doesn't touch the GPU RAM (at least not in the z80_bridge). Here's the process:

1) A key is pressed
2) ps2_keyboard_to_ascii.vhd converts the keycode to an ASCII code, after filtering 'break' codes, shifts, caps, etc.
3) PS2_RDY goes HIGH to signal valid char data in z80_bridge.
4) The char is latched into the PS2_CHAR register (line 289 in z80_bridge)

That's it for z80_bridge.  Currently I'm not using interrupts, so the char sits in PS2_CHAR until it's overwritten with another character or the Z80 initiates an IO read cycle addressing the PS/2 IO port:

1) IO_DATA_RL goes HIGH on detection of an IO cycle addressing the PS2 port (240) (lines 312-317)
2) After a short delay, IO_DATA_RL goes HIGH, causing the bidirectional data bus to switch to output (TO Z80) and placing the char onto the data bus (lines 320-327)
3) At the end of the IO cycle, PS2_CHAR is cleared to zero (important as the Z80 software takes a zero value as no char, otherwise it would repeatedly think the same key has been pressed)
4) The bidirectional data bus switches back to TO FPGA and goes hi-Z

So all I'm using to store the PS/2 character code is an 8-bit register.  Once the Z80 has received a valid character it does whatever it needs to with it and may send it back to the GPU RAM as a character to display (echoing the key press on the screen).

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 03:15:47 pm
not enough,  need the full project you are working with...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 03:26:15 pm
Give this line a try:
Code: [Select]
// This will make sure the Write_GPU_RAM is high for 3 consecutive clocks.  The output 'gpu_wr_ena' will still only pulse for 1 clock cycle.
// Think of this like a noise removal for the bus write command and address with extra time for the Z80 data bus to stabilize before accepting and writing the data to the GPU
gpu_wr_ena     <= (Write_GPU_RAM && last_Z80_WR && last_Z80_WR2) && ~last_Z80_WR3; // (data_mux bug fixed, pulse for only 1 clock, not 2) 2 ; // Pulse the GPU ram's write enable only once after the Z80 write cycle has completed
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 03:44:36 pm
Hmm.. well, aside from the background colour being dark yellow instead of black and the text getting corrupted (but only when the screen scrolls up), it's a bit of an improvement.

Using the memory editor, I can see that there are random read errors appearing in the data.  I'm viewing the 2nd page of GPU RAM, which is empty (all zeros), and every time I read that page I'm getting between 0-3 errors - they're coming up as 0x7Es, not that it means much I guess.

Perhaps we need to delay the Write_GPU_RAM for a little longer?

EDIT:  If it helps, I found that putting data onto the Z80's data bus too early in the IO cycle meant I got garbage when trying to read a value from the GPU via IO.  The memory cycle timing is tighter, but perhaps it's the same issue?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 04:04:31 pm
Now, keeping the 3 clock verified write request, test 2 new things.

A) On the data_mux, change the 'READ_CLOCK_CYCLES' to 3.

Then:
B) gpu_rd_req     <= (Read_GPU_RAM  &&  last_Z80_RD  &&  last_Z80_RD2) && ~last_Z80_RD3 ;

Then:
C) On the data_mux, change the 'READ_CLOCK_CYCLES' back to 2.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 04:56:57 pm
Now, keeping the 3 clock verified write request, test 2 new things.

A) On the data_mux, change the 'READ_CLOCK_CYCLES' to 3.

Then:
B) gpu_rd_req     <= (Read_GPU_RAM  &&  last_Z80_RD  &&  last_Z80_RD2) && ~last_Z80_RD3 ;

Then:
C) On the data_mux, change the 'READ_CLOCK_CYCLES' back to 2.

Okay, I did A & B together and tested, works fine.  Made the change in C, tested - works fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 05:05:42 pm
Ok, so far, so good.  Stay with 'C'.  I found some errors when simulating the data_mux_v2 in 'Timing' mode instead of 'Functional' mode.  I will post an update of the newer 'data_mux_v2' later tonight.

As of this point, we now know that single cycle write&read req pulses now work.
We also seem to need to really delay/slow down the Z80 data by 20-30ns to get proper results.

Q: Does your keyboard work fine?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 05:23:38 pm
Here is update #1 for 'data_mux_v2.sv'.
You will need to generate and update symbol in quartus for the new 'ZERO_LATENCY' parameter to appear.
For now, keep it at 0.  The setting of 1 has some issues when simulating in 'Timing Mode'.  The 0 latency bug is in the new 'FIFO_3word_0_latency.sv' which I will update soon.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 03, 2020, 08:36:38 pm
Ok, all fixed up.  Both functional simulation and timing simulation give matching correct results with all configurations.

You will need to create and update symbol so that the new parameter 'REGISTER_GPU_PORT' shows up.
When on, this parameter improves the FMAX, but adds a 1 clock delay to the read_req's.

If you get read errors, increase the READ_CLOCK_CYCLES to 3.

You can test the code with REGISTER_GPU_PORT=1 or 0, verifying that the FMAX of C0>125MHz.  With the register port = 0, if your FMAX is above 125 now, I bet it wont be when we add the geometry unit.

New simulation results in 'timing mode'.  Though messier, you can see the reads match the green functional simulation above.  Before, the above code gave crap results when simulating in 'timing mode'.  This is a sign that your design may exhibit meta-stability issues or may function erradically from 1 FPGA to the next.

[attach=1]

All files attached below.
Don't forget to copy over the 'fifo_3word_0_latency.sv' as well.
Damn that was a lot of work........
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 03, 2020, 11:58:41 pm
Just thought I'd check this quickly before I go offline for the night.  Works perfectly.  :-+

I've still got duplicate keys appearing when I type, but they're about as frequent/possibly slightly less frequent than before.  More an annoyance than a critical problem.

No read errors at all when I view the GPU RAM memory pages.  No artefacts or errors in the display setup, so it looks like RD/WR are working nicely now. :-+

I'm not sure I know exactly what I'm doing checking Fmax, but I've looked at the Timing Analyzer->Slow 1200mV 85C Model->Fmax Summary, and it's showing 4 clocks:

    Fmax           Restricted Fmax  Clock Name
1: 77.68 MHz    77.68 MHz          inst17|altpll_component|auto_generated|pll1|clk[2]
2: 139.18 MHz  139.18 MHz        inst17|altpll_component|auto_generated|pll1|clk[0]
3: 268.6 MHz    268.6 MHz          inst17|altpll_component|auto_generated|pll1|clk[1]

(and a 919.12 MHz Fmax for the PS/2 keyboard_to_ascii debounce circuit)

So hopefully all working well now (apart from the IO read cycle / PS2_CHAR register output).   ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2020, 12:22:39 am

I'm not sure I know exactly what I'm doing checking Fmax, but I've looked at the Timing Analyzer->Slow 1200mV 85C Model->Fmax Summary, and it's showing 4 clocks:

    Fmax           Restricted Fmax  Clock Name
1: 77.68 MHz    77.68 MHz          inst17|altpll_component|auto_generated|pll1|clk[2]
2: 139.18 MHz  139.18 MHz        inst17|altpll_component|auto_generated|pll1|clk[0]
3: 268.6 MHz    268.6 MHz          inst17|altpll_component|auto_generated|pll1|clk[1]

(and a 919.12 MHz Fmax for the PS/2 keyboard_to_ascii debounce circuit)

So hopefully all working well now (apart from the IO read cycle / PS2_CHAR register output).   ;D

This is your 'pll1', 'inst17' you have in your project.  It has 4 clock outputs in use.  clk[0,1,2].  (don't worry about the missing c[3], it just feeds 1 flipflop data input, it's actually not clocking anything so it is not reported)
[attachimg=1]

     I calculated the frequencies of the clock outs clk [0,1,2] based on the PLL settings in the window.  Now, in the timing report, are all the reported fastest possible clocks of the GPU for each clk[ # ] domain fast enough to operate without flaw according to the actual clock speeds we are running those sections at? 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2020, 12:32:48 am
I've still got duplicate keys appearing when I type, but they're about as frequent/possibly slightly less frequent than before.  More an annoyance than a critical problem.
Upload the current Quartus project so I can take a look.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 04, 2020, 11:20:12 am
This is your 'pll1', 'inst17' you have in your project.  It has 4 clock outputs in use.  clk[0,1,2].  (don't worry about the missing c[3], it just feeds 1 flipflop data input, it's actually not clocking anything so it is not reported)
(Attachment Link)

     I calculated the frequencies of the clock outs clk [0,1,2] based on the PLL settings in the window.  Now, in the timing report, are all the reported fastest possible clocks of the GPU for each clk[ # ] domain fast enough to operate without flaw according to the actual clock speeds we are running those sections at?

Thanks - I figured that was the case, just wasn't sure I was looking at the right report in the Timing Reports section - there's so many.  Yes, looks like we're above the minimum clock speeds for the domains we're using.  clk[0] requires 125 MHz, has an Fmax of 139.18 MHz, and clk[1] requires 250 MHz, has an Fmax of 268.6 MHz, so looking good so far, though the margins are slim.

I've still got duplicate keys appearing when I type, but they're about as frequent/possibly slightly less frequent than before.  More an annoyance than a critical problem.
Upload the current Quartus project so I can take a look.

Current project attached.  To my untrained mind, it looks like it's a timing problem with the Z80_bridge when it puts the data for the ASCII char onto the Z80's data bus.  I did some experimentation with it a week or so ago and arrived at the code and timings you'll see in the project by trial and error. :-//

The following lines in Z80_bridge.sv are relevant to what's going on:

287-299 - latches the ASCII char into PS2_CHAR register when PS2_READY goes HIGH for one cycle.  (Ignore the INT_TYP conditional - it's always LOW until I get the interrupts up and running).
309-339 - handles putting the PS2_CHAR data onto the Z80 data bus during an IO read cycle.  PS2_CHAR should be 0x00, unless it has valid ASCII data from the ps2_keyboard_to_ascii.vhd module.  That way, the Z80 reads the PS2 IO port (240) and ignores it if it gets 0x00 back, otherwise it receives an ASCII char and acts upon it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2020, 01:38:28 pm
Hows the ellipse and filled ellipse coming?
After that, we have triangle & 4 vector polygon, then filled versions.
For these 2, we will have to update the line function so you can run 4 of them.

Either 4 independent (a for loop can build 4 engines with 4 sets of arrays), or 1 engine with 4 banks of registers which will use less gates, but 1 line coordinate will be computed at a time.

These will based on but replace the current line.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2020, 01:47:54 pm
Current project attached.
ZERO_LATENCY should be = 1.
Please make it 1 and give it a try.

1 means reqs take immediate action.  0 means an additional clock cycle is waited until the req is considered.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2020, 04:32:30 pm
Ok, I cleaned up the 'geometry_xy_plotter.sv'.  The big change is I moved the absolute value size of dx&dy to lines 237&238.

Now, the setup for drawing the line is down to 1 clock.  This is as efficient as my box algorithm every time it increases the Y axis.  This is important because we will be getting rid of my old box algorithm in place of running 3 line algorithms.

For now, skip the ellipse and lets expand the line to support 4 different lines being drawn with a pre-setup geo_shape which calls calls the lines in sequence to generate a:

1) basic line
2) line-to (same as line but automatically updates x[0] & y[0] with x[1] and y[1] after the line was drawn)
3) box/filled box
4) triangle/filled triangle
5) 4 coordinate polygon.

Later, we will make an additional varible control to the line algorithm to generate a Bézier curve / arc.
Once done, calling ellipse will just call #1, #3 or #5 to generate with the right arc radius to generate an ellipse or an ellipse at any angle.

Then, you geometry engine is done.  We will save blitter copy for when the pixel memory writer is working and you successfully run the current geometry shapes.

I attached the patched line .sv & updates Quartus sim project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 04, 2020, 05:10:27 pm
Hows the ellipse and filled ellipse coming?

Haven't had a chance to make a start on them yet - hopefully I've got a bit of a time now to make some progress.

After that, we have triangle & 4 vector polygon, then filled versions.
For these 2, we will have to update the line function so you can run 4 of them.

Either 4 independent (a for loop can build 4 engines with 4 sets of arrays), or 1 engine with 4 banks of registers which will use less gates, but 1 line coordinate will be computed at a time.

These will based on but replace the current line.

Sounds good.  With 10 MAGGIEs, the current build is taking up 85% of total logic elements in the EP4CE10, with 62% of memory bits, so there's still room.  It's taking over 4 minutes to build the project, though.  Those extra MAGGIEs seem to have slowed the build down a lot. :o

ZERO_LATENCY should be = 1.
Please make it 1 and give it a try.

1 means reqs take immediate action.  0 means an additional clock cycle is waited until the req is considered.

Made it 1, have just been testing it - all looks very good.  It's probably luck or psychological, but it seems I'm getting less keyboard errors.  They're still there, but seem less frequent.

Ok, I cleaned up the 'geometry_xy_plotter.sv'.  The big change is I moved the absolute value size of dx&dy to lines 237&238.

Thank you - will download it and give it a try in a sec.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2020, 10:54:07 pm
The following lines in Z80_bridge.sv are relevant to what's going on:

287-299 - latches the ASCII char into PS2_CHAR register when PS2_READY goes HIGH for one cycle.  (Ignore the INT_TYP conditional - it's always LOW until I get the interrupts up and running).
309-339 - handles putting the PS2_CHAR data onto the Z80 data bus during an IO read cycle.  PS2_CHAR should be 0x00, unless it has valid ASCII data from the ps2_keyboard_to_ascii.vhd module.  That way, the Z80 reads the PS2 IO port (240) and ignores it if it gets 0x00 back, otherwise it receives an ASCII char and acts upon it.

Darn that Z80_bridge has turned into a mess, however, there are valid reasons why.
Do you have a simulation setup?  If so, post it here...

Were going to re-do most of it in a better way.

Step #1 will be to denounce and isolate any Z80 read request trigger point and Z80 write request trigger point.
The bus debounce and transaction delay will be built in to these 2 1-shot strobes.  These will have a programmable # of debounce/deglitch GPU clock cycles.  This is where you also take care of interrupts.
Currently, these are only done for the GPU ram with gpu_rd_req & gpu_wr_ena, then you have a bunch of other if's and delays for the other possible devices like the keyboard.

Step #2, the 1 shot strobes will acquire the address and data being sent from Z80 to FPGA.

Step #3, Based on address and request direction, all possible read or write data ports will be set here.

Step #4, the 1 shot Z80 read req will change the 245 IO direction until the read req terminates.

We will use a separate data_in and data out_reg for the Z80's data bus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 04, 2020, 11:43:04 pm
Darn that Z80_bridge has turned into a mess, however, there are valid reasons why.
Do you have a simulation setup?  If so, post it here...

Yes, it has become a bit messy since I have added stuff for testing and trying to get IO RD/WR from the Z80 working.  I guess I should housekeep the code more often.  :-[

Test setup for the Z80_bridge attached.  This is what I used in the other thread when I was testing the IO cycle.

What do you mean by 'denounce'?  Not sure on the terminology here.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2020, 12:40:41 am
Darn that Z80_bridge has turned into a mess, however, there are valid reasons why.
Do you have a simulation setup?  If so, post it here...

Yes, it has become a bit messy since I have added stuff for testing and trying to get IO RD/WR from the Z80 working.  I guess I should housekeep the code more often.  :-[

Test setup for the Z80_bridge attached.  This is what I used in the other thread when I was testing the IO cycle.

What do you mean by 'denounce'?  Not sure on the terminology here.
:palm: DE-Bounce.  Bloody auto-correct.
In other words, give the Z80 bus command lines time to settle before considering the address and data coming in. then deciding if a transaction is required and if data should be returned to the Z80.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2020, 01:16:34 am
Ok, I converted the GPU ram port from 8bit into a dynamic 16bit version.  This means I modified and adapted the following sections of the GPU:

sixteen_port_gpu_ram gpu_RAM.sv
vid_osd_generator.sv
GPU.bdf
data_mux_v2.sv

I also had to modify the compiler settings to ensure the compiler would meet the timing for the GPU ram as the old settings were receiving a few address & write_enable bits a little late.  Though, it was there in your existing version, it probably didn't cause any problem as the silicon usually performs better than the compiler's report which takes into consideration the worst possible conditions based on the set operating specs.

Let me know if the attached project works.  If so, you will need to switch to that project from now on.

Also, why do you have your palette system memory set shy of 32k and your palette memory set right after?
Quartus still wasted the Cyclone's ram with the missing bytes in the main system memory with 32k and then wrote the separate palette memory in that shared address space.  Also, why is the main system memory an odd number of bytes?  You should have used 32768 for main ram and 32768 for the offset of the palette memory.  But, you could have gone even a bit larger on the main system memory.  See here:

[attachimg=1]

With the attached project and my settings, you now have 41kb, just enough memory for a 320x240 16 color screen plus a 256 character 8x8 pixel font.  Or, 640x240 4 color, or 640x480 2 color screen.  Even 160x240 @ 256 colors, 160x120 @ 65536 colors.

It should compile and function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2020, 05:02:32 am
Darn that Z80_bridge has turned into a mess, however, there are valid reasons why.
Do you have a simulation setup?  If so, post it here...

Yes, it has become a bit messy since I have added stuff for testing and trying to get IO RD/WR from the Z80 working.  I guess I should housekeep the code more often.  :-[

Test setup for the Z80_bridge attached.  This is what I used in the other thread when I was testing the IO cycle.

What do you mean by 'denounce'?  Not sure on the terminology here.

What where you able to discern from that?

I've attached the project with the actual Z80 vectors in the waveform editor. The Z80 clock is set to 8 Mhz and the gpu clk is set to 125MHz.  The bus transaction timing you see is real from the Z80 datasheet, or as close as I can get it based on the poor datasheets I have access to.

Is there anything new you can gather from my layout?
Do you have any new insights when zooming into the simulation?

You need to shore up the Z80_bridge and add a few test signal tap signals to see whats going on inside your bridge.

Also, now it may be time to look at taking into account the Z80 CLK so that you wait for the next edge before reading the bus status too quickly before all the data and address lines are ready.

Now that the Data_mux has been fixed, and you can simulate the Z80 buss interactions 'for real', we can fix that module and call it a day.

Note that we are missing the 'Z80_nWAIT' signal.  The Z80 seems to assert it during a port read or port write.
It also seems if you were to read or write a memory address that the access is 1 clock faster as those transfers do not force that 1 clock cycle wait state.

(Note that for the Z80 data input, I made the data = $D0 when the Z80 outputs the correct data and make that same signal $D1 for the complete amount of time the Z80 expects to receive read valid data.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2020, 10:40:53 am
What do you mean by 'denounce'?  Not sure on the terminology here.
:palm: DE-Bounce.  Bloody auto-correct.

Sorry about that, if it wasn't so late at night and I wasn't so tired when I read the post, I'd have worked that out for myself.  :-\

Ok, I converted the GPU ram port from 8bit into a dynamic 16bit version.... I also had to modify the compiler settings to ensure the compiler would meet the timing for the GPU ram as the old settings were receiving a few address & write_enable bits a little late.  Though, it was there in your existing version, it probably didn't cause any problem as the silicon usually performs better than the compiler's report which takes into consideration the worst possible conditions based on the set operating specs.

Let me know if the attached project works.  If so, you will need to switch to that project from now on.

Yes, works fine (seems to have cut 30 seconds off the compile time too!) so I've switched to the updated version for the project.  Thanks. :)

Also, why do you have your palette system memory set shy of 32k and your palette memory set right after?

Probably because it seemed like a good idea at the time. :-//

Quartus still wasted the Cyclone's ram with the missing bytes in the main system memory with 32k and then wrote the separate palette memory in that shared address space.  Also, why is the main system memory an odd number of bytes?  You should have used 32768 for main ram and 32768 for the offset of the palette memory.  But, you could have gone even a bit larger on the main system memory.  See here:

(Attachment Link)

I went with 32 KB GPU RAM as it's the nearest 16 KB multiple.  The next (obviously) would be 48 KB, but the EP4CE10 doesn't have that much RAM.  The reason why this is (possibly un-)important is:

The host Z80's MMU can map 16 KB banks of RAM into the the Z80's logical 64 KB address space.  So the EP4CE10 presents two complete 16 KB banks of RAM that can be accessed by the Z80.  The way the Z80_bridge works at the moment is to return 0xFF's for any addresses the Z80 attempts to read (and prevents writes) to memory above 32 KB.  So although the new project has 40 KB of RAM, the Z80 can only see and write to the first 32 KB.

I could remove the check and allow the Z80 to try and read/write any address in the 512 KB space, but it would get random data back and I need 0xFF's so that the software can work out if there's actual RAM available or not.  The easiest way to do that was to check for addresses over 32 KB (15 bits) and return 0xFF.

Will need to re-visit that code in the Z80_bridge to allow the Z80 to access the GPU RAM up to an odd (i.e. non-multiple of 16KB) address range.  That's the mem_valid_range register, set on line 219 in Z80_bridge.


With the attached project and my settings, you now have 41kb, just enough memory for a 320x240 16 color screen plus a 256 character 8x8 pixel font.  Or, 640x240 4 color, or 640x480 2 color screen.  Even 160x240 @ 256 colors, 160x120 @ 65536 colors.

It should compile and function.

It sure does.  I just need to sort out the mem_valid_range register to allow the Z80 access to the additional 9 KB of RAM.  It doesn't matter if the third bank of GPU RAM is only 'RAM' for the first 9KB, so long as the remainder returns 0xFF.  It just means the additional 9 KB of RAM won't show up in the total memory reported by the system.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2020, 11:19:42 am
What where you able to discern from that?

Well, the fact that z80_DATA_DIR and z80_BDIR_EN were going HIGH too early - I managed to get the PS/2 IO port from 100% not working to producing the odd duplicated character once in perhaps 20 key strokes.

I've attached the project with the actual Z80 vectors in the waveform editor. The Z80 clock is set to 8 Mhz and the gpu clk is set to 125MHz.  The bus transaction timing you see is real from the Z80 datasheet, or as close as I can get it based on the poor datasheets I have access to.

Is there anything new you can gather from my layout?
Do you have any new insights when zooming into the simulation?

I'm grasping at straws here, but perhaps the data for the IO RD cycle should be placed onto the z80_DATA bus a quarter of a (Z80) clock cycle later?

You need to shore up the Z80_bridge and add a few test signal tap signals to see whats going on inside your bridge.

Also, now it may be time to look at taking into account the Z80 CLK so that you wait for the next edge before reading the bus status too quickly before all the data and address lines are ready.

So wait for the next leading edge of the Z80's clock?

Note that we are missing the 'Z80_nWAIT' signal.  The Z80 seems to assert it during a port read or port write.

I don't have access to the WAIT signal from the Z80 on the current GPU card.  I could bodge-wire it into a spare IO, but didn't think it was necessary.

It also seems if you were to read or write a memory address that the access is 1 clock faster as those transfers do not force that 1 clock cycle wait state.

(Note that for the Z80 data input, I made the data = $D0 when the Z80 outputs the correct data and make that same signal $D1 for the complete amount of time the Z80 expects to receive read valid data.)

Are you thinking the D1s are faults?  The datasheet shows an overlap for valid data at the end of the MREQ / IOREQ cycle, but the timing charts quote 0 ns for that time for a 10 MHz Z80 CPU, so in reality there is no need for the data to be held past the end of the MREQ/IOREQ cycles.

It does seem that z80_DATA_DIR and z80_BDIR_EN are HIGH for a long time before the Z80 actually needs to read the data off the bus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2020, 03:19:58 pm
Are you thinking the D1s are faults?  The datasheet shows an overlap for valid data at the end of the MREQ / IOREQ cycle, but the timing charts quote 0 ns for that time for a 10 MHz Z80 CPU, so in reality there is no need for the data to be held past the end of the MREQ/IOREQ cycles.

It does seem that z80_DATA_DIR and z80_BDIR_EN are HIGH for a long time before the Z80 actually needs to read the data off the bus.
The way you read the data sheet, for the data in and data out, the small time slot where the Z80 has the 'D1' means that you need to present valid data to the Z80 beginning anytime before that time slot begins, and then hold data on the bus until after the 'D1' time slot ends.
Now, do we send data to the Z80, figuring it takes an additional 5-10ns for the data to get there from the assertion of the OE & data out signals, will the data reach the Z80 in time to ensure a good read?
Now, do we hold that data we are sending out to the Z80 long enough until the end of the Z80 'D1' time slot that we guarantee the Z80 will receive a correct byte?

Remember, the time scale on the simulation is accurate, so you have the ns ruler at the to.  In simulate in timing mode and it will even be closer.  (Adds around up to another 2.5ns of delay on the FPGA outputs.)

Also, about the wait state, if you look at the port read and write, there is an extra Z80 clock cycle, wait state which you may need to wait before beginning a transaction just to be safe.

You have the function in your Z80 module, but not a basic setup where you can manipulate a response.  You need to clean that up.


In the other direction, a Z80 write, you should be taking the data from the Z80 data bus after the valid 'D0' time has begun and before it ends.  Now there is an additional caveat here too.  Yo need to consider all the delays created by you bus' potential load on the data lines as well as the address lines.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2020, 05:31:56 pm
The way you read the data sheet, for the data in and data out, the small time slot where the Z80 has the 'D1' means that you need to present valid data to the Z80 beginning anytime before that time slot begins, and then hold data on the bus until after the 'D1' time slot ends.

So a two or three gpu_clk cycle delay after detecting the end of the MREQ or IORQ RD cycle is needed?

Now, do we send data to the Z80, figuring it takes an additional 5-10ns for the data to get there from the assertion of the OE & data out signals, will the data reach the Z80 in time to ensure a good read?
Now, do we hold that data we are sending out to the Z80 long enough until the end of the Z80 'D1' time slot that we guarantee the Z80 will receive a correct byte?

Well, the D1 slot ends at the same time as MREQ or IORQ goes HIGH at the end of the read cycle (the data sheet indicates that the Z80 has read the data by this point), so add in the 1 gpu_clk delay to detect the end-of-cycle and act upon it, then the delay inherent in the 245 and the FPGA's bidirectional IO pins, and you have a built-in delay holding the data on the bus slightly past the end of the read cycle anyway?

Memory reads have been rock solid, so I can't fault the timings of the function handling the MREQ RD cycle in the Z80_bridge.

Also, about the wait state, if you look at the port read and write, there is an extra Z80 clock cycle, wait state which you may need to wait before beginning a transaction just to be safe.

This is something I might have to test a little more.  From how I read the datasheet, there should be no issue with data being pushed onto the data bus by the peripheral (i.e. the FPGA) before the WAIT state.

You have the function in your Z80 module, but not a basic setup where you can manipulate a response.  You need to clean that up.

Where do I start? Set up a delay sequencer so that different delays can be tested?

In the other direction, a Z80 write, you should be taking the data from the Z80 data bus after the valid 'D0' time has begun and before it ends.  Now there is an additional caveat here too.  Yo need to consider all the delays created by you bus' potential load on the data lines as well as the address lines.

What sort of delays are we talking about here?  It seems to me that the odd nanosecond here and there aren't going to be a problem - the Z80's clock cycle is 125 ns long at 8 MHz...?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 02:44:27 am
Looking at you existing Z80 bridge, you can see you don't hold the data output until the period 'D1' ends.  Electrical capacitance on the data bus or a fast Z80 may be whats keeping your read data clean.  See here:

[attach=4]

Ok, I completely redone your Z80 bridge and present to you the new Z80_bridge_v2.sv.  It operated based on the bus commands which are each filtered through programmable bidirectional 'hysteresis' timers.

When parameter 'USE_Z80_CLK' is 0 (off), the 'Z80_CLK_FILTER' parameter sets the required number of GPU clk cycles of a valid bus command on the Z80 inputs before command will be considered true.  It will take once again the same number of GPU clk cycles for the current command to be considered false.  The default value for 'Z80_CLK_FILTER' should be 3, equivalent to a 24ns low pass filter.  (use 1 for a 20MHz Z80.  1 would probably still work fine with an 8 MHz Z80.)

When parameter 'USE_Z80_CLK' is 1 (on), the 'Z80_CLK_FILTER' parameter should be set to 0 as this means any valid command input will only become valid during the next Z80 clk transition.  If you set the 'Z80_CLK_FILTER' to 1, it would now wait for 2 Z80 clk cycle and this may miss a few commands.

I did almost everything except for the port inputs and outputs.  I did leave an example port read and write in the code with a dummy test counter for the keyboard read, use this to test the keyboard port access as each read should increment the returned value by 1, and an example port write to the speaker.  If reading the keyboard reveals a perfect 8 bit counter every read, but your keyboard interface still glitches with this Z80 bridge, then the error lies in you keyboard decoder source code.

This is a snapshot of the attached Quartus 9.1 simulation test bench with default filter setup.  As you can see, I have the commands labeled so you may change 1 or 2 to test your 3 port functions which I didn't add.  As you can see, the latest version gives ample time at each junction in the bus cycle to allow the address and data lines to settle and be captured both for input and output.

[attach=1]

The code is much simpler than what you had.  I wasn't sure about the port address width so I made it 16 bits.  If it needs changing, I'm sure you can fix this yourself.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 11:25:22 am
Looking at you existing Z80 bridge, you can see you don't hold the data output until the period 'D1' ends.  Electrical capacitance on the data bus or a fast Z80 may be whats keeping your read data clean.  See here:

(Attachment Link)

But the Z80 datasheet quotes ZERO time to hold the data on the line after the end of the RD cycle.  The timing diagram is misleading, as it seems to show the data being held a little way past RD/WR going high, but in reality there is no need for such a delay.

Timing diagram:
[attach=1]

Timing values:
[attach=2]

This is borne out with practical experience - I get zero memory read errors in practice, so holding the data past the end of a RD cycle seems unnecessary, unless I'm missing something?

Ok, I completely redone your Z80 bridge and present to you the new Z80_bridge_v2.sv.  It operated based on the bus commands which are each filtered through programmable bidirectional 'hysteresis' timers.

Thank you.  ^-^

I did almost everything except for the port inputs and outputs.  I did leave an example port read and write in the code with a dummy test counter for the keyboard read, use this to test the keyboard port access as each read should increment the returned value by 1, and an example port write to the speaker.  If reading the keyboard reveals a perfect 8 bit counter every read, but your keyboard interface still glitches with this Z80 bridge, then the error lies in you keyboard decoder source code.

I've spent the last hour or so trying to get IO reads to work - all I'm getting is 0x78 back, whether I try to read the PS2_DATA port or the PS2_STAT port, so there are timing issues here.  Writing to the IO_SPKR port seems to work - the speaker bleeps when I output 1 to the IO_SPKR port, but then it would do that whatever value it gets as long as it's not 0.

Also, I've got some modification of the code to do to get the BANK_ID returned to the Z80 again and to return 0xFF's for memory reads outside of mem_in_range.  Otherwise, memory reads and writes appear to be working just fine.

The code is much simpler than what you had.  I wasn't sure about the port address width so I made it 16 bits.  If it needs changing, I'm sure you can fix this yourself.

It sure is simpler.  Have made the port address width 8-bits - there are tricks to use the full 16-bit port address, but the Z80 was intended to use only 256 ports originally.  Also had to add in the assignments for EA_DIR and EA_OE - without these, the system hangs as there is contention on the extended address bus caused by the level converter not knowing which direction to go.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 02:18:57 pm

This is borne out with practical experience - I get zero memory read errors in practice, so holding the data past the end of a RD cycle seems unnecessary, unless I'm missing something?

With that data sheet, no do not need any data past the rise of the RDn flag.  You can use a filter value of 1 or 0 if you like.  However, I find it strange that we had to add a read/write request delay on the earlier Z80 module to get rid of a few errors.

As for the port reads, did you try using my dummy internal counter example read?
If that internal counter works, its the way you retrieve data from the PS2 keyboard vhdl module which is messing up.

Note that you can set the Z80 to operate off the Z80 clk input and for the ports, you can add a second filter parameter of 1 or 2 instead of 0 to delay the input/output data past that 'TW' added state.

This is why I made the module the way I did.  You can separate  clocks, either GPUclk or Z80clks for each command without modifying the basic input/output data and OE part.

Send me your updated .sv.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 02:32:46 pm
This is borne out with practical experience - I get zero memory read errors in practice, so holding the data past the end of a RD cycle seems unnecessary, unless I'm missing something?
With that data sheet, no you are not.  You can use a filter value of 1 or 0 if you like.

Will give that a try later then.  :)

As for the port reads, did you try using my dummy internal counter example read?
If that internal counter works, its the way you retrieve data from the PS2 keyboard vhdl module which is messing up.

Yes, I'm using the internal counter - I've amended the code slightly to use the counter on the IO_STAT port, otherwise the system would be unusable as the counter would be giving false ASCII codes whenever it was polled.

I've sorted the timing on the IO reads now, it just seems I need to work on the code.  I'm getting valid values when I attempt to read from a non-existent IO port (it returns 0x55 as I've set it to), but the IO_STAT port (with the counter) is missing counts.  If I run several 'IN 240' commands in a row, I'm getting values along the lines of:

23
69
104
128
160
196
238
252

So I'm just looking at the code and tightening it up a little, but it seems I'm missing something (probably very obvious).

On the other hand, I seem to be getting valid ASCII char values from the PS2_DATA port, I'm just not clearing them currently when I read them.  Is this next bit of code okay?
Code: [Select]
Z80_rData    <= PS2_CHAR;
PS2_CHAR     <= 8'b0;

This is where it should return the value in the PS2_CHAR register when the Z80 is polling the PS2_DATA port.  Once the data is read by the Z80, PS2_CHAR should be set to 0.  However, given that both those lines of code execute at the same time, I'm thinking I should perhaps delay the second line by one clock cycle?

Note that you can set the Z80 to operate off the Z80 clk input and for the ports, you can add a second filter parameter of 1 or 2 instead of 0 to delay the input/output data past that 'TW' added state.

This is why I made the module the way I did.  You can separate  clocks, either GPUclk or Z80clks for each command without modifying the basic input/output data and OE part.

Right, I'll have a closer look at how to do that in a sec.  I've gone and created another delay pipeline for IO reads which perhaps I should have done via the new method you've described.  :o

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 02:41:52 pm
Ooops, you posted the 'OLD' bridge.sv...

Also, to get around your long compile times, send me your current project and I will send it back (renamed) with compiler setting plus a few items removed to get it to compile in 45 seconds...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 02:50:25 pm
Ooops, you posted the 'OLD' bridge.sv...

D'oh!   :palm:

Also, to get around your long compile times, send me your current project and I will send it back (renamed) with compiler setting plus a few items removed to get it to compile in 45 seconds...

 :o  Okay, no worries.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 03:30:24 pm
Think I've spotted the problem with the PS2_STAT not incrementing in 1's - has to do with how I was incrementing the port_dly pipeline.  Will edit this post when I've had a chance to test the code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 03:38:08 pm
Here you go. 1min, 20 sec compile time. (Well on my PC, it used to be over 4min to compile.)

The main changes is that I set layers to 2, meaning you have enough for text. (Assuming you are only using the first 2 layers right now...)

And a few compiler fitter settings.
A few minor timing violations, but so minor that it should either properly work, or you will see speckles on the screen.

Careful, keep this folder separate...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 03:51:16 pm
I'm using a 13-bit pipeline to delay the return data going onto the bus for an IO read.  If I do this each clk:

Code: [Select]
port_dly[12:1] <= port_dly[11:0];
It works, but with the IO_STAT counter going up in big jumps between IO reads of the IO_STAT port.  Does Verilog add zeros on the LSB side in this case?  If not, port_dly will just fill with ones and that's probably why IO_STAT is jumping up all the time, because it's incrementing constantly, whether it's read or not.  If I do this:

Code: [Select]
port_dly[12:0] <= { port_dly[11:0], 1'b0 };
IO reads don't work at all, I just get 0x78 back (which means nothing was put onto the data bus).   :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 04:11:29 pm
Ahhh, now we are zeroing in on the true problem.  That increment error means every time you access the read port once, the Z80 bridge is seeing multiple port reads.

Now, is this because of
(A) noise on the bus IO controls making the Z80 bridge thing multiple read ports are taking place.
(B) just the way the Z80 makes these random bus transition during the 'wait' state.
(C) other parts of your code are calling that read multiple random times in between you reading the test counter.

This problem will lead to false keyboard reads, however, the only reason why your keyboard might have worked so well is that the PS2 data coming in only changes 1 keypress and you were reading duplicate copies instead of treating a single port read as an actual single port read.  I think I have a way to fix this universally, but I need to look as the data sheets.

Send me your updated Z80bridgev2.sv code now.

BTW, Quartus 12.0 compiles your GPU in 1 minute, using only 1 cpu core (no choice here).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 04:23:37 pm
??? How did you do that IO read delay????
It makes no sense...

You were only supposed to edit these lines:

Code: [Select]
        if ( ~z80_op_read_port    && (z80_read_port_fc    != 1'd0                ) ) z80_read_port_fc    <= z80_read_port_fc    - 1'd1;
   else if (  z80_op_read_port    && (z80_read_port_fc    != Z80_CLK_FILTER[2:0] ) ) z80_read_port_fc    <= z80_read_port_fc    + 1'd1;
        if ( ~z80_op_read_port    && (z80_read_port_fc    == 1'd0                ) ) z80_read_port       <= 1'b0;
   else if (  z80_op_read_port    && (z80_read_port_fc    == Z80_CLK_FILTER[2:0] ) ) z80_read_port       <= 1'b1;

To something like:
Code: [Select]
        if ( ~z80_op_read_port    && (z80_read_port_fc    != 1'd0                ) ) z80_read_port_fc    <= z80_read_port_fc    - 1'd1;
   else if (  z80_op_read_port    && (z80_read_port_fc    != Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port_fc    <= z80_read_port_fc    + 1'd1;
        if ( ~z80_op_read_port    && (z80_read_port_fc    == 1'd0                ) ) z80_read_port       <= 1'b0;
   else if (  z80_op_read_port    && (z80_read_port_fc    == Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port       <= 1'b1;

Same for the write port.

I went through all that hassle so you could keep the read and write ports and ram all the same as I had it, not special circumventing work around code.  If you wanted a special delay state for any of the bus transaction, just add or subtract a number in my command filter section.

Your test counter isn't even working in the simulation, though I think you screwed up my code's concept from the beginning.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 04:29:53 pm
??? How did you do that IO read delay????

Using a specific pipeline, like we did previously, as I wasn't 100% sure about the new method you're using, so I jury-rigged a delay for quick testing. :-\

It makes no sense...

You were only supposed to edit these lines:

Code: [Select]
        if ( ~z80_op_read_port    && (z80_read_port_fc    != 1'd0                ) ) z80_read_port_fc    <= z80_read_port_fc    - 1'd1;
   else if (  z80_op_read_port    && (z80_read_port_fc    != Z80_CLK_FILTER[2:0] ) ) z80_read_port_fc    <= z80_read_port_fc    + 1'd1;
        if ( ~z80_op_read_port    && (z80_read_port_fc    == 1'd0                ) ) z80_read_port       <= 1'b0;
   else if (  z80_op_read_port    && (z80_read_port_fc    == Z80_CLK_FILTER[2:0] ) ) z80_read_port       <= 1'b1;

To something like:
Code: [Select]
        if ( ~z80_op_read_port    && (z80_read_port_fc    != 1'd0                ) ) z80_read_port_fc    <= z80_read_port_fc    - 1'd1;
   else if (  z80_op_read_port    && (z80_read_port_fc    != Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port_fc    <= z80_read_port_fc    + 1'd1;
        if ( ~z80_op_read_port    && (z80_read_port_fc    == 1'd0                ) ) z80_read_port       <= 1'b0;
   else if (  z80_op_read_port    && (z80_read_port_fc    == Z80_CLK_FILTER_PORT[2:0] ) ) z80_read_port       <= 1'b1;

Same for the write port.

I went through all that hassle so you could keep the read and write ports and ram all the same as I had it, not special circumventing work around code.  If you wanted a special delay state for any of the bus transaction, just add or subtract a number in my command filter section.

Now I have a better idea how it works, I'll do it properly - I just wanted to get the IO working, then I'd worry about the code after.

Current Z80_bridge code attached as requested.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 06:02:37 pm
Ok, is this what you want?

[attach=1]

I've cleaned up what you messed in my code.
I've attached the Quartus simulation project.  You should be taking a closer look at the simulation results and coding and asking questions.

I changed the GPU clk filter to using the Z80 clk filter.  This is because in the Z80 data sheet, the delayed data out is timed to an additional Z80 clock cycle, not a fixed amount of time.

Since this is the first time we are using the Z80 clk, I hope the memory read and write still works.
Remember to update the block diagram, clear the old one and re-paste to get all the new default parameters updated as well.  Otherwise you might get some old  figures.

Also, if you simulate, you will notice that using a 'Z80_CLK_FILTER_P = 3', 1 more Z80 clk, makes the data out window really small and sweat, but I not sure it will work without scoping your Z80 bus to ensure timing.  Either that, or if your port reads are making random increments, maybe a setting of 3 will do the trick as it waits quite a bit of time before assessing the port address and then deciding to output the data or not.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 06:09:39 pm
It looks like you've saved the PNG image of the simulation timings as the Z80_bridge.zip file.   :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 06:24:19 pm
Make 1 new change to my new source:

Change this line (around 256):
Code: [Select]
if ( z80_read_opcode || z80_read_memory || z80_read_port ) begin  // this section sets the output enable sends the correct data back to the Z80
To this:
Code: [Select]
if ( ~Z80_RDn_r ) begin  // this section sets the output enable sends the correct data back to the Z80
This turns off the read OE 1 gpu clk after the read data line on the bus as soon as possible right after the Z80_RDn_r goes high the way you like it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 06:48:50 pm
I can't download your new source - the file you've attached in that previous post isn't a zip file, it's a PNG saved with a .zip extension.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 06:57:39 pm
Its a bug at eevblog forum with multiple attachements... Here you go....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 08:28:45 pm
Something weird is going on with the keyboard input.  :o

If I do individual 'IN' commands, or a sequence of them, to the PS2_STAT port, I get a nice incrementing number.

If I switch to polled keyboard input (so the 'OS' is constantly polling the PS2_DATA port for ASCII chars) - and I press a key on the keyboard - the screen fills with that key and the system locks up.

All I have changed in the Z80_bridge you sent was this:
Code: [Select]
   if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin  // Z80 is reading PS/2 port
      Z80_rData  <= PS2_CHAR;
      PS2_CHAR   <= 8'b0;
   end

I removed the incrementing value you'd made for the PS2_DATA port and made it return the PS2_CHAR value instead.  The value should be reset to 0x00 when it is read.

As soon as I get some time, I'll start simulating and looking to see if I can replicate the issue there.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 08:47:03 pm
Something weird is going on with the keyboard input.  :o

If I do individual 'IN' commands, or a sequence of them, to the PS2_STAT port, I get a nice incrementing number.
Yay, read port now works error free perfectly fine.  No glitching.  I assume that memory read and writes and port writes are good too.

Z80_bridge now good  :) .

Quote
If I switch to polled keyboard input (so the 'OS' is constantly polling the PS2_DATA port for ASCII chars) - and I press a key on the keyboard - the screen fills with that key and the system locks up.

All I have changed in the Z80_bridge you sent was this:
Code: [Select]
   if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin  // Z80 is reading PS/2 port
      Z80_rData  <= PS2_CHAR;
      PS2_CHAR   <= 8'b0;
   end

Do not change these lines, they are correct.

This isn't where your error is.  This is the way the PS2 VHDL is written and that its working at 50MHz, not 125MHz. 

Your lines:
Code: [Select]
   if (PS2_RDY) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Is where the problem lies.

PS2_RDY input may remain high for an indefinite number of clock cycles.  In fact, it may stay high and go low only for a few clk cycles as a new character is updated, though, I have not read up on the unknown VHDL code you are using.

try this instead:
Code: [Select]
reg [7:0] PS2_RDY_r;
.......
PS2_RDY_r[7:0] <= {PS2_RDY_r[6:0],PS2_RDY};
   if (PS2_RDY_r[7:0] == 8'b00001111 ) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

This means that the PS2_RDY needs to come in for 4 clocks low, then 4 clocks high in a row for the PS2_CHAR to latch the data on that 1 single clock shot, however, this will not solve reading the keyboard port & hitting a key simultaneously.

To fix that problem, you need to:
Code: [Select]
   if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin  // Z80 is reading PS/2 port
      Z80_rData  <= PS2_CHAR;
      if (PS2_RDY_r[7:0] != 8'b00001111 )  PS2_CHAR   <= 8'b0;
end

That if will prevent the clearing of the PS2_CHAR if a new key is pressed at the same time you are reading the current character.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 09:19:38 pm
What you will need to eventually do is make an 8 byte port where if you have multiple keys pressed, each byte will retain one of the 8 keys while they are still pressed.  As they keys are released the keyboard HDL will clear the correct one of the 8 bytes to 0.  The read port will not clear each key's set byte, but HDL will react to you releasing each key on the keyboard by clearing to 0 of the correct one of the 8 bytes.

Your Z80 can scan the 8 bytes and decide what to do, like key repeats, or in game mode, have raw access to those 8 bytes for game controls.

If you want the Z80 to clear any one of the 8 keyboard bytes, you would just write to that port byte.

Or, just 'F' it and do it in software.  Use the current setup and use the bit 8 in the character to send to the Z80 normal key bottom 7 bit code plus the same code again with bit 8 signifying that the key was released.

This way it is backwards compatible with what you have now as long as you ignore any incoming characters with a value above 127.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 09:54:56 pm
Z80_bridge now good  :) .

 ;D ;D ;D

This isn't where your error is.  This is the way the PS2 VHDL is written and that its working at 50MHz, not 125MHz. 

Your lines:
Code: [Select]
   if (PS2_RDY) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Is where the problem lies.

Ah! Of course!  :palm:  PS2_RDY is a one-shot, but it's running at 50 MHz, not 125 MHz.  So it's more of a long-shot.   ;D  I need an edge-detect on it...

try this instead:
Code: [Select]
reg [7:0] PS2_RDY_r;
.......
PS2_RDY_r[7:0] <= {PS2_RDY_r[7:1],PS2_RDY};
   if (PS2_RDY_r[7:0] == 8'b00001111 ) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Yeah, that's the thing.  :-+

Oh, shouldn't that be:
Code: [Select]
PS2_RDY_r[7:0] <= {PS2_RDY_r[6:0],PS2_RDY};
???

This means that the PS2_RDY needs to come in for 4 clocks low, then 4 clocks high in a row for the PS2_CHAR to latch the data on that 1 single clock shot, however, this will not solve reading the keyboard port & hitting a key simultaneously.

To fix that problem, you need to:
Code: [Select]
   if ( z80_read_port_1s && Z80_addr_r[7:0]==IO_DATA[7:0] ) begin  // Z80 is reading PS/2 port
      Z80_rData  <= PS2_CHAR;
      if (PS2_RDY_r[7:0] != 8'b00001111 )  PS2_CHAR   <= 8'b0;
end

That if will prevent the clearing of the PS2_CHAR if a new key is pressed at the same time you are reading the current character.

I'll test this tomorrow, it's getting late and I'm up early tomorrow (actually I might just hang on and try a build!), thanks for pinning the problem down.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 09:58:42 pm
try this instead:
Code: [Select]
reg [7:0] PS2_RDY_r;
.......
PS2_RDY_r[7:0] <= {PS2_RDY_r[7:1],PS2_RDY};
   if (PS2_RDY_r[7:0] == 8'b00001111 ) begin           // valid data on PS2_DAT
      PS2_CHAR   <= PS2_DAT;    // Latch the character into Ps2_char register
   end

Yeah, that's the thing.  :-+

Oh, shouldn't that be:
Code: [Select]
PS2_RDY_r[7:0] <= {PS2_RDY_r[6:0],PS2_RDY};
???
Doh...  |O  My dyslexia.
Lucky you caught that one.

Depending on the VHDL, if the:
if (PS2_RDY_r[7:0] == 8'b00001111 )
is too fat to respond to any key press, then change it to:
if (PS2_RDY_r[5:0] == 6'b000111 )

Don't forget to match the if ( != ) as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2020, 10:10:20 pm
The keyboard now works perfectly.  As in no errors whatsoever.   ;D ;D ;D ;D

What you will need to eventually do is make an 8 byte port where if you have multiple keys pressed, each byte will retain one of the 8 keys while they are still pressed.  As they keys are released the keyboard HDL will clear the correct one of the 8 bytes to 0.  The read port will not clear each key's set byte, but HDL will react to you releasing each key on the keyboard by clearing to 0 of the correct one of the 8 bytes.

Your Z80 can scan the 8 bytes and decide what to do, like key repeats, or in game mode, have raw access to those 8 bytes for game controls.

If you want the Z80 to clear any one of the 8 keyboard bytes, you would just write to that port byte.

Or, just 'F' it and do it in software.  Use the current setup and use the bit 8 in the character to send to the Z80 normal key bottom 7 bit code plus the same code again with bit 8 signifying that the key was released.

This way it is backwards compatible with what you have now as long as you ignore any incoming characters with a value above 127.

I like that last suggestion.  Makes it easy to ignore the break codes, but at the same time gives the software (i.e. a game) the ability to read and monitor multiple key presses at the same time.  I'll just need to modify the ps2_to_ascii (or whatever it's called - I haven't got Quartus open right now) module to send break codes in the format you've suggested - should be easy enough.

So the gate is open for progress on the hardware graphics engine again now the Z80_bridge is behaving itself?  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2020, 10:24:32 pm
Yes.
      Now the Z80_bridge works synchronously to the Z80_CLKn input.  Other than other functions I don't know you want to add, just adding read and write ports should now be easy peasy.  This includes adding the GPU 'ID' onto the Z80 data lines if the address is within a specific range.

      It should also be easier to introduce interrupt requests in the future, make sure you understand why I made the code the way I did and you shouldn't have a problem now that you can assert the interrupt at the right time and hold for the right amount of true Z80 clock cycles.

     Also, the bus_mux now responds to memory requests on a sequenced priority basis, with 3 word deep FIFOs at each command port inputs.  The bus_mux also now has 16 bit access to the GPU core memory allowing the pixel writer to work with 16 bit words.

     Now that everything is AOK, I'll add a third command input port to the bus_mux for the geometry pixel writer.

     You should begin on making the single line engine into a channel 4-line engine.  Then you will make the drawn triangle filled triangle commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2020, 06:42:07 am
Other than other functions I don't know you want to add, just adding read and write ports should now be easy peasy.  This includes adding the GPU 'ID' onto the Z80 data lines if the address is within a specific range.

I just need to get the Z80_bridge to return 0xFF if a read is attempted on any address above MEM_SIZE_BYTES, except for the last 16 bytes at the very top of MEMORY_RANGE, where it should return BANK_ID.

As these two conditions are part of the memory read cycle, I'm thinking I should modify the following bits of code to do this (lines 225-230 in Z80_bridge_v2.sv):
Code: [Select]
   if ( z80_read_memory_1s && mem_in_range ) begin                   // pass read request to GPU ram
      gpu_addr   <= Z80_addr_r[19:0];
      gpu_rd_req <= 1'b1;       // Flag HIGH for 1 clock when reading from GPU RAM
   end else begin
      gpu_rd_req <= 1'b0;       // Flag HIGH for 1 clock when reading from GPU RAM
   end

I'll need to add an 'else if' above to trigger a dummy gpu_rd_req for reads in MEMORY_RANGE, but above MEM_SIZE_BYTES.  Then in lines 254-261:
Code: [Select]
   if ( ~Z80_RDn_r ) begin  // this section sets the output enable and sends the correct data back to the Z80
      //if (z80_read_opcode) // unused
      if (z80_read_memory && mem_in_range && gpu_rd_rdy ) begin    // if a valid read memory range and the GPU returns a gpu_rd_rdy, send out data
         Z80_rData       <= gpu_rData ;
         Z80_245data_dir <= data_out;
         Z80_rData_ena   <= 1'b1 ;
         Z80_245_oe      <= 1'b0 ;
      end else if (z80_read_memory && <RD ADDR above MEM_SIZE_BYTES but below MEMORY_RANGE> && gpu_rd_rdy) begin
         <return 0xFF if below BANK_ID address> or <return BANK_ID byte if in BANK_ID range>
      end

I'll need to add an else if to return either 0xFF or a byte from BANK_ID according to the address read above MEM_SIZE_BYTES.

Does that sound right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2020, 11:28:57 am
Are you talking about this?

Code: [Select]
wire   mem_in_bank;
assign mem_in_bank         = (Z80_addr_r[21:19]==MEMORY_RANGE[2:0]) ; // Define the memory access window
wire   mem_in_range;
assign mem_in_range        = (Z80_addr_r[18:0] < MEM_SIZE_BYTES[19:0]) ; // The size of GPU ram + GPU palette ram

and then

Code: [Select]
   if ( z80_read_memory_1s && mem_in_bank ) begin                   // pass read request to GPU ram
      gpu_addr   <= Z80_addr_r[19:0];
      gpu_rd_req <= 1'b1;       // Flag HIGH for 1 clock when reading from GPU RAM
   end else begin
      gpu_rd_req <= 1'b0;       // Flag HIGH for 1 clock when reading from GPU RAM
   end

and then

Code: [Select]
if ( ~Z80_RDn_r ) begin  // this section sets the output enable sends the correct data back to the Z80
            //if (z80_read_opcode) // unused
            if (z80_read_memory && mem_in_bank && gpu_rd_rdy ) begin    // if a valid read memory range and the GUP returns a gpu_rd_rdy, send out data

                                                                if (mem_in_range) Z80_rData       <= gpu_rData ;
                                                                else              Z80_rData       <= BANK_ID[Z80_addr_r[3:0]];

                                                                Z80_245data_dir <= data_out;
                                                                Z80_rData_ena   <= 1'b1 ;
                                                                Z80_245_oe      <= 1'b0 ;
                                                                end

This would make best sense.  You can simulate the reads on the simulation test bench by changing the read address to what you like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2020, 11:39:53 am
Also, protect your writes to GPU ram:

Code: [Select]
   if ( z80_write_memory_1s && mem_in_bank && mem_in_range ) begin                  // pass write request to GPU ram
And for the 'SUPER' stingy version (this one removes the 'gpu_rd_req' flag and it's reliance to return a pulse from the GPU ram section to return a 'BANK_ID') :

Code: [Select]
   if ( z80_read_memory_1s && mem_in_bank && mem_in_range ) begin                   // pass read request to GPU ram
      gpu_addr   <= Z80_addr_r[19:0];
      gpu_rd_req <= 1'b1;       // Flag HIGH for 1 clock when reading from GPU RAM
   end else begin
      gpu_rd_req <= 1'b0;       // Flag HIGH for 1 clock when reading from GPU RAM
   end

and

Code: [Select]
           if (z80_read_memory && mem_in_bank && ~mem_in_range ) begin    // memory read outside memory range, but inside the bank.  Return BANK_ID
                                                                Z80_rData       <= BANK_ID[Z80_addr_r[3:0]];
                                                                Z80_245data_dir <= data_out;
                                                                Z80_rData_ena   <= 1'b1 ;
                                                                Z80_245_oe      <= 1'b0 ;
                                                                end
          if (z80_read_memory && mem_in_bank && mem_in_range && gpu_rd_rdy ) begin    // if a valid read memory range and the GUP returns a gpu_rd_rdy, send out data
                                                                Z80_rData       <= gpu_rData ;
                                                                Z80_245data_dir <= data_out;
                                                                Z80_rData_ena   <= 1'b1 ;
                                                                Z80_245_oe      <= 1'b0 ;
                                                                end

Remember to simulate test this code...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2020, 02:36:12 pm
Simulations are running perfectly - getting 0xFF and BANK_ID values back from appropriate read addresses, just waiting for a project compile to complete to test on the board.   :-+

Wanted to ask a question re: BGA soldering to anyone reading this, really.  Bearing in mind I'm looking to fabricate a PCB for the EP4CE22F17 (256-fBGA with 1mm pitch), is it necessary to have a pre-heater or some form of board heater to use in addition with the hot air gun to solder the BGA effectively?  I don't have an expensive hot air gun - it's a pretty cheap one to be honest, but has served me well so far soldering the EQFP-144 packages.

Is pre-heating (is that the right term?) necessary?  Could I just get away with hot-air soldering the BGA onto the PCB in a skillet over the cooker, if necessary?

EDIT:  Z80_bridge is working 100% now, returning correct values for non-RAM areas and the ID at the top of its memory space.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2020, 02:48:49 pm
You can get away with just hot air.  Also you should get a re-balling stencil and paste like in the video I showed you as you might fail your first mounting.

When placing the BGA, having the PCB on a hot place to kick the PCB up to around 125 degree C just helps when using the hot air as it will easily melt with minimal air.  (I would use an old pan and portable stove on minimum warm only if I can assure the pan's surface temperature.)  Professionals use all the proper pre-heating rules and mounting to ensure no PCB or IC goes to waste, they also don't want to remount an IC and ensure the mounted IC will not fail for over the 20 or so year lifetime of the PCB.

You are building 2 to 5 PCBs.  A bad solder means remove - reball - remount like in the provided video, but you are not a production assembly house where every point of failure is = to time and money loss on an industrial scale.  This is why they need to own and use all the right tools.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2020, 03:06:16 pm
You should begin on making the single line engine into a channel 4-line engine.  Then you will make the drawn triangle filled triangle commands.

Errr... where do I start with that?  It should take in four sets of parameters and draw the lines simultaneously, or....?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2020, 03:11:43 pm
Try making all the line's registers [3:0] / 4 slot arrays.
This also means when running a line, you draw a single pixel of a single line, 1 at a time, or select a few in sequence.

Also think of the sub-routine steps to run and stop each line or part of a line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2020, 03:22:20 pm
Try making all the line's registers [3:0] / 4 slot arrays.
This also means when running a line, you draw a single pixel of a single line, 1 at a time, or select a few in sequence.

Also think of the sub-routine steps to run and stop each line or part of a line.

So the function would iterate through the 4 slots, drawing a pixel from each?  Or would it be quicker to just draw an entire shape first before moving on to the next one in the array?

On a side note, I've just thought of something for the graphics mode that would be an important addition (you've probably already thought of it) - the ability to write text to the graphics memory?  So the existing character tilemaps could be used to display text in the graphics RAM?  I suppose that would just be a blitter function (with some decoding of the character tile into a bitmap)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2020, 04:18:20 pm
Think about what you need to do to fill in a non-right angle triangle...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2020, 05:43:29 am
Please test the attached updated 'FIFO_3word_0_latency.sv'.  If it works, please update all your project folders with the new version.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 08, 2020, 08:48:32 am
Please test the attached updated 'FIFO_3word_0_latency.sv'.  If it works, please update all your project folders with the new version.

Yes, that works fine.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2020, 12:33:54 pm
Have you tried to figure out how to draw a filled triangle, why it needs 3 running lines.
Try to make a working one in the FreeBasic geo.bas and show it to me.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on July 08, 2020, 01:27:18 pm
Wanted to ask a question re: BGA soldering to anyone reading this, really.  Bearing in mind I'm looking to fabricate a PCB for the EP4CE22F17 (256-fBGA with 1mm pitch), is it necessary to have a pre-heater or some form of board heater to use in addition with the hot air gun to solder the BGA effectively?  I don't have an expensive hot air gun - it's a pretty cheap one to be honest, but has served me well so far soldering the EQFP-144 packages.

Is pre-heating (is that the right term?) necessary?  Could I just get away with hot-air soldering the BGA onto the PCB in a skillet over the cooker, if necessary?
Don't worry about preheating. It's a nice thing to have, and makes process easier and faster, but it's not a necessity. In case you're wondering, I don't have a preheater either, but I recently upgraded my hot air gun from cheap-ass $99 affair (that served me for over 3 years) to this one (https://www.aliexpress.com/item/4000823812383.html?spm=a2g0s.9042311.0.0.4ecd4c4dNI2plm), and it sped things up quite a bit because it's more powerful.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 08, 2020, 02:00:15 pm
Have you tried to figure out how to draw a filled triangle, why it needs 3 running lines.
Try to make a working one in the FreeBasic geo.bas and show it to me.

Haven't had much time to think about, really.  I've given some thought to how to draw a non-filled rectangle - the easiest method seems to be just to draw three lines, but that's no good for a filled triangle - looks like the lines will need to be drawn simultaneously, which could be a headache as it'll involve three sets of variables in the same line function...   :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2020, 04:45:30 pm
When I said 3 lines for triangle, a hint would be that 1 line is always re-drawing with a new start and stop coordinates every time it finishes.  Now, what are the other 2 line drawing engines doing?

Can this still work for fill 4 coordinate geometric shapes as well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 08, 2020, 06:29:53 pm
When I said 3 lines for triangle, a hint would be that 1 line is always re-drawing with a new start and stop coordinates every time it finishes.

So one line draws the perimeter of the triangle?  It would draw a line from x0,y0 to x1,y1, then from x1,y1 to x2,y2, then from x2,y2 to x0,y0?

Now, what are the other 2 line drawing engines doing?

Supervising the work of the first one?  ;)

Erm... a random guess would be filling the shape - one engine to each half (top/bottom) of the shape??  :-//

Can this still work for fill 4 coordinate geometric shapes as well?

I suppose so.  A 4-coordinate geometric shape is just a compound shape made of two triangles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2020, 06:53:18 pm
When I said 3 lines for triangle, a hint would be that 1 line is always re-drawing with a new start and stop coordinates every time it finishes.

So one line draws the perimeter of the triangle?  It would draw a line from x0,y0 to x1,y1, then from x1,y1 to x2,y2, then from x2,y2 to x0,y0?

Now, what are the other 2 line drawing engines doing?

Supervising the work of the first one?  ;)

Erm... a random guess would be filling the shape - one engine to each half (top/bottom) of the shape??  :-//

Can this still work for fill 4 coordinate geometric shapes as well?

I suppose so.  A 4-coordinate geometric shape is just a compound shape made of two triangles.
|O  Nope...

Method #1, using 2 line generators.  (Eats less gates)

Make line generator #1 = to points A&B on a triangle.
Loop until line #1 is finished:
{
Step Line #1
run line generator #2 with the current coordinates of line#1 for it's beginning and the triangle's point C for it's ending and draw a complete line line.
}
To complete an unfilled triangle, the running of line generator #2 should only take place on the first and last pixel of line generator #1.

Method 2:

Load the first 2 line generators with the coordinates of 2 edges of the triangle.  EG: Line 1 points =A&B, Line #2 points =B&C.
Loop until line #1 and line #2 are finished:
{
Step Line #1 & #2 by 1 pixel
load line generator #3 with the current coordinates of line#1 for it's beginning and current coordinates of line #2 for it's ending and draw a complete line.
}

The difference between filled and non filled is that line generator #3 is only run once at the beginning and when line generators #1&#2 are finished.  Or, you can just draw 3 lines in sequence.

The advantage of #2 is that you have 4 coordinates, (Loading line 1 with points A&B, loading line #2 with points C&D)  a start and stop position for 2 line generators meaning you can draw a filled 4 sided polygon.  Drawing a triangle with this engine means that 2 points on the 4 sided polygon share the same coordinates.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2020, 07:13:14 pm
Come to think of it, you can use my method #1 and draw 2 back-back triangles.

Still need to consider giving the line engines an ARC parameter, ie look at how the ellipse draws a curve in the existing geo.bas software as it is nothing but a fancy line drawing algorithm generating 2 halves of each quadrant of the ellipse.

I'm thinking that the line begins in the center with a delta X/Y offset, then proceeded drawing to the end-points in each direction curving it's path as it goes.  With this not only are the circles easy as the delta X&Y are easy to compute, but manually entering these coordinates on an angle will allow ellipses to be generated at odd angles.

Using method #1, maybe you will just create 2 completely separate line generator modules as the gate count wont be terrible compared to 3 or 4 line generators.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 09, 2020, 12:54:22 am
None of the suggested methods for filling a triangle sounds like the way I would do it, which is this:

Let A, B, C be the vertices in order from top to bottom. Initialise two line generators, L1 from A to B and L2 from A to C. Step them both together vertically and fill horizontal rows between L1 and L2 at each step. When L1 reaches B, reset it to go from B to C and continue.

This method only requires two line generators, and has the advantage that it writes consecutive pixels horizontally, which could be important if your graphics memory benefits from burst accesses. It also doesn't rely on adjacent non-axis-aligned lines fitting together perfectly without leaving gaps.

Polygons with more than three vertices can be handled by dividing them into triangles. This is probably best done in software rather than trying to make the hardware do it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 09, 2020, 02:48:42 am
None of the suggested methods for filling a triangle sounds like the way I would do it, which is this:

Let A, B, C be the vertices in order from top to bottom. Initialise two line generators, L1 from A to B and L2 from A to C. Step them both together vertically and fill horizontal rows between L1 and L2 at each step. When L1 reaches B, reset it to go from B to C and continue.

This method only requires two line generators, and has the advantage that it writes consecutive pixels horizontally, which could be important if your graphics memory benefits from burst accesses. It also doesn't rely on adjacent non-axis-aligned lines fitting together perfectly without leaving gaps.

Polygons with more than three vertices can be handled by dividing them into triangles. This is probably best done in software rather than trying to make the hardware do it.
This works great and works so long as you draw lines A&B vertically downward, you step each until they increment on the Y axis, then fill.  This way the filling of pixels on a line are drawn once.  My 2 line method is cheaper and easier to do, however it's shortcoming is that pixels are filled over multiple times.  My only question is when we increment an angled line, the line itself may fill another adjacent pixel or 2 on the X axis.  The horizontal line generator would need to take the maximum X width unless we use a different line generator optimized for this task.  One that jumps an X&Y position on each clock and rely on the horizontal line filler to fill in the gaps.

Remember, our current line generator is optimized for fill in all the gaps as it generates a line and is not intended/optimized to be part of a fill generator.

Yes, our memory is our bottle neck and we will have up to a horizontal 16 pixel cache since we do need read-modify-write to support the bitplane modes, translucency & collision detection when drawing.  Your horizontal line filling, though a little trickier to implement for best results, would accelerate filled triangles by a larger and larger degree as the triangle grows in size compared to my dumb engine which makes use of what we already have.  Let's see if nockieboy would like to tackle this type of triangle engine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 09, 2020, 09:13:40 am
Okay, I feel like I'm waaay out of my depth here trying to come up with even just the BASIC interpretation of a routine to draw these triangles.  Now you're presenting me with options?! :scared:  ;)

Right, just so I'm (and the average reader is) clear, these are the three different methods available to draw a filled triangle so far (thanks for chipping in, @gcewing!):

[attach=1]

[attach=2]

[attach=3]

Order of drawing is (mostly) in alphabetical order in those diagrams.

I had an instant reservation pop up as soon as I read about method #1 - and that's the concern that some pixels might be missed when starting a line from a point on line #1 and a lot of pixels will be overwritten as the 2nd line converges on C.  This was a technique used in the 80's and early 90's on 8-bit computers (and even on 16-bit systems in the demo scene) to produce random-ish pretty Moire patterns etc. by taking advantage of the limitations of the graphics systems.

Method #2 looks logical and with less wasted effort (less overwritten pixels - if any).   I like this one, but again the concern is how effective would the fill be?  For certain angles and triangle sizes, is there a chance pixels could be missed in the fill?

Method #3 looks to have the least pixel overwrites (none) due to rasterising the triangle in a way that is sympathetic to the system it's being drawn on, but as @BrianHG has pointed out, a diagonal line with an angle less than 45 degrees from horizontal will sometimes have more than one pixel on an edge with the same Y value, creating an overwritten line filling that segment of the triangle.  Diagram below shows darker pink lines where multiple horizontal fill lines would overwrite each other:

[attachimg=4]

I'm limited by my understanding of translating all this into BASIC, then HDL, unfortunately.  I'm going to have to go away and make a serious effort to understand how the routines are working in the FreeBASIC simulator, but I'm inclined to go with method #3.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 09, 2020, 09:44:29 am
@BrianHG has pointed out, a diagonal line with an angle less than 45 degrees from horizontal will sometimes have more than one pixel on an edge with the same Y value, creating an overwritten line filling that segment of the triangle.
You need to move exactly one pixel in the y direction at each step, and however many pixels are needed in the x direction. As BrianHG said, your line generator may need modifying to make this possible.

But I don't think you need two different kinds of line generator, one for lines and one for triangles -- just one kind that's sufficiently general. You can use it for drawing lines as well, as long as you pick the right direction to step in depending on the slope.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 09, 2020, 10:48:48 am
Here's some python3 code I wrote to try out the idea. It runs two Bresenham line algorithms in parallel. The outer loop takes one step in y on each iteration, and inner loops advance the left and right x coordinates the appropriate amount. It draws each pixel exactly once.

There may be a more efficient way that avoids the inner loops, but I haven't thought about it very deeply yet.

Code: [Select]
screen = [[' '] * 79 for y in range(23)]

def fill_triangle(x0, y0, x1, y1, x2):
    # Fills a flat-bottomed triangle with apex at (x0, y0) and
    # lower vertices at (x1, y1), (x2, y1). Assumes x1 <= x0 <= x2
    # and y0 <= y1.
   
    xL = xR = x0
    y = y0
    dxL = x0 - x1
    dxR = x2 - x0
    dy = y1 - y0
    eL = eR = 0
    n = dy
    while n > 0:
        fill_raster_line(xL, xR, y)
        eL += dxL
        while eL > 0:
            xL -= 1
            eL -= dy
        eR += dxR
        while eR > 0:
            xR += 1
            eR -= dy
        y += 1
        n -= 1

def fill_raster_line(x0, x1, y):
    x = x0
    n = x1 - x0 + 1
    while n > 0:
        draw_pixel(x, y)
        x += 1
        n -= 1

def draw_pixel(x, y):
    screen[y][x] = '*'

fill_triangle(50, 5, 10, 20, 60)
for row in screen:
    print(''.join(row))
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 09, 2020, 12:02:19 pm
Here's some python3 code I wrote to try out the idea. It runs two Bresenham line algorithms in parallel. The outer loop takes one step in y on each iteration, and inner loops advance the left and right x coordinates the appropriate amount. It draws each pixel exactly once.

There may be a more efficient way that avoids the inner loops, but I haven't thought about it very deeply yet.

                                                  *                           
                                               *****                           
                                            *********                         
                                          ***********                         
                                       ***************                         
                                    *******************                       
                                  *********************                       
                               *************************                       
                            *****************************                     
                          *******************************                     
                       ***********************************                     
                    ***************************************                   
                  *****************************************                   
               *********************************************                   
            ************************************************* 

Thanks @gcewing, that works well :-+ - I don't know how it could be modified to draw a triangle in any orientation or point order, but I'm sure @BrianHG will have some thoughts on it. :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 09, 2020, 01:57:19 pm
Method #3 it is.
It is easy enough to try in the geo.bas as you are just using counters.
If you are not sure about the 'absolute' edge of the triangle, remember, you can alway draw 3 connected normal line after the triangle is already filled, however, this may be up to you.

Since we are organizing the 3 sets or coordinates A,B,C in order by Y position first, vertically drawing LineGen#1 between A&C while the other LineGen#2 goes between A&B, then once it reaches B, it will start again going from B to C, all along using (well sort of) a dumb X axis line generator #3 only drawing from the coordinates of LineGen#1 to LineGen#2 after every Y increment.

The goal here is for every time you increment 1 Y axis on each line, what is the delta X.  A slight modification to the current line generators, however, because of your setup, you always know that Y is incrementing from top to bottom, otherwise the triangle is 1 pixel tall and you will end up filling a line from the most left X coordinates to the most right X coordinates among pints A,B,C.

You can still use your existing line generator to solve the triangle edges with a small penalty for it drawing in the edge pixels between each fill, however, it will still out-pace your pixel writer.

Let's see what kind of plan you have to do this.
I would stick with just using 2 of your existing line generators as you know they work.
Also, to speed things further up, you just completely skip a fill at each Y increment if the X coordinates of LineGen#1 & #2 have X coordinates within +/- 1 of each other as the line generators would have drawn those pixels.  (If you do it that way.)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 09, 2020, 02:08:27 pm
Here, I'll start you off:

Step #1, sort points A,B,C into points new_A,B,C where the Y coordinate of new_A is the lowest coordinate and the Y coordinate of new_C is the highest.

Step #2, Setup (not run) line gen #1 & #2, and setup #3 which is still run by LineGen#2 once it reaches point new_B
LineGen#1 = new_A to new_C
LineGen#2 = new_A to new_B
LineGen#3 = new_B to new_C


Step #3:
 Make a screen_Y position loop from new_A(y) to new_C(y)

(What do you do in here).
(it will involve the line generators as is with only 2 tiny patches.  They will still function normally when used by themselves)
For now, only worry about 1 LineGen #1, see what you can come up with.

Next screen_Y

Hope this helps.

The only difference between my idea and gcewing python cod is that I don't care about sorting on the X coordinates as the line filler wont care (either it's bidirectional, or, it will swap the X coordinates and always draw from left to right) and we are still using our existing line generator code which may take a few additional clocks to generate a horizontal strip based on the edges of an angles of the line, however this does not matter as they will be doing the work where the line-fill missed the edges and corners of and extreme angle line at the beginning of a new Y coordinate.

Your other choice is to do M.N style floating point (still integer, just that you use the upper 12 bits as the mantissa) delta-X addition for every Y increment.  This means a 24 bit adder and a little additional setup math at the beginning.  You will also need to deal with how the edges of each line are filled especially when connecting 2 triangles to generate filled 4 sided polygons.  (.N is the err added at every Y step, however, it needs to be per-determined an can now be a value greater than 1 for every Y increment.)

How do you want to proceed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 09, 2020, 03:36:19 pm
This is how far I've gotten based on the guidance above.  I've tried to convert the existing DrawLine function in our Free Basic test program to draw three lines.  There must be a simpler way of ordering the vertices at the start than what I've done?   :-//

After the ordering IF..ELSE IF structure, I set up some of the variables for the three line generators, sufficient to run all three in parallel.  Then I've made a start on the loop, but obviously it won't work as it currently stands.  I'm thinking that we need to draw a horizontal line between Ax and Cx every time y1 is incremented - but we need to make sure y2 has incremented as well, don't we? Or will they both increment at the same time by some weird conjunction of maths and the planets?

Code: [Select]
Sub drawTriangle (ByVal Ax as Integer, byval Ay as Integer, byval Bx as Integer, byval By as Integer, byval Cx as Integer, byval Cy as Integer, byval color_val As UByte)

   Dim As Integer new_Ax,new_Ay,new_Bx,new_By,new_Cx,new_Cy
   Dim As Integer dx1,dy1,x1,y1,sx1,sy1,errd1,magic1
   Dim As Integer dx2,dy2,x2,y2,sx2,sy2,errd2,magic2
   Dim As Integer dx3,dy3,x3,y3,sx3,sy3,errd3,magic3
   Dim As Boolean is_done

If (Ay > By > Cy ) Then
new_Ax = Ax
new_Ay = Ay
new_Bx = Bx
new_By = By
new_Cx = Cx
new_Cy = Cy
Else If (By > Cy > Ay) Then
new_Ax = Bx
new_Ay = By
new_Bx = Cx
new_By = Cy
new_Cx = Ax
new_Cy = Cy
Else If (Cy > Ay > By) Then
new_Ax = Cx
new_Ay = Cy
new_Bx = Ax
new_By = Ay
new_Cx = Bx
new_Cy = By
Else If (Ay > Cy > By) Then
new_Ax = Ax
new_Ay = Ay
new_Bx = Cx
new_By = Cy
new_Cx = Bx
new_Cy = By
Else If (Cy > By > Ay) Then
new_Ax = Cx
new_Ay = Cy
new_Bx = Bx
new_By = By
new_Cx = Ax
new_Cy = Ay
Else If (By > Ay > Cy) Then
new_Ax = Bx
new_Ay = By
new_Bx = Ax
new_By = Ay
new_Cx = Cx
new_Cy = Cy
EndIf

   Rem bounding box's width and height for the three line generators
   Rem And set the loop's sign
   Rem # Line Gen #1
   dx1 = new_Cx - new_Ax
   dy1 = new_Cy - new_Ay
   Rem # Line Gen #2
   dx2 = new_Bx - new_Ax
   dy2 = new_By - new_Ay
   Rem # Line Gen #3
   dx3 = new_Cx - new_Bx
   dy3 = new_Cy - new_By
   
   If (dx1 < 0) Then
      dx1 = -dx1
      sx1 = -1
   Else
      sx1 = 1
   End If
   
   If (dy1 > 0) Then
      dy1 = -dy1
      sy1 = 1
   Else
      sy1 = -1
   End If
   
   If (dx2 < 0) Then
      dx2 = -dx2
      sx2 = -1
   Else
      sx2 = 1
   End If
   
   If (dy2 > 0) Then
      dy2 = -dy2
      sy2 = 1
   Else
      sy2 = -1
   End If
   
   If (dx3 < 0) Then
      dx3 = -dx3
      sx3 = -1
   Else
      sx3 = 1
   End If
   
   If (dy3 > 0) Then
      dy3 = -dy3
      sy3 = 1
   Else
      sy3 = -1
   End If

   magic1 = 0
   errd1  = dx1 + dy1
   x1     = new_Ax
   y1     = new_Ay
   
magic2 = 0
   errd2  = dx2 + dy2
   x2     = new_Ax
   y2     = new_Ay
   
   magic3 = 0
   errd3  = dx3 + dy3
   x3     = new_Bx
   y3     = new_By
   
   For screen_Y = new_Ay To new_Cy
   
      draw_pixel (x1,y1,color_val)

      magic1 = errd1 shl 1
      if (magic1 > dy1) Then
         errd1 += dy1
         x1    += sx1
      End If
       
      if (magic1 < dx1) Then
         errd1 += dx1
         y1    += sy1
      End If
     
      draw_pixel (x2,y2,color_val)

      magic2 = errd2 shl 1
      if (magic2 > dy2) Then
         errd2 += dy2
         x2    += sx2
      End If
       
      if (magic2 < dx2) Then
         errd2 += dx2
         y2    += sy2
      End If
   
      draw_pixel (x3,y3,color_val)

      magic3 = errd3 shl 1
      if (magic3 > dy3) Then
         errd3 += dy3
         x3    += sx3
      End If
       
      if (magic3 < dx3) Then
         errd3 += dx3
         y3    += sy3
      End If
     
   Next

End Sub
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 09, 2020, 03:44:11 pm
Your other choice is to do M.N style floating point (still integer, just that you use the upper 12 bits as the mantissa) delta-X addition for every Y increment.  This means a 24 bit adder and a little additional setup math at the beginning.  You will also need to deal with how the edges of each line are filled especially when connecting 2 triangles to generate filled 4 sided polygons.  (.N is the err added at every Y step, however, it needs to be per-determined an can now be a value greater than 1 for every Y increment.)

How do you want to proceed.

 :o

Which way is going to be the quickest?

The M.N style sounds simpler and perhaps easier for me to grasp, but that's only because I don't really know the intricacies of either method - it just seems adding a constant value (be it a float or an integer) to x for every y increment is the easier-to-read way to go.  I can't imagine a 24-bit adder will take up too much space in the FPGA?  I'm running at about 85% logic usage currently, but with plans to expand to over double the resources in a BGA package later on, I'm not exactly scrimping and saving every last logic gate here.

Either way will involve lots of dumb expressions from me and stupid questions, so I'll defer to your expert knowledge of the subject.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 09, 2020, 03:59:53 pm
The Y sort will be done in a single clock as the command is being called, IE 0 clock cycles.
Like before, the setup for all 3 lines will take 1 clock, then you can begin drawing the line.

As for the draw line function, for now, keep your setup and just draw line #1.

Then let's modify that line engine to temporarily escape at a chosen Y coordinate, then continue to another, being the next  Y coordinate.
 (make it a called sub-function for ease of reading.  You probably wont have the luxury of using a function's call arrays as this line generator when called will only complete part of a line at a time.  You might be stuck using 'Dim Shared' for the line arrays.)

We will stop here and make sure the alterations you make can implement in your verilog line generator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 09, 2020, 05:16:12 pm
For the M.N method, we need to calculate it this way, unless you can come up with a shorter method.


First for float:
Code: [Select]
div = abs( ay - by )
  if div = 0 then div=1
  delta_x_per_y_increment =  ( bx-ax ) / div
xp = ax

For yp = ay to by
  draw_pixel ( int(xp),int(yp),color_val)
  xp=xp + delta_x_per_y_increment
next yp

See new attached geo.bas  in the attached geo_trifill_testfloat.zip with everything updated.
I'm drawing the float line using the 'drawFilledTriangle' right at the end.

Now, since pixels will be filled from left to right, the line wont have bits in it.
However, I also plotted a normal line right on top of the third line and you see extra added pixels on the right which would not be caught by the left to right fill.

24 bit Integer version coming in next post so you can see what that will be like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 09, 2020, 05:56:42 pm
Damn it, I'm either too sleepy or cant get rid of that divide.
If it were a multiply, IE if I were to operate with everything at 4096x, (that's using M.N), multiply and bit shift as a divide by 4096 could work but my head is in the clouds. (divides are slow, like 11 clock cycles and eat resources.  You could speed this up by pipe-lining making the divides at 125 million a second, but I want to see filled triangle plots by Monday.)

Instead, lets use our existing line engine doubled.
Well use the 2 Bresenham line generators to plot/create the outer edges of the line and use a simple for x1 to x2 for filling in the inside.  At worst, you pixel drawing engine / command may have to draw a few repetitious pixels on a line, but since they are adjacent pixels, you are only talking 1/125 millionth of a second per extra dot.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 10, 2020, 12:19:48 am
There must be a simpler way of ordering the vertices at the start than what I've done?   :-//
You could hard-code a 3-element bubble sort.

Keep in mind that these kinds of setup tasks can be done in software. I'd concentrate on just doing the parts that really need to be fast in hardware, at least initially. You can think about migrating some of the setup into hardware later if you want.

Google "sorting network" for some ideas on how to implement a sort in hardware.

Quote
After the ordering IF..ELSE IF structure, I set up some of the variables for the three line generators, sufficient to run all three in parallel.
You only need to run 2 line generators in parallel. When you reach the middle vertex, switch one of them from doing the upper half to doing the lower half.

Quote
we need to make sure y2 has incremented as well, don't we? Or will they both increment at the same time by some weird conjunction of maths and the planets?
In my Python code I only have one y variable shared between the two line generators, so this issue doesn't arise.  :)

Despite what I said earlier, I think it's better to think of the triangle filler as its own thing, and not try to make it share hardware with whatever you're using to draw lines. Instead of "liine generators" think of "side generators". There are two of them, but they're not completely independent, they share some state.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 10, 2020, 12:32:07 am
The M.N style sounds simpler and perhaps easier for me to grasp,
It's certainly easier to get one's head around! The only reason I didn't suggest it myself is because of the need for divisions during the setup, but like I said before, you can leave that to software for now.

A nice property of the fixed-point approach is that a step in the y direction can be done in a single clock cycle, instead of potentially requiring multiple cycles to update the x coordinates.

Another benefit is that it may be easier to adapt for more complicated shapes such as circles and bezier curves if you want to go there later.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 10, 2020, 12:44:51 am
There must be a simpler way of ordering the vertices at the start than what I've done?   :-//
You could hard-code a 3-element bubble sort.

Keep in mind that these kinds of setup tasks can be done in software. I'd concentrate on just doing the parts that really need to be fast in hardware, at least initially. You can think about migrating some of the setup into hardware later if you want.

Google "sorting network" for some ideas on how to implement a sort in hardware.

Quote
After the ordering IF..ELSE IF structure, I set up some of the variables for the three line generators, sufficient to run all three in parallel.
You only need to run 2 line generators in parallel. When you reach the middle vertex, switch one of them from doing the upper half to doing the lower half.

Quote
we need to make sure y2 has incremented as well, don't we? Or will they both increment at the same time by some weird conjunction of maths and the planets?
In my Python code I only have one y variable shared between the two line generators, so this issue doesn't arise.  :)

Despite what I said earlier, I think it's better to think of the triangle filler as its own thing, and not try to make it share hardware with whatever you're using to draw lines. Instead of "liine generators" think of "side generators". There are two of them, but they're not completely independent, they share some state.

2 Line generators running in parallel or series makes no difference plotting pixels speed wise since we use the line generators to plot the pixels on the line itself and if there is vacant space inbetween line gen #1 and #2, we fill in a straight line between them.  Having 2 run in parallel would only help if we had a 2 channel pixel writer where we can write 2 different pixels to ram at the same time.

In System verilog, this becomes easy as you make the all current line generators integers into arrays.  This way, at every clock, your single array selection variable will select which line generator increments.  On each increment, like the Y coordinate increasing, you can make the array pointer increment to work on the other face of the triangle, all with 0 latency in the transition.  Our pixel writer will not be able to keep up with this speed and as it's FIFO command buffer goes full, it will tell the geometry_xy_plotter to pause many times.

As for the top down sort, however it is done, a simple magnitude / if / else if would work in a single clock as no matter how you engineer the tree, the compiler would simplify it anyways.  Sorting based on 3 12 bit numbers should still reach our core clock of 125MHz.  If not, we would need to break that sort into 2 stages.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 10, 2020, 12:46:15 am
At worst, you pixel drawing engine / command may have to draw a few repetitious pixels on a line, but since they are adjacent pixels, you are only talking 1/125 millionth of a second per extra dot.
I'd suggest treating the raster lines as half-open intervals, i.e. x1 <= x < x2. Then adjacent triangles will fit together without overdrawing or leaving gaps.

Overdraw is harmless if you're just overwriting pixels, but if you might want other drawing modes such as XOR or alpha blending, it's something you'll want to avoid.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 10, 2020, 12:57:29 am
The M.N style sounds simpler and perhaps easier for me to grasp,
It's certainly easier to get one's head around! The only reason I didn't suggest it myself is because of the need for divisions during the setup, but like I said before, you can leave that to software for now.

A nice property of the fixed-point approach is that a step in the y direction can be done in a single clock cycle, instead of potentially requiring multiple cycles to update the x coordinates.

Another benefit is that it may be easier to adapt for more complicated shapes such as circles and bezier curves if you want to go there later.

It makes no difference about the Y direction in 1 clock since we have to draw those pixels anyways.  Remember, each clock, we draw a pixel.  When we enter a new Y coordinate on both line gen #1 and #2, we fill the void in between, then continue the Bresenham line gens #1 and #2 which will plot the missing pixels due to rounding errors which would not be done with the M.N method.  Remember, there is 0 pause or latency here, switching from the line fill back to incrementing the line gens will continue to push out pixels as if the horizontal fill generator was just continuing to fill a longer line.  The M.N would only fill the pixels in between the 2 points including the points.  Though, with the M.N, you can make a dithered line's edge knowing the relative analog center of the line's X location.

The ellipse and curve algorithm has also been with nothing more than adds and X^2 & Y^2 and multiples of 8 in the same way Bresenham's line algorithm works.  We already the ellipse running in geo.bas and it can be broken down into it's 8 quadrants to generate Bézier curves or rotated ellipses.  No divides needed.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 10, 2020, 01:21:26 am
Another benefit is that it may be easier to adapt for more complicated shapes such as circles and bezier curves if you want to go there later.

Bézier curves without divide on this web page.  I know that the author used 'long' and 'double' for his Bézier curves and Ellipse, but they work fine with all int's.  All the multiplies of divides are by 2 and by 4.  All the other multiplies total 8 which the Cyclone IV can handle in a single clock at 125MHz.  Also, our GPU has yet to use a single hardware multiplier in the Cyclone IV.

http://members.chello.at/easyfilter/bresenham.html (http://members.chello.at/easyfilter/bresenham.html)

My plan is to eventually swap out the line gens and ellipse for the Bézier curve line gens and when a line or triangle is called, it's basically a Bézier curve line with an arc setting on the line itself, or 0.  Generating ellipses just calls 4 Béziers with the arc having the right delta.  Like this, we can now also generate rotated ellipses or triangles with curved faces.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 10, 2020, 10:33:07 am
Okay, thanks to spinning several plates (one of which is work) I'm losing track of where we are and what I'm supposed to be doing.  I had completed the setup for a three line (two line?) function to start drawing a triangle, but since then I've got Free BASIC code to draw triangle edges using M.N and the conversation has moved on.   ???

What should I be working on next?  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 10, 2020, 02:50:50 pm
Go back here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3127872/#msg3127872 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3127872/#msg3127872)

Your post after mine began ok.  Remember, we got it backwards, we want point new_A to have the lowest Ay and point new_Cy to have the highest Cy.

The geo.bas I've uploaded may have the 'divide' method of generating a line in the triangle_filled routine, however, you will erase that little line loop and place in the work you begun.  Since we have a working Bresenham's in Verilog, we will use one with with 3 set array which you may increment 1 of 3 at a time.  Follow my instructions to generate a proper rasterized fill.

When going to verilog, the 3 set array is the easiest upgrade to do.  If your FMAX drops too low, we will try downgrading to a 2 set array.  If the FMAX is still too low, we will go back to a single 1 set array line, like now, and add a second Bresenham's line generator to mimic a 2 set array, IE 2 line drawing engines.

Step 1, get it working in geo.bas.  (program to make it easy to switch to verilog)
Step 2, upgrade verilog code to mimic geo.bas.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 11, 2020, 01:49:16 pm
Remember, we got it backwards, we want point new_A to have the lowest Ay and point new_Cy to have the highest Cy.

Right, so I've reversed the IF.. conditional in the setup:
Code: [Select]
If (Ay > By > Cy ) Then
new_Ax = Cx
new_Ay = Cy
new_Bx = Bx
new_By = By
new_Cx = Ax
new_Cy = Ay
ElseIf (By > Cy > Ay) Then
new_Ax = Ax
new_Ay = Ay
new_Bx = Cx
new_By = Cy
new_Cx = Bx
new_Cy = By
ElseIf (Cy > Ay > By) Then
new_Ax = Bx
new_Ay = by
new_Bx = Ax
new_By = Ay
new_Cx = Cx
new_Cy = Cy
ElseIf (Ay > Cy > By) Then
new_Ax = Bx
new_Ay = By
new_Bx = Cx
new_By = Cy
new_Cx = Ax
new_Cy = Ay
ElseIf (Cy > By > Ay) Then
new_Ax = Ax
new_Ay = Ay
new_Bx = Bx
new_By = By
new_Cx = Cx
new_Cy = Cy
ElseIf (By > Ay > Cy) Then
new_Ax = Cx
new_Ay = Cy
new_Bx = Ax
new_By = Ay
new_Cx = Bx
new_Cy = By
EndIf

The geo.bas I've uploaded may have the 'divide' method of generating a line in the triangle_filled routine, however, you will erase that little line loop and place in the work you begun.  Since we have a working Bresenham's in Verilog, we will use one with with 3 set array which you may increment 1 of 3 at a time.  Follow my instructions to generate a proper rasterized fill.

 ???  Okay, so you want the setup above inserted into the drawFilledTriangle routine, but Ax/Ay, Bx/By, Cx/Cy replaced with a 3-element array [x,y], then the loop modified to not just draw one line, but all three lines defined in the array?  I'm having trouble following.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 11, 2020, 03:07:03 pm
Yes you got it.  Remember, fill and setup the 3 line elements.

begin first pixel of line #1,#2,&#3.

Start a separate for loop raster_Y position counter from the lowest Y to the highest Y coordinate.
Should be equal to new_Ay and new_Cy. (line#1 beginning and ending Y position)

run/draw line #1 until you reach the raster_Y.
run/draw line #2 until you reach the raster_Y (when line#2 ends, swap line#2's into line#3's and step/run line #3.)

if there are pixels between line #1x and line #2x, do a horizontal fill
 
next raster_Y position.

Finish lines #1 and line #3.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 11, 2020, 06:53:38 pm
Okay, got this far:
Code: [Select]
Sub drawFilledTriangle (ByVal x0 as Integer, byval y0 as Integer, byval x1 as Integer, byval y1 as Integer, byval x2 as Integer, byval y2 as Integer, byval color_val As UByte)
   
        Dim As double ax,ay,bx,by,cx,cy,div,xp,yp,delta_x_per_y_increment
Dim As Double x[2],y[2]

If (y0 > y1 > y2 ) Then
x[0] = x2
y[0] = y2
x[1] = x1
y[1] = y1
x[2] = x0
y[2] = y0
ElseIf (y1 > y2 > y0) Then
x[0] = x0
y[0] = y0
x[1] = x2
y[1] = y2
x[2] = x1
y[2] = y1
ElseIf (y2 > y0 > y1) Then
x[0] = x1
y[0] = y1
x[1] = x0
y[1] = y0
x[2] = x2
y[2] = y2
ElseIf (y0 > y2 > y1) Then
x[0] = x1
y[0] = y1
x[1] = x2
y[1] = y2
x[2] = x0
y[2] = y0
ElseIf (y2 > y1 > y0) Then
x[0] = x0
y[0] = y0
x[1] = x1
y[1] = y1
x[2] = x2
y[2] = y2
ElseIf (y1 > y0 > y2) Then
x[0] = x2
y[0] = y2
x[1] = x0
y[1] = y0
x[2] = x1
y[2] = y1
EndIf

div = abs( y[0] - y[2] )
If div = 0 then div = 1
delta_x_per_y_increment = ( x[1] - x[0] ) / div
xp = x[0]

For yp = y[0] to y[2]
  draw_pixel ( int(xp),int(yp),color_val )
  xp= xp + delta_x_per_y_increment
Next yp

End Sub

I'm not entirely sure what I'm doing with the setup near the start of the loop.  When setting delta_x_per_y_increment, shouldn't that be x[2] instead of x[1], and aren't I going to have to sort the x array to find the lowest and highest values and use those in the formula to calculate the correct delta_x_per_y_increment?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 11, 2020, 07:23:28 pm
Okay, got this far:
Code: [Select]
Sub drawFilledTriangle (ByVal x0 as Integer, byval y0 as Integer, byval x1 as Integer, byval y1 as Integer, byval x2 as Integer, byval y2 as Integer, byval color_val As UByte)
   
        Dim As double ax,ay,bx,by,cx,cy,div,xp,yp,delta_x_per_y_increment
Dim As Double x[2],y[2]

If (y0 > y1 > y2 ) Then
x[0] = x2
y[0] = y2
x[1] = x1
y[1] = y1
x[2] = x0
y[2] = y0
ElseIf (y1 > y2 > y0) Then
x[0] = x0
y[0] = y0
x[1] = x2
y[1] = y2
x[2] = x1
y[2] = y1
ElseIf (y2 > y0 > y1) Then
x[0] = x1
y[0] = y1
x[1] = x0
y[1] = y0
x[2] = x2
y[2] = y2
ElseIf (y0 > y2 > y1) Then
x[0] = x1
y[0] = y1
x[1] = x2
y[1] = y2
x[2] = x0
y[2] = y0
ElseIf (y2 > y1 > y0) Then
x[0] = x0
y[0] = y0
x[1] = x1
y[1] = y1
x[2] = x2
y[2] = y2
ElseIf (y1 > y0 > y2) Then
x[0] = x2
y[0] = y2
x[1] = x0
y[1] = y0
x[2] = x1
y[2] = y1
EndIf

div = abs( y[0] - y[2] )
If div = 0 then div = 1
delta_x_per_y_increment = ( x[1] - x[0] ) / div
xp = x[0]

For yp = y[0] to y[2]
  draw_pixel ( int(xp),int(yp),color_val )
  xp= xp + delta_x_per_y_increment
Next yp

End Sub

I'm not entirely sure what I'm doing with the setup near the start of the loop.  When setting delta_x_per_y_increment, shouldn't that be x[2] instead of x[1], and aren't I going to have to sort the x array to find the lowest and highest values and use those in the formula to calculate the correct delta_x_per_y_increment?
Reread my post here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3128938/#msg3128938 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3128938/#msg3128938)

There may be some occasional repeat plots with really steep shrinking/converging X axis lines, but these triangles will need to be so flat and wide that they would look like a flat line.  We will spit out 125 million pixels a second in these cases and for a wide triangle, like the width of the screen and only 2-5 lines tall, we may be re-painting 50% of those pixels on those lines.  If you want to save these double pixel plots, I would say wait till after we got everything working then take a look back and perform that optimization step.

(Here's that optimization step, but don't let it mess with your head for now) When determining the beginning and ending X coordinates for the raster line fill, when the X direction of the line shrinks, wait for the line generator to leave the current raster_Y coordinate before pausing it's drawing and using it's X coordinate for the horizontal raster fill.  When the X line position increases, pause the line generator as it enters the current raster_Y coordinate and then use it's current X coordinate for the horizontal raster fill.


(Remember, we cant use a divide nor does that routine with the divide work out the bleeding pixels along the edge of the triangle, you need to use and adapt Bresenham's line algorithm.)

(Well, we can use a divide, but there is a huge setup penalty and gate count resources)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 11, 2020, 08:08:35 pm
Please insert and test this final version 3.0 of my 'FIFO_3word_0_latency.sv'.  Let me know if it works.
If you like, here is it's project thread: https://www.eevblog.com/forum/fpga/home-made-systemverilog-3-word-zero-latency-fifo-documented-for-beginners/msg3123336/#msg3123336 (https://www.eevblog.com/forum/fpga/home-made-systemverilog-3-word-zero-latency-fifo-documented-for-beginners/msg3123336/#msg3123336)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Nominal Animal on July 12, 2020, 01:58:44 am
An illustration of the possible different types of triangles might help here:
(https://www.nominal-animal.net/answers/triangle-types.svg)
A row-scanning rasterizer first sorts the three vertices according to the y coordinates.  There are six types of triangles, based on the y coordinates:
If you use two Bresenham lines in parallel, you must remember the minimum x on each row y for the left side, and the maximum x on each row y for the right side, and draw the horizontal line between those (including the end points).

A filler loop that can draw a single triangle of the red or blue type above, but not a combination of both, is the simplest to implement.  Many triangles then involve running the filler loop twice, for y1 <= y < y2 and for y2 <= y <= y3.

Note that the filler loop could allow y coordinates smaller than the viewport minimum, and x coordinates outside the viewport.  Then, it can draw triangles partially outside the viewport without issues.  You simply avoid drawing any horizontal lines when y is smaller than the viewport minimum y coordinate, and draw only the part of the horizontal line that is within the viewport.

If you write a filler that can draw any triangle, you'll simply switch the error and delta terms in the inner loop if it enters x == x2, y == y2.

If you use fixed-point arithmetic, you should include an adjustment term for the left and right sides, for calculating the starting and ending x coordinates for the horizontal line for each y coordinate. (This corresponds to finding the minimum x included on the line on the left side, and maximum x included on the line on the right side.)
For the left side, the adjustment is zero if the slope is positive, and half a step if the slope is negative.
For the right side, the adjustment is zero if the slope is negative, and half a step if the slope is positive.

The slope itself, or the change in x coordinate whenever y changes, for the side from (xA, yA) to (xB, yB) is
    dx = (xB - xA) / (yB - yA)

Here's an example Python floating-point implementation:
Code: [Select]
x_min = 0
y_min = 0
x_max = 79
y_max = 39

def HLine(y, left, right):
    line = [ ]
    for x in range(x_min, x_max + 1):
        if x >= left and x <= right:
            line.append('#')
        else:
            line.append('.')
    print('%3d: %s (%d)' % (y, ''.join(line), len(line)))

def Fill(x1,y1, x2,y2, x3,y3):
    # Sort the points with increasing y
    if y1 > y2:
        x1,y1, x2,y2 = x2,y2, x1,y1
    if y1 > y3:
        x1,y1, x3,y3 = x3,y3, x1,y1
    if y2 > y3:
        x2,y2, x3,y3 = x3,y3, x2,y2

    # Completely outside the viewport?
    if y1 > y_max or y3 < y_min:
        return
    if min(x1, x2, x3) > x_max or max(x1, x2, x3) < x_min:
        return

    # Slope from (x1,y1) to (x2,y2)
    if y1 < y2:
        dx12 = (x2 - x1) / (y2 - y1)
    else:
        dx12 = 0

    # Slope from (x1,y1) to (x3,y3)
    if y1 < y3:
        dx13 = (x3 - x1) / (y3 - y1)
    else:
        dx13 = 0

    # Slope from (x2,y2) to (x3,y3)
    if y2 < y3:
        dx23 = (x3 - x2) / (y3 - y2)
    else:
        dx23 = 0

    # Start at x1,y1
    y,xL,xR = y1,x1,x1

    if dx12 >= dx13:
        # (x2,y2) is on the right side of the triangle
        dxL, dxL2 = dx13, dx13
        dxR, dxR2 = dx12, dx23
    else:
        # (x2,y2) is on the left side of the triangle
        dxL, dxL2 = dx12, dx23
        dxR, dxR2 = dx13, dx13

    # Left adjustments
    if dxL < 0:
        axL = dxL/2
    else:
        axL = 0
    if dxL2 < 0:
        axL2 = dxL2/2
    else:
        axL2 = 0

    # Right adjustments
    if dxR > 0:
        axR = dxR/2
    else:
        axR = 0
    if dxR2 > 0:
        axR2 = dxR2/2
    else:
        axR2 = 0

    # Do not progress outside the viewport.
    if y3 > y_max:
        y3 = y_max

    # Blitter loop
    while y <= y3:

        # Changeover point?
        if y == y2:
            dxL, axL = dxL2, axL2
            dxR, axR = dxR2, axR2

        # y within the viewport?
        if y >= y_min:

            # Adjust edges.
            iL = int(xL + axL)
            iR = int(xR + axR)

            # Any part of horizontal line within viewport?
            if iR >= x_min and iL <= x_max:
                HLine(y, max(x_min, iL), min(iR, x_max))

        # y step.
        y  = y  + 1
        xL = xL + dxL
        xR = xR + dxR

if __name__ == '__main__':
    # Fill(-35,-13, 75,13, 43,57)
    # Fill(99,-2, 17,15, -12,43)
    Fill(1,1, 78,15, 39,38)
There are three divisions (a fixed-point/float value divided by an integer) to get the slopes, and four halving of a fixed-point/float value.  Lots of comparisons in the inner loop, though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2020, 02:16:33 am
Thanks Nominal Animal.
My directions for nockieboy are intended for him to approach the problem of filling the triangles by making his existing HDL code perform what you illustrated by adding a few brackets and 1 extension to an IF() at the top.  It will perform the 2 right hand triangles with 1 more extension to that IF().

What my directions do not cover is the optimization involved in drawing the flat horizontal line in your first 2 illustrated triangles.  The flat line would be drawn twice, however, an addition to the IF() inside the raster fill may be used to prevent that fill.

My step 1 is to get the triangles filled with what we have.  Once done, optimizing the 6 conditions types in your list will be just a bit of juggling and selection of the 2/3 Bresenham's linegen setup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2020, 02:27:21 am
Sorry to do this again nockieboy, but here is a FIFO update.  It is the same as the last, but now has full proper 'System Verilog' compliant lexicon.

When doing the next 2 geometry modules, we will switch over to the style in the attached 'FIFO_3word_0_latency.sv.txt'.
Changing the current geopetry_xy_plotter.sv is optional as it functions, however, there arent many changes to be done.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2020, 11:01:51 am
Please insert and test this final version 3.0 of my 'FIFO_3word_0_latency.sv'.  Let me know if it works.

It works.  :) :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2020, 11:10:59 am
Sorry to do this again nockieboy, but here is a FIFO update.  It is the same as the last, but now has full proper 'System Verilog' compliant lexicon.

That one works as well.  ;)  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2020, 11:36:20 am
I'm having REAL trouble trying to get this triangle drawing function off the ground. |O

I have modified the drawFilledTriangle function in the attached Geo.bas file to include the setup and it should draw two lines simultaneously, even if one line isn't fully complete or goes on forever there should be TWO lines, but I'm getting nothing. Nowt. Zip. Nada.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2020, 02:59:58 pm
Code: [Select]
      Rem Reached the End
      If (x1 = x(1) And y1 = y(1) And x2 = x(2) And y2 = y(2)) Then
      is_done = TRUE
      Else
      is_done = FALSE
      End If
Hehehe, you are expecting both lines to end at the same time.  This will usually never happen at it's not what you are supposed to do.

Step #1 Loop line gen #1 once.

(Perform steps #2,3,4 only if Line #1 y begin and y end arent the same value.)
Step #2, setup your raster_Y for loop counter
Step #3, lets draw only the tallest line, line #1 until it reaches that raster_Y position, ie, loop line gen #1 until it's current Y position = raster_Y position.
Step #4, wait for keypress & next raster_Y position.

Step #5, do a normal finish of line gen #1.

Once this is done, test that no matter the angle of the line in your triangle_fill command, each time you press a key at the key-press, the drawn line on the screen advances vertically by 1 pixel.  This means if the line is at an odd angle from left to right, after each key press, the line should plot multiple pixels on the X axis, but only travel 1 pixel on the Y axis.

Once done, we will add a line gen #2.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2020, 03:26:07 pm
Hehehe, you are expecting both lines to end at the same time.  This will usually never happen at it's not what you are supposed to do.

Well no, not really - I suspected the condition would never be true as the lines would most likely be different lengths, but what I did expect was to see parts of lines drawn or an infinite line (or two).  Instead, I'm getting nothing at all.  I've removed all references to line #2 in the loop now and I'm still getting nothing drawn.   I've tried with different combinations as I thought perhaps the first line should be tending towards x(2) y(2) instead, and using corresponding dx2, dy2, magic2 and errd2, but still nothing. |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2020, 03:40:51 pm
Where is your drawing.asm file?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2020, 03:50:04 pm
Where is your drawing.asm file?

It's going to be something silly, isn't it?  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2020, 04:37:27 pm
Here you go.  This is the beginning you should have come up with.

You will need to compile.

I did not do the triangle edges sorting as you last coded didn't do it right.  The if() weren't taken into proper account.

Next step.  Recreate the sort, though, in my provided drawing.asm, I already sorted the points.

Then, modify my code to draw to 1 vertical line at a time, for linegen 1 only.
Then do lines 1&2, swapping to 1&3 at the right time.
The fill in the raster void.

This is basic stuff since I setup the linegens for you to address each one.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 13, 2020, 01:27:34 pm
I did not do the triangle edges sorting as you last coded didn't do it right.  The if() weren't taken into proper account.

Next step.  Recreate the sort, though, in my provided drawing.asm, I already sorted the points.

Okay, that's sorted.  I had made a syntax mistake in the IF conditionals - not being used to Free BASIC and all.  ::)

Then, modify my code to draw to 1 vertical line at a time, for linegen 1 only.
Then do lines 1&2, swapping to 1&3 at the right time.

Right, I think I've got this far successfully.  Latest code attached.

The fill in the raster void.

This bit I'm having trouble with.  I can fill the first half of the triangle, but I'm getting errors.  As for the second half, well, no chance.  Everything I've tried just comes out completely wrong.

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 13, 2020, 03:29:28 pm
Arrrrrrrgggggg,  What did you do? ? ? ? ? ?
Nooooooooooooo.....
OMG...... ? run_duallinegen_num ?  Why?

I've erased what you did and provided the next step.  You need to fill in the rest...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 13, 2020, 07:03:22 pm
Arrrrrrrgggggg,  What did you do? ? ? ? ? ?
Nooooooooooooo.....
OMG...... ? run_duallinegen_num ?  Why?

I've erased what you did and provided the next step.  You need to fill in the rest...

Didn't want to mess up the original function, so I created a new one then forgot to swap it for the old one when I posted the code.  :-\

Okay, so I'm not sure about where/how I should be filling the triangle now.  It looks like I need to draw a horizontal line between line 0 and line 1 for every raster_Y_pos step, right?  I've been playing around with the code and have the first half filling, but can't seem to get the second half to fill without major errors in the fills.

[attachimg=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 13, 2020, 07:52:16 pm
Arrrrrggggg, I give up...
How many times will you be drawing that line every-time Bresenham algorithm is being called?
This is what you were supposed to place inbetween the 2 REM comments I inserted in the last geo.bas.
Here you go:

Now, see if you can work out why the blue triangle is messed up.  I don't think it's my code I just entered.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 13, 2020, 09:50:45 pm
Now, see if you can work out why the blue triangle is messed up.  I don't think it's my code I just entered.

No, it was the point ordering.  I had a brain fart when I wrote it and messed up the first condition for y0 >= y1 >= y2.

[attachimg=2]

Full Geo.bas attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 13, 2020, 10:14:39 pm
Ok, test a few new triangles with different orders to points 1,2,3.

Maybe the same triangle, 1 after the other with the same points, but in a different order with a different color to make sure the new triangles perfectly overlap with one another in geo.bas.

The 1 thing I didn't do in the code was:

   For raster_Y_pos = ya(0) to yb(0)
.....
   Next raster_Y_pos

Should only be executed if the height of ya(0) to yb(0) was greater than 2.  And before the FOR loop, I should have begun the lines just as after the loop, I finished the lines.  The for loop should have also been written like this:
   For raster_Y_pos = ya(0)+1 to yb(0)-1

This way, when you have a triangle height > 2. you only raster fill the void inside, not the tip and bottom peaks which are already drawn by the LineGen itself.

It is your choice if you now want to approach the verilog and put in this triangle fill first, or, we will do the pixel writer and Z80 interface so you will see a picture when testing the triangle fill.


Now the way this geo.bas code is written should carry easy over to our existing System Verilog as it is nothing more than the old line generator with an array selection for 3 lines, each being run one at a time until the line is finished or reaches a defined raster Y coordinate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 14, 2020, 06:21:29 am
This way, when you have a triangle height > 2. you only raster fill the void inside, not the tip and bottom peaks which are already drawn by the LineGen itself.
I don't understand why this is an issue. For filling a triangle, line generators shouldn't be drawing *any* pixels themselves. They should only be figuring out where the raster lines to be filled start and end.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 14, 2020, 09:40:02 am
Ok, test a few new triangles with different orders to points 1,2,3.

[attachimg=1]

Maybe the same triangle, 1 after the other with the same points, but in a different order with a different color to make sure the new triangles perfectly overlap with one another in geo.bas.

[attachimg=2]

 :-+

The 1 thing I didn't do in the code was:

   For raster_Y_pos = ya(0) to yb(0)
.....
   Next raster_Y_pos

Should only be executed if the height of ya(0) to yb(0) was greater than 2.

Okay, have added a check in before the for...next loop.  :-+

And before the FOR loop, I should have begun the lines just as after the loop, I finished the lines.

Sorry, I don't follow..  :-//

It is your choice if you now want to approach the verilog and put in this triangle fill first, or, we will do the pixel writer and Z80 interface so you will see a picture when testing the triangle fill.

I'm all for seeing results, so shall we start on the pixel writer and interface?  I can then test the line function straight away, in theory.

Now the way this geo.bas code is written should carry easy over to our existing System Verilog as it is nothing more than the old line generator with an array selection for 3 lines, each being run one at a time until the line is finished or reaches a defined raster Y coordinate.

I'll take your word for that.  Updated Geo.bas attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: FenTiger on July 14, 2020, 01:21:31 pm
Just a suggestion: test some pathological cases too, such as

I wondered briefly about the case where one or more points is outside the visible screen, too, but I think you're best off just forbidding this and punting the responsibility for this case onto software.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 14, 2020, 03:05:22 pm

The 1 thing I didn't do in the code was:

   For raster_Y_pos = ya(0) to yb(0)
.....
   Next raster_Y_pos

Should only be executed if the height of ya(0) to yb(0) was greater than 2.

Okay, have added a check in before the for...next loop.  :-+

And before the FOR loop, I should have begun the lines just as after the loop, I finished the lines.

Sorry, I don't follow..  :-//

It is your choice if you now want to approach the verilog and put in this triangle fill first, or, we will do the pixel writer and Z80 interface so you will see a picture when testing the triangle fill.

I'm all for seeing results, so shall we start on the pixel writer and interface?  I can then test the line function straight away, in theory.

Now the way this geo.bas code is written should carry easy over to our existing System Verilog as it is nothing more than the old line generator with an array selection for 3 lines, each being run one at a time until the line is finished or reaches a defined raster Y coordinate.

I'll take your word for that.  Updated Geo.bas attached.

You got most of it right, just add these 2 lines before your if() like this:
Code: [Select]
   run_linegen_num ( 0, ya(0)+1, color_val ) : Rem finish the triangle's first line
   run_linegen_num ( 1, ya(0)+1, color_val ) : Rem finish the triangle's third line

If ( yb(0) - ya(0) > 2) Then

   For raster_Y_pos = ya(0)+1 to yb(0)-1

This begins the linegens #1&#2 on the first raster position and brings them up to the second, or, ends the lines..
And my mistake at the end:
Code: [Select]
   run_linegen_num ( 0, yb(0)+1, color_val ) : Rem finish the triangle's first line
   run_linegen_num ( 2, yb(0)+1, color_val ) : Rem finish the triangle's third line
-1 should always worke since Y position would never go there under normal circumstances.  But we will be supporting coordinates from -2048 to 2047, adding 1 to the Y end point ensures the line tries to finish drawing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 14, 2020, 03:14:48 pm
Just a suggestion: test some pathological cases too, such as
  • two, or all three, points being the same
  • two, or all three, points sharing an X or Y coordinate
  • all three points being perfectly co-linear

I wondered briefly about the case where one or more points is outside the visible screen, too, but I think you're best off just forbidding this and punting the responsibility for this case onto software.
These tests are good for optimization where we stop the lineGens from pulling triple duty.  These checks will be added in Verilog.

The raster filler already doesn't execute if there are no free void pixels in-between the lines except occasionally on shear angles with triangle just above 3 lines tall.  A few pixel points at 1 face edge may be written twice.  For now, we are not touching this 1 optimization where we seek the smallest 2 coordinates inside a completed raster Y coordinate after the lingen has passed that Y raster position.

Off screen raster fills will be tested and skipped, but, the line gens will still operate to off screen coordinates so a triangle can be shifted/animated off the screen and still retain it's shape.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 14, 2020, 03:57:54 pm
Ok, next onto 2 additions to the geometry_xy_plotter.sv.

1- Get the reset input working.  Reset to a bunch of defaults please.
2- Get the 'draw_busy' input working.

The 'draw_busy' should pause then entire 'geometry_xy_plotter.sv' unit whenever it's 'draw_cmd_tx' is high, except for reset condition.

Next, we will make a new simulation project called xy_plot_2_pixel_address.  This .sv module will accept the 36 bit 'draw_cmd' and 'draw_cmd_rdy'.  It will work out the memory write/read addresses from the x/y coordinates with base memory address, bytes per width of image, and bits per pixel settings.  It will send the memory address with which bits in that 16 bit word will be changed with read & write color to the next module.

Last module project.  This one pixel_2_ram, which takes the address from the previous module and reads/modifies appropriate bits/writes the 16 bit memory which will get sent to a new 'Data_mux_geo' (I'll prepare this one) which will have a third 16 bit read/write port.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 14, 2020, 11:56:54 pm
I have updated my Python code. It no longer uses inner loops to increment the x coordinates, although the setup now requires some integer divisions.

It also handles sides sloped in either direction, so it does not need any particular ordering of the x coordinates.

Code: [Select]
def fill_triangle(screen, x0, y0, x1, y1, x2):
    # Fills a flat-bottomed triangle with apex at (x0, y0) and
    # lower vertices at (x1, y1), (x2, y1). Assumes y0 < y1.
   
    xL = xR = x0
    y = y0
    dy = y1 - y0
    dxL, deL = divmod(x1 - x0, dy)
    dxR, deR = divmod(x2 - x0, dy)
    if dxL < 0:
        deL = -deL
    if dxR < 0:
        deR = -deR
    eL = eR = 0
    n = dy
    while n > 0:
        fill_raster_line(screen, xL, xR, y)
        xL += dxL
        eL += deL
        if eL > 0:
            if dxL < 0:
                xL -= 1
            else:
                xL += 1
            eL -= dy
        xR += dxR
        eR += deR
        if eR > 0:
            if dxR < 0:
                xR -= 1
            else:
                xR += 1
            eR -= dy
        y += 1
        n -= 1

def fill_raster_line(screen, x0, x1, y):
    x = x0
    n = x1 - x0 + 1
    while n > 0:
        draw_pixel(screen, x, y)
        x += 1
        n -= 1

def draw_pixel(screen, x, y):
    screen[y][x] = '*'

#----------------------- Testing -------------------------

def test(x0, y0, x1, y1, x2):
    screen = [[' '] * 79 for y in range(23)]
    fill_triangle(screen, x0, y0, x1, y1, x2)
    for row in screen:
        print(''.join(row))

test(50, 5, 10, 20, 60)
test(50, 5, 10, 20, 40)
test(30, 5, 40, 20, 60)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2020, 09:03:01 am
1- Get the reset input working.  Reset to a bunch of defaults please.

Here's what I've done:

Code: [Select]
always @(posedge clk or posedge reset) begin

    if (reset) begin    // reset to defaults
       
        // reset coordinate registers
        for ( integer i = 0; i < 4; i++ ) begin
            x[i]  <= { 12'b0 };
            y[i]  <= { 12'b0 };
        end
        max_x     <= 12'b0;
        max_y     <= 12'b0;

        // reset draw command registers
        draw_cmd_func        <= 4'b0;
        draw_cmd_data_color  <= 8'b0;
        draw_cmd_data_word_Y <= 12'b0;
        draw_cmd_data_word_X <= 12'b0;
        draw_cmd_tx          <= 1'b0;

        // reset geometry sequencer controls
        geo_shape     <= 4'b0;
        geo_fill      <= 1'b0;
        geo_mask      <= 1'b0;
        geo_paste     <= 1'b0;
        geo_run       <= 1'b0;
        geo_color     <= 8'b0;
       
        // reset geometry counters
        geo_x         <= 12'b0;
        geo_y         <= 12'b0;
        geo_xdir      <= 12'b0;
        geo_ydir      <= 12'b0;
        geo_sub_func1 <= 4'b0;
        geo_sub_func2 <= 4'b0;
        dx            <= 12'b0;
        dy            <= 12'b0;
        errd          <= 12'b0;

    end else begin

         if (cmd_ready && ~geo_run ) begin...

Hopefully that's all okay?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2020, 09:19:12 am
2- Get the 'draw_busy' input working.

The 'draw_busy' should pause then entire 'geometry_xy_plotter.sv' unit whenever it's 'draw_cmd_tx' is high, except for reset condition.

Done.  I've just changed this line to include a !draw_busy check:

if ( cmd_ready && ~geo_run && !draw_busy ) begin

... and this one...

end else if ( geo_run && !draw_busy ) begin

Here's a simulation:

[attachimg=1]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2020, 03:08:47 pm
Looks Ok, code update pls.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2020, 03:16:12 pm
Here it is.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2020, 04:11:41 pm
Ok, you can change your line:
Code: [Select]
        if ( cmd_ready && ~geo_run && !draw_busy ) begin  // when the cmd_read input is high and the geometry unit geo_run is not running, execute the following command input
To:
Code: [Select]
        if ( cmd_ready && ~geo_run && !(draw_busy && draw_cmd_tx) ) begin  // when the cmd_read input is high and the geometry unit geo_run is not running, execute the following command input

All this has done is if after pulsing the 'draw_cmd_tx' for 1 clock, or the draw_busy just went high after the draw_cmd_tx' has ended, the geometry_xy_plotter can still receive new commands like setup x/y coordinates which do not get transmitted to the pixel writer, so those commands are still free to be run.

Also, let's see you make a cheap addition which will prevent the 'draw_cmd_tx' from going high when the drawing coordinates are outside the minimum and maximum screen view area.  Show a functional test.  (This one should be easy peasy)

Next, the pixel_address_generator.sv

This module sits in-between the geometry_xy_plotter.sv and pixel_writer.sv.
Like I said in my last post, it takes in the draw command, holds / intercepts the commands with registers settings it uses itself to calculate a memory address (2 of them, normal write pixel and read pixel), pixel bitplane type & pixel location on the bitplane, and passes the write / read command with pixel bitplane type and color to the next pixel_writer.sv module.

Let's see how you would begin this module.  Remember the commands which will be fed through this module:
Code: [Select]
    //  AUX=0  : Do nothing
    //  AUX=1  : Write pixel,                             : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=2  : Write pixel with color 0 mask,           : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=3  : Write from read pixel,                   : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=4  : Write from read pixel with color 0 mask, : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=6  : Read source pixel,                       : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=7  : Set Truecolor pixel color                : 31:24 8 bit alpha blend mix value : bits 23:0 hold RGB 24 bit color
    //                                                    Use function Aux3/4 to draw this color, only works if the destination is set to 16 bit true-color mode

    //  AUX=10 ; Resets the Write Pixel collision counter           : 31:24 sets transparent masked out color : bits 23:0 in true color mode, this holds RGB 24 bit mask color, in 8 bit mode, this allows for 3 additional transparent colors
    //  AUX=11 ; Resets the Write from read pixel collision counter : 31:24 sets transparent masked out color : bits 23:0 in true color mode, this holds RGB 24 bit mask color, in 8 bit mode, this allows for 3 additional transparent colors

    //  AUX=12 : Set destination raster width in bytes    : 15:0 holds destination raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
    //  AUX=13 : Set source raster width in bytes,        : 15:0 holds source raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
    //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
    //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel

Now choose output buss which can drive the pixel_writer.sv.
Like mem address, bitplane size, read/write, color.  In fact, make it another 36bit pixel_cmd  bus with a 'pixel_cmd_rdy' and decide what the structure of the bits within will contain with 16 possible functions.

Let's see how your pixel_address_generator.sv will begin.

I have time now to work on the new data_mux_geo.sv.

----------------------------------------------------------------------
Maybe we should move :
' 31:24 bitplane mode ' in aux 14&15 into the top of aux 12&13.  This way, there is more space a larger address for future growth.
----------------------------------------------------------------------
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2020, 08:22:37 pm
Here it is, the new Data_mux_GEO.sv module.
If you care to decipher this sim snapshot, be my guest...

[attach=1]

I've attached the Quartus project 'Data_mux_geo_sim.zip' for reference.
I've also attached the Quartus project 'GPU_EP4CE10_quick_Data_mux_GEO.zip' which contains a full new GPU project with the new Data_mux_geo wired into the top schematic block diagram.  There was also a minor change in the 16 port memory interface.  Please compile and use this new GPU project from now on as it will become obligatory within a few days as your geo_xy_plotter/pixel_writer requires it to function if you want to see any geometric objects.

There was even an addition to the 'rs232_DEBUGGER.v' to make it's 'host_rd_req's a single clock cycle long.  So you need to test the RS232 debugger display ram as well.

'rs232_DEBUGGER.v' ver. 1.1 located here: rs232_DEBUGGER forum thread. (https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/msg3138916/#msg3138916)

(That lousy async VHDL PS2 keyboard decoder is screwing up your final fitter's results with tons of timing violations.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2020, 02:37:43 am
A little math says that even under the worst case scenario, at 320x240x16 colors, your geometry plotter can fill the entire screen with triangles over 300 times a second.  Or, in 1/60th of a second, you can repaint the entire screen just over 5 times.

I'm not sure the Z80 can keep up unless all it did was re-transmit the same filled triangle / filled box / filled ellipse, 1 which would cover the entire screen with just a new color each time, written in assembly.  Maybe just a random number generator for making random screen shapes & random sizes / colors might peak the geometry unit.  You might need a 20MHz Z80.

Hurry up so we can get past the geometry engine to the blitter stage so I can force some upgrades there as well.
Though, your gonna want more ram very quick here.  But I guess you can work with 160x120@16 or 256 colors for now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2020, 06:39:27 am
A little math says that even under the worst case scenario, at 320x240x16 colors, your geometry plotter can fill the entire screen with triangles over 300 times a second.  Or, in 1/60th of a second, you can repaint the entire screen just over 5 times.

I'm not sure the Z80 can keep up unless all it did was re-transmit the same filled triangle / filled box / filled ellipse, 1 which would cover the entire screen with just a new color each time, written in assembly.  Maybe just a random number generator for making random screen shapes & random sizes / colors might peak the geometry unit.  You might need a 20MHz Z80.

I was thinking along the  lines of a random line/triangle generator.  Will write one as soon as we finalise the interface.  :-+

Hurry up so we can get past the geometry engine to the blitter stage so I can force some upgrades there as well.

Yeah, sorry - my day job is getting in the way at the moment.  I've downloaded the project files, but won't be able to look at anything for maybe another 8 hours as I'm out in a sec.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2020, 01:05:44 pm
Here it is, the new Data_mux_GEO.sv module.

There's some weird stuff going on with the attachments.  Looks like Data_mux_geo_sim.zip is okay, but GPU_EP4CE10_quick_Data_mux_GEO.zip is coming out as a PNG.  :-//

The forum bug strikes again. :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2020, 02:34:40 pm
The forum is in meltdown mode, read here: https://www.eevblog.com/forum/chat/website-error-reports/msg3138580/#msg3138580 (https://www.eevblog.com/forum/chat/website-error-reports/msg3138580/#msg3138580)

I'm re-posting the attachments here:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2020, 03:19:22 pm
Warning, the Z80_bridge_v2 is missing the additions made over here:

https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3123790/#msg3123790 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3123790/#msg3123790)

& the post right after...


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2020, 03:23:21 pm
Warning, the Z80_bridge_v2 is missing the additions made over here:

https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3123790/#msg3123790 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3123790/#msg3123790)

& the post right after...

Can I just copy the Z80_bridge_v2.sv into your latest version of the project, or did you make any changes to that as well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2020, 03:46:19 pm
yes.  just copy is fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2020, 04:23:45 pm
Okay, new project works fine (just had to key-in the correct memory size into the Z80_bridge's parameters).  In other news, the RS232_debugger update seems to be working fine as well, with no issues reading the GPU RAM so far.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2020, 06:28:55 pm
Ok, lets see your setup of the pixel memory address generator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2020, 07:27:47 pm
Ok, lets see your setup of the pixel memory address generator.

I haven't had any time to really make progress with it.  This is all I've got so far:

Code: [Select]
module pixel_address_generator (

    // inputs
    input wire clk,              // System clock
    input wire reset,            // Force reset
   
    input wire draw_cmd_rdy,     // Pulsed HIGH when data on draw_cmd[15:0] is valid
    input wire [35:0] draw_cmd,  // Bits [35:32] hold AUX function number 0-15:
    //  AUX=0  : Do nothing
    //  AUX=1  : Write pixel,                             : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=2  : Write pixel with color 0 mask,           : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=3  : Write from read pixel,                   : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=4  : Write from read pixel with color 0 mask, : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=6  : Read source pixel,                       : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=7  : Set Truecolor pixel color                : 31:24 8 bit alpha blend mix value : bits 23:0 hold RGB 24 bit color
    //                                                    Use function Aux3/4 to draw this color, only works if the destination is set to 16 bit true-color mode

    //  AUX=10 ; Resets the Write Pixel collision counter           : 31:24 sets transparent masked out color : bits 23:0 in true color mode, this holds RGB 24 bit mask color, in 8 bit mode, this allows for 3 additional transparent colors
    //  AUX=11 ; Resets the Write from read pixel collision counter : 31:24 sets transparent masked out color : bits 23:0 in true color mode, this holds RGB 24 bit mask color, in 8 bit mode, this allows for 3 additional transparent colors

    //  AUX=12 : Set destination raster width in bytes    : 15:0 holds destination raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
    //  AUX=13 : Set source raster width in bytes,        : 15:0 holds source raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
    //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
    //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel

    // outputs
    output wire pixel_cmd_rdy,
    output wire [35:0] pixel_cmd
   
);

wire [3:0]  aux_cmd_in;
wire [7:0]  command_in;
wire [11:0] command_data12;
wire [7:0]  command_data8;

assign aux_cmd_in     [3:0] = draw_cmd[35:32];
assign command_in     [7:0] = draw_cmd[15:8];
assign command_data12[11:0] = draw_cmd[11:0];
assign command_data8  [7:0] = draw_cmd[7:0];

always @(posedge clk or posedge reset) begin

    if ( draw_cmd_rdy && ( aux_cmd_in[3:0] == 1 || aux_cmd_in[3:0] == 6 ) ) begin   // AUX command 1 (write pixel) or 6 (read pixel)

    end

end // always @ posedge clk or reset

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2020, 07:31:03 pm
You posted way too early.
Your commands have nothing to do with the AUX labels and data entities.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2020, 07:35:03 pm
You posted way too early.
Your commands have nothing to do with the AUX labels and data entities.

You said you wanted to see what I'd done so far.  :-//  I have updated the code in my previous post with what I think is required for picking out the write and read pixel commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 17, 2020, 09:51:09 am
Also, let's see you make a cheap addition which will prevent the 'draw_cmd_tx' from going high when the drawing coordinates are outside the minimum and maximum screen view area.  Show a functional test.  (This one should be easy peasy)

Yeah, you say that, but...  ???

So, I've got max_x and max_y, geo_x and geo_y to work with.  So a simple check in the draw_cmd_rdy assignment should do the trick?

Code: [Select]
assign draw_cmd_rdy    = draw_cmd_tx && geo_x < max_x && geo_y < max_y;

I've simulated the code, but something odd is happening.  I've included the test project for you to try.  I'm setting max_x and max_y to 160,100 and the line to start at 25,20 and end at 175,110.  However, it seems the line doesn't reach x=175 and y=110 simultaneously, so it fails the end check and continues forever. (The 'outside screen bounds' check seems to be working, though).  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 17, 2020, 10:19:05 am
I'm setting max_x and max_y to 160,100 and the line to start at 25,20 and end at 175,110.  However, it seems the line doesn't reach x=175 and y=110 simultaneously, so it fails the end check and continues forever.
You only need to check one of the coordinates to decide when to stop. Preferably whichever one you're taking single pixel steps along.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 17, 2020, 04:36:02 pm
Also, let's see you make a cheap addition which will prevent the 'draw_cmd_tx' from going high when the drawing coordinates are outside the minimum and maximum screen view area.  Show a functional test.  (This one should be easy peasy)

Yeah, you say that, but...  ???

So, I've got max_x and max_y, geo_x and geo_y to work with.  So a simple check in the draw_cmd_rdy assignment should do the trick?

Code: [Select]
assign draw_cmd_rdy    = draw_cmd_tx && geo_x < max_x && geo_y < max_y;

I've simulated the code, but something odd is happening.  I've included the test project for you to try.  I'm setting max_x and max_y to 160,100 and the line to start at 25,20 and end at 175,110.  However, it seems the line doesn't reach x=175 and y=110 simultaneously, so it fails the end check and continues forever. (The 'outside screen bounds' check seems to be working, though).  :-//
Arrrg, you found a line which fails... hang on a sec....
Looking back...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 17, 2020, 05:15:14 pm
Geo.bas does not fail to find the end of the line where as we have this problem here with the verilog version:

Ending illustration:

[attach=1]

Beginning illustration:

[attach=2]

Debug time...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 17, 2020, 05:25:31 pm
Found bug:
Line 311 was:
Code: [Select]
if (((errd+dy)<<1) < dx) beginShould have been:
Code: [Select]
if (((errd<<1)+dy) < dx) begin
errd had to be shifted first, then add the dy.

Next post, your limit-box drawing area code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 17, 2020, 05:45:00 pm
Ok, here are how the limits should have been done in the attached simulation project.

We need the check inside the plotting look since we may have other variables sent to be plotted other than geo_x/geo_y, like during the raster fill.

Because of F-MAX (we are on the red line), we may need to separate the plotting of pixels by 1 clock and doing the valid range test on those intermediate registers.  For now, let's continue as it is functional.  Remember, this will come back to us.  We may just make a range module in between the plotter and address generator, or part of the address generator.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 17, 2020, 05:53:02 pm
I'm setting max_x and max_y to 160,100 and the line to start at 25,20 and end at 175,110.  However, it seems the line doesn't reach x=175 and y=110 simultaneously, so it fails the end check and continues forever.
You only need to check one of the coordinates to decide when to stop. Preferably whichever one you're taking single pixel steps along.
This solution would have led to never fixing our edge of line rounding error as our verilog Bresenham algorithm did an add before a bit shift coding error seen here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3141704/#msg3141704 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3141704/#msg3141704)

This is the reason for the geo.bas emulator.  Double verification of bugs.

Also validating only 1 coordinate means if we check the Y coordinate only, and we are drawing a 2 pixel tall, 100 pixel wide horizontal line, right at the last Y increment, we would have completed the line before drawing across the rest of the screen to the end x coordinate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 17, 2020, 06:27:53 pm
Awww, another future bug:
Line 137:
Code: [Select]
        if ( cmd_ready && ~geo_run && !(draw_busy && draw_cmd_tx) ) begin  // when the cmd_read input is high and the geometry unit geo_run is not running, execute the following command input

Should be switched back to:
Code: [Select]
        if ( cmd_ready && ~geo_run && !draw_busy ) begin  // when the cmd_read input is high and the geometry unit geo_run is not running, execute the following command input

I know I said otherwise but I forgot that the line drawing may be processing pixels off the edge of the visible display.

Attached is the latest:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 18, 2020, 12:33:07 am
Also validating only 1 coordinate means if we check the Y coordinate only, and we are drawing a 2 pixel tall, 100 pixel wide horizontal line, right at the last Y increment, we would have completed the line before drawing across the rest of the screen to the end x coordinate.
A line like that would normally be drawn by incrementing the x coordinate, not the y coordinate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 18, 2020, 12:34:28 pm
Can I just clarify exactly what's going on with the pixel_address_generator?

As I understand it, it takes 36-bit draw commands in from the geometry_xy_plotter and converts the x and y coordinates into a memory address, then passes that memory address out (and associated command relating to what is to be done at that address) as a 36-bit pixel_cmd.

So it will need to act upon the following AUX commands (and maybe more?):
But, initially at least, you want to work on AUX 1 & 6.  Is that right?

Code: [Select]
module pixel_address_generator (

    // inputs
    input wire clk,              // System clock
    input wire reset,            // Force reset
   
    input wire draw_cmd_rdy,     // Pulsed HIGH when data on draw_cmd[15:0] is valid
    input wire [35:0] draw_cmd,  // Bits [35:32] hold AUX function number 0-15:
    //  AUX=0  : Do nothing
    //  AUX=1  : Write pixel,                             : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=2  : Write pixel with color 0 mask,           : 31:24 color         : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=3  : Write from read pixel,                   : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=4  : Write from read pixel with color 0 mask, : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=6  : Read source pixel,                       : 31:24 ignored       : 23:12 Y coordinates : 11:0 X coordinates
    //  AUX=7  : Set Truecolor pixel color                : 31:24 8 bit alpha blend mix value : bits 23:0 hold RGB 24 bit color
    //                                                    Use function Aux3/4 to draw this color, only works if the destination is set to 16 bit true-color mode

    //  AUX=10 ; Resets the Write Pixel collision counter           : 31:24 sets transparent masked out color : bits 23:0 in true color mode, this holds RGB 24 bit mask color, in 8 bit mode, this allows for 3 additional transparent colors
    //  AUX=11 ; Resets the Write from read pixel collision counter : 31:24 sets transparent masked out color : bits 23:0 in true color mode, this holds RGB 24 bit mask color, in 8 bit mode, this allows for 3 additional transparent colors

    //  AUX=12 : Set destination raster width in bytes    : 15:0 holds destination raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
    //  AUX=13 : Set source raster width in bytes,        : 15:0 holds source raster image width in #bytes so the proper memory address can be calculated from the X&Y coordinates
    //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
    //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel

    // outputs
    output wire pixel_cmd_rdy,
    output wire [35:0] pixel_cmd
   
);

// 3     3 3             2 2               1     1 1     0 0             0
// 5     2 1             4 3               5     2 1     8 7             0
// |     | |             | |               |     | |     | |             |
// 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
// |-AUX-|                                 |--COMMAND IN-| |COMMAND_DATA8|
// |-AUX-|                                 |-CMD-| |----COMMAND_DATA12---|
// |AUX01| |----COLOUR---| |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX02| |----COLOUR---| |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX03|                 |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX04|                 |-----Y COORDINATE----| |-----X COORDINATE----|
// ...
// |AUX06|                 |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX07| |-ALPHA BLEND-| |-------------24-bit RGB COLOUR---------------|
// ...
// |AUX10| |-TRANSP MASK-| |RGB 24-bit MASK COLOUR OR 3 ADD TRANS COLOURS|
// |AUX11| |-TRANSP MASK-| |RGB 24-bit MASK COLOUR OR 3 ADD TRANS COLOURS|
// |AUX12|                                 |---DEST RASTER IMAGE WIDTH---|
// |AUX13|                                 |--SOURCE RASTER IMAGE WIDTH--|
// |AUX14| |BITPLANE MODE| |-------DESTINATION BASE MEMORY ADDRESS-------|
// |AUX15| |BITPLANE MODE| |----------SOURCE BASE MEMORY ADDRESS---------|

wire [3:0]  aux_cmd_in     = draw_cmd[35:32];
wire [7:0]  command_in     = draw_cmd[15:8];
wire [11:0] command_data12 = draw_cmd[11:0];
wire [7:0]  command_data8  = draw_cmd[7:0];

wire [11:0]              x = draw_cmd[11:0];
wire [11:0]              y = draw_cmd[23:12];

always @(posedge clk or posedge reset) begin

    if ( draw_cmd_rdy && ( aux_cmd_in[3:0] == 1 || aux_cmd_in[3:0] == 6 ) ) begin   // AUX command 1 (write pixel) or 6 (read pixel)



    end

end // always @ posedge clk or reset

endmodule


I'm hoping what I've done above is vaguely on the right track, but I'm short on ideas as to what to do next.  To translate to a memory address, we're going to need to take into account the screen mode (bits/bytes per pixel) and do some multiplication along the lines of:

memory_address = offset + ( y * screen_width + x ) * bytes_per_pixel
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 18, 2020, 03:16:22 pm
Ok, close...
the 'AUX' is the command.  Being 4 bits, we can feed 0 through 16, + 'draw_cmd_rdy' which says something valid has come to eat.

Code: [Select]
// |-AUX-|                                 |--COMMAND IN-| |COMMAND_DATA8|
// |-AUX-|                                 |-CMD-| |----COMMAND_DATA12---|

wire [7:0]  command_in     = draw_cmd[15:8];
wire [11:0] command_data12 = draw_cmd[11:0];
wire [7:0]  command_data8  = draw_cmd[7:0];
These do not exist here.

You code should look like this:

Code: [Select]
    if ( draw_cmd_rdy) begin
       case (aux_cmd_in)
               4'd01 : 
               4'd02 : 
               4'd03 : 
       endcase
   end

As for the memory address outputs...

reg complete_address_[w/r][24bits] = (DESTINATION/SOURCE BASE MEMORY ADDRESS +  ( y * screen_width + x ))

output wire memory_address_out = complete_address_[w/r][20bits] >> ( the correct amount of 16 bit words per pixel).
And don't forget to mute out the LSB address to 0 as it fools the 16 portGPU ram into addressing a 16bit word in 8 bit mode.

Remember, we are addressing 16 bits here, not 8 like in the MAGGIE.

we want other outputs.
memory_w/r_bit_size[3:0]   = number of bits to write/read  0..15 = 1..16bits
memory_w/r_bit_offset[3:0] = bit position, 0..15.

There's also a color output.

Your output should reflect what the pixel writer needs to operate.  Think of the things we need to say to the pixel writer and make an appropriate bus.  (Yes you can use your current outputs, but you need to tell us how you want to pack all the above required information into that bus like what I did on the output of the geometry xy plotter unit.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 19, 2020, 11:03:39 am
There's some pieces missing from this puzzle.  ???

Base memory addresses:
Destination and/or source base memory addresses need to be set somehow.  They're not going to be set by the geometry_xy_plotter, they're going to be set by something else - the Z80_bridge, perhaps?  The screen memory being written to could be anywhere in the GPU RAM and specified by software via the MAGGIE/hardware registers, right?

So the two 24-bit address registers for source/destination base addresses will need to be set via an additional command/input route?

Output bus format:
In terms of the output (the 36-bit pixel_cmd bus), is there any need to deviate from the existing draw_cmd packing specification?  Instead of two 12-bit x/y coordinates, they'll be replaced by a 24-bit address, but the colour and aux_cmd values can remain - the need for the colour value is obvious, but the aux_cmd value will tell the pixel_writer whether it's writing or reading.  Am I missing something?  :-//

Code: [Select]
module pixel_address_generator (

    // inputs
    input wire         clk,              // System clock
    input wire         reset,            // Force reset
   
    input wire         draw_cmd_rdy,     // Pulsed HIGH when data on draw_cmd[15:0] is valid
    input wire [35:0]  draw_cmd,         // Bits [35:32] hold AUX function number 0-15:

    // outputs
    output wire        pixel_cmd_rdy,
    output wire [35:0] pixel_cmd,
    output wire [3:0]  memory_w/r_bit_size,
    output wire [3:0]  memory_w/r_bit_offset
   
);

// 3     3 3             2 2               1     1 1     0 0             0
// 5     2 1             4 3               5     2 1     8 7             0
// |     | |             | |               |     | |     | |             |
// 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
// |AUX01| |----COLOUR---| |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX02| |----COLOUR---| |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX03|                 |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX04|                 |-----Y COORDINATE----| |-----X COORDINATE----|
// ...
// |AUX06|                 |-----Y COORDINATE----| |-----X COORDINATE----|
// |AUX07| |-ALPHA BLEND-| |-------------24-bit RGB COLOUR---------------|
// ...
// |AUX10| |-TRANSP MASK-| |RGB 24-bit MASK COLOUR OR 3 ADD TRANS COLOURS|
// |AUX11| |-TRANSP MASK-| |RGB 24-bit MASK COLOUR OR 3 ADD TRANS COLOURS|
// |AUX12|                                 |---DEST RASTER IMAGE WIDTH---|
// |AUX13|                                 |--SOURCE RASTER IMAGE WIDTH--|
// |AUX14| |BITPLANE MODE| |-------DESTINATION BASE MEMORY ADDRESS-------|
// |AUX15| |BITPLANE MODE| |----------SOURCE BASE MEMORY ADDRESS---------|

wire [3:0]  aux_cmd_in = draw_cmd[35:32];
wire [11:0]          x = draw_cmd[11:0];
wire [11:0]          y = draw_cmd[23:12];

reg  [23:0] complete_address         = 24'b0;
reg  [23:0] destination_base_address = 24'b0;
reg  [23:0] source_base_address      = 24'b0;

//assign pixel_cmd = complete_address[19:0] >> ( the correct amount of 16-bit words per pixel)

always @(posedge clk or posedge reset) begin

    if ( draw_cmd_rdy ) begin

case (aux_cmd_in) begin
   
4'd01 : begin

// write pixel with colour, x & y - generate address for pixel
complete_address[23:0] <= {destination_base_address[23:1], 1'b0} + ( y * scr_width + x );

end

4'd02 :

4'd03 :

4'd04 :

4'd06 : begin

// write pixel with x & y

end

endcase

    end

end // always @ posedge clk or reset

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 19, 2020, 04:31:32 pm
The geometry_xy_plotter tells the pixel_address_generator what it is.  It is stored in the pixel address generator.

Take a look at lines 143 through 157 in the geometry_xy_plotter.  It does send out an aux command with an address.

Things sent to the pixel writer:
You do need to send an address to the pixel_writer with what 8 bit color, which bits within the 16bit word are affected, if its a read or a write pixel, will the write pixel use a transparent color mask.  Or, if the written color should be what's in the read pixel color buffer multiplied/mixed by a source color.

There is also the reset read pixel collision pixel counter and write collision pixel counter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 20, 2020, 09:47:48 am
Things sent to the pixel writer:
You do need to send an address to the pixel_writer with what 8 bit color, which bits within the 16bit word are affected, if its a read or a write pixel, will the write pixel use a transparent color mask.  Or, if the written color should be what's in the read pixel color buffer multiplied/mixed by a source color.

Okay, I've had a little time this morning to do some work on this (but time is getting more scarce at the moment :( ), have attached latest code.  I've added cases for setting raster width and base addresses and am using those registers in the memory calculations for AUX 1 and 6 now.  I've sketched out a rough idea of what pixel_cmd's composition should look like and am assigning values to it for the two AUX commands you asked me to start with.

As far as the pixel_cmd and its constituent bits, what exactly do you mean by "which bits within the 16bit word are affected"?  I've taken that to mean whether the high or low byte is being written to, but am not sure that's what you mean and am not sure how to handle this.  :-//

There is also the reset read pixel collision pixel counter and write collision pixel counter.

Where are these counters going to live?  In the pixel_writer?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 20, 2020, 01:13:08 pm
Actually, you are doing good.

Now, you cannot have:
pixel_cmd_rdy    <= 1'b1;
for a wire, only a reg...

To make your life easier, look at my fifo 3 word and switch to system verilog logic syntax and let the compiler auto-select whether your logic names are regs or wires.

This includes 'always_ff' for the clocked regs & before that, the 'always_comb' for the combinational logic which replaces the assigns with the same lines, but, no 'assign' needed.

Please be more defined about what the ' 4'd06 : begin   // write pixel with x & y, no colour' means.
Why, what's different?

Also:
{destination_base_address[23:1], 1'b0} + ( y * dest_rast_width[15:0] + x )

Can create an odd memory address and the entire line does not reflect the proper read/write address if you are in 16bits per pixel mode, 4 bits per pixel mode, 2 bits per pixel mode, or, 1 bit per pixel mode.  It only reflects the proper address when in 8 bit per pixel mode, but with the LSB swinging as if we are addressing 8 bits.

Maybe you should make a temporary logic name in the combinational section like:
dest_base_address_offset = ( (y * dest_rast_width[15:0] + x ) << 1 ) >> CORRECT NUMBER OF BITS base on bits per pixel  )
and in the:
            4'd01 : begin   // write pixel with colour, x & y
           
                pixel_cmd[19:0]     <= (destination_base_address +  dest_base_address_offset) and shave off the LSB
                pixel_cmd[23:20]   <= which bit offset should be edited

Also:   4'd14 : dest_base_address[23:0] <= { draw_cmd[23:1], 1'b0 };
Do not shave off the LSB here.

Aslo:

            4'd01 : begin   // write pixel with colour, x & y
           
                pixel_cmd[23:0]  <= {destination_base_address[23:1], 1'b0} + ( y * dest_rast_width[15:0] + x ); // generate address for the pixel
                pixel_cmd[31:24] <= draw_cmd[31:24];                                                            // include colour information
                pixel_cmd[35]    <= 1'b1;                                                                       // WRITE command
                pixel_cmd[34:32] <= 3'b0;                                                                       // No transparency, no R/M/W, affected bits unknown
                pixel_cmd_rdy    <= 1'b1;

Maybe you should combine these 2 lines into a ' pixel_cmd[35:32] <= 4'd## '
Also, you haven't created a difference between the pixel write command # 4'd01 and # 4'd06.

Usually what we would do here is create a localparams:
(these are examples, you may switch them the way you like)
cmd_out_write_pixel_color = 4'b1000
cmd_out_write_pixel_color_transparent = 4'b1001

and in the transmit command section:
                pixel_cmd[35:32] <= cmd_out_write_pixel_color ;

This way in the next pixel writer module, you can import the localparams and switch the
cmd_out_ to cmd_in_
and use them for you case statement there.

Just like you should right now go into the geometry_xy_plotter, copy and paste it's localparams:
Code: [Select]
localparam CMD_OUT_NOP           = 0;
localparam CMD_OUT_PXWRI         = 1;
localparam CMD_OUT_PXWRI_M       = 2;
localparam CMD_OUT_PXPASTE       = 3;
localparam CMD_OUT_PXPASTE_M     = 4;

localparam CMD_OUT_PXCOPY        = 6;
localparam CMD_OUT_SETARGB       = 7;

localparam CMD_OUT_RST_PXWRI_M   = 10;
localparam CMD_OUT_RST_PXPASTE_M = 11;
localparam CMD_OUT_DSTRWDTH      = 12;
localparam CMD_OUT_SRCRWDTH      = 13;
localparam CMD_OUT_DSTMADDR      = 14;
localparam CMD_OUT_SRCMADDR      = 15;
replace the 'CMD_OUT_' with 'CMD_IN_' and use them in your case statements instead of the completely nondescript:
            4'd15 :

So far so good.

Next, you will need to decide how to pass the information like which bits in a 16 bit word are to be edited.  the grand total of 32 bits for address and color are just enough since we have only 20 bits addressing for maggie.  Lets see how you progress.

Separately, you should also need to tell the pixel writer how many bits are in a pixel as this information is needed as well.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 22, 2020, 12:09:36 am
I might not be available for August.  Better get a move on...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 22, 2020, 09:42:01 am
To make your life easier, look at my fifo 3 word and switch to system verilog logic syntax and let the compiler auto-select whether your logic names are regs or wires.

Okaaay.. I'm not familiar with the SystemVerilog syntax (not that it's much different), so I'm hoping I don't introduce more errors as a result.

Please be more defined about what the ' 4'd06 : begin   // write pixel with x & y, no colour' means.
Why, what's different?

There's no colour data?

Also:
{destination_base_address[23:1], 1'b0} + ( y * dest_rast_width[15:0] + x )

Can create an odd memory address and the entire line does not reflect the proper read/write address if you are in 16bits per pixel mode, 4 bits per pixel mode, 2 bits per pixel mode, or, 1 bit per pixel mode.  It only reflects the proper address when in 8 bit per pixel mode, but with the LSB swinging as if we are addressing 8 bits.

Maybe you should make a temporary logic name in the combinational section like:
dest_base_address_offset = ( (y * dest_rast_width[15:0] + x ) << 1 ) >> CORRECT NUMBER OF BITS base on bits per pixel  )

Okay, done that, but I'm unsure about how the 'correct number of bits' relates to bits per pixel.  Firstly, how is bits-per-pixel getting into the module?  Is it going to be set by the geometry_xy_plotter, or the Z80_bridge, or something else?

Also:   4'd14 : dest_base_address[23:0] <= { draw_cmd[23:1], 1'b0 };
Do not shave off the LSB here.

Should I also not be shaving off the LSB for 4'd15 as well, or is the source address being treated differently?

Aslo:

            4'd01 : begin   // write pixel with colour, x & y
           
                pixel_cmd[23:0]  <= {destination_base_address[23:1], 1'b0} + ( y * dest_rast_width[15:0] + x ); // generate address for the pixel
                pixel_cmd[31:24] <= draw_cmd[31:24];                                                            // include colour information
                pixel_cmd[35]    <= 1'b1;                                                                       // WRITE command
                pixel_cmd[34:32] <= 3'b0;                                                                       // No transparency, no R/M/W, affected bits unknown
                pixel_cmd_rdy    <= 1'b1;

Maybe you should combine these 2 lines into a ' pixel_cmd[35:32] <= 4'd## '
Also, you haven't created a difference between the pixel write command # 4'd01 and # 4'd06.

Ah. I've added a bit to the CMD part of pixel_cmd to allow for colour/no-colour (the 36th bit).

Hang on - have I misunderstood the TRANSPARENCY bit?  Is that what I should be using for 4'd06?  :-//

So far so good.

Next, you will need to decide how to pass the information like which bits in a 16 bit word are to be edited.  the grand total of 32 bits for address and color are just enough since we have only 20 bits addressing for maggie.  Lets see how you progress.

Okay, well I think I've done that - with the bits saved from dropping the memory address from 24- to 20-bits, I've included 4 bits (unimaginatively called 'BIT' in the code comments for the pixel_cmd format) to identify exactly which bit in the 16-bit word needs modifying.

Where I really need some help is with bit_mode.  How does that feed into dest_base_address_offset etc?  Is it literally just a bit-shift right as you've indicated in the example for dest_base_address_offset?

Separately, you should also need to tell the pixel writer how many bits are in a pixel as this information is needed as well.

Yes, I've asked about this above.  Is this going to feed in from the video generator, or somewhere else?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 22, 2020, 09:43:00 am
I might not be available for August.  Better get a move on...

Going as fast as I can, but I'm BAF this week (and probably next as well).  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 22, 2020, 07:02:48 pm
To make your life easier, look at my fifo 3 word and switch to system verilog logic syntax and let the compiler auto-select whether your logic names are regs or wires.

Okaaay.. I'm not familiar with the SystemVerilog syntax (not that it's much different), so I'm hoping I don't introduce more errors as a result.

Please be more defined about what the ' 4'd06 : begin   // write pixel with x & y, no colour' means.
Why, what's different?

There's no colour data?
Perhaps you didn't catch my drift.
Does function #6 even write a pixel?
I thought it is a copy IE: read pixel command.
Quote
Also:
{destination_base_address[23:1], 1'b0} + ( y * dest_rast_width[15:0] + x )

Can create an odd memory address and the entire line does not reflect the proper read/write address if you are in 16bits per pixel mode, 4 bits per pixel mode, 2 bits per pixel mode, or, 1 bit per pixel mode.  It only reflects the proper address when in 8 bit per pixel mode, but with the LSB swinging as if we are addressing 8 bits.

Maybe you should make a temporary logic name in the combinational section like:
dest_base_address_offset = ( (y * dest_rast_width[15:0] + x ) << 1 ) >> CORRECT NUMBER OF BITS base on bits per pixel  )

Okay, done that, but I'm unsure about how the 'correct number of bits' relates to bits per pixel.  Firstly, how is bits-per-pixel getting into the module?  Is it going to be set by the geometry_xy_plotter, or the Z80_bridge, or something else?

Looking inside the geometry unit, in the transmitted commands section, #14 and #15, after the address:
Code: [Select]
    //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
    //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel
The 'bitplane mode' will contain the number of bits per pixel.
Remember, the copy pixel and write pixel may have 2 different bitplane modes.  This way if you want to print a 2 color font, IE 1 bit per pixel, onto a 16 color graphics screen, IE 4 bits per pixel, the address generator will send both individual values to the pixel writer/reader so it may perform the translation in real time.  Without this, you would have to store a 16 color font for your 16 color screen which takes more ram and also wont allow you to chose individual character colors as the font itself would already be colorized.
Quote

Also:   4'd14 : dest_base_address[23:0] <= { draw_cmd[23:1], 1'b0 };
Do not shave off the LSB here.

Should I also not be shaving off the LSB for 4'd15 as well, or is the source address being treated differently?

Code: [Select]
I guess what I was trying to say is that the shaving should only be done right at the last step before output.  Technically, since we are calculating a 16 bit offset for the read/write pointer, this should automatically be done by the math if the formula is right.

Aslo:

            4'd01 : begin   // write pixel with colour, x & y
           
                pixel_cmd[23:0]  <= {destination_base_address[23:1], 1'b0} + ( y * dest_rast_width[15:0] + x ); // generate address for the pixel
                pixel_cmd[31:24] <= draw_cmd[31:24];                                                            // include colour information
                pixel_cmd[35]    <= 1'b1;                                                                       // WRITE command
                pixel_cmd[34:32] <= 3'b0;                                                                       // No transparency, no R/M/W, affected bits unknown
                pixel_cmd_rdy    <= 1'b1;

Maybe you should combine these 2 lines into a ' pixel_cmd[35:32] <= 4'd## '
Also, you haven't created a difference between the pixel write command # 4'd01 and # 4'd06.

Ah. I've added a bit to the CMD part of pixel_cmd to allow for colour/no-colour (the 36th bit).

Hang on - have I misunderstood the TRANSPARENCY bit?  Is that what I should be using for 4'd06?  :-//

So far so good.

Next, you will need to decide how to pass the information like which bits in a 16 bit word are to be edited.  the grand total of 32 bits for address and color are just enough since we have only 20 bits addressing for maggie.  Lets see how you progress.

Okay, well I think I've done that - with the bits saved from dropping the memory address from 24- to 20-bits, I've included 4 bits (unimaginatively called 'BIT' in the code comments for the pixel_cmd format) to identify exactly which bit in the 16-bit word needs modifying.

Where I really need some help is with bit_mode.  How does that feed into dest_base_address_offset etc?  Is it literally just a bit-shift right as you've indicated in the example for dest_base_address_offset?

Separately, you should also need to tell the pixel writer how many bits are in a pixel as this information is needed as well.

Yes, I've asked about this above.  Is this going to feed in from the video generator, or somewhere else?

Ok, about the bit selection, and the missing bit width.
The -
Code: [Select]
    //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
    //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel
- bitplane mode tells the address generator how many bits there are in a pixel.  The address generator needs to tell the pixel writer that number of bits in a pixel.  It also needs to use this information to calculate the right memory address as the X coordinate will now change how much the address increases, but also, depending on the pixel width and where the X coordinate lands, the pixel writer also needs that information as well so it may edit the correct bits within the word.  IE, the pixel writer knowing the bits per pixel set by the 'bitplane mode' is half of what it needs.  It also needs where inside the 16 bits the X coordinate landed on so it may edit the right parts of the 16 bit word.

This second piece of information in effect is the correct lower 0-3 bits of the X coordinates.  Also, your output bus isn't large enough for this added 4 bits, so a total of 36 bits needs another 4 bits of data.

BITS:
20 - (A) address
  4 - (B) pixel width bits
  4 - (C) sub-pixel location within a 16 bit word
  8 - (D) color function
  4 - (E) function to perform IE AUX command
----------------------------------------------------------
40 bits total.

Now, since (A&C&D&E) are needed to read and write a pixel while (B) can be sent to the pixel_reader/writer as it's own function, you can cheat and still use a 36bit bus, but, when we add a fifo between the geo_address_generator and the geo_pixel_reader_writer, that will be 1 additional word in the fifo which will occasionally need to be sent.  With a 40 bit bus, we eliminate that 1 word in out 3 word cache since the fifo will now be 40bit instead of 36 bit and that info will be sent in parallel with every read or write command.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 23, 2020, 09:55:23 am
Perhaps you didn't catch my drift.
Does function #6 even write a pixel?
I thought it is a copy IE: read pixel command.

Uh... of course it is.  |O

Ok, about the bit selection, and the missing bit width.
The -
Code: [Select]
    //  AUX=14 : Set destination mem address,             : 31:24 bitplane mode : 23:0 hold destination base memory addres for write pixel
    //  AUX=15 : Set source mem address,                  : 31:24 bitplane mode : 23:0 hold the source base memory address for read source pixel
- bitplane mode tells the address generator how many bits there are in a pixel.  The address generator needs to tell the pixel writer that number of bits in a pixel.  It also needs to use this information to calculate the right memory address as the X coordinate will now change how much the address increases, but also, depending on the pixel width and where the X coordinate lands, the pixel writer also needs that information as well so it may edit the correct bits within the word.  IE, the pixel writer knowing the bits per pixel set by the 'bitplane mode' is half of what it needs.  It also needs where inside the 16 bits the X coordinate landed on so it may edit the right parts of the 16 bit word.

This second piece of information in effect is the correct lower 0-3 bits of the X coordinates.

[attachimg=1]

There's probably a blindingly obvious solution to calculating the address based on the X,Y position, bitplane mode and pixel width involving a simple bit-shift, but I'm feeling like the guy in the picture above trying to work it out.

As far as the pixel_cmd bus goes, I've widened it to 40-bits and included the changes from your last post, made a few changes to the code accordingly, but am hanging on the solution to the address calculations based off of the supplied parameters.

The address generator needs:

From that it should be able to spit out:

Right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 23, 2020, 11:45:35 am
I gave you the correct address calculation in Reply #1354.  Read the line with blue text and the next few lines after.

The Z80 tells the geometry xy plotter which base address, raster pixel width and bits per pixel will be used when writing/reading pixels.  You need to set that since you can have multiple screens with different color depths and widths.  So, those figures need to change when plotting / addressing a new screen.

The geometry passes these settings into the pixel address generator when it sends the:
Code: [Select]
            CMD_IN_DSTRWDTH : dest_rast_width[15:0]   <= draw_cmd[15:0];    // set destination raster image width
            CMD_IN_SRCRWDTH : srce_rast_width[15:0]   <= draw_cmd[15:0];    // set source raster image width
            CMD_IN_DSTMADDR : dest_base_address[23:0] <= draw_cmd[23:0];    // set destination base memory address
            CMD_IN_SRCMADDR : srce_base_address[23:0] <= draw_cmd[23:0];    // set source base memory address )

Now, with the last 2, you only forgot to latch/retain the 4 bit setting srce_ and desc_ bits per pixel.

Now, like you said, when a write or read pixel is received from the geometry plotter, the pixel address generator takes the stored proper dest_xxxx or srce_xxxx depending on a pixel read or write, and sends it out to the pixel writer if it is not busy.

The only weird commands sent to the pixel_write are these:
Code: [Select]
localparam CMD_IN_SETARGB       = 7;
localparam CMD_IN_RST_PXWRI_M   = 10;
localparam CMD_IN_RST_PXPASTE_M = 11;
The setargb just passes the first 32bits input to the first 32 bits in the output.
The RST_xxx just sends the command, the data bits on the output are ignored.

Your almost done.  Setup a simulation test bench, fill in the final address math, compile and make sure your FMAX passes 125MHz and we should be ready to do the pixel writer.  This one is a little tricky if you want to make it extra fast and efficient, but once working, you are ready to draw hardware accelerated lines, boxes & filled boxes.  Your will next need to add triangles and filled triangles referencing the work in geo.bas.

Also, in the geometry xy plotter, you will finally add a simple rectangular box copy command which will copy a rectangle from the video source video port to the destination port.  All line drawing functions, not fills, should also be able to drive the destination coordinates of the copy function and use the copy source as a paint brush so you may, as an example, hardware accelerate draw a fat circular brush for the line function when pixel writing using the transparency feature.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 23, 2020, 12:42:01 pm
I gave you the correct address calculation in Reply #1354.  Read the line with blue text and the next few lines after.

So this is correct, then?

Code: [Select]
dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> bits_per_pixel[3:0] );
...and...

Code: [Select]
pixel_cmd[19:0]  <= { destination_base_address[19:0] + dest_base_address_offset, 1'b0 };  // generate address for the pixel
?

The Z80 tells the geometry xy plotter which base address, raster pixel width and bits per pixel will be used when writing/reading pixels.

The geometry passes these settings into the pixel address generator when it sends the:
Code: [Select]
            CMD_IN_DSTRWDTH : dest_rast_width[15:0]   <= draw_cmd[15:0];    // set destination raster image width
            CMD_IN_SRCRWDTH : srce_rast_width[15:0]   <= draw_cmd[15:0];    // set source raster image width
            CMD_IN_DSTMADDR : dest_base_address[23:0] <= draw_cmd[23:0];    // set destination base memory address
            CMD_IN_SRCMADDR : srce_base_address[23:0] <= draw_cmd[23:0];    // set source base memory address )

Now, with the last 2, you only forgot to latch/retain the 4 bit setting srce_ and desc_ bits per pixel.

Ah yes, I missed that.  Okay, I've created a register to store the screen mode (bits_per_pixel).  However, I'm a little unsure that I've done it properly.  bits_per_pixel is only 4 bits, but bit_mode (where bits_per_pixel is latched from) is 8 bits as the plotter passes an 8-bit field for BITPLANE-MODE - I've set bits_per_pixel from the bottom 4-bits of the BITPLANE-MODE field.  Is that okay?

I've been trying to find where this BITPLANE-MODE 8-bit field in draw_cmd is set in the geometry_xy_plotter.sv, and aside from not being able to find it, I think I've found an error in the code as well.  Bearing in mind that CMD_OUT_DSTMADDR is defined as a localparam on line 42, it's later referenced as a bus on line 144?

Code: [Select]
Line 42 : localparam CMD_OUT_DSTMADDR      = 14;
Line 144: draw_cmd_func        <= CMD_OUT_DSTMADDR[3:0];   // sets the output function

Same issue with CMD_OUT_SRCMADDR on line 152.  :-//

The only weird commands sent to the pixel_write are these:
Code: [Select]
localparam CMD_IN_SETARGB       = 7;
localparam CMD_IN_RST_PXWRI_M   = 10;
localparam CMD_IN_RST_PXPASTE_M = 11;
The setargb just passes the first 32bits input to the first 32 bits in the output.
The RST_xxx just sends the command, the data bits on the output are ignored.

Okay, I've added the case statement code for those commands now.  Hopefully all correct.

Your almost done.  Setup a simulation test bench, fill in the final address math, compile and make sure your FMAX passes 125MHz and we should be ready to do the pixel writer.  This one is a little tricky if you want to make it extra fast and efficient, but once working, you are ready to draw hardware accelerated lines, boxes & filled boxes.  Your will next need to add triangles and filled triangles referencing the work in geo.bas.

:-+ Just need to sort these last niggling questions above, and I can't shake the feeling that the 'final address math' isn't complete - I'll be a lot happier once you've given me the official thumbs-up for what's in the attached code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 23, 2020, 02:39:55 pm
Got thing a little backwards:
Code: [Select]
            CMD_IN_DSTMADDR : begin
                dest_base_address[23:0] <= draw_cmd[23:0];    // set destination base memory address
                bits_per_pixel[3:0]        <= bit_mode[3:0];     // set screen mode (bits per pixel)
            end
           
            CMD_IN_SRCMADDR : begin
                srce_base_address[23:0] <= draw_cmd[23:0];    // set source base memory address (even addresses only?)
                bits_per_pixel[3:0]     <= bit_mode[3:0];     // set screen mode (bits per pixel)
            end

Ok, I see where 'draw_cmd[23:0]' is coming from the command input, but, where is 'bit_mode[3:0]' coming from?
Also, if you are reading a srce 1 bit font to write onto an 8 bit dest screen, how will your pixel read(copy) and pixel write command switch between the 2 when they go back and forth pixel by pixel if you are erasing/overwriting that same ' bits_per_pixel[3:0]' register?

Next :
Code: [Select]
            CMD_IN_PXCOPY : begin   // read pixel with x & y
                pixel_cmd[19:0]  <= { destination_base_address[19:0] + dest_base_address_offset, 1'b0 };  // generate address for the pixel
                pixel_cmd[23:20] <= target_bit;                                                           // which bit to read from the addressed byte
                pixel_cmd[27:24] <= bits_per_pixel[3:0];                                                  // set bits per pixel for current screen mode
                pixel_cmd[35:28] <= 8'b0;                                                                 // no colour information
                pixel_cmd[39:36] <= CMD_OUT_READ_PIXEL;                                                   // NO COLOUR, READ, NO TRANS, NO R/M/W
                pixel_cmd_rdy    <= 1'b1;
            end
Why are you transmitting the pixel writing destination base address (plus extras) when you are calling the (copy) read source pixel command?

This line (this my be partially my fault):
Code: [Select]
    dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> bits_per_pixel[3:0] );
Now, if we have 1 bit per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 2 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 4 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 8 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 16 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.

Now, can we even make a 4 bit number 1 through 16?

You will see that your shift wont give you the right results unless you will be placing a custom figure for 'bits_per_pixel[3:0]' calculated by the Z80.  Perhaps look at maggies bit/pixel setting and try to match it's figure so that the Z80 may just copy the figure of the screen setting if you like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 24, 2020, 11:26:35 am
Got thing a little backwards:
Code: [Select]
            CMD_IN_DSTMADDR : begin
                dest_base_address[23:0] <= draw_cmd[23:0];    // set destination base memory address
                bits_per_pixel[3:0]        <= bit_mode[3:0];     // set screen mode (bits per pixel)
            end
           
            CMD_IN_SRCMADDR : begin
                srce_base_address[23:0] <= draw_cmd[23:0];    // set source base memory address (even addresses only?)
                bits_per_pixel[3:0]     <= bit_mode[3:0];     // set screen mode (bits per pixel)
            end

Backwards? How so?

Ok, I see where 'draw_cmd[23:0]' is coming from the command input, but, where is 'bit_mode[3:0]' coming from?

bit_mode[3:0] is set here:
Code: [Select]
Line 93:     bit_mode[7:0]   = draw_cmd[31:24];  // number of bits per pixel

This relates to a question I asked in my previous post - there seems to be 8 bits set aside in draw_cmd for bitplane_mode, but only 4 bits for passing it on to the pixel writer, so I chose the bottom 4 bits?

Also, if you are reading a srce 1 bit font to write onto an 8 bit dest screen, how will your pixel read(copy) and pixel write command switch between the 2 when they go back and forth pixel by pixel if you are erasing/overwriting that same ' bits_per_pixel[3:0]' register?

So I needed two bits_per_pixel registers, one for source and one for destination?  Have added them in now.

Why are you transmitting the pixel writing destination base address (plus extras) when you are calling the (copy) read source pixel command?

Fixed.  :-+

This line (this my be partially my fault):
Code: [Select]
    dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> bits_per_pixel[3:0] );
Now, if we have 1 bit per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 2 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 4 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 8 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.
Now, if we have 16 bits per pixel, and each memory address is 16 bits wide, how much do we divide the x coordinate.

Now, can we even make a 4 bit number 1 through 16?

You will see that your shift wont give you the right results unless you will be placing a custom figure for 'bits_per_pixel[3:0]' calculated by the Z80.  Perhaps look at maggies bit/pixel setting and try to match it's figure so that the Z80 may just copy the figure of the screen setting if you like.

 :o I have no idea how the address calculation maths is working here anyway, so I just went with what you said.  I'll need to go away and think this through, so will come back to it over the weekend (hopefully!)  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 24, 2020, 09:33:24 pm
Code: [Select]
localparam CMD_OUT_WRITE_PIXEL_COLOUR   = 5'b11000;
localparam CMD_OUT_READ_PIXEL           = 5'b00000;

5 bits?

Code: [Select]
    dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> dest_bits_per_pixel[3:0] );
    srce_base_address_offset = ( ( y * srce_rast_width[15:0] + x ) << 1 ) >> srce_bits_per_pixel[3:0] );

Code: [Select]
                pixel_cmd[19:0]  <= { destination_base_address[19:0] + dest_base_address_offset, 1'b0 };  // generate address for the pixel
You need to work out and learn how you access pixels and what this code is doing and decide if it does what you want it to do.

Now, I've said that every read or written byte by the GEO port reads and writes 16 bits at once ignoring the address LSB.

I will repeat.  In 8 bit color mode, each pixel is 1 byte, or 2 pixels consume one 16 bit word.  In 16 bit mode, 1 pixel is 2 bytes, or when addressing a 16 bit word, 1 pixel = one 16 bit word.  In 4 bit mode, 2 pixels make up 1 byte, or, 4 pixels make up one 16 bit word.  Ect.

You have a base address.  This address point to the first byte in the display graphics memory.

You also have a X&Y coordinate and a rast_width which defines how many pixels to jump for every Y coordinate position.  Now when calculating the new memory position to be addressed, remember you want to know how much you need to add to the base address to get to the right pixel.

You also need a means of telling the address generator how many bits per pixel (you have set in MAGGIE) so it may do the mathematics properly, this is the bits_per_pixel[] register setting.

Begin with thinking that you only have 8 bit pixels with 8 bit memory.  What would that math look like?
Next, how would you change that calculation if you had a 4 bit pixel where every 2 pixels take up 1 byte?

Again, think this through carefully and I'm sure you can solve the problem.


Next:
Code: [Select]
            CMD_IN_PXWRI_M :
           
            CMD_IN_PXPASTE :
           
            CMD_IN_PXPASTE_M :

These are identical to the 'CMD_IN_PXWRI' except they send out a different function to the pixel writer so it knows to enable the feature when generating the pixel to be written.

Next, the :
Code: [Select]
            CMD_IN_SETARGB       : pixel_cmd[31:0]    <= draw_cmd[31:0];    // pass through first 32-bits of input to output ( Alpha Blend and 24-bit RGB colour data)
           
            CMD_IN_RST_PXWRI_M   : pixel_cmd[39:36]   <= draw_cmd[35:32];   // pass through command only
           
            CMD_IN_RST_PXPASTE_M : pixel_cmd[39:36]   <= draw_cmd[35:32];   // pass through command only

If you never send out a:
Code: [Select]
                pixel_cmd_rdy    <= 1'b1;The pixel writer will never know it was being sent a command to take action.

After all is said and done, you also need to add a:
Code: [Select]
    input logic draw_busy,        // HIGH when pixel writer is busy, so address generator will pause before sending any new pixels
And a reset as well.

Let's see a good test simulation so we can go onto the pixel writer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 27, 2020, 09:59:30 am
Code: [Select]
localparam CMD_OUT_WRITE_PIXEL_COLOUR   = 5'b11000;
localparam CMD_OUT_READ_PIXEL           = 5'b00000;

5 bits?

Well spotted.  :-+

You also need a means of telling the address generator how many bits per pixel (you have set in MAGGIE) so it may do the mathematics properly, this is the bits_per_pixel[] register setting.

I'd tacked this onto the CMD_IN_DSTMADDR and CMD_IN_SRCMADDR functions - so dest/src_bits_per_pixel is set by whatever is in the bit_mode bits in the draw_cmd.  However, there's nothing in the geo module to pass the bitmode value and it doesn't seem logical that it would know the screen mode anyway.  You've mentioned getting bits_per_pixel from the MAGGIE - but which one?  How would the address generator know which MAGGIE to read?

Begin with thinking that you only have 8 bit pixels with 8 bit memory.  What would that math look like?

Next, how would you change that calculation if you had a 4 bit pixel where every 2 pixels take up 1 byte?

Like this?

Code: [Select]
dest_base_address_offset = y * dest_rast_width[15:0] + ( x << dest_bits_per_pixel[3:0] );
srce_base_address_offset = y * srce_rast_width[15:0] + ( x << srce_bits_per_pixel[3:0] );

Next:
Code: [Select]
            CMD_IN_PXWRI_M :
           
            CMD_IN_PXPASTE :
           
            CMD_IN_PXPASTE_M :

These are identical to the 'CMD_IN_PXWRI' except they send out a different function to the pixel writer so it knows to enable the feature when generating the pixel to be written.

Okay, I've done CMD_IN_PXWRI_M (I think), but how are PXPASTE and PXPASTE_M any different to PXWRI and PXWRI_M?

After all is said and done, you also need to add a:
Code: [Select]
    input logic draw_busy,        // HIGH when pixel writer is busy, so address generator will pause before sending any new pixels
And a reset as well.

Okay, all should be present and correct. Latest code attached. I just need clarification on where the address generator is getting the bits_per_pixel value from.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 27, 2020, 03:39:01 pm
Code: [Select]
localparam CMD_OUT_WRITE_PIXEL_COLOUR   = 5'b11000;
localparam CMD_OUT_READ_PIXEL           = 5'b00000;

5 bits?

Well spotted.  :-+

You also need a means of telling the address generator how many bits per pixel (you have set in MAGGIE) so it may do the mathematics properly, this is the bits_per_pixel[] register setting.

I'd tacked this onto the CMD_IN_DSTMADDR and CMD_IN_SRCMADDR functions - so dest/src_bits_per_pixel is set by whatever is in the bit_mode bits in the draw_cmd.  However, there's nothing in the geo module to pass the bitmode value and it doesn't seem logical that it would know the screen mode anyway.  You've mentioned getting bits_per_pixel from the MAGGIE - but which one?  How would the address generator know which MAGGIE to read?
You are correct, it was accidentally omitted in the geo plotter module.
In the geo plotter, take a look at functions 8'b011111?? and 8'b011110??.  They are kinda wrong.
The 'draw_cmd_data_color' which is set to 8'h00 should contain the 'command_data8' where you would place the bitplane mode you desire.

Also, commands 8'd115 through 8'd112 should be re-written like this so you may support screen widths beyond 4096 pixels, they will now support the 65535 pixel wide screen.  In fact, I would prefer moving the bitplane mode to these 4 commands.

Code: [Select]
                       
                8'd115 : begin  // set the number of bytes per horizontal line in the destination raster
                    draw_cmd_func        <= CMD_OUT_DSTRWDTH[3:0];   // sets the output function
                    draw_cmd_data_color  <= command_data8;                   // clears the unused function data
                    draw_cmd_data_word_Y <= y[2];                   // null
                    draw_cmd_data_word_X <= x[2];                    // sets the lower 12 bits of the destination address
                    draw_cmd_tx          <= 1'b1;                    // transmits the command
                end
                   
                8'd114 : begin  // set the number of bytes per horizontal line in the destination raster
                    draw_cmd_func        <= CMD_OUT_SRCRWDTH[3:0];   // sets the output function
                    draw_cmd_data_color  <= command_data8;                   // clears the unused function data
                    draw_cmd_data_word_Y <= y[2];                    // sets the lower 12 bits of the destination address
                    draw_cmd_data_word_X <= x[2];                   // null
                    draw_cmd_tx          <= 1'b1;                    // transmits the command
                end
                   
                8'd113 : begin  // set the number of bytes per horizontal line in the destination raster
                    draw_cmd_func        <= CMD_OUT_DSTRWDTH[3:0];   // sets the output function
                    draw_cmd_data_color  <= command_data8;                   // clears the unused function data
                    draw_cmd_data_word_Y <= y[3];                   // null
                    draw_cmd_data_word_X <= x[3];                    // sets the lower 12 bits of the destination address
                    draw_cmd_tx          <= 1'b1;                    // transmits the command
                end
                   
                8'd112 : begin  // set the number of bytes per horizontal line in the destination raster
                    draw_cmd_func        <= CMD_OUT_SRCRWDTH[3:0];   // sets the output function
                    draw_cmd_data_color  <= command_data8;                   // clears the unused function data
                    draw_cmd_data_word_Y <= y[3];                    // sets the lower 12 bits of the destination address
                    draw_cmd_data_word_X <= x[3];                   // null
                    draw_cmd_tx          <= 1'b1;                    // transmits the command
                end


Quote
Begin with thinking that you only have 8 bit pixels with 8 bit memory.  What would that math look like?

Next, how would you change that calculation if you had a 4 bit pixel where every 2 pixels take up 1 byte?

Like this?

Code: [Select]
dest_base_address_offset = y * dest_rast_width[15:0] + ( x << dest_bits_per_pixel[3:0] );
srce_base_address_offset = y * srce_rast_width[15:0] + ( x << srce_bits_per_pixel[3:0] );


Ok, the changes you made now makes the 'dest_rast_width[15:0]' define the screen width in bytes, not pixel width.  There is nothing wrong with this as long as you know what you are doing when setting the register.

Now for the 'x' if you set the 'dest_bits_per_pixel[3:0]' to it's top value of 15, you are shifting the 'X' value by 15 slots, or multiplying X by 32768.  This means that with an dest_bits_per_pixel or 15 and an X coordinate or 2, your already at 65536, more than the memory available to you.

Remember, the shifts either multiply by 1,2,4,8,16,32 or in the other direction divide by 1,2,4,6,16,32 with a value of 0,1,2,3,4,5.  The earlier version was more right as you need to divide down the 'X' value feeds the address as the number of pixels in a byte increase.


Quote

Next:
Code: [Select]
            CMD_IN_PXWRI_M :
           
            CMD_IN_PXPASTE :
           
            CMD_IN_PXPASTE_M :

These are identical to the 'CMD_IN_PXWRI' except they send out a different function to the pixel writer so it knows to enable the feature when generating the pixel to be written.

Okay, I've done CMD_IN_PXWRI_M (I think), but how are PXPASTE and PXPASTE_M any different to PXWRI and PXWRI_M?


No, the PXPASTE and PXPASTE_M arent any different.  Inside the pixel writer module, it will select which color or where it's getting it's color from to draw depending which type of pixel write/paste command it receives.

Quote

After all is said and done, you also need to add a:
Code: [Select]
    input logic draw_busy,        // HIGH when pixel writer is busy, so address generator will pause before sending any new pixels
And a reset as well.

Okay, all should be present and correct. Latest code attached. I just need clarification on where the address generator is getting the bits_per_pixel value from.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 27, 2020, 05:39:57 pm
You are correct, it was accidentally omitted in the geo plotter module.
In the geo plotter, take a look at functions 8'b011111?? and 8'b011110??.  They are kinda wrong.
The 'draw_cmd_data_color' which is set to 8'h00 should contain the 'command_data8' where you would place the bitplane mode you desire.

Also, commands 8'd115 through 8'd112 should be re-written like this so you may support screen widths beyond 4096 pixels, they will now support the 65535 pixel wide screen.  In fact, I would prefer moving the bitplane mode to these 4 commands.

Okay, code updated as suggested.  Updated files attached at the bottom of this post.

Quote
Begin with thinking that you only have 8 bit pixels with 8 bit memory.  What would that math look like?

Next, how would you change that calculation if you had a 4 bit pixel where every 2 pixels take up 1 byte?

Like this?

Code: [Select]
dest_base_address_offset = y * dest_rast_width[15:0] + ( x << dest_bits_per_pixel[3:0] );
srce_base_address_offset = y * srce_rast_width[15:0] + ( x << srce_bits_per_pixel[3:0] );


Ok, the changes you made now makes the 'dest_rast_width[15:0]' define the screen width in bytes, not pixel width.  There is nothing wrong with this as long as you know what you are doing when setting the register.

 ???  It does?

Now for the 'x' if you set the 'dest_bits_per_pixel[3:0]' to it's top value of 15, you are shifting the 'X' value by 15 slots, or multiplying X by 32768.  This means that with an dest_bits_per_pixel or 15 and an X coordinate or 2, your already at 65536, more than the memory available to you.

Remember, the shifts either multiply by 1,2,4,8,16,32 or in the other direction divide by 1,2,4,6,16,32 with a value of 0,1,2,3,4,5.  The earlier version was more right as you need to divide down the 'X' value feeds the address as the number of pixels in a byte increase.

Uh, well it seemed to work on paper.  :-\  I've reverted the changes until I can work this out.  I need the X/Y coordinates to resolve to an 16-bit memory address, with a 4-bit value indicating the specific bit at that address that we're writing/reading to/from?  But the target bit could be a byte, a word, or a variable number of bits depending on bits_per_pixel...  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 27, 2020, 06:18:11 pm
Updates to geo plotter good.

Now for your formula:
dest_base_address_offset = y * dest_rast_width[15:0] + ( x << dest_bits_per_pixel[3:0] );

Ok, if we want 8 bits per pixel, say you make the ' dest_bits_per_pixel[3:0]  ' = 0.
This will sort of work.
If X=0, you want to write the top 8 bits of 16 bit word address 0.
If X=1, you want to write the bottom 8 bits of 16 bit word address 0.
If X=2, you want to write the top 8 bits of 16 bit word address 2.
If X=3, you want to write the bottom 8 bits of 16 bit word address 2.
It would appear you just need to shave off the bottom address bit and use a ' dest_bits_per_pixel[3:0]  ' setting of 0 to get this to work.

Now, if you have 4 bits per pixel, this means:
If X=0, you want to write the top 4 bits of 16 bit word address 0.
If X=1, you want to write bits 8-11 of 16 bit word address 0.
If X=2, you want to write bits 4-7 of 16 bit word address 0.
If X=3, you want to write the bottom 4 bits 16 bit word address 0.
If X=4, you want to write the top 4 bits of 16 bit word address 2.
If X=5, you want to write bits 8-11 of 16 bit word address 2.
If X=6, you want to write bits 4-7 of 16 bit word address 2.
If X=7, you want to write the bottom 4 bits 16 bit word address 2.
What's the value of 'dest_bits_per_pixel[3:0]' I need to make this happen?

Now, if you have 16 bits per pixel, this means:
If X=0, you want to write all 16 bits of 16 bit word address 0.
If X=1, you want to write all 16 bits of 16 bit word address 2.
If X=2, you want to write all 16 bits of 16 bit word address 4.
If X=3, you want to write all 16 bits of 16 bit word address 6.
What's the value of 'dest_bits_per_pixel[3:0]' I need to make this happen?


Now, if you have 2 bits per pixel, this means:
If X=0, you want to write the top 2 bits of 16 bit word address 0.
If X=1, you want to write bits 12-13 of 16 bit word address 0.
If X=2, you want to write bits 10-11 of 16 bit word address 0.
If X=3, you want to write bits 8-9 of 16 bit word address 0.
If X=4, you want to write bits 6-7 of 16 bit word address 0.
If X=5, you want to write bits 4-5 of 16 bit word address 0.
If X=6, you want to write bits 2-3 of 16 bit word address 0.
If X=7, you want to write the bottom 2 bits 16 bit word address 0.
If X=8, you want to write the top 2 bits 16 bit word address 2.
What's the value of 'dest_bits_per_pixel[3:0]' I need to make this happen?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 27, 2020, 08:39:50 pm
Remember, 'dest_bits_per_pixel[3:0]' just tells the address generator how many pixels per word.

You will be sending the to the pixel writer with the 'dest_bits_per_pixel[3:0]' so that module will also know how many bits make up 1 pixel and you will also send the least significant bits of the 'X'  coordinate which will tell the pixel writer which part of the 16bit word will be written to.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 29, 2020, 09:33:13 am
How about this?  I've pasted the same process for each bpp setting, although the process is slightly simplified for 16 and 8 bpp there should be no reason why the same algorithm can't be used on them all.

However, target_bit refers to the addressed nybble, crumb or bit depending on the bits_per_pixel (bpp) setting, but doesn't correlate directly to the correct bit number:
I guess that would need to be inverted?

Am I on the right track?  I have no idea how this would translate to a single line of HDL without using a CASE or IF conditional.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 29, 2020, 03:11:30 pm
Ok, now you are on to it.  Yes, the same argument can be use for all bitplane modes.

You can do it this way:
First do a << 1 to everything in brackets.
Then do a >> dest_bits_per_pixel[2:0] to that bracket.
Noting that this value isn't truly bits/pixel.

You cal always use a lookup table and convert dest_bits_per_pixel[3:0] into a proper 'shift' value if you like.
Something like a:
parameter int LUT_bits_to_shift[16]      = '{4,3,3,2,2,2,2,1,1,1,1,1,1,1,1,0};  // shift bits/pixel-1  0=1 bit, 1=2bit, 3=4bit, 7=8bit, 15-16bit.
Though this is more dumb from a programming stand point on the Z80 side.

Don't forget to include the Y*dest_rast_width[15:0] in the brackets so that the Y position is included in the math.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 29, 2020, 05:54:17 pm
Okay, I'm using your lookup table suggestion as a simpler solution isn't jumping out at me:

Code: [Select]
parameter int LUT_bits_to_shift[16] = '{ 4,3,3,2,2,2,2,1,1,1,1,1,1,1,1,0 };  // shift bits/pixel-1  0=1 bit, 1=2bit, 3=4bit, 7=8bit, 15-16bit.

dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[dest_bits_per_pixel[3:0]] );
srce_base_address_offset = ( ( y * srce_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[srce_bits_per_pixel[3:0]] );

Updated code attached.

Now I just need to move bit 0 of the address_offset into target_byte, take the remainder and place that in target_bit, then zero the last bit of address_offset?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 29, 2020, 06:04:12 pm
You got it, now, there is 1 last mistake:
Code: [Select]
pixel_cmd[19:0]  <= { destination_base_address[19:0] + dest_base_address_offset, 1'b0 };  // generate address for the pixel

I basically want address bit 0 cleared, not the whole thing shifted.
Better:
Code: [Select]
pixel_cmd[19:0]  <= (destination_base_address[19:0] + dest_base_address_offset) && 20'b11111111111111111110 ;  // generate address for the pixel

Do this for all of them.

Come to think of it, you could have done everything right shifted by 1, including the base address.  Then on this add line, left shift everything by 1.  But, no big difference.  The compiler would end up making the same gates anyways.

Also, what's the 'target_bit'?
In the comb section, you can make it:
target_bit = x[3:0];

Make sure this module works and now begin the pixel writer.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 29, 2020, 07:11:59 pm
Specifications for the pixel writer coming in a few hours.  Be ready by making sure this module works.

The connection the geometry xy plotter unit and the address generator is direct.

The connection between the address generator and the pixel writer will have 1 of my 3 word fifo in between.

FIFO input side:
Data coming from the address generator should feed the fifo data input.
The fifo full output should feed both 'draw_busy' inputs of the geometry plotter and address generator.
The pixel_cmd_rdy output of the address generator should go through a gate:
(pixel_cmd_rdy && !fifo_full) -> this should feed the fifo's 'shift_in' input.

FIFO output -> pixel writer input:
fifo_not_empty -> this should feed the pixel_writer's 'cmd_ready' input.
fifo's data out   -> this should feed the pixel_writer's cmd_input.
the pixel_writer's load_next_cmd output should feed the fifo's 'shift_out'

This fifo should have it's underflow and overflow protection turned on.

I also want 4 new 8 bit input ports added to the Z80 bridge.  You will feed FIFO status flags here and 2 collision counters from the pixel writer unit.
Also make a strobe for each read port so you may use that strobe to see a read and it may be used to clear counters or status bits.

I also want to see a 16 bit output port added to the Z80 but.  Basically 2 adjacent 8 bit ports, with a write strobe output for each.  (This is so you can select loading data into the geo-unit after the low byte is sent, or, after the high byte is sent since the geo unit needs to take in 16bit at a time)  If you do not want to 2 ports to write to the geometry_xy_plotter, but a memory address bytes instead, you will need to do this on your own later.  This 16 bit port will feed a 512x16 word ALT_FIFO megafunction into the geometry_xy_plotter module.

You can test your added Z80 in and out ports by wiring them to the RS232 debugger's real-time in and out ports.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 29, 2020, 07:37:22 pm
Quartus lpm_fifo setup for feeding the geometry_xy_plotter input:

Here, your 16 bit output port will feed the lpm_fifo  data.
Your chosen high or low output port data strobe will be tied to the lpm_fifo wrreq.
(You will decide which output port byte you want to feed first, even or odd, and use the second one's data strobe to tie to the lpm_fifo's wrreq).
You will also tie the lpm_fifo's 'almost_full' output to a chosen bit in one of the 4 input ports.  Before sending data to the lpm_fifo unit for the geometry unit, test this bit to make sure you arent writing into a full fifo.

The lpm_fifo data out 'q' should go to the geometry_xy_plotter cmd_data.
The lpm_fifo's output empty should be INVERTED and && the geometry units load_cmd, also && with !draw_busy then fed into the geometry unit's cmd_rdy input and it should also feed the lpm_fifo's rdreq input.

The lpm_fifo sclr should be tied to the reset signal.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 29, 2020, 10:28:15 pm
Here, I vastly simplified the LPM_FIFO so you may insert it directly into the geometry_xy_plotter.sv

Code: [Select]
scfifo scfifo_component (
              .sclr        (rst),                   // reset input
              .clock       (clk),                   // system clock
              .wrreq       (fifo_cmd_rdy),          // connect this to the 'strobe' on the selected high.low Z80 bus output port.
              .data        (fifo_cmd_in),           // connect this to the 16 bit output port on the Z80 bus.
              .almost_full (fifo_cmd_busy),         // send to a selected bit on the Z80 status read port

              .empty       (fifo_cmd_rdy_n),         // remember, when low, the FIFO has commands for the geometry unit to process
              .rdreq       (load_cmd && !draw_busy), // connect to the listed inputs.
              .q           (geo_cmd_data),           // to geometry_xy_plotter cmd_data input.
              .full        ()                        // optional, unused
              );
     defparam
          scfifo_component.add_ram_output_register = "ON",
          scfifo_component.almost_full_value = 510,
          scfifo_component.intended_device_family = "Cyclone III",
          scfifo_component.lpm_hint = "RAM_BLOCK_TYPE=M9K",
          scfifo_component.lpm_numwords = 512,
          scfifo_component.lpm_showahead = "ON",
          scfifo_component.lpm_type = "scfifo",
          scfifo_component.lpm_width = 16,
          scfifo_component.lpm_widthu = 9,
          scfifo_component.overflow_checking = "ON",
          scfifo_component.underflow_checking = "ON",
          scfifo_component.use_eab = "ON";

Remember, now your geometry modules inputs drive the fifo directly.  The the fifo outputs will drive the rest of the geometry unit.  You will need to make an additional output for the 'fifo_cmd_busy' to tell the Z80 that it has to wait before adding instructions.

fifo_cmd_rdy_n will need to be inverted and && with (load_cmd && !draw_busy) before being sent to the geometry units internal 'cmd_ready'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 01:57:40 am
Ok, here comes the pixel_writer.sv

Now, you will need the command inputs:
clk, reset,
cmd_in[39:0], cmd_rdy which come from the 3 word fifo's data out and fifo_not_empty.

Command outputs:
next_cmd which drives the 3 word fifo's shift_out

Next you will need these memory access port IO which feeds the data_mux_geo I prepared for you.
Inputs:
rd_data_in[15:0]  this gets wired to the data_out_geo[15:0] on the  data_mux_geo
rd_data_rdy_a  this gets wired to the geo_rd_rdy_a on the  data_mux_geo
rd_data_rdy_b  this gets wired to the geo_rd_rdy_b on the  data_mux_geo
ram_mux_busy   this gets wired to the geo_port_full on the data_mux_geo

Outputs:
rd_req_a  this gets wired to the geo_rd_req_a on the  data_mux_geo
rd_req_b  this gets wired to the geo_rd_req_b on the  data_mux_geo
wr_ena    this gets wired to the geo_wr_ena on the  data_mux_geo
ram_addr[19:0]  this gets wired to the address_geo on the data_mux_geo
ram_wr_data[15:0] this gets wired to the data_in_geo on the data_mux_geo

Collision saturation counters IO:
outputs:
collision_rd[7:0]  this feeds 1 read port on the Z80_bridge_v2
collision_wr[7:0]  this feeds a second read port on the Z80_bridge_v2
inputs:
collision_rd_rst, collision_wr_rst - these 2 inputs will be connected to their associated read port's read strobe so they will be automatically cleared after they have been read.

The collision counter will count up to 255, and stop on 255.  This is what is meant by a saturation counter.

When reading a pixel (copy pixel), it will be checked if that address has already been read, if not, the appropriate rd_req_a will be sent out.  When the data comes in by the rd_data_rdy_a, the 16 bit word will be held and the new addressed for that cached 16bit word will be updated.  This is done so if a read of the same address is done again, no rd_req_a is required, we already have the data.  Remember to hold the color setting(an optional read transparency function), sub-pixel address and bits_per_pixel setting as they are needed to convert the read pixel to a value for the paste write pixel.

When any write pixel is done, first the ram address needs to be read into it's own 16 bit word cache (if necessary) just like the read pixel except you will use the rd_req_b channel.  (Makes the latching of read data easy to separate between the 2 different read destinations)  Once you have the valid data in the write pixel's read cache, you will then edit the correct bits depending on the type of pixel write and then do a 'wr_ena'.  (Basically the wr_ena is being held off until the 2 16 bit word caches have valid read data)  Plus, if the write address = the current copy_pixel read_address cache's 16 bit word, you will simultaneously copy the 16 bit write data (just the changes bits) into the copy_pixel read cache's 16 bit word.

Now, it's all in the edit.  This is where you look at you settings, bits per pixel & pixel types, and transparency settings and decide what to change the write pixel 16bit data to when sending out the wr_ena.
This will depend on color setting, write bits per pixel and sub-pixel offset.
Also, depending on transparency settings with copy pixel, and source data, you may edit the write pixel data, or just skip the write.

Also remember, when doing a copy & paste from a low color bitmap like 2 colors, to a high bitmap, like 256 colors, you should multiply the supplied 8 bit color value with the write-paste command's read lower color source pixel.  This way, you can paint a 2 color image, like a B&W paint brush image of a circle, to any new color you like.  Using the mask feature means you can do accelerated painting of low color images to the screen with more colors with a new color choice, with optional color 0 transparency (paste 'mask' feature).  Masked out pixels during a paste-mask will not add or count to the write pixel collision counter.

Remember, though rare, it is still possible to fill the data_mux_geo's fifo, so when reading and writing bytes, you may need to pause based on the ram_mux_busy input.

As for the collision counters, the read collision counts if the read data does not equal the set read color.
As for the write pixel collision, it increments if a pixel writes over a non-0 color pixel.  Remember that a write does not take place from a copy source if that source has a transparent color on it's read pixel.

(I would clearly simulate this one module in it's own project)

A little more to come....

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 02:17:04 am
Last (after triangle fill and ellipse/ellipse fill), adding an X/Y block copy function to the geometry_xy_plotter.

This will copy a rectangular block from source A to destination B with all the fancy features listed in the pixel writer.

Running the copy command will do just that with the optional transparency mask settings and destination color multiplier.

This code should have it's own defined arrays so you will be able to update and replace the line and ellipse function write pixel with a trigger of the copy command using the write pixel coordinates to set the destination B coordinates so that you may paint lines and ellipses with a stored brush such as a 2 bit color circle.  This way, you can make thick lines and thick circles.  Extended example, angular shaded lines stored in the copy's source would generate a shadow effect on drawn lines and ellipses.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 30, 2020, 09:57:33 am
Whoah steady tiger, I'm still trying to get the pixel_address_generator finished.  ;)

Also, what's the 'target_bit'?
In the comb section, you can make it:
target_bit = x[3:0];

Is that all that's required for it?

Are these outputs...

Code: [Select]
    output logic[3:0]  memory_rw_bit_size,
    output logic[3:0]  memory_rw_bit_offset

...unnecessary or will I need to pass the extra information here:

Now I just need to move bit 0 of the address_offset into target_byte, take the remainder and place that in target_bit, then zero the last bit of address_offset?

...into those two outputs?

At the moment, I don't seem to be doing anything with the lost bits (the remainder) when I right-shift the address_offsets by LUT_bits_to_shift?  Unleeeesss... oh - that'll be because target_bit is being set by the raw x[3:0] value?

Just so I'm on the same page, the target_byte and target_bit that I spoke about in my quote above - these are both handled by target_bit[3:0] in the code?

Wouldn't it be better to change this:

Code: [Select]
target_bit      = x[3:0]         ;
... to this :

Code: [Select]
target_bit      = draw_cmd[3:0];
I guess it won't make much difference in the HDL, but seems to cut out the 'middle man' as x[] is derived from draw_cmd[] anyway?

Make sure this module works and now begin the pixel writer.

You make it sound so easy. :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 10:55:21 am
Ok, you are curently telling the pixel writer the:

pixel_cmd[27:24] <= dest_bits_per_pixel[3:0]; 

This tells the pixel writer that a pixel is:
1 bit wide,
2 bits wide,
4 bits wide,
8 bits wide, or
16 bits wide.

Now, to work, the pixel writer needs a second bit of information.  Remember when we set the video source or destination to 1 bit per pixel, the:
( y * dest_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[dest_bits_per_pixel[3:0]]
is effectively divided by 16 (since we are eventually muting bit 0 in the address).

Now, since the address stays the same for every 16 pixels when in 1 bit pixel mode, we need to sub-shifts to the right bit position every 16 coordinates on the X/Y axis when in that 1 bit per pixel mode.  The pixel writer still needs that sub-position location which shifts by 1 every 1 pixels while the provided address stays the same for every 16 pixels.

This is the:
pixel_cmd[23:20] <= target_bit;   (You actually need 2 of them, a dest & srce target bit)

When in 1 bit mode, the pixel writer/reader will concentrate on the first 4 bits of the X coordinate which was lost from the address generator which was divided by 16 meaning:

dest_target_bit[3:0] = ( y * dest_rast_width[15:0] + x ) && 4'b1111;
srce_target_bit[3:0] = ( y * srce_rast_width[15:0] + x ) && 4'b1111;

Now, if x=0, the pixel writer knows to edit bits 15 in 1 bit mode.
Now, if x=1, the pixel writer knows to edit bits 14 in 1 bit mode.
Now, if x=2, the pixel writer knows to edit bits 13 in 1 bit mode.
Now, if x=3, the pixel writer knows to edit bits 12 in 1 bit mode.
Now, if x=4, the pixel writer knows to edit bits 11 in 1 bit mode.

In 2 bit mode, the pixel write knows to pay attention to the bottom 3 bits of the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit bits 15..14 in 2 bit mode.
Now, if x=1, the pixel writer knows to edit bits 13..12 in 2 bit mode.
Now, if x=2, the pixel writer knows to edit bits 11..10 in 2 bit mode.
Now, if x=3, the pixel writer knows to edit bits 9..8 in 2 bit mode.
Now, if x=4, the pixel writer knows to edit bits 7..6 in 2 bit mode.

In 4 bit mode, the pixel write knows to pay attention to the bottom 2 bits of the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit bits 15..12 in 4 bit mode.
Now, if x=1, the pixel writer knows to edit bits 11..8 in 4 bit mode.
Now, if x=2, the pixel writer knows to edit bits 7..4 in 4 bit mode.
Now, if x=3, the pixel writer knows to edit bits 3..0 in 4 bit mode.
Now, if x=4, the pixel writer knows to edit bits 15..12 in 4 bit mode.  (remember, only the bottom 2 bits of x is used)

In 8 bit mode, the pixel write knows to pay attention to the bottom 1 bit of the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit bits 15..8 in 8 bit mode.
Now, if x=1, the pixel writer knows to edit bits 7..0 in 8 bit mode.
Now, if x=2, the pixel writer knows to edit bits 15..8 in 8 bit mode.
Now, if x=3, the pixel writer knows to edit bits 7..0 in 8 bit mode.
Now, if x=4, the pixel writer knows to edit bits 15..8 in 8 bit mode.

In 16 bit mode, the pixel write knows to ignore the srce/dest_target_bit[3:0].
Now, if x=0, the pixel writer knows to edit all bits 15..0 in 16 bit mode.
Now, if x=1, the pixel writer knows to edit all bits 15..0 in 16 bit mode.

You've sort of done this before.  Take a look at your 'bart.v' source code. It has:
colour_mode_in[2:0], similar to srce/dest_bits_per_pixel[3:0] with different values.
The difference is that it works using only the bottom 3 bits of the X coordinate, and in it works it's way toward bit x[2] as the bits per pixel increases.

With our pixel writer, we we work toward the bottom of the X coordinate bit, down to bit X[0] when we go up to 8 bit color and ignoring the srce/dest_target_bit all together when operating in 16 bit mode.


Like this: (beginning of lines 109, get rid of line 107)
Code: [Select]
    dest_base_address_offset = ( ( y * dest_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[dest_bits_per_pixel[3:0]] ;
    srce_base_address_offset = ( ( y * srce_rast_width[15:0] + x ) << 1 ) >> LUT_bits_to_shift[srce_bits_per_pixel[3:0]] ;
    dest_target_bit[3:0] = ( y * dest_rast_width[15:0] + x ) && 4'b1111;
    srce_target_bit[3:0] = ( y * srce_rast_width[15:0] + x ) && 4'b1111;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 30, 2020, 11:25:44 am
Aha, thanks for the clarification. :-+  Now that last missing piece is in, it's making a lot more sense to me as it correlates 1:1 with the algorithm outlined in my earlier post.

I've removed these outputs as you haven't confirmed they're needed and, as far as I understand it all, they're not needed anyway.

Code: [Select]
    output logic[3:0]  memory_rw_bit_size,  // ***** ARE THESE NEEDED ANYMORE? *****
    output logic[3:0]  memory_rw_bit_offset // ***** ARE THESE NEEDED ANYMORE? *****

Okay, so the attached code for the pixel_address_generator (PAGE or PAGET I guess, if we're naming everything Amiga-style) should be the complete article.

I'll get started on simulating next.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 11:34:44 am
Sorry, my little booboo...

    dest_target_bit[3:0]     = ( y * dest_rast_width[15:0] + x ) && 4'b1111 ;
    srce_target_bit[3:0]     = ( y * srce_rast_width[15:0] + x ) && 4'b1111 ;

I had 3 1's, not the proper 4...
looks finished...

Hurry up, tomorrow may be my last day.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 12:15:21 pm

Code: [Select]
    output logic[3:0]  memory_rw_bit_size,  // ***** ARE THESE NEEDED ANYMORE? *****
    output logic[3:0]  memory_rw_bit_offset // ***** ARE THESE NEEDED ANYMORE? *****

No, they are not needed anymore.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 30, 2020, 12:20:20 pm
Ironically I'd noticed the mistake in your post, but forgot to correct it when I updated the code!  :-DD

I'm running on pure coffee at the moment, so these tests may be a bit 'spray n pray'.  :o

Quick question - how do I get the Vector Waveform to simulate longer than 1000ns?  Can't seem to find an option that changes it - have tried Assignments/Settings/Simulator Settings/Simulation Period - End Simulation at:  but it doesn't seem to make a difference to the length of the .vwf file.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 12:28:36 pm
Open the .vwf. Then just
Go to 'Edit / End Time' in the normal 'Edit' menu.

Any signals you have already drawn will just repeat.
Only go around 10x as the longer you make it, the more time to simulate.
Also, once you have an initial .vwf, go to 'Assignment sertings / Simulator Settings '
and change 'Timing Simulation' to 'functional simulation'.

To get access to adding/removing IO pin labels, you may need to initially do a compile first.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 30, 2020, 12:33:09 pm
Hmm.. okay, here's my test project.  I've connected up the pixel_address_generator in the schematic, I've compiled the whole project, then generated a functional simulation netlist before going to geo3.vwf and trying to add signals.

I can only seem to find signals relating to the geometry_xy_plotter.  :-//

Oh, hang on - I need output pins for the pixel_cmd bus? D'oh!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 12:45:27 pm
You can change the parameter LUT_bits_to_shift to a localparam as it will not be something you would adjust...
Finish the simulation with output pins and see the results after setting the new bitmap controls.
You really jumped the gun....
I would generate output pins decomposing the address generator's output data into:
cmd ready
cmd function[3..0]
address[19..0]
color[7..0]
bits per pixel[3..0]
bit offset[3..0]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 01:00:38 pm
also include the intermediary output between the geometry_xy_plotter and address generator so you may see what's getting passed through.  This may be done with signal tap, you do not necessarily need output pins unless Quartus has simplified out you module's signal names.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 30, 2020, 01:25:57 pm
Okay, I've got as far as setting up the test environment - I just need to work out the commands to send to the geometry plotter and insert them into the .vwf.

This is about all I can manage today, work calls - will have to come back to it tomorrow morning now.   :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 30, 2020, 01:49:45 pm
Think there's a problem with the above project setup.  I'm not getting any draw commands out of the geo_plotter.  :-//

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 02:59:17 pm
You were missing an important input pin:
[attachimg=1]

Right ow you have an FMAX problem reaching only 60MHz in the address generator, however continue your verification work.
I'll upload a 2 stage piped address generator tonight which will get it up to 125MHz.

It that we are asking the cyclone to calculate (y*width+x)>>shifted + base_address all in a single clock.
Piping means breaking this down into 2 steps meaning the output will be delayed by 1 clock.  Doing this means all the address generator's cmd outputs which are assigned in a single clock need to be delayed by an additional clock.  I'm sure this will be puzzling as the command input will need to pipe along in 2 stages as well.

I doubt such piping will be necessary in the pixel_writer as all it needs to do is manipulate a 16bit word with a bunch of small conditions attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 07:24:38 pm
Geometry_xy_plotter, line 369.  I had to add this:
Code: [Select]
        end else   draw_cmd_tx <= 1'b0;    // stop transmit output command function//  end of (geo_run) flag
Without ending the draw_cmd_tx, after sending 'CMD_OUT_DSTRWDTH', the output went on indefinately.

Also in your current address generator, lines 72-79:
Code: [Select]
// CMD_OUT:
// bit 3 = COLOUR (HIGH for colour data included, LOW for none)
// bit 2 = WRITE bit (HIGH for WR, LOW for RD)
// bit 1 = TRANSPARENT bit (HIGH for transparent mask, LOW for none, ignored if bit 35 is LOW)
// bit 0 = READ/MODIFY/WRITE (ignored if bit 2 is LOW)
localparam CMD_OUT_WRITE_PIXEL_COLOUR   = 4'b1100 ;
localparam CMD_OUT_WRITE_PIXEL_MASK     = 4'b1110 ;
localparam CMD_OUT_READ_PIXEL           = 4'b0000 ;
3 commands? And read pixel is command 0, usually reserved for nop.
Read the '           case (aux_cmd_in)' at line 132.
Each command has it's own pixel write function.  It's in the actual CMD_IN_PX?????.

Here, this is better:
Code: [Select]
// CMD_OUT:
localparam CMD_OUT_NOP           = 0;
localparam CMD_OUT_PXWRI         = 1;
localparam CMD_OUT_PXWRI_M       = 2;
localparam CMD_OUT_PXPASTE       = 3;
localparam CMD_OUT_PXPASTE_M     = 4;
localparam CMD_OUT_PXCOPY        = 6;

Ok, I fixed up a few other things and cleaned up the order of the formulas for better reading and it will give me some leg room to optimize the FMAX.
Here is the latest sim:
[attachimg=1]

Also, I've attached the latest simulation complete project with both updated source codes.  The only issue is that the compiled FMAX is 70MHz, but we require 125MHz.  I'll improve the FMAX in a few hours.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 08:46:02 pm
Ok, here you go:
[attachimg=1]

As you see, the output of the address generator is now delayed by 2 clocks instead of the usual 1 clock.

With this change, the FMAX has reached 134MHz, good enough for your 125MHz core.

I've attached the new simulation test bench with the new source code changes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 08:52:13 pm
You are just missing the 'scfifo   scfifo_component' at the beginning of the geometry_xy_plotter command input.

Time to make the pixel_writer.
Do not attach it to the geometry project, make a whole new Quartus simulation project to develop it, all by itself.  It has so few commands and IO to check all on it's own.

Also, remember when adding the new Z80 input and output ports, you have a full simulation test bench ready which I made you last time to verify the new ports work and the single clock 'strobe' output for each port when they are accessed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 30, 2020, 09:03:08 pm
Oooops, a little bug in some of the commands in the new address_generator.
Some of the second sequence clocked ( s2_ ) functions were getting their data from the first clock stage.
No difference on the above simulation as these functions were never called.

You also didn't properly pass these commands to the pixel_writer.

The new FMAX limit of 134MHz is now restricted by logic inside the geometry_xy_plotter.
(I updated the simulation test bench Quartus project above...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 31, 2020, 11:25:32 am
Latest geometry_xy_plotter attached, with scfifo added and (hopefully) wired in correctly.

EDIT: Also added the geo_pixel_writer file - currently only consists of module declaration and I/O as you've specified.  Hopefully all correct so far.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 31, 2020, 02:42:45 pm
Latest geometry_xy_plotter attached, with scfifo added and (hopefully) wired in correctly.

Well, does it simulate.  (I think not as it doesn't compile)
It should still simulate when running through a FIFO inside.

Also, this line:
Code: [Select]
    .sclr        (rst),                    // reset input
Do you have a 'rst' input wire?  It should be called 'reset'.

Code: [Select]
    .wrreq       (fifo_cmd_rdy),           // connect this to the 'strobe' on the selected high.low Z80 bus output port.
' _rdy ', not ' _ready '  ?

You also need these 2 before the FIFO:
Code: [Select]
logic [15:0] cmd_data;
logic        fifo_cmd_rdy_n;

I've added the ' !fifo_cmd_rdy_n ' to this line in the fifo:
Code: [Select]
    .rdreq       (load_cmd && !draw_busy && !fifo_cmd_rdy_n), // connect to the listed inputs.
It's just another check to prevent a read if the fifo is empty.

Ok, I've made the changes & it finally simulates properly.  Your geometry_xy_plotter now has a 510 word instruction cache which you might never be able to fill up with a slow 8 MHz Z80 unless all you are doing is non-stop 16bit color full screen copy & fills.

Don't forget to generate and update symbol in your simulation + if you want, add the 'fifo_cmd_busy' output which you could never make it go high in simulation unless it is deliberate.

(LOL, I like there's a 3 clock delay from the first loaded instruction until the geometry_xy_plotter sees and executes it.  If we used my FIFO_3/7word_0_latency FIFO, the execute would have been executed just as immediate as if it wasn't in the circuit.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 31, 2020, 02:45:35 pm
EDIT: Also added the geo_pixel_writer file - currently only consists of module declaration and I/O as you've specified.  Hopefully all correct so far.

So far perfect...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 31, 2020, 08:03:47 pm
Well, does it simulate.  (I think not as it doesn't compile)
It should still simulate when running through a FIFO inside.

Ah well done, yes there were a few cut 'n' paste errors in the FIFO instantiation.  ::)

Ok, I've made the changes & it finally simulates properly.  Your geometry_xy_plotter now has a 510 word instruction cache which you might never be able to fill up with a slow 8 MHz Z80 unless all you are doing is non-stop 16bit color full screen copy & fills.

Yes, simulating just fine here too.  :-+  I really can't think of any situations where I'm going to be filling the FIFO - I can't see FMV or the need to hypnotise the user cropping up any time soon!  :o

(LOL, I like there's a 3 clock delay from the first loaded instruction until the geometry_xy_plotter sees and executes it.  If we used my FIFO_3/7word_0_latency FIFO, the execute would have been executed just as immediate as if it wasn't in the circuit.)

Is the sc_FIFO up to the task then?  Would using your zero-latency FIFO be overkill?

I'm going to work on the rest of your posts above as quickly as I can, but I just don't have the time to sit down and work on it all in continuous blocks of time.  I'm certainly not going to get any more done before tomorrow. :(  I'll keep plugging away at it over the next month and might post questions here as I hit blocks, but won't expect any responses during August.  Thanks for all the help so far!  ^-^
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 31, 2020, 09:04:46 pm
Hold on, don't quit yet.  I might still be available for another 2-3 weeks...
However, once I'm unavailable, I doubt I'll be able to get back to anything serious...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 31, 2020, 09:56:32 pm
Is the sc_FIFO up to the task then?  Would using your zero-latency FIFO be overkill?
It's not slow, it still runs at 125MHz.  This just means when you send the first command, there is a 1/41 millionth of a second before the geometry_xy_plotter will see it and begin to compute.  However, if the geometry plotter is busy for a long time, you can keep on adding 510 additional geometry commands which will get immediately executed as soon as the 'load_cmd' signal goes high.  The fifo size was chosen based on it using only 1- Cyclone M9K block of ram to store these commands.

My zero-latency FIFO  may remove that 1/41 millionth pipe delay, but, it stores it's 4 16 bit words of data in logic cell registers, not M9K memory blocks.  This doubles if you set it to 8 word mode.

Because of your GPU design, you cannot increase your current bulk graphics FPGA memory because of it's width & depth unless you use a larger FPGA, but you still have a few free odd M9K blocks left.  These are perfect for the geometry input fifo.

You also don't even need a fifo, but the Z80 might need to wait a few times when dumbly copying a precompiled list of commands filling and copying the largest possible objects to a high color depth screen.

Now, with the next 3 weeks, do you think you can squeeze in past the triangle fill to ellipse fill and do a copy & paste function to finish this geometry unit V1.0 meaning you may even be able to paint (blit) software fonts on a normal graphics screen and even draw/copy/render multiple sprites all over the screen being able to replicate car racing games like 'Out Run' at full arcade speed and quality?

https://youtu.be/ELUl-cAtUIE?t=1142

Ok, you'll need either the Lattice FPGA with a little trickery to retain the full 320x240 res, and/or add the 512k ram chip to get every single asset for this one running on a 256 color full arcade quality 320x240 screen.  With some added logic to the rectangle copy command, you could get a Z80 to play Doom at a reasonable framerate as you would have a scaling feature inside the copy command though the Z80 side would still need 8mb of memory.

I hope you have a good BGA Cyclone choice + add at least 1 or 2 of those ZBT rams chips for 1mb.  You will be able to do full audio as well.
Note that the sampling audio system will eat up the RS232 debugger port to the GPU ram controller.

Yes, if you want DDR ram with full efficient access, especially for the geometry unit, there will be a ton leg work to do on your own.  The ZBT ram would be a drop-in addition which still requires a little steering logic inside the 'vid_osd_generator.sv' to give access to it's own 1 or 2 MAGGIE layers as it is will be 2x slower at 125MHz, or if you are lucky you can run it at 250MHz, but it can still get the read data back in 3 clocks instead of 2.  (Easy interleave trick to sync the core and external ram, add 1 dummy clock cycle delay on the read of your FPGA core ram (changing all the read delay parameters) and it will match the external ram, unless you want to learn about defining external IO constraints like tsu/tpd/th, then you can get the read down to 2 clocks with any certainty, but forget getting the external ram to run at 250MHz.)  Also remember, Maggie currently can only address 1 megabyte as much of the rest of your design also has only 20 bit addressing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 01, 2020, 09:27:49 am
Now, with the next 3 weeks, do you think you can squeeze in past the triangle fill to ellipse fill and do a copy & paste function to finish this geometry unit V1.0 meaning you may even be able to paint (blit) software fonts on a normal graphics screen and even draw/copy/render multiple sprites all over the screen being able to replicate car racing games like 'Out Run' at full arcade speed and quality?

I don't know, is the honest answer.  I know enough about the design to know what I don't know - and it feels like a lot.  I don't have the large chunks of time I really need to sit down and process what's going on and work on the next steps effectively at the moment, so that's a cause for concern, but I will do my best.

Ok, you'll need either the Lattice FPGA with a little trickery to retain the full 320x240 res, and/or add the 512k ram chip to get every single asset for this one running on a 256 color full arcade quality 320x240 screen.

I was considering the jump to an EP4CE22F17 for the BGA - would that be able to handle what we're trying to do, or do I need to look at Lattice FPGAs specifically?

I hope you have a good BGA Cyclone choice + add at least 1 or 2 of those ZBT rams chips for 1mb.  You will be able to do full audio as well.
Note that the sampling audio system will eat up the RS232 debugger port to the GPU ram controller.

Okay, so the ZBT RAM chips are a definite requirement then?  I'll add them to the BOM for the BGA design and (when I get a chance) I'll work them into the design.  The BGA design hasn't really progressed much at all, thanks to everything else I've had going on.

Yes, if you want DDR ram with full efficient access, especially for the geometry unit, there will be a ton leg work to do on your own.  The ZBT ram would be a drop-in addition which still requires a little steering logic inside the 'vid_osd_generator.sv' to give access to it's own 1 or 2 MAGGIE layers as it is will be 2x slower at 125MHz, or if you are lucky you can run it at 250MHz, but it can still get the read data back in 3 clocks instead of 2.

I wouldn't have a clue how to connect up DDR ram.  I mean, the actual physical connection should be easy enough (with a little learning about matching trace lengths and some other oddities of PCB design), but actually integrating it into the GPU HDL would be the big issue for me. :(  Having access to megabytes of RAM would be massively advantageous, though.  Not just for the GPU, but for any application I'd decide to put the FPGA to.  I could get rid of all the 'old' hardware (memory, CF card, CPU) and have it all on the one PCB, for example.

Also remember, Maggie currently can only address 1 megabyte as much of the rest of your design also has only 20 bit addressing.

That'd be easy enough to improve, though - at least in theory. :o

Okay, I'm going to use any spare time I have today to try and focus on the Z80_bridge changes.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 01, 2020, 09:54:03 am
I've added an input to the pixel_address_generator called fifo_full which connects to the output of the same name (presumably) on the zero-latency fifo.

In the comb section of the pixel_address_generator, pixel_cmd_rdy is now the ANDed product of (what was called) pixel_cmd_rdy && !fifo_full, so pixel_cmd_rdy only goes high now when cmd_rdy is HIGH AND fifo_full is LOW.

Shouldn't draw_busy also be ANDed with !fifo_full, so the pixel_address_generator (I'm calling it PAGET from now on) stops working whilst the pixel_writer's input fifo is full?

Just read in your previous post(s) that it should do.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 01, 2020, 10:32:02 am
Z80_bridge_v2 attached, with inputs and outputs added as described.

I also want to see a 16 bit output port added to the Z80 but.  Basically 2 adjacent 8 bit ports, with a write strobe output for each.  (This is so you can select loading data into the geo-unit after the low byte is sent, or, after the high byte is sent since the geo unit needs to take in 16bit at a time)  If you do not want to 2 ports to write to the geometry_xy_plotter, but a memory address bytes instead, you will need to do this on your own later.  This 16 bit port will feed a 512x16 word ALT_FIFO megafunction into the geometry_xy_plotter module.

Won't I need a third IO port to tell the Z80_bridge to send the data to the geo-unit?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 01, 2020, 02:57:03 pm
I've added an input to the pixel_address_generator called fifo_full which connects to the output of the same name (presumably) on the zero-latency fifo.

In the comb section of the pixel_address_generator, pixel_cmd_rdy is now the ANDed product of (what was called) pixel_cmd_rdy && !fifo_full, so pixel_cmd_rdy only goes high now when cmd_rdy is HIGH AND fifo_full is LOW.

Shouldn't draw_busy also be ANDed with !fifo_full, so the pixel_address_generator (I'm calling it PAGET from now on) stops working whilst the pixel_writer's input fifo is full?

Just read in your previous post(s) that it should do.  :-+
NO.  The already 'draw_busy' input goes to the 3 word zero latency fifo's 'fifo_full' flag.  Like I said, the address generator was finished.
The 'draw_busy' input of the geometry_xy_plotter also is tied to the same fifo_full output flag.
This is how they know to stop sending data to the pixel_writer unit since it isn't reading anything from the 3 word FIFO.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 01, 2020, 03:14:26 pm
Z80_bridge_v2 attached, with inputs and outputs added as described.

I also want to see a 16 bit output port added to the Z80 but.  Basically 2 adjacent 8 bit ports, with a write strobe output for each.  (This is so you can select loading data into the geo-unit after the low byte is sent, or, after the high byte is sent since the geo unit needs to take in 16bit at a time)  If you do not want to 2 ports to write to the geometry_xy_plotter, but a memory address bytes instead, you will need to do this on your own later.  This 16 bit port will feed a 512x16 word ALT_FIFO megafunction into the geometry_xy_plotter module.

Won't I need a third IO port to tell the Z80_bridge to send the data to the geo-unit?  ???
Code: [Select]
   input logic WR_PX_CTR_STROBE, // HIGH to clear the WRITE PIXEL collision counter
   input logic [7:0] WR_PX_CTR,  // WRITE PIXEL collision counter from pixel_writer
   
   input logic WFR_PX_CTR_STROBE,// HIGH to clear the WRITE FROM READ PIXEL collision counter
   input logic [7:0] WFR_PX_CTR, // WRITE FROM READ PIXEL collision counter from pixel_writer
   
   input logic PAGET_FIFO_STROBE,// HIGH for valid data on PAGET_FIFO bus
   input logic [7:0] PAGET_FIFO, // pixel_address_generator FIFO flags
   
   input logic GEOFF_FIFO_STROBE,// HIGH for valid data on GEOFF_FIFO bus
   input logic [7:0] GEOFF_FIFO, // geometry_xy_plotter FIFO flags

The '_STROBE' are outputs, not inputs.  This is how we are able to tell if the Z80 read each one of those ports so we may auto clear and update their values.

'WRITE FROM READ PIXEL collision counter'  Should just be a COPY READ PIXEL  collision counter.  The 'WRITE PIXEL' collision counter is already doing what you describe.

'GEOFF_FIFO_STROBE' & 'PAGET_FIFO_STROBE', these are outside of your control.  you do not have Z80 access to these.

What you want is:
GEO_STATUS_STROBE output and
GEO_STATUS_DATA_READ_IN    8 bit input read port where we may tie the 510 word scfifo's almost full flag to bit 0, and maybe some other status information to to any other of the 7 bits, like a 1 bit VS frame counter or spare programmable H/V strobe output on bit 1 so you may sync animation to a new frame or chosen line of video.
GEO_STATUS_DATA_WRITE_OUT   this output on the same port is optional as you may use a selected bit, say bit 7 to feed all the reset lines for the entire geometry section so it may be kept in sleep until you release the reset.  Or, if the geometry unit crashes, IE 510 word scfifo's almost full flag stays full for a consecutive 65535 reads, you may assume a geo crash and reset the entire section and send a fault error to your OS graphics driver.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 01, 2020, 03:28:09 pm
I wouldn't have a clue how to connect up DDR ram.  I mean, the actual physical connection should be easy enough (with a little learning about matching trace lengths and some other oddities of PCB design), but actually integrating it into the GPU HDL would be the big issue for me. :(  Having access to megabytes of RAM would be massively advantageous, though.  Not just for the GPU, but for any application I'd decide to put the FPGA to.  I could get rid of all the 'old' hardware (memory, CF card, CPU) and have it all on the one PCB, for example.

The CycloneIV operatives nowhere near enough high speed that you could ever need to match length traces unless for some reason, you have 1 trace going through circular hoops to get to it's destination.  The biggest time delay you need to worry about here is vias as they have slightly more decernable delay at the top 200MHz(400MTPS) speed you can operate the ram at.  For the CLK, DATA & DQS Strobes, if one of these signals goes through a via, then all of them need to go through at least 1 via to reach their destination.  Otherwise, route everything on the top layer exclusively and you wont have a problem.

Note that the same goes for the ZBT ram.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 01, 2020, 03:33:37 pm
Also remember, Maggie currently can only address 1 megabyte as much of the rest of your design also has only 20 bit addressing.

That'd be easy enough to improve, though - at least in theory. :o

I left space open to support 24 bits max all round the design.  This means 16 megabytes is your absolute limit unless you are really prepared for some massive surgery or workarounds.  Because of how the maggie is wired, only in 16bit color mode can you trick it to appear to address 32 megabytes of graphic data.  But then, the entire geometry unit will need a little surgery.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 01, 2020, 04:05:43 pm
The '_STROBE' are outputs, not inputs.  This is how we are able to tell if the Z80 read each one of those ports so we may auto clear and update their values.

'WRITE FROM READ PIXEL collision counter'  Should just be a COPY READ PIXEL  collision counter.  The 'WRITE PIXEL' collision counter is already doing what you describe.

'GEOFF_FIFO_STROBE' & 'PAGET_FIFO_STROBE', these are outside of your control.  you do not have Z80 access to these.

Ah okay, I've updated the Z80_bridge code accordingly.  I've called the 'COPY READ PIXEL' counter port simply 'RD_PX_CTR_STROBE'.

What you want is:
GEO_STATUS_STROBE output and
GEO_STATUS_DATA_READ_IN    8 bit input read port where we may tie the 510 word scfifo's almost full flag to bit 0, and maybe some other status information to to any other of the 7 bits, like a 1 bit VS frame counter or spare programmable H/V strobe output on bit 1 so you may sync animation to a new frame or chosen line of video.
GEO_STATUS_DATA_WRITE_OUT   this output on the same port is optional as you may use a selected bit, say bit 7 to feed all the reset lines for the entire geometry section so it may be kept in sleep until you release the reset.  Or, if the geometry unit crashes, IE 510 word scfifo's almost full flag stays full for a consecutive 65535 reads, you may assume a geo crash and reset the entire section and send a fault error to your OS graphics driver.

Okay, I think I've got the IO as you want it now.  Z80_bridge attached.  Obviously there's nothing driving or reading these new ports yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 01, 2020, 04:10:34 pm
I assume you want the zero-latency FIFO for the pixel_writer to be instantiated in the pixel_writer module, rather than as a separate entity on the schematic diagram?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 01, 2020, 04:13:57 pm
That's fine.
Remember, that fifo's 'fifo_full' output drives an output port called 'draw_busy' which tells the other 2 geometry units to wait before sending over additional write pixel commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 01, 2020, 04:17:27 pm
The '_STROBE' are outputs, not inputs.  This is how we are able to tell if the Z80 read each one of those ports so we may auto clear and update their values.

'WRITE FROM READ PIXEL collision counter'  Should just be a COPY READ PIXEL  collision counter.  The 'WRITE PIXEL' collision counter is already doing what you describe.

'GEOFF_FIFO_STROBE' & 'PAGET_FIFO_STROBE', these are outside of your control.  you do not have Z80 access to these.

Ah okay, I've updated the Z80_bridge code accordingly.  I've called the 'COPY READ PIXEL' counter port simply 'RD_PX_CTR_STROBE'.

What you want is:
GEO_STATUS_STROBE output and
GEO_STATUS_DATA_READ_IN    8 bit input read port where we may tie the 510 word scfifo's almost full flag to bit 0, and maybe some other status information to to any other of the 7 bits, like a 1 bit VS frame counter or spare programmable H/V strobe output on bit 1 so you may sync animation to a new frame or chosen line of video.
GEO_STATUS_DATA_WRITE_OUT   this output on the same port is optional as you may use a selected bit, say bit 7 to feed all the reset lines for the entire geometry section so it may be kept in sleep until you release the reset.  Or, if the geometry unit crashes, IE 510 word scfifo's almost full flag stays full for a consecutive 65535 reads, you may assume a geo crash and reset the entire section and send a fault error to your OS graphics driver.

Okay, I think I've got the IO as you want it now.  Z80_bridge attached.  Obviously there's nothing driving or reading these new ports yet.

   // geo_unit inputs
   input logic [7:0] WR_PX_CTR,  // WRITE PIXEL collision counter from pixel_writer
   input logic [7:0] RD_PX_CTR,  // COPY READ PIXEL collision counter from pixel_writer
   input logic [7:0] PAGET_FIFO, // pixel_address_generator FIFO flags   NO - NOT NEEDED
   input logic [7:0] GEOFF_FIFO, // geometry_xy_plotter FIFO flags       NO - NOT NEEDED
   input logic [7:0] GEO_STAT_RD,// bit 0 = scfifo's almost full flag, other bits free for other data


add 1 additional output:
   output logic GEO_RD_STAT_STROBE, // HIGH when sending reading data from the GEO_STAT_RD bus
rename:
   output logic GEO_WR_STAT_STROBE, // HIGH when sending data on GEO_STAT_WR bus

Let's see the simulation of a read and write port & what happens to the strobe signals and output data.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2020, 10:06:43 am
I'm looking at setting up the Z80_bridge code to send data to the FIFO currently, and can't see a way to do it without adding a third IO port to trigger the send.  Is that right?

You're treating the 16-bit bus between the Z80_bridge and the geo_xy_plotter's FIFO as two independent 8-bit buses?

Also, is there any reason I can't just merge GEO_WR_LO and GEO_WR_HI into one 16-bit bus with one strobe?  I can't see the advantage of being able to send one byte instead of one word, so I've probably missed something important.  :-//  (i.e. the Z80 could load the 16-bit register via two IO writes for the low and high byte, then write to the third port to send the 16-bit word to the geo_unit?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2020, 10:56:37 am
[attachimg=1]

Above image shows a simulation of the Z80_bridge as two bytes are written to GEOFF.  The IOs shown as the Z80 writes the low byte first, then the high byte, then triggers the two strobes to let the FIFO know new data is on the bus.

I'm holding off on going further in case I go too far down the wrong path (with the third IO, buffering the low/high byte until ready to send both etc).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2020, 12:43:21 pm
Where are the:

   output logic GEO_WR_LO_STROBE,// HIGH to write low byte to geo unit
   output logic GEO_WR_HI_STROBE,// HIGH to write high byte to geo unit

outputs?

They seem dead when you write GEO_LO_BYTE and write GEO_HI_BYTE....

Why are they pulsing when you send something to port 248?

You have 2 strobes to just get used to the fact that each IO port should have it's associated strobe.
Separate ones for each read and separate ones for each write.
For the geo write data, you will only be using one of them, the one associated with the second half of the 16bit word you will be sending.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2020, 03:23:10 pm
Where are the:

   output logic GEO_WR_LO_STROBE,// HIGH to write low byte to geo unit
   output logic GEO_WR_HI_STROBE,// HIGH to write high byte to geo unit

outputs?

They seem dead when you write GEO_LO_BYTE and write GEO_HI_BYTE....

Why are they pulsing when you send something to port 248?

You have 2 strobes to just get used to the fact that each IO port should have it's associated strobe.
Separate ones for each read and separate ones for each write.
For the geo write data, you will only be using one of them, the one associated with the second half of the 16bit word you will be sending.

They're there - I did explain previously that I was unsure how/when you wanted the GEO_LO_BYTE and GEO_HI_BYTE to be read by GEOFF's FIFO, so I thought a third IO port would be necessary to signal the FIFO that valid 16-bit data was available on the GEO_xx_BYTE bus(es).  Both strobes go high together when IO port 248 is written to.  If there's a better way to do it, I'm all ears..  :)

I'm looking at setting up the Z80_bridge code to send data to the FIFO currently, and can't see a way to do it without adding a third IO port to trigger the send.  Is that right?

Also, is there any reason I can't just merge GEO_WR_LO and GEO_WR_HI into one 16-bit bus with one strobe?  I can't see the advantage of being able to send one byte instead of one word, so I've probably missed something important.  :-//  (i.e. the Z80 could load the 16-bit register via two IO writes for the low and high byte, then write to the third port to send the 16-bit word to the geo_unit?)

As above, I questioned whether two strobes were necessary and the GEO_xx_BYTE buses can't just be treated as one 16-bit bus?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2020, 04:28:35 pm
Ok, write the low byte, then the low byte out is held in it's 'GEO_WR_LO'.
Now write the high byte, and the high byte is held in the 'GEO_WR_HI'.
Now, what happens if you had the 'GEO_WR_HI_STROBE' tied to the geometry plotter's input 'fifo_cmd_ready'?

So long as you always send the LO first and HI second, wont the HI's strobe tell the geometry unit's 'fifo_cmd_ready' to take the stored 'GEO_WR_LO' with the now new 'GEO_WR_HI' together at that point?

Well?

Maybe you prefer sending 16 bit words in Little-endian format.  If this case, you would wire the LO's strobe instead of the HI's strobe to the 'fifo_cmd_ready's input.  Then you must send the HI byte first, then the LO byte and when sending the LO byte, it's LO strobe would tell the 'fifo_cmd_ready's input to take both the previously sent 'GEO_WR_HI' with the new 'GEO_WR_LO'.
 
In either case, you are treating the final result as a 16 bit bus.  You just need to decide when copying memory from somewhere else in your Z80 ram, which direction the results are written into the LO and HI port and select which one of those strobes signify that the full 16bit value has been transmitted to both.  Unless, you have hidden a 16 bit data bus from me entering the Z80_bridge, how else has all 8bit MCUs/CPUs send out 16 bit wide registers.

The Z80 is a slow snail.  You must shave off every cycle possible and make the GPU take control data in the least amount of clock cycles.  Shaving off that silly third port writer action to take in data makes a ~35% speed improvement in sending data to the geometry unit.  And at around 1 million writes per second VS 0.75,  (4-8MHz clock port access cycle).  Take the speed improvement.

It might even be faster to change the ports to 2 bytes of memory access as the have a 3-8MHz clock cycle.  I'll leave the lessons learned here and you may choose to swap to a memory ram address in place of reading and writing to ports to drive the geometry unit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2020, 05:33:00 pm
You just need to decide when copying memory from somewhere else in your Z80 ram, which direction the results are written into the LO and HI port and select which one of those strobes signify that the full 16bit value has been transmitted to both.

Well, all the time I'm using I/O to get the data into the geometry unit, it's a fairly moot point as I can only send one byte at a time.  I'll go with little endian as that'll match up with my intended method of getting the data across via memory instead of IO later on.

It might even be faster to change the ports to 2 bytes of memory access.  I'll leave the lessons learned here and you may choose to swap to a memory ram address in place of reading and writing to ports to drive the GPU.

That's my intention - memory access will be a lot faster than IO access - but that's something I'll sort out later.

Here's the latest simulation with the third IO removed.  Will the strobes be okay or are they a little early for the GEO_WR_HI and _LO lines to stabilise?

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2020, 05:47:17 pm
Here's the latest simulation with the third IO removed.  Will the strobes be okay or are they a little early for the GEO_WR_HI and _LO lines to stabilise?
Try Zooming in to see.
There should be no stabilization time.  The moment the
out <= data_in ;

The data will be valid.
Now if you have:
out <= data_in ;
out_strobe <= 1 ;

Both become valid and acknowledgeable at the same time.
Remember, everything is tied to the 125MHz clock and it is all synchronous logic here inside the FPGA.
If it weren't so, ohhhh boy, everything we have written to date would completely fall apart and not function.

Your code looks fine.

Get on the pixel writer...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2020, 06:21:26 pm
One minor note:

Code: [Select]
   // **** Manage IO interface to GEOFF ****
   if ( z80_write_port_1s && Z80_addr_r[7:0]==GEO_LO ) begin     // Write to GEOFF low-byte register
      GEO_WR_LO     <= Z80_wData_r[7:0] ;
      GEO_WR_LO_STROBE <= 1'b1 ;                                 // Pulse both strobes HIGH to signal to FIFO new data on the bus
   end
   
   if ( z80_write_port_1s && Z80_addr_r[7:0]==GEO_HI ) begin     // Write to GEOFF high-byte register
      GEO_WR_HI     <= Z80_wData_r[7:0] ;
      GEO_WR_HI_STROBE <= 1'b1 ;
   end   
   // ***** End of GEOFFs IO interface *****
   
   // **** ONE-SHOTS ****
   if ( GEO_WR_HI_STROBE ) GEO_WR_HI_STROBE <= 1'b0 ; //
   if ( GEO_WR_LO_STROBE ) GEO_WR_LO_STROBE <= 1'b0 ; //
   // *******************

We prefer to write it as:

Code: [Select]
   // **** Manage IO interface to GEOFF ****
   if ( z80_write_port_1s && Z80_addr_r[7:0]==GEO_LO ) begin     // Write to GEOFF low-byte register
      GEO_WR_LO     <= Z80_wData_r[7:0] ;
      GEO_WR_LO_STROBE <= 1'b1 ;                                 // Pulse both strobes HIGH to signal to FIFO new data on the bus
   end else GEO_WR_LO_STROBE <= 1'b0 ;
   
   if ( z80_write_port_1s && Z80_addr_r[7:0]==GEO_HI ) begin     // Write to GEOFF high-byte register
      GEO_WR_HI     <= Z80_wData_r[7:0] ;
      GEO_WR_HI_STROBE <= 1'b1 ;
   end else GEO_WR_HI_STROBE <= 1'b0 ;
   // ***** End of GEOFFs IO interface *****
What's going on here is that if somehow, (I don't know how), but imagine somehow, if the xxx_STROBE = 1 and a write port to that same strobe comes in at the same time, you would simultaneously be setting the xxx_STROBE to a 1 and the 'one shots' below will be trying to set that xxx_STROBE to 0 at the same time.

Using the 'else' means the xxx_STROBE will be continuously cleared to 0 unless that port write happens where it would be set to a '1' for that port write cycle, then back to clearing the strobe under any other circumstance.

However, as you can see, your simulation still worked anyways.  You decide how you want to keep your code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2020, 07:10:17 pm
Using the 'else' means the xxx_STROBE will be continuously cleared to 0 unless that port write happens where it would be set to a '1' for that port write cycle, then back to clearing the strobe under any other circumstance.

However, as you can see, your simulation still worked anyways.  You decide how you want to keep your code.

No, I like how you've done it - much neater and, as you say, it removes the edge-case situation too.  :-+

Latest pixel_writer below for confirmation that I'm on the right track.  Not sure how to progress the case statement now - have included all the commands that could be sent from the pixel_writer (haven't added a default yet) but as far as what goes into each command statement, I'm going to need more of a steer.  The read process seems like it's manageable, I just need to latch the address and value and return that instead of performing a second read to the same address - a bit like a cache, but much, much smaller.  ;)

The write process, however, seems like it's going to need some sort of pipeline as it involves a read, then some calculation to address the target bit/s, then a write...  :o

I haven't created registers for the address, colour value, sub-pixel address and bpp to hold the data yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2020, 09:17:16 pm
So far so good on the pixel writer.
Step #1 hint, for always_comb (combinational logic section)

ram_addr = address input;

Yup, no clocked register delay.

Step #2, add a reset please.

Step #3, copy pixel function.  Since this is a read pixel ram only function, lets begin here as the pixel writer begins with the same logic with added functions.
a) Check if our copy pixel read cache has already read the same address and the read cache valid flag is set, if so, store the new read bits per pixel setting & latch the sub pixel bit position & color data.  Do nothing else.
b) If not, stop the fifo read command (shift_out) and send a 'rd_req_a' pulse and clear the read cache valid flag to 0.
c) once the 'rd_data_rdy_a' pulse comes in, latch the read data & latch the read address & latch the read bits per pixel setting & latch the sub pixel bit position & color data and set the read cache valid flag to 1.

Done. (for now, it's a start)

Let's see a simulation with a block of external 4096x16 alt_syncram function tied onto the top block diagram with dummy data.  (Just generate a 16 bit counting data with the .mif editor)  Also, pass the 2 rd_req_a/b, outputs through 2 clocked DFF back to the 2 rd_data_rdy_a/b simulating the read delay of the read cycle for the alt_syncram megafunction.

Don't forget to decompose the cmd_in bus to multiple inputs making it easy to edit in the .vwf an address, pixel bits, bit position, color and command function all separately.

Then we will be able to issue commands and watch the pixel writer in action with an authentic block of ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2020, 09:12:36 am
Step #3, copy pixel function.  Since this is a read pixel ram only function, lets begin here as the pixel writer begins with the same logic with added functions.
a) Check if our copy pixel read cache has already read the same address and the read cache valid flag is set, if so, store the new read bits per pixel setting & latch the sub pixel bit position & color data.  Do nothing else.
b) If not, stop the fifo read command (shift_out) and send a 'rd_req_a' pulse and clear the read cache valid flag to 0.
c) once the 'rd_data_rdy_a' pulse comes in, latch the read data & latch the read address & latch the read bits per pixel setting & latch the sub pixel bit position & color data and set the read cache valid flag to 1.

Okay, got as far as b) above before confusion set in. ::)

How am I getting data out of the FIFO?  Am I supposed to be checking each clock cycle if the pixel_writer is free, then strobing the FIFO's 'shift_out' line to get the next command?  I'm a little fuzzy on the details here.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2020, 01:02:39 pm
The if the 'pixel_cmd_rdy', you should be always be reading the fifo's shift_out, except when busy.  This should be a combination function to erase 1 clock cycle.

IE inside always_comb

load_next_cmd = pixel_cmd_rdy && !stop_fifo_read;

I know some things here appear to get ugly as we try to erase every wasted clock cycle as each read from ram takes 2+ clock cycles while a write takes only 1.  And you also need to do a read every time you write a pixel +1 processing clock cycle.  We are trying to get that down to 0 cycles and do just the processing and write in a single clock cycle.  Example, a copy pixel will take 2 clocks for the read, then write pixel will take another 2 to read it's mem posistion, then another 1 to edit the right bits within that 16 bit word & write the output.  Without cache, this means each copy bliter function of four 16 color pixels to 4 16 color pixels will take 2rc+2rw+1w,2rc+2rw+1w,2rc+2rw+1w,2rc+2rw+1w clocks for a total of 20 clocks.  (rc = read in pixel copy command, rw = read in pixel write command, w = write in pixel write data to ram) With a two read word caches, one for each read&write pixel command, here is the new clock count:  2rc+2rw+1w,1w,1w,1w for a total of 8 clocks.  Now when copying filled boxes 4 at least 4 pixels wide, 20:8 for 16 color graphics this is a 2.5 fold speed increase.  For filled triangles, boxes and ellipses, it is a 1.5x speed increase.  The speed increase is even greater with 2 bit color and 1 bit color graphics.  (For DDR ram, since that ram has a minimum fixed size read & write bursts (something like 4 or even 8 16 bit words with an additional setup delay of additional 8 clocks making 16 clocks for 1 access), these caches would need to increase to that width in bits and then you would want a write data cache which wont send out a write until it is filled a 4-8 word chunk as well since our wait with such memory transactions will be huge compared to the onchip static ram.)

Code: [Select]
cache_address           <= 20'b0 ;
cache_colour            <= 8'b0  ;
cache_bpp               <= 4'b0  ;
cache_target            <= 4'b0  ;

There are two read caches, one for the pixel copy and one for the pixel write which also needs to read ram data before generating a word to write back to ram.

You also need a cache_data_valid bit for each since after reset, this bit should be cleared.  Otherwise, after reset, if you read/write to address 0, without this extra bit, the cache contents will be assumed correct since it now has an address of 0.  (We will also have to add a 'stale' timer later on which automatically clears this flag if no reads happens within a set period of time since the geometry unit won't know if the Z80 manually edited the same memory word within each cache, so it should be re-read even if the same address was requested once again after doing nothing for something like 255 clock cycles.)

Yes it is possible to chain and shave off one clock cycle on the required read memory when doing back-back read/copy and write pixel commands, we will tackle that one if you are up to it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2020, 06:18:59 pm
Latest code attached.  I'm not sure what should be going in the CMD_IN_PXCOPY case if a valid address and cache hit is found. It seems it shouldn't be doing anything as the cache values will already have the necessary data in them already?  Shouldn't that data then be written out somewhere?

Sorry.  I've been away from this for about six hours and I've already lost my thread.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2020, 07:09:01 pm
Ok, you just about got it.

1) Always store a copy of all the pixel parameters like bits-pixel, bit position and color data.  Even if the cache address is a valid match (cache hit), the bits/pixel, sub-pixel location and color function may change within the same address.  IE reading the next adjacent pixel within the same memory address.

2) If the read address is different, then also store the cache copy of the new read address and wait for the 'rd_data_rdy_a' flag to come in.  Once it comes in, set the rd_cache_valid flag, latch the read ram data and clear the stop_fifo_read.

hmmmm, 'stop_fifo_read'.   I don't like that.  Let's change it to 'read_wait_a' and for the pixel writer we will make a 'read_wait_b' registers.  For the fifo control, we will use for the shift_out something like:

cmd_shift_out = ( (  !(read_wait_a && !rd_data_rdy_a) && !(read_wait_b && !rd_data_rdy_b) ) && pixel_cmd_rdy ) ;

The first 2 if set stop the fifo reading while the second optional two '!rd_data_rdy_a/b' will begin the fifo once again 1 clock early before the 'read_wait_a/b' get cleared by the 'rd_data_rdy_a/b'.  Reading the fifo will only begin if only if there is a new 'pixel_cmd_rdy'.

I just realized that if a rd_data_rdy_a/b never comes after a rd_req_a/b, EG something wrong with the command to the ram controller, the pixel write may stay frozen until a reset.  You will need to decide if we should include some sort of recovery timeout, out, you can just do this in the Z80 if the geometry plotter fifo fill up and never empties.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 04, 2020, 10:25:45 am
1) Always store a copy of all the pixel parameters like bits-pixel, bit position and color data.  Even if the cache address is a valid match (cache hit), the bits/pixel, sub-pixel location and color function may change within the same address.  IE reading the next adjacent pixel within the same memory address.

Okay, I've done this by setting the colour, bpp and target caches outside of the check for a cache miss, so they get set every time CMD_IN_PXCOPY is valid.

This is in the cache-miss conditional now, as I didn't want to overwrite the read colour data from RAM when the read completes, but I'm caching it in a different register now so it's not an issue.  Should work fine as it is, though?

2) If the read address is different, then also store the cache copy of the new read address and wait for the 'rd_data_rdy_a' flag to come in.  Once it comes in, set the rd_cache_valid flag, latch the read ram data and clear the stop_fifo_read.

Okay, if there's a cache miss I'm updating the cache address with the new one, setting rd_wait_a and rd_req_a and resetting rd_cache_valid.  I hope I'm using the right method to wait for the data to return, though:

Code: [Select]
end else if ( pixel_cmd_rdy & ~rd_wait_a & ~rd_wait_b ) begin
The above check should stop the case from executing if either rd_wait_a or _b are high.

Now I'm a little lost with what to do with the data that's been returned from RAM.  There's a clock delay whilst rd_wait_a is reset, cache_valid is set and the read data from RAM is cached.  Then CMD_IN_PXCOPY executes a second time, branching into the empty half of the IF..conditional to do something with the read data?  Is that right?  Seems like I'm using 2 clocks when you're going to tell me it can all be done in zero...  ???

I just realized that if a rd_data_rdy_a/b never comes after a rd_req_a/b, EG something wrong with the command to the ram controller, the pixel write may stay frozen until a reset.  You will need to decide if we should include some sort of recovery timeout, out, you can just do this in the Z80 if the geometry plotter fifo fill up and never empties.

I think a timeout will make it more robust?

EDIT: Seems there a problem with the HDL as it is - I'm getting these two errors:

Error (10200): Verilog HDL Conditional Statement error at geo_pixel_writer.sv(133): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct
Error (10200): Verilog HDL Conditional Statement error at geo_pixel_writer.sv(166): cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2020, 04:12:57 pm
Ok...

1) always_ff @( posedge clk or posedge reset or posedge collision_rd_rst or posedge collision_wr_rst ) begin

This means that all the flipflops inside will have 4 clock edge sources.  Wont that slow down/delay all these flipflops with so many edge conditions?

What's wrong with this?
always_ff @( posedge clk) begin

2) These guys:
Code: [Select]
    if ( collision_rd_rst ) rd_px_collision_counter <= 8'b0 ;   // reset the COPY/READ PIXEL COLLISION counter
    if ( collision_wr_rst ) wr_px_collision_counter <= 8'b0 ;   // reset the WRITE PIXEL COLLISION counter
   
    if ( rd_data_rdy_a ) begin  // valid data from RAM

rd_cache_valid <= 1'b1 ;
rd_wait_a      <= 1'b0 ;
rd_data_cache  <= rd_data_in ;

end
Why do they have higher priority than the system reset line?
And if the reset is set, and a 'rd_data_rdy_a' comes in at the same time, wont 'rd_cache_valid' be assigned a 1 and 0 simultaneously?
Shouldn't these be set after the else of 'reset'?

3)    end else if ( pixel_cmd_rdy & !rd_wait_a & !rd_wait_b ) begin
Wouldn't it be better to write this like this?
       end else begin
Now, you may have functions after the reset which may run both during the 'exec_cmd' and also separately during the '!exec_cmd' while the system waits for a response.

4) if ( pixel_cmd_rdy & !rd_wait_a & !rd_wait_b )
Single '&' instead of '&&'.  If I were you, just change it to:
    if ( exec_cmd )

5) I said to assign these 3:
Code: [Select]
rd_cache_col   <= colour   ;
rd_cache_bpp   <= bpp      ;
rd_cache_bit   <= target   ;

Whether of not there is a cache hit, so why are they inside the if:
Code: [Select]
                if ( !rd_cache_valid | !rd_addr_valid ) begin  // check for cache miss on read address
Also you use | instead or ||.

Now, there is also a new 'end else begin' at the bottom since we want some actions during the '!exec_cmd', like maybe the:
Code: [Select]
    if ( rd_data_rdy_a ) begin  // valid data from RAM

rd_cache_valid <= 1'b1 ;
rd_wait_a      <= 1'b0 ;
rd_data_cache  <= rd_data_in ;

end

Give this a try.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 04, 2020, 04:34:54 pm
Darn typos. :palm:

Compiling fine now.  As for the triggers in the always_ff @(), I forgot to remove those when I was trying to find the source of the compile errors. D'oh.

All makes a bit more sense now.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2020, 04:50:03 pm
Again:

   if ( !rd_cache_valid || !rd_addr_valid ) begin  // check for cache miss on read address
   
      rd_cache_col   <= colour   ;
      rd_cache_bpp   <= bpp      ;
      rd_cache_bit   <= target   ;
      rd_cache_addr  <= ram_addr ; // cache new address
      rd_wait_a      <= 1'b1     ; // hold everything while we wait for data from RAM
      rd_req_a       <= 1'b1     ; // send 'rd_req_a' pulse
      rd_cache_valid <= 1'b0     ; // clear cache valid flag in case it wasn't already cleared
   
   end else begin

The guys in red are always set on a 'CMD_IN_PXCOPY', whether there is a cache hit or miss.
The guy in purple should only be set once the new data read is valid, however, the system as a whole should still be functional where you have it right now.  This one you can leave where it is.

Now, show me a complete simulation of multiple pixel reads.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 04, 2020, 07:17:33 pm
I'm at the end of my time today - I'm not likely to get anything done tomorrow as I'm in meetings all day.  ::)

Here's the current test setup for pixel_writer.  I've set up the schematic as best I can, but I've missed something obvious somewhere as the simulation isn't running properly (no data is returned from RAM). I'll maybe have some time tomorrow evening to take a look at what's up.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2020, 10:05:16 pm
Well, it seems to simulate for me.
Though, as you can see, I decomposed your command input so I can read what command I'm sending:

[attachimg=1]

Now, when simulating, as you can see, the read_req_a is sent out, but, it stays on indefinitely and has a delay:

[attachimg=2]

Now, as you can see, I've added output pins to tap the memory and read rdy flags.

In the attached .zip, I've also added the 'SDC1.sdc' file to tell Quartus that we need the design to at least function at 125MHz so the timing report will be accurate instead of all red.

In the simulation, I've changed your clock to 100MHz exact so it is easy to read and edit the stimulus inputs.

Your next task is to fix the logic of the 'read_req_a' so it has 0 delay and stays on only for 1 clock.

Oh, BTW, did I ever say we needed a 'next_cmd' output?  I don't remember.
Get rid of it unless for now you tie it to 'exec_cmd' just to see what it's doing.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2020, 03:47:15 pm
Is this what you're after?

[attachimg=1]

I suspect I'll need to add a few more constraints to the rd_req_a signal, some of the pixel commands won't require a read before every write in every screen mode, surely?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2020, 04:24:40 pm
Ok, it's a start but this is your :

 rd_req_a       = exec_cmd && !last_exec_cmd  ;

What if there are 2 sequential reads?
What if the command is not a 'CMD_IN_PXCOPY'?
What if there is a valid cache hit?  (IE, no read req should be sent, the stored data should just be used)
What if we are in a reset state?

You need a few additional conditions on that line, then it should work.

    rd_cache_hit  = ( ram_addr == rd_cache_addr ) && rd_cache_valid ;
    wr_cache_hit  = ( ram_addr == wr_cache_addr ) && wr_cache_valid ;
    rd_req_a       = exec_cmd && !rd_cache_hit && (pixel_cmd[3:0] == CMD_IN_PXCOPY) && !reset;

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2020, 05:10:06 pm
What if there are 2 sequential reads?

No idea. :-//

What if the command is not a 'CMD_IN_PXCOPY'?

See my previous comment:

I suspect I'll need to add a few more constraints to the rd_req_a signal, some of the pixel commands won't require a read before every write in every screen mode, surely?

I can't see why any of the pixel writes or copies wouldn't require a read before a write, unless we're operating in 16-bit colour mode when the entire 16-bit word would just be overwritten by the new word (but even then, only unless it's not writing in mask mode).

The NOP, RST (and SETARGB?) commands won't need a read either.  What's the neatest way to include those conditions in the assignment, though?  It's going to be a long line of AND's otherwise.  I guess I could create another signal that goes high if the command is one of those that don't need a read...

    rd_cache_hit  = ( ram_addr == rd_cache_addr ) && rd_cache_valid ;
    wr_cache_hit  = ( ram_addr == wr_cache_addr ) && wr_cache_valid ;
    rd_req_a       = exec_cmd && !rd_cache_hit && (pixel_cmd[3:0] == CMD_IN_PXCOPY) && !reset;

Ah - you hid the extra bit above and I didn't see it until I was writing my reply.  My question still stands, though - surely there's more commands that would need a read before write other than PXCOPY?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2020, 05:37:16 pm
Go ahead and try this: (I'm sorry, but you must engineer this an inch at a time.  Getting 1 thing wrong means things going awry and you'll be in debugging nightmare and never get it to work right without creating code which generated numerous consistent wasted clock cycles slowing everything down by more than 50%.)

[attachimg=1]

If your cache works, the second read command will do nothing.
Add another read at a new address and it should activate another read_req.

Now, there is 1 other thing the read command needs to do, generate a 16bit color pixel value which an adjacent potential 'CMD_IN_PXPASTE' / 'CMD_IN_PXPASTE_M' command will need to use to draw the copied color.

For now, make an output 'PX_COPY_COLOR[15:0]' and then you will need to engineer the necessary function to create that register.

Now, that function will need to operate in 2 ways, if there is a cache hit, it's source will be taken from the 'rd_data_cache' and computed immediately.  If there isn't a cache hit, the function will need to wait until the 'rd_data_rdy_a' comes in and it will generate the 'PX_COPY_COLOR' from the 'rd_data_in' instead since you would be wasting an additional clock cycle for the 'rd_data_cache' to update before you could compute the result.

Let's see how you solve this one...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2020, 05:49:10 pm
Now, when I say 'Function', yes, I mean add another separate module inside the pixel_writer since you will be using this logic twice, once for the read/copy, and once again for all the different pixel write/paste commands.

Give the function a name like this:  bitplane_memory_data_to_pixel_color

It will be all combinational logic, no clocks, no reset, just a raw funct with a bunch of inputs and one 16 bit color output.

Inputs Hint:
ram_data_rdy
latched_color
latched_bpp
latched_target
immediate_color
immediate_bpp
immediate_target

Output:
pixel_color


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2020, 05:55:39 pm
Ah - you hid the extra bit above and I didn't see it until I was writing my reply.  My question still stands, though - surely there's more commands that would need a read before write other than PXCOPY?
No, not really.  Usually after a PXCOPY, a pixel paste/paste_m command would be next.
But were aren't there yet.  First finish the PXCOPY.

And I hid that extra red bit since your were supposed to figure that one out on your own, the:
&& (pixel_cmd[3:0] == CMD_IN_PXCOPY) && !reset;
Portion which would prevent the 'read_req_a' if the incoming command wasn't a PXCOPY or during a reset.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 09:51:21 am
Go ahead and try this: (I'm sorry, but you must engineer this an inch at a time.  Getting 1 thing wrong means things going awry and you'll be in debugging nightmare and never get it to work right without creating code which generated numerous consistent wasted clock cycles slowing everything down by more than 50%.)

If your cache works, the second read command will do nothing.
Add another read at a new address and it should activate another read_req.

How's this?

[attachimg=2]

Now, there is 1 other thing the read command needs to do, generate a 16bit color pixel value which an adjacent potential 'CMD_IN_PXPASTE' / 'CMD_IN_PXPASTE_M' command will need to use to draw the copied color.

For now, make an output 'PX_COPY_COLOR[15:0]' and then you will need to engineer the necessary function to create that register.

Now, that function will need to operate in 2 ways, if there is a cache hit, it's source will be taken from the 'rd_data_cache' and computed immediately.  If there isn't a cache hit, the function will need to wait until the 'rd_data_rdy_a' comes in and it will generate the 'PX_COPY_COLOR' from the 'rd_data_in' instead since you would be wasting an additional clock cycle for the 'rd_data_cache' to update before you could compute the result.

Let's see how you solve this one...

Working on this now...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2020, 10:10:19 am
 :clap:
So far so good!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 10:22:44 am
Quick question - do I need to get rd_cache_valid set at the same time as rd_data_rdy_a goes high (instead of currently a clock later when it goes low again)?  Will need another wire and an AND gate if I do, I think.

Actually no, looks like it's better as it is as I can use the immediate values to return a colour from the bitplane_memory_data_to_pixel_colour module all the time rd_data_rdy_a is high, and the latched values when rd_cache_valid is high, and nothing at any other time?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 11:18:58 am
Preliminary files attached for the new module (it's name is too long to keep writing :-DD) and its instantiation in the pixel_writer module.

I've tweaked the name of a couple of the inputs to the new module - instead of latched_colour and immediate_colour, I've called them latched_word and immediate_word as I feel it's more descriptive.

Right, so now I've got to come up with some combinational logic to return the word/byte/nybble/crumb/bit from the supplied word, based on the bpp value.

The returned value will have to be 16 bits wide to accommodate returning whole words in true colour mode, for example.

Will go away and have a think about this for a bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 01:39:59 pm
Okay, is this along the right lines?

Code: [Select]
pixel_colour = ( ram_data_rdy ) ? immediate_word[( 15 - immediate_target ) : ( ( 15 - immediate_target ) - immediate_bpp )] : latched_word[( 15 - latched_target ) :( ( 15 - latched_target ) - latched_bpp )] ;

Assuming I'm on the right lines, the only issue with the above code that I'm aware of is the bit-width of the resultant value - pixel_colour is a 16-bit output and I'd need to pad the computed value with zeroes somehow, unless I'm completely off the table and into someone's pint of beer.

EDIT: Appears I'm in the beer.  Having real trouble making the code above work without errors - looks like Verilog doesn't like having non-constants on either side of the : when selecting a bit range...  :-\

Simplified the above code to this (assuming I understand the -: properly):

Code: [Select]
pixel_colour = ( ram_data_rdy ) ? immediate_word[ immediate_target -: immediate_bpp ] : latched_word[ latched_target -: latched_bpp ] ;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2020, 04:41:57 pm
I could not download your 'geo_pixel_writer.sv.txt '.  It said 'Atachment Not Found'.
However you have done it, perhaps in this case, maybe you should use 2 dimensional IF statements.
IE

IF (bpp[3:0]==BPP_16bit) begin

end else IF (bpp[3:0]==BPP_8bit) begin

end else IF (bpp[3:0]==BPP_4bit) begin

end else IF (bpp[3:0]==BPP_2bit) begin

end else IF (bpp[3:0]==BPP_1bit) begin

end

Inside each one IF (bpp[3:0]), make another IF (target[ x:x ] == ##) begin end else if (target[ x:x ] == ##)... exc ...
Remember, you pay attention to different x:x bits depending on the bpp size.

Also, when generating the color output, we want to multiply the colour[] input with the isolated pixel value so we shift the 1 bpp color pixel value to a selected new screen color if the output screen has 8bpp.

Take a look at 'bitplane_to_raster.v' in your main project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2020, 04:48:39 pm
Also, you are allowed to have multiple modules defined inside one xxxx.sv file.  This module could have been placed inside the 'geo_pixel_writer.sv' just after the line 'endmodule'.

In fact, for the geometry unit, we were going to place all the 'xxxx.sv' together into a single 'geometry_processor.sv' so you have a single complete module to interface with in Quartus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2020, 05:10:11 pm
Okay, is this along the right lines?

Code: [Select]
pixel_colour = ( ram_data_rdy ) ? immediate_word[( 15 - immediate_target ) : ( ( 15 - immediate_target ) - immediate_bpp )] : latched_word[( 15 - latched_target ) :( ( 15 - latched_target ) - latched_bpp )] ;

Assuming I'm on the right lines, the only issue with the above code that I'm aware of is the bit-width of the resultant value - pixel_colour is a 16-bit output and I'd need to pad the computed value with zeroes somehow, unless I'm completely off the table and into someone's pint of beer.

EDIT: Appears I'm in the beer.  Having real trouble making the code above work without errors - looks like Verilog doesn't like having non-constants on either side of the : when selecting a bit range...  :-\

Simplified the above code to this (assuming I understand the -: properly):

Code: [Select]
pixel_colour = ( ram_data_rdy ) ? immediate_word[ immediate_target -: immediate_bpp ] : latched_word[ latched_target -: latched_bpp ] ;
Ok, you are attacking the problem again in a different way than what I was expecting.

You are correct that depending on the (ram_data_rdy), there is a selection of which source data becomes relevant.  :-+

However, depending if you have already noticed, there is a little trick inside here.  We will see what happens when you simulate and output the read pixel color.

Ok, now, look at my 'IF' code above, since I want the code to look like that which narrows down the window and ignores erroneous bpp settings, you will need some intermediate variables from the above 'muxs' to feed this section to generate the 'read pixel color' output.


Your graphic in this above post https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3176276/#msg3176276 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3176276/#msg3176276) is now corrupt.  Re-uplodd it if you still have it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 05:49:45 pm
Have re-uploaded the graphic you said was corrupted.  Should be working now.

Also re-uploading my most recent geo_pixel_writer and bitplane_memory_data_to_pixel_colour modules.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 05:53:24 pm
Also, you are allowed to have multiple modules defined inside one xxxx.sv file.  This module could have been placed inside the 'geo_pixel_writer.sv' just after the line 'endmodule'.

In fact, for the geometry unit, we were going to place all the 'xxxx.sv' together into a single 'geometry_processor.sv' so you have a single complete module to interface with in Quartus.

Aha, yes, I was getting a little trigger-happy with the new modules.  ;)  Have moved it into geo_pixel_writer.sv module now.  :-+

EDIT: Seems the forum is hiccuping and not allowing uploads... here's the latest code from my pixel_writer module:

Code: [Select]
module bitplane_memory_data_to_pixel_colour (

// *** INPUTS
    input logic         ram_data_rdy,
    input logic  [15:0] latched_word,
    input logic  [3:0]  latched_bpp,
    input logic  [3:0]  latched_target,
    input logic  [15:0] immediate_word,
    input logic  [3:0]  immediate_bpp,
    input logic  [3:0]  immediate_target,

// *** OUTPUTS
    output logic [15:0] pixel_colour
   
);

// these params are not final - I've just thrown them together for testing
localparam BPP_16bit = 4'b1000;
localparam BPP_8bit  = 4'b0100;
localparam BPP_4bit  = 4'b0010;
localparam BPP_2bit  = 4'b0001;
localparam BPP_1bit  = 4'b0000;

logic [3:0]  source_bpp    ;
logic [3:0]  source_target ;
logic [15:0] source_word   ;

always_comb begin

    // output colour from latched values all the time ram_data_rdy is low
    // otherwise output colour from immediate values
   
    //pixel_colour = ( ram_data_rdy ) ? immediate_word[ immediate_target -: immediate_bpp ] : latched_word[ latched_target -: latched_bpp ] ;
   
    // set source data according to RAM read
    source_bpp    = ( ram_data_rdy ) ? immediate_bpp    : latched_bpp    ;
    source_target = ( ram_data_rdy ) ? immediate_target : latched_target ;
    source_word   = ( ram_data_rdy ) ? immediate_word   : latched_word   ;
   
    if ( source_bpp[3:0] == BPP_16bit ) begin
   
        if ( source_target[3:0] == 1'b0 ) begin
       
            pixel_colour = source_word ;
       
        end

    end else if ( source_bpp[3:0] == BPP_8bit ) begin
   
        if ( source_target[3:0] == 0 ) begin
       
            pixel_colour = source_word[15:8] ;
       
        end else if ( source_target[3:0] == 1 ) begin
       
            pixel_colour = source_word[7:0]  ;
       
        end

    end else if ( source_bpp[3:0] == BPP_4bit ) begin

    end else if ( source_bpp[3:0] == BPP_2bit ) begin

    end else if ( source_bpp[3:0] == BPP_1bit ) begin

    end
   
end

endmodule

However, this doesn't compile.  I'm getting the following error:

Error (10166): SystemVerilog RTL Coding error at geo_pixel_writer.sv(312): always_comb construct does not infer purely combinational logic
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 06:45:19 pm
Latest pixel_writer.  Hopefully the colour module is progressing along the right lines.  I'm not sure I completely understand what you're after here:

Also, when generating the color output, we want to multiply the colour[] input with the isolated pixel value so we shift the 1 bpp color pixel value to a selected new screen color if the output screen has 8bpp.

Take a look at 'bitplane_to_raster.v' in your main project.

Had a look at bitplane_to_raster, but unless you smack me in the mouth with it, it's not springing out at me.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2020, 06:56:35 pm
Ok, change the 'always_comb' to 'always'.  I believe system verilog is expecting an 'always_ff' so that it can latch something from the 'always_comb' structure.

Also:
Code: [Select]
        if ( source_target[3:0] == 0 ) begin
       
            pixel_colour = source_word[15:8] ;
       
        end else if ( source_target[3:0] == 1 ) begin
       
            pixel_colour = source_word[7:0]  ;
       
        end
You need to assign the unused 'pixel_colour' bits to a definite value to get rid of the warnings galore..

Also, what happened to the source:
rd_cache_col   <= colour   ;

IE, inputs:
latched_colour.
&
immediate_colour.

These inputs, now muxed to 'source_colour' should be multiplied with the 'source_word' when lower than 16 bit color.  In 16 bit color, we may change this one case so that the 'source_colour' may be a brightness or contrast setting instead of simple multiply.

Also, in the pixel_writer module, the 'PX_COPY_COLOUR' output will be latched by a clock before it feeds an output pin, however, for now, keep it as is for simulating.

Next, add the other bitplanes and correct your current code as the target is wrong and you need to define the missing bits of pixel colour & perform that multiply.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2020, 07:24:42 pm
Ok, change the 'always_comb' to 'always'.  I believe system verilog is expecting an 'always_ff' so that it can latch something from the 'always_comb' structure.

Also:
Code: [Select]
        if ( source_target[3:0] == 0 ) begin
       
            pixel_colour = source_word[15:8] ;
       
        end else if ( source_target[3:0] == 1 ) begin
       
            pixel_colour = source_word[7:0]  ;
       
        end
You need to assign the unused 'pixel_colour' bits to a definite value to get rid of the warnings galore..

Yes, I found out what the problem was - every outcome of the IF conditional needs to drive pixel_colour to a value.  It's working now as an 'always_comb'.

Also, what happened to the source:
rd_cache_col   <= colour   ;

IE, inputs:
latched_colour.
&
immediate_colour.

These inputs, now muxed to 'source_colour' should be multiplied with the 'source_word' when lower than 16 bit color.  In 16 bit color, we may change this one case so that the 'source_colour' may be a brightness or contrast setting instead of simple multiply.

Ah.  That stemmed out of confusion about what they were for.  I did ask about this in a previous post - I had reworded then to latched_word and immediate_word instead, but thinking about it, we won't be passing a word into the function, we're just reading, so I'll rename them back and hope it doesn't confuse things too much.

We're still going to need a 16-bit input into the function for it to extract the pixel data from, though, so instead of 'renaming it back', I'll just add in the latched_ and immediate_ colour inputs, if that's right?

Where does the colour value come from the read RAM?  I'll be caching the 16-bit word that's read from RAM, not any particular colour value?

Next, add the other bitplanes and correct your current code as the target is wrong and you need to define the missing bits of pixel colour & perform that multiply.

The target's wrong? How so?

As for the colour - I'm still not sure about this multiplication?  Why are we changing the read data for a copy pixel operation?  Are you saying that I should just literally multiply the source_word by the source_colour?  ??? ??? ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2020, 07:36:45 pm
Arrrrrrrrggggg...
Look at the command structure in the pixel_writer.sv
Is there not a colour value sent with every command?

Look at the simulation stimuli, is there not a cmd_color[7:0] input?

This is not the memory pixel which was read, it's the color setting provided in the cmd_color[7:0] function.

Tell me, if you are copying a 1 bit B&W color source bitmap memory onto a 256 color screen, with nothing but a dumb copy, your output will always be 0 & 1 on a 0-255 on the destination screen.  Don't you want some sort of flexibility on the output color here?

Also take a look at the address generator output here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3165360/#msg3165360 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3165360/#msg3165360)

 and redo the sim with some different bitplane figures so you may correct all your 'if ( source_target[3:0] == 0 ) begin' mistakes.

HINT: Read the output pixel coordinates and read the generated address and generated target#.  You will see that all the targets bits don't always matter and they are upside-down...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 07, 2020, 10:20:12 am
Arrrrrrrrggggg...

I get that a lot. :-[

Also take a look at the address generator output here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3165360/#msg3165360 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3165360/#msg3165360)

 and redo the sim with some different bitplane figures so you may correct all your 'if ( source_target[3:0] == 0 ) begin' mistakes.

HINT: Read the output pixel coordinates and read the generated address and generated target#.  You will see that all the targets bits don't always matter and they are upside-down...

Been busy here, it's hot as well which isn't all that helpful, but I've got the following simulation output:

[attachimg=1]

The PX_COPY_COLOUR output appears to be delayed by a clock - but I guess that's because I'm using the output pin which is a register output from the pixel_writer module.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 07, 2020, 02:22:58 pm
Funny, my version has 0 delay, see here:

[attachimg=1]

As you can see, the with the red cache miss, the same cycle the rd_data_ready comes in, the PX_COPY_COLOUR data has the right word.  During the green cache hit, the PX_COPY_COLOUR has the new correct colour value immediately during the same clock.

First few little issues, please stop using binary when we assigned numerical values to our parameters like bpp:
Code: [Select]
// these params are not final - I've just thrown them together for testing
localparam BPP_16bit = 4'd15;
localparam BPP_8bit  = 4'd7;
localparam BPP_4bit  = 4'd3;
localparam BPP_2bit  = 4'd1;
localparam BPP_1bit  = 4'd0;
Your binary figures were all wrong.

Also, this looks a little backwards:
Code: [Select]
    end else begin // assume BPP_1bit
   
pixel_colour = source_word[ ( source_target[3:0] ) ] ;  // only need to return 1 bit
   
    end

Now, you first need to figure out why your 'PX_COPY_COLOUR' seems to have a delay.  I did warn/give you a hint a few posts back with the latched and immediate.  Copy my simulation stimuli to help.

Once that works, you will need to add to you simulation stimuli the following to uncover another bug.  First only add the part I have in green an check for bugs.  There will be one.  Once fixed, add in the yellow then simulate for a full run.

[attachimg=2]

I hope this teaches you that you need to work and simulate in tiny bits with FPGA code unless you are an expert.  The code you are engineering has to perform exactly otherwise the results will be all out of place and crap.  The memory bitplane color decoder will also be used by the all the pixel writer commands so it may read a pixel and edit just the correct color bits and then write that back to the same ram address.

Once your sim is done, we will add the 'cmd_color' feature to the copy pixel command.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 08, 2020, 10:23:32 am
Now, you first need to figure out why your 'PX_COPY_COLOUR' seems to have a delay.  I did warn/give you a hint a few posts back with the latched and immediate.  Copy my simulation stimuli to help.

Ok, change the 'always_comb' to 'always'.  I believe system verilog is expecting an 'always_ff' so that it can latch something from the 'always_comb' structure.

Also, in the pixel_writer module, the 'PX_COPY_COLOUR' output will be latched by a clock before it feeds an output pin, however, for now, keep it as is for simulating.

I don't see where it could be latched now?  I've specified wires for the PX_COPY_COLOUR output, so that clock delay should be removed?

Nope - I've spent an hour combing the code to find out what's causing this delay, have specified wires instead of logic, always instead of always_comb, I'm clearly missing something obvious and now my frustration is blinding me to the possible cause.   :( :( :( |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 08, 2020, 02:34:48 pm
That delay has nothing to do with the 'always_comb'.  That part you have correct.

Think carefully, what's available when either you are using data coming from the ram, or data that is in the cached byte...  When is each usable byte coming from each point valid under each circumstance?

Code: [Select]
    // set source data according to RAM read
    source_bpp    = ( ram_data_rdy ) ? immediate_bpp    : latched_bpp    ;
    source_colour = ( ram_data_rdy ) ? immediate_colour : latched_colour ;
    source_target = ( ram_data_rdy ) ? immediate_target : latched_target ;
    source_word   = ( ram_data_rdy ) ? immediate_word   : latched_word   ;

Make sure your simulation stimuli matches mine in my previous post as well.  Maybe you are seeing confusing results.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 08, 2020, 03:41:40 pm
Think carefully, what's available when either you are using data coming from the ram, or data that is in the cached byte...  When is each usable byte coming from each point valid under each circumstance?

Well, rd_data_rdy_a is either HIGH or LOW.  If it's low, we should be using the latched values, if it's high we use the immediate values.  The immediate values are all piped into the function using wires, so I can't see any delay there?  I'm looking at immediate values being the issue currently, so am not overly concerned with the latched values yet.

Make sure your simulation stimuli matches mine in my previous post as well.  Maybe you are seeing confusing results.

It matches yours - except your PX_COPY_COLOUR seems to be labelled PC_COPY_COL...   :-//

Dealing with a family bereavement now (of the pet variety) so I won't be back for a while.  :'(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 08, 2020, 04:09:42 pm
Well, rd_data_rdy_a is either HIGH or LOW.  If it's low, we should be using the latched values, if it's high we use the immediate values.  The immediate values are all piped into the function using wires, so I can't see any delay there?  I'm looking at immediate values being the issue currently, so am not overly concerned with the latched values yet.

Ok, I need you to think this through like your life depended on it...

If we are not using the 'rd_data_rdy_a', meaning that the command has immediately come in from the cmd and the memory data source is coming from the latched value, what should be your selection here?

Now, if we are getting the data from the 'rd_data_rdy_a', meaning that the cmd was sent earlier, hence the original cmd controls were sent and lost to the next cmd ones, but now, the source memory data is available at this point in time immediately.  How will your selection switches look in this setup?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 09, 2020, 11:08:02 am
If we are not using the 'rd_data_rdy_a', meaning that the command has immediately come in from the cmd and the memory data source is coming from the latched value, what should be your selection here?

Now, if we are getting the data from the 'rd_data_rdy_a', meaning that the cmd was sent earlier, hence the original cmd controls were sent and lost to the next cmd ones, but now, the source memory data is available at this point in time immediately.  How will your selection switches look in this setup?

Ah daaang...  |O  :palm:

The other cmd settings - colour, bits_per_pixel, width - are all lost when the cmd clears after the first clock.  If the module is checking the same address as previously, the cached settings are used, but if it has to read RAM and wait for the result, it uses the 'immediate' values when the RAM comes back with data.  Problem is, the colour, bits_per_pixel and width settings are all lost by this point so the PX_COPY_COLOUR is garbage.

I've switched the 'immediate' data feeds to using the cached settings instead of the 'immediate' (invalid) ones and am getting this simulation output:

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 09, 2020, 03:05:06 pm
What did you do?
Your simulation is still wrong.
It doesn't look anything like mine.

Why did you change these?  These were correct originally:

Code: [Select]
    .latched_word     ( rd_data_cache[15:0] ), // 16-bit word from the catch
    .latched_colour   ( rd_cache_col[7:0]   ), // 8-bit cached colour value
    .latched_bpp      ( rd_cache_bpp[3:0]   ), // cached bits-per-pixel value
    .latched_target   ( rd_cache_bit[3:0]   ), // cached target word/byte/nybble/crumb/bit
   
    .immediate_word   ( rd_data_in[15:0]    ), // 16-bit word from GPU RAM
    .immediate_colour ( rd_cache_col[7:0]   ), // current colour value
    .immediate_bpp    ( rd_cache_bpp[3:0]   ), // current bits-per-pixel value
    .immediate_target ( rd_cache_bit[3:0]   ), // current target word/byte/nybble/crumb/bit

You just made things 10x worse for you.
Why did you not concentrate on my words and this block?:
Code: [Select]
    // set source data according to RAM read
    source_bpp    = ( ram_data_rdy ) ? immediate_bpp    : latched_bpp    ;
    source_colour = ( ram_data_rdy ) ? immediate_colour : latched_colour ;
    source_target = ( ram_data_rdy ) ? immediate_target : latched_target ;
    source_word   = ( ram_data_rdy ) ? immediate_word   : latched_word   ;

     Maybe think of why I called these 'LATCHED' and 'IMMEDIATE'.  Think of what you wrote in your own post above.  Every single clue is there for you to solve.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 09, 2020, 10:20:26 pm
What did you do?

I changed this:

Code: [Select]
bitplane_memory_data_to_pixel_colour get_pixel_colour_1 (
    .ram_data_rdy     ( rd_data_rdy_a       ), // use immediate values when HIGH, latched values when LOW
   
    .latched_word     ( rd_data_cache[15:0] ), // 16-bit word from the catch
    .latched_colour   ( rd_cache_col[7:0]   ), // 8-bit cached colour value
    .latched_bpp      ( rd_cache_bpp[3:0]   ), // cached bits-per-pixel value
    .latched_target   ( rd_cache_bit[3:0]   ), // cached target word/byte/nybble/crumb/bit
   
    .immediate_word   ( rd_data_in[15:0]    ), // 16-bit word from GPU RAM
    .immediate_colour ( colour[7:0]         ), // current colour value
    .immediate_bpp    ( bpp[3:0]            ), // current bits-per-pixel value
    .immediate_target ( target[3:0]         ), // current target word/byte/nybble/crumb/bit
   
    .pixel_colour     ( PX_COPY_COLOUR )       // current pixel colour value from above parameters
);

... to this:

Code: [Select]
bitplane_memory_data_to_pixel_colour get_pixel_colour_1 (
    .ram_data_rdy     ( rd_data_rdy_a       ), // use immediate values when HIGH, latched values when LOW
   
    .latched_word     ( rd_data_cache[15:0] ), // 16-bit word from the catch
    .latched_colour   ( rd_cache_col[7:0]   ), // 8-bit cached colour value
    .latched_bpp      ( rd_cache_bpp[3:0]   ), // cached bits-per-pixel value
    .latched_target   ( rd_cache_bit[3:0]   ), // cached target word/byte/nybble/crumb/bit
   
    .immediate_word   ( rd_data_in[15:0]    ), // 16-bit word from GPU RAM
    .immediate_colour ( rd_cache_col[7:0]         ), // current colour value
    .immediate_bpp    ( rd_cache_bpp[3:0]            ), // current bits-per-pixel value
    .immediate_target ( rd_cache_bit[3:0]         ), // current target word/byte/nybble/crumb/bit
   
    .pixel_colour     ( PX_COPY_COLOUR )       // current pixel colour value from above parameters
);

... for the reasons outlined in my post.  I haven't had a lot of time this weekend to spend on this and I feel like I've been fumbling for solutions and going round in circles, wasting time. :scared:

Your simulation is still wrong.
It doesn't look anything like mine.

Yep, I realise that now that I've compared the two.  Back when I ran the simulation earlier today I saw the delay had gone and thought, "Eureka!"  Clearly it was premature and I should have waited to check the results in more detail, but I didn't have time.

Why did you change these?  These were correct originally:

Code: [Select]
    .latched_word     ( rd_data_cache[15:0] ), // 16-bit word from the catch
    .latched_colour   ( rd_cache_col[7:0]   ), // 8-bit cached colour value
    .latched_bpp      ( rd_cache_bpp[3:0]   ), // cached bits-per-pixel value
    .latched_target   ( rd_cache_bit[3:0]   ), // cached target word/byte/nybble/crumb/bit
   
    .immediate_word   ( rd_data_in[15:0]    ), // 16-bit word from GPU RAM
    .immediate_colour ( rd_cache_col[7:0]   ), // current colour value
    .immediate_bpp    ( rd_cache_bpp[3:0]   ), // current bits-per-pixel value
    .immediate_target ( rd_cache_bit[3:0]   ), // current target word/byte/nybble/crumb/bit

You just made things 10x worse for you.

I think I explained "why" pretty well in my previous post? ???  I clearly don't understand enough about the hardware or HDL subtleties to be able to see the problem.  How long have you worked with this stuff?  You must be qualified and have gone to university and studied EE or something similar, not to mention however many years working in the industry?  I obviously don't have that training or experience (other than what you've been patient enough to teach me).  :(

Why did you not concentrate on my words and this block?:
Code: [Select]
    // set source data according to RAM read
    source_bpp    = ( ram_data_rdy ) ? immediate_bpp    : latched_bpp    ;
    source_colour = ( ram_data_rdy ) ? immediate_colour : latched_colour ;
    source_target = ( ram_data_rdy ) ? immediate_target : latched_target ;
    source_word   = ( ram_data_rdy ) ? immediate_word   : latched_word   ;

     Maybe think of why I called these 'LATCHED' and 'IMMEDIATE'.  Think of what you wrote in your own post above.  Every single clue is there for you to solve.

Well that block - to me - is a closed book.  ram_data_rdy is a wire (rd_data_rdy_a, in fact) - there's no delay on it that I'm aware of.  So the source_ values are assigned instantly to either their immediate values or their latched values, depending on whether ram_data_rdy is HIGH or LOW.

According to my limited understanding of the subject and my internal logic, there is an issue with the immediate values - not the latched values.  That could be my first mistake, but I consider it a fair assumption based on what I know.  My previous thinking was that there is no guarantee that the immediate_colour, target or bpp will have valid values by the time ram_data_rdy goes high as they all become invalid once cmd_rdy goes LOW.  In fact, all their values go to zero. 

In fact, this appears to be what is happening in the simulation - when rd_data_rdy_a goes HIGH, the immediate values (all zero) for color, target and bpp are used on the incoming data word from RAM, and a valid value isn't returned by the function until rd_data_rdy_a goes LOW and the inputs are switched over to the latched values instead, which have all the correct settings saved and thus a valid value is returned in PX_COPY_COLOUR.

I'm still not 100% on why you say my previous change was wrong, because of my thinking above.

Now I'm clearly missing a connection or I'm not making a link because I can't see any further than that.  I'm just staring at waveforms and numbers and code and it's all just staring back at me.

I'm going to bed.  Maybe sleeping on the problem (again) will help.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 09, 2020, 10:28:03 pm
Ok, I give up, see if you can figure out and explain to me why this works.

Code: [Select]
    // set source data according to RAM read
    source_bpp    = ( !ram_data_rdy )  ? immediate_bpp    : latched_bpp    ;
    source_colour = ( !ram_data_rdy )  ? immediate_colour : latched_colour ;
    source_target = ( !ram_data_rdy )  ? immediate_target : latched_target ;
    source_word   = (  ram_data_rdy )  ? immediate_word   : latched_word   ;

Once you understand that, next copy the green part of my stimuli on my second sim setup with the green and yellow patch.  There is a minor bug there and once you solve it, adding the yellow section running 6 adjacent commands should simulate fine.


BTW, I'm self taught.  No schooling in this field.  However, yes, I've been working in electronics since the mid 80's when I began it as a hobby.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 10, 2020, 08:38:43 am
Ok, I give up, see if you can figure out and explain to me why this works.

Code: [Select]
    // set source data according to RAM read
    source_bpp    = ( !ram_data_rdy )  ? immediate_bpp    : latched_bpp    ;
    source_colour = ( !ram_data_rdy )  ? immediate_colour : latched_colour ;
    source_target = ( !ram_data_rdy )  ? immediate_target : latched_target ;
    source_word   = (  ram_data_rdy )  ? immediate_word   : latched_word   ;

For crying out loud... |O  Why do I always go straight to the complicated solutions?  I wasn't even considering changing the polarity of the ram_data_rdy signal.  The solution is always obvious when you can see it. :palm:

Once you understand that, next copy the green part of my stimuli on my second sim setup with the green and yellow patch.  There is a minor bug there and once you solve it, adding the yellow section running 6 adjacent commands should simulate fine.

Right.  Let's get off on the right foot with this one.  Treat me as if I'm a complete imbecile as I'm not even sure what the bug is! :-//  I've worked out the values on paper for PX_COPY_COLOUR for the green section and I'm getting results of 4 and 5 for the first two read requests, as they are output in the simulation when rd_data_rdy_a goes high.  So what's the issue?  Is it because the function is outputting garbage the rest of the time or because rd_req_a is extended?

I need to know I'm focusing my full cognitive ability (like a bag of cats) on the bug and not some harmless (or intended) feature that I think is a bug because I'm going stir crazy looking at simulation outputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 01:37:46 pm
Yep, next step, change this line:

Code: [Select]
    exec_cmd       = ( ( !(rd_wait_a && !rd_data_rdy_a) && !(rd_wait_b && !rd_data_rdy_b) ) && pixel_cmd_rdy ) ;
to this:
Code: [Select]
    exec_cmd       = ( ( !(rd_wait_a ) && !(rd_wait_b ) ) && pixel_cmd_rdy ) ;
The '!rd_data_rdy_a' was causing the fifo to begin reading too early.

Do a simulate with first my green, then yellow added stimuli.  The cache hits should now stream out with valid pixel data right after the read.

Now, I think we should add a new output to the 'bitplane_memory_data_to_pixel_colour' called:
color_eq_0

the equation is simple:
color_eq_0 = ( pixel_colour == 0 );


Now, before the 'end // else reset' we want to add a smart register for the 'PX_COPY_COLOUR' and the new 'PX_COPY_COLOUR_eq0' , do this:  (We need to hold onto the results for when a PXPASTE/_M commands comes in)

Code: [Select]
          if ( !rd_data_rdy_a || (exec_cmd && (pixel_cmd[3:0]==CMD_IN_PXCOPY) && rd_cache_hit) ) begin  // if pixel color data came in from ram or was immediately available when the command came in and there was a cache hit
                            PX_COPY_COLOUR_reg     <= PX_COPY_COLOUR ;     // Store pixel color
                            PX_COPY_COLOUR_eq0_reg <= PX_COPY_COLOUR_eq0 ; // store the color =0
          end


Last, we need to add the color translation/conversion function to the 'bitplane_memory_data_to_pixel_colour' module.

The formula is simple, output pixel_colour should now equal:

pixel_colour = pixel_colour * source_colour; // give the option fot the pixel copy command to change the read color to a new larger color.

However, you cannot do this with combinational logic.  Without any latch, pixel_colour would be assigned twice, so, rename and replace all the other 'pixel_colour' in that section with 'int_pixel_colour' and add a:

logic [15:0] int_pixel_colour;

and

pixel_colour = int_pixel_colour * source_colour; // give the option fot the pixel copy command to change the read color to a new larger color.


With the other logic s in that module.

Redoo the simulations, and check that the new PX_COPY_COLOUR_reg holds the read and that the changing the source CMD_color from 1 to other values alters the read pixel value.

If everything is good, we have 1 new addition to the 'bitplane_memory_data_to_pixel_colour' for another color transformation from multiply to XOR.  Then, we will do the pixel write command.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 10, 2020, 03:16:31 pm
Redoo the simulations, and check that the new PX_COPY_COLOUR_reg holds the read and that the changing the source CMD_color from 1 to other values alters the read pixel value.

Is this right?  I've highlighted the PX_COPY_COLOUR values that have changed compared to the previous simulation results (i.e. with cmd_colour set to 1 all the way through):

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 04:12:46 pm
Does this help you see it:

[attachimg=1]

If you used a CMD_Colour of always 1, it may have been easier to see the output colors...

Now, output the 'PX_COPY_COLOUR_reg' instead.  It should be delayed by an additional clock.

Next, all of the pixel writing routines.

(1 weird thing, why it you 'CMD_COLOR' input showing a single digit instead of 01, 04, 02,...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 04:39:35 pm
There was a typo in my above line#263.

 if ( !rd_data_rdy_a || ( exec_cmd && ( pixel_cmd[3:0] == CMD_IN_PXCOPY ) && rd_cache_hit ) ) begin

Get rid of that !, the line should read:

if ( rd_data_rdy_a || ( exec_cmd && ( pixel_cmd[3:0] == CMD_IN_PXCOPY ) && rd_cache_hit ) ) begin

Now if you output your 'PX_COPY_COLOUR_reg', it will have the right data at the right time.

Arrrg, now we hit an FMAX issue where this module only wants to operate at 100MHz max.  I've got a little bit of work to do to find the best fix.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 04:55:52 pm
Ok, found the FMAX bottleneck, it's line #324:

    pixel_colour  = int_pixel_colour * source_colour ; // give the option for the pixel copy command to change the read color to a new larger color

For now, change it to :

    pixel_colour  = int_pixel_colour ; //  * source_colour ; // We will move this function's feature into the pixel writer to increase the FMAX.

And now you will need to add an output to the 'bitplane_memory_data_to_pixel_colour' called:
    output logic [7:0] source_color;

And add the appropriate initiation of the function + add this new green line here:

      if ( !rd_data_rdy_a || ( exec_cmd && ( pixel_cmd[3:0] == CMD_IN_PXCOPY ) && rd_cache_hit ) ) begin
         // if pixel color data came in from RAM or was immediately available when the command came in and there was a cache hit
         PX_COPY_COLOUR_reg <= PX_COPY_COLOUR ;     // Store pixel color
         PX_COPY_COLOUR_eq0 <= PX_COPY_COLOUR_eq0 ; // store the color =0
         PX_COPY_COLOUR_opt_reg  <= PX_COPY_COLOUR_opt ; // store the CMD_COLOR option
      end

Send me your updated .sv to verify.
Also now pass out the 'PX_COPY_COLOUR_reg' instead of the regular 'PX_COPY_COLOUR'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 10, 2020, 06:36:32 pm
(1 weird thing, why it you 'CMD_COLOR' input showing a single digit instead of 01, 04, 02,...)

Erm... probably because I have it set to 'unsigned decimal'.

Ok, found the FMAX bottleneck, it's line #324:

    pixel_colour  = int_pixel_colour * source_colour ; // give the option for the pixel copy command to change the read color to a new larger color

For now, change it to :

    pixel_colour  = int_pixel_colour ; //  * source_colour ; // We will move this function's feature into the pixel writer to increase the FMAX.

And now you will need to add an output to the 'bitplane_memory_data_to_pixel_colour' called:
    output logic [7:0] source_color;

And add the appropriate initiation of the function + add this new green line here:

      if ( !rd_data_rdy_a || ( exec_cmd && ( pixel_cmd[3:0] == CMD_IN_PXCOPY ) && rd_cache_hit ) ) begin
         // if pixel color data came in from RAM or was immediately available when the command came in and there was a cache hit
         PX_COPY_COLOUR_reg <= PX_COPY_COLOUR ;     // Store pixel color
         PX_COPY_COLOUR_eq0 <= PX_COPY_COLOUR_eq0 ; // store the color =0
         PX_COPY_COLOUR_opt_reg  <= PX_COPY_COLOUR_opt ; // store the CMD_COLOR option
      end

Send me your updated .sv to verify.
Also now pass out the 'PX_COPY_COLOUR_reg' instead of the regular 'PX_COPY_COLOUR'.


Okay, I got a little lost in these instructions so I've attached the entire project, just in case.  :-//

EDIT:  Oh jeez, I've just scanned the code again and realised that source_colour is already a wire in the system - I've now created it as an input at your request - will that cause issues or was that intended?  I've also had to infer that PX_COPY_COLOUR_opt is connected to source_colour from the function.  Seems like there could be a number of errors in that project I posted.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 07:09:47 pm
Ok, I fixed up a few minor glitches on your part.

I made these outputs:
Code: [Select]
    output logic [15:0] PX_COPY_COLOUR,
    output logic [15:0] PX_COPY_COLOUR_reg,
    output logic [7:0]  PX_COPY_COLOUR_opt_reg

Also, this is 8 bits, not 16 bits:
Code: [Select]
logic [7:0] PX_COPY_COLOUR_opt     ;
Fixed the simulation and grouped the individual 'BIT' buses at the bottom.
I've attached the update.

Next, writing pixels.  For this one, I'll have a good explanation in an hour or 2...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 10:28:34 pm
Ok, all the pixel write CMD.

Step 1, they must read the current CMD memory address unless it's a cache hit, and check if the current chosen pixel was not a 0, otherwise you need to increment the 'rd_px_collision_counter' and you might need to increment the 'wr_px_collision_counter' if you have incremented the rd collision and the color you are writing isn't a transparent color 0 when the transparent mask '_M' CMD feature is enabled.

Step 2, change the appropriate bits in the write word cache and send out a write req & new write data.

Step 2.5 Now, if the copy pixel cache address and the write pixel cache address matches, when a write is done, the copy pixel cache will need to be updated with a copy of the data written to the ram.

The 3 above steps needs to appropriately set and clear the write busy flag so that a write may take place without a read.


Once we get this simulating and working, you will need to combine this module with the geometry unit in a new project under a single .sv call geometry_processor.sv which calls all 3 sub geometry units.  That  geometry_processor.sv will be wired into your GPU project and you will need to write some software to test the first graphic line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 10, 2020, 11:16:59 pm
Step A, like the module 'bitplane_memory_data_to_pixel_colour', you now need a another module:

memory_pixel_bits_editor

Notes:

Code: [Select]
Inputs:

    input logic         ram_data_rdy,
    input logic  [15:0] latched_word,
    input logic  [7:0]  latched_colour,
    input logic  [3:0]  latched_bpp,
    input logic  [3:0]  latched_target,
    input logic  [15:0] immediate_word,
    input logic  [7:0]  immediate_colour,
    input logic  [3:0]  immediate_bpp,
    input logic  [3:0]  immediate_target,

    input logic         paste_enable,
    input logic  [15:0] paste_colour,
    input logic         transparent_mask_enable,


Outputs

    output logic        collision_rd_inc,
    output logic        collision_wr_inc,
    output logic [15:0] output_word

Local params:
// these params are not final - I've just thrown them together for testing
localparam BPP_16bit = 4'd15;
localparam BPP_8bit  = 4'd7;
localparam BPP_4bit  = 4'd3;
localparam BPP_2bit  = 4'd1;
localparam BPP_1bit  = 4'd0;

Other logic...
logic [3:0]  source_bpp       ;
logic [15:0] source_colour    ;
logic [3:0]  source_target    ;
logic [15:0] source_word      ;
logic [15:0] target_colour    ;
logic        target_colour_0  ;
logic [15:0] edited_word ;

you must already know this part:

source_color[15:8] = 0 ; // Assign 0 to the upper 8 bits of the source color.

    // set source data according to RAM read
    source_bpp            = ( !ram_data_rdy ) ? immediate_bpp    : latched_bpp    ;
    source_colour[7:0] = ( !ram_data_rdy ) ? immediate_colour : latched_colour ;
    source_target         = ( !ram_data_rdy ) ? immediate_target : latched_target ;
    source_word          = (  ram_data_rdy ) ? immediate_word   : latched_word   ;

    target_colour        =  ( paste_enable )  ?   paste_colour : source_colour ;
    target_colour_0    =   (target_colour == 0) ;
    collision_wr_inc   = collision_rd_inc && (!target_colour_0 || !transparent_mask_enable);

    output_word        = (transparent_mask_enable && target_colour_0) ? source_word : edited_word ; // choose output word based on transparency mask.


and then:

    if ( source_bpp[3:0] == BPP_16bit ) begin
       
                                    edited_word        = target_colour            ;
                                    collision_rd_inc   = (source_word[15:0]  !=0) ;

    end else if ( source_bpp[3:0] == BPP_8bit ) begin
   
       if (source_target[0]) begin                                                  // place target color into the first 8 bits and retain the upper 8 bits.
                                    edited_word[15:8]  = target_colour[7:0]       ;
                                    edited_word[7:0]   = source_word[7:0]         ;
                                    collision_rd_inc   = (source_word[15:8]  !=0) ;

       end else begin                                                               // place target color into the upper 8 bits and retain the lower 8 bits.
                                    edited_word[7:0]   = target_colour[7:0]       ;
                                    edited_word[15:8]  = source_word[15:8]        ;
                                    collision_rd_inc   = (source_word[7:0]   !=0) ;
       end

    end else if ( source_bpp[3:0] == BPP_4bit ) begin

if ( source_target[1:0] == 0 ) begin        // place target color into the first 4 bits and retain the upper 12 bits.
                                    edited_word[15:12] = target_colour[3:0]       ;
                                    edited_word[11:0]  = source_word[11:0]        ;
                                    collision_rd_inc   = (source_word[15:12] !=0) ;

    end else if ( source_target[1:0] == 1 ) begin        // place target color into the second 4 bits and retain the upper 8 bits and lower 4 bits.
                                    edited_word[11:8]  = target_colour[3:0]      ;
                                    edited_word[15:12] = source_word[15:12]      ;
                                    edited_word[7:0]   = source_word[7:0]        ;
                                    collision_rd_inc   = (source_word[11:8] !=0) ;


You should be able to figure out the rest...

Send me an updated code with the inserted pixel write CMD as far as you can work out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 11, 2020, 09:56:02 am
Okay, I'm posting the 'code so far' so you can pull me up if I'm heading in the wrong direction.

Quick question about the new module - BPP_1bit is clearly a special case, I'm not sure if I'm handling it correctly.  I haven't tried to synthesise yet as the rest of the code is incomplete, but SystemVerilog seems to have a bit of a fit when it comes to variable bit-selection.

What I've done is set the target bit in the edited word - that's easy enough - but I need to set the bits above and below the targeted bit to the same value as their counterpart in the source word.  If the targeted bit is 15 or 0, a special case arises, so I've handled it like this:

Code: [Select]
end else if ( source_bpp[3:0] == BPP_1bit ) begin

edited_word[ ( ~source_target[3:0] ) ] = target_colour[0] ;
collision_rd_inc = ( source_word[ ( ~source_target[3:0] ) ] != 0 ) ;

if ( ~source_target[3:0] != 15 ) edited_word[ 15 : ( ~source_target[3:0] + 1 ) ] = source_word[ 15 : ( ~source_target[3:0] + 1 ) ] ;
if ( ~source_target[3:0] != 0 )  edited_word[ ( ~source_target[3:0] - 1 ) : 0 ]  = source_word[ ( ~source_target[3:0] - 1 ) : 0 ]  ;

end

I'm hoping it's okay, but I'm expecting errors.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 11, 2020, 11:58:33 pm
Ok, your gonna flip after I simplified over a weeks of work down to 4 lines, plus 2 look up tables.
The 4 lines:
Code: [Select]
wr_pix_c_miss = rd_data_in & (16'hFFFF ^ (LUT_mask[wc_bpp] << LUT_shift[{wc_bpp,wc_target}])) | ( (wc_colour & LUT_mask[wc_bpp]) << LUT_shift[{wc_bpp,wc_target}] ) ; // Separate out the PX_COPY_COLOUR
wr_pix_c_hit  = wcd        & (16'hFFFF ^ (LUT_mask[bpp   ] << LUT_shift[{bpp   ,target   }])) | ( (colour    & LUT_mask[bpp   ]) << LUT_shift[{bpp   ,target   }] ) ; // Separate out the PX_COPY_COLOUR

rd_pix_c_miss = ( rd_data_in >> LUT_shift[{rc_bpp,rc_target}]) & LUT_mask[rc_bpp] ; // Separate out the PX_COPY_COLOUR
rd_pix_c_hit  = ( rcd        >> LUT_shift[{bpp   ,target   }]) & LUT_mask[bpp   ] ; // Separate out the PX_COPY_COLOUR
Oh well....  The entire code is now 1/4 the size and the 2 added modules at the end are now non-existent.

The pixel write command seems to work fine.  I've removed a the fancy copy, mask and collision counter features, we should test this with software before I add more stuff.

Here is a simulation.  The red line denotes a cache miss (IE, new write pixel address) and the green lines denotes a cache hit (IE, same address, but different pixel on the bitplane).

I attached the source Quartus simulation project.
It is time to merge this code with the geometry code like I said in the previous post and tie it into the GPU project.

You should be able to draw lines, boxes and filled boxes on 256, 16, 4 & 2 color screens.
Lets see some results as I comment the code changes I made on my end.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 12, 2020, 05:24:40 am
Damn, you forgot to place the 'ram_mux_busy' input on the simulation, so, I forgot to code for it...

Here is the updated Quartus project and simulation with the 'ram_mux_busy' input.
The rd_collision counter is now functional as well.

I still need to make the paste, mask & wr_collision functions work, but basic pixel writing now works.

Let's see you integrate everything into the GPU project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 12, 2020, 12:02:26 pm
[attachimg=1]

Wow.  That's really impressive.

Here's what my geometry_processor.sv looks like.  It compiles, but I haven't tried connecting it up to the modified Z80_bridge in the actual GPU project yet (that's next) - I'm just hoping there's no obvious mistakes.  ;)

EDIT: Hmm.. Fmax is coming out at 108.28 MHz..  How do you identify which part of the HDL is causing the slow down?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 12, 2020, 12:50:32 pm
Final compilation after inserting the geo_unit into the GPU project shows an Fmax on clk[0] of 101.79 MHz.  :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 12, 2020, 04:12:11 pm
Arrrggg, all you needed was this beginning part:
(We are still developing, testing and adding code to all the geo_xxx.sv  modules.  After changes and simulations you cannot expect to cut and paste code without errors and messing things up.)

Code: [Select]
module geometry_processor (

// inputs
input logic clk,                    // System clock
    input logic reset,                  // Force reset
    input logic fifo_cmd_ready,         // 16-bit Data Command Ready signal    - connects to the 'strobe' on the selected high.low Z80 bus output port
    input logic [15:0] fifo_cmd_in,     // 16-bit Data Command bus             - connects to the 16-bit output port on the Z80 bus

// data_mux_geo inputs
    input logic [15:0] rd_data_in,      // input from data_out_geo[15:0]
    input logic rd_data_rdy_a,          // input from geo_rd_rdy_a
    input logic rd_data_rdy_b,          // input from geo_rd_rdy_b
    input logic ram_mux_busy,           // input from geo_port_full
   
    // data_mux_geo outputs
    output logic rd_req_a,              // output to geo_rd_req_a on data_mux_geo
    output logic rd_req_b,              // output to geo_rd_req_b on data_mux_geo
    output logic wr_ena,                // output to geo_wr_ena   on data_mux_geo
    output logic [19:0] ram_addr,       // output to address_geo  on data_mux_geo
    output logic [15:0] ram_wr_data,    // output to data_in_geo  on data_mux_geo
   
    // collision saturation counter outputs
    output logic [7:0]  collision_rd,   // output to 1st read port on Z80_bridge_v2
    output logic [7:0]  collision_wr    // output to 2nd read port on Z80_bridge_v2
   
);

// wire interconnects for the sub-modules
logic draw_busy        ; 
logic [35:0] draw_cmd  ;
logic draw_cmd_rdy     ;
logic fifo_cmd_busy    ;
logic [39:0] pixel_cmd ;
logic pixel_cmd_rdy    ;

geometry_xy_plotter geoff (

// inputs
.clk            ( clk            ),
.reset          ( reset          ),
.fifo_cmd_ready ( fifo_cmd_ready ),
.fifo_cmd_in    ( fifo_cmd_in    ),
.draw_busy      ( draw_busy      ),
//outputs
.draw_cmd_rdy   ( draw_cmd_rdy   ),
.draw_cmd       ( draw_cmd       ),
.fifo_cmd_busy  ( fifo_cmd_busy  )

);

pixel_address_generator paget (

    // inputs
    .clk           ( clk           ),
    .reset         ( reset         ),
    .draw_cmd_rdy  ( draw_cmd_rdy  ),
    .draw_cmd      ( draw_cmd      ),
    .draw_busy     ( draw_busy     ),
    // outputs
    .pixel_cmd_rdy ( pixel_cmd_rdy ),
    .pixel_cmd     ( pixel_cmd     )

);

 geo_pixel_writer pixie (

    // inputs
    .clk              ( clk           ),
    .reset            ( reset         ),
    .cmd_rdy          ( pixel_cmd_rdy ),
    .cmd_in           ( pixel_cmd     ),
    .rd_data_in       ( rd_data_in    ),
    .rd_data_rdy_a    ( rd_data_rdy_a ),
    .rd_data_rdy_b    ( rd_data_rdy_b ),
    .ram_mux_busy     ( ram_mux_busy  ),
    .collision_rd_rst ( 1'b0          ),
    .collision_wr_rst ( 1'b0          ),
   
    // outputs
    .draw_busy        ( draw_busy     ),
    .rd_req_a         ( rd_req_a      ),
    .rd_req_b         ( rd_req_b      ),
    .wr_ena           ( wr_ena        ),
    .ram_addr         ( ram_addr      ),
    .ram_wr_data      ( ram_wr_data   ),
    .collision_rd     ( collision_rd  ),
    .collision_wr     ( collision_wr  )

);

endmodule


Redo it with just that.

Remember all you need to do in Quartus is add-files-to project and add all the separate geo_xxxx.sv. source files.  Quartus will seek out the initiated module names in all the source files which you are calling inside this 'geometry_processor.sv' and automatically link in the code.  You can even add source files from another directory where you are doing the simulating and editing.  But I personally prefer just copying over each proven single .sv file to my main project folder when changes have been certified.

Also, even if you arent using them, make sure you list all the inputs and output of each module when calling their instances.  And don't forget the parameters.  They are also missing.  To fix the FMAX, it may just be a parameter change.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 12, 2020, 08:55:54 pm
Arrrggg, all you needed was this beginning part:
(We are still developing, testing and adding code to all the geo_xxx.sv  modules.  After changes and simulations you cannot expect to cut and paste code without errors and messing things up.)
...
Redo it with just that.

There I was thinking I was doing good by putting them all into the same file as you'd mentioned that previously.

Remember all you need to do in Quartus is add-files-to project and add all the separate geo_xxxx.sv. source files.  Quartus will seek out the initiated module names in all the source files which you are calling inside this 'geometry_processor.sv' and automatically link in the code.  You can even add source files from another directory where you are doing the simulating and editing.  But I personally prefer just copying over each proven single .sv file to my main project folder when changes have been certified.

Yep, happy with that - I prefer copying the files over from the test folders into the main project folder too, rather than linking to the test files directly.

Also, even if you arent using them, make sure you list all the inputs and output of each module when calling their instances.  And don't forget the parameters.  They are also missing.  To fix the FMAX, it may just be a parameter change.

Ah okay.  I'd only removed the PX_COPY_COLOUR output from pixel_write as (I think?) we only added it for simulation testing.  Am now listing all the I/O for each module.

It all compiles - as it should - but I'm still only getting an Fmax on clk[0] of 103.16 MHz.  I suspect the (slight) increase in Fmax is more due to me changing one of the compilation settings.  I'd changed Compiler Settings -> Optimisation mode to Performance (Aggressive - increases runtime and area), whilst I was searching the net for information on trying to track down bottlenecks in Fmax.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 12, 2020, 09:17:45 pm
It all compiles - as it should - but I'm still only getting an Fmax on clk[0] of 103.16 MHz.  I suspect the (slight) increase in Fmax is more due to me changing one of the compilation settings.  I'd changed Compiler Settings -> Optimisation mode to Performance (Aggressive - increases runtime and area), whilst I was searching the net for information on trying to track down bottlenecks in Fmax.

Please do not choose any compiler options for 'AREA', it means it's trying to shrink the design giving you more area at the cost of FMAX.

I'll look at the code tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 12, 2020, 10:21:22 pm
It all compiles - as it should - but I'm still only getting an Fmax on clk[0] of 103.16 MHz.  I suspect the (slight) increase in Fmax is more due to me changing one of the compilation settings.  I'd changed Compiler Settings -> Optimisation mode to Performance (Aggressive - increases runtime and area), whilst I was searching the net for information on trying to track down bottlenecks in Fmax.

Please do not choose any compiler options for 'AREA', it means it's trying to shrink the design giving you more area at the cost of FMAX.

I'll look at the code tonight.

I thought that particular option was the other way around - it optimised and prioritised Fmax over area and compilation time.  It did actually increase Fmax from 101.8 MHz to 103.16 MHz, but I was just experimenting whilst trying to find the bottleneck.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 04:26:41 am
Ok, here you go.  Everything has been updated.
The current bottleneck is a signal path in the pixel_address_generator.sv  limiting the FMAX to 132MHz.
I also increased the maggie layer count to 5.

All 3 quartus projects have been updated and supplied here in separate .zip.
(geo & pixel writer are the simulation projects.  GPU has everything inside.)

You forgot a few connections in the geometry_processor to the Z80_Bridge_v2.sv.
Take a look at the top.bdf so you see the connections and how to drive the geo unit.

Let's see a few pixels, lines, boxes & filled boxes being drawn.
I know of 1 bug I intentionally didn't fix regarding the endian of the stored 16bit graphics, but, let's see this work first before we swap the high & low data byte in the 16bit word.  The error pattern generated when drawing lines will be predictable.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 11:16:35 am
Uhh, really sorry, I seem to have fallen at the first hurdle.  :-[  |O

Here's what I'm trying to do:

1. Set the destination memory pointer to 0x6000
2. Set destination raster width
3. Send command to draw a line from 5,5 to 10,7

I don't mind what colour really, it's overwriting an existing image being displayed in an existing MAGGIE.

I'm clearly not setting up the drawing commands properly as I can't get anything to appear on screen.  I've switched to simulation to test the commands I'm using, and I'm getting the output I've attached at the bottom of this post (seems the forum doesn't like inline images still).

It appears from the simulation that I'm not setting the destination memory pointer properly, as it's writing to address 0000 no matter what I send in the first command.

Obviously I wasn't taking sufficient notes as we built the geo_xy_plotter.  :-[

Oh - the attached image shows a spurious value for the destination memory pointer as I was testing random values to try to get it to write to a memory address other than 0000...  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 12:25:24 pm
If you don't set the 'cmd_rdy' high, the command isn't accepted.
See:


Also, make sure you arent forcing the GEO unit into a constant reset.  Make sure port 'GEO_STAT_WR' = 0.

Remember, you also need to set the screen pixel width and bits per pixel...

With no screen width set and a bits/pixel setting of 0 as well, your line would only occupy only a single pixel on a 256 color bitmap and 1.2 pixels on a 16 color bitmap.  On a 1 bit color bitmap, your line would occupy 6 horizontal pixels, once again all on Y-coordinate 0, all of them white if the color is an odd number, all black if the color is an even number or 0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 01:50:15 pm
Ok, here is what I did.

I tied some of the geometry functions to the RS232 debugger.

When debug port Out0[0] = 0, then
Port In0 = GEO_WR_HI / geo_cmd[15:8].
Port In1 = GEO_WR_LO / geo_cmd[7:0].
Port In2 = geo_ram_addr[15:8].
Port In3 = geo_ram_addr[7:0].
When setting debug port Out0[0] = 1, then only port In2 changes to:
Port In2 = collision_rd[7..0] / RD_PX_CTR.

Ports In0 and In1 should hold your last sent command.
Ports In2 and In3 should hold the last write memory address by the pixel writer.

When port Out0[0] = 1, then In2 increase every time you write a pixel on top of anything other than color 0.  IE:  If the place where the pixel is being written does not contain a value of 0 black, that counter will increase.  IE, plot a white line on a black screen from 0,0 to 9,0, the counter will stay at 0.  Plot the same line again on the same coordinates, since those 10 pixels are white and you are drawing a white line on top, the RD_PX_CTR should increase to 10.  Redraw the same line again and the counter will become 20.  To clear that counter, you will need to read the RD_PX_CTR port which would return that 20, then is should be cleared to 0 on the debugger.

Now, if you were to set the screen width to 16 and 256 color image.
Plotting a line from 0,0 to 0,0 with color 0x25, viewing the base memory address in the RS232 debugger should place the number 0x25 in that first character.
In fact drawing a line from 0,0 to 15,15 should draw a diagonal line on the RS232 debugger's memory window.  Box fills should fill up the debugger's memory window with the selected color.
You may also select a screen width of 32 and 16 color image.  Now the drawn pixels will every half byte.

I've attached the Quartus project in the next post.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 02:07:43 pm
Woops, stop, I'm fixing the debugger...

Ok, here is the patched _v2 debugger.
The write pixel address now properly shows only the last address where any data has been written to alone.

Here is the attached updated Quartus project:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 03:32:58 pm
Okay, the simulation seems to be running okay now but I'm not getting comparable results in the hardware.  :-BROKE

I've attached an image of the simulation output - the commands and data being entered into the simulation are the same as I'm entering into the GPU via 'OUT' commands, i.e.:

Code: [Select]
OUT 246,19;:OUT 247,160
Ready
OUT 246,7;:OUT 247,115
Ready
OUT 246,0;:OUT 247,128
Ready
OUT 246,6;:OUT 247,192
Ready
OUT 246,1;:OUT 247,124
Ready
OUT 246,90;:OUT 247,128
Ready
OUT 246,100;:OUT 247,192
Ready
OUT 246,0;:OUT 247,95
Ready
OUT 246,1;:OUT 247,128
Ready
OUT 246,4;:OUT 247,192
Ready
OUT 246,20;:OUT 247,4
Ready
OUT 246,4;:OUT 247,208
Ready
OUT 246,255;:OUT 247,1
Ready

As you can see, I'm entering them one 16-bit command at a time.  In theory (at least), when that last OUT 247,1 is executed, the geo_unit should draw a broken (dotted?) line across my image.  The RS232_debugger confirms that the GPU is receiving the commands - so either I'm making a silly mistake (likely) or there's a problem in the HDL?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 03:36:52 pm
Does the debugger show a write address?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 03:44:21 pm
Does the debugger show a write address?

Yes, shows the following:

Code: [Select]
In0[7:0]=8'b00000001 =8'h01=8'd001.
In1[7:0]=8'b11111111 =8'hFF=8'd255.
In2[7:0]=8'b01100000 =8'h60=8'd096.
In3[7:0]=8'b10100010 =8'hA2=8'd162.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 04:07:46 pm
Now when looking at that address in the debugger, what is the value.  Is it the written color number?

BTW, if the geo didn't send a true write comman, that address would read 0.

Making a line to a new ending coordinate, as long as it is at a different address will also change that number..

When testing, try making a single point line where you know the address would be.
Reading that address in the debugger will show you if and what data has been written in real time.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 04:13:01 pm
Now, am I wasting my time making building your latest project into my fixture and programming the geo unit byte-by-byte using the rs232 debugger to verify your results?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 04:14:40 pm
Okay, I've cleared the image to zero and it appears to be writing to 604C and 604D - both FF values.  That doesn't match the sim output?

Now, am I wasting my time making building your latest project into my fixture and programming the geo unit byte-by-byte using the rs232 debugger to verify your results?

You know me too well.  :-[
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 04:41:49 pm
Okay, so a single-pixel write at location 1,1 causes a write to GPU address 6015, value FF.  As the RS232_debugger confirms, it looks as though the base memory address is set slightly higher than 6000.

Single-pixel write to location 2,2 causes a write to GPU addresses 6014 AND 6029 (with just 6028 appearing in the simulator).

Drawing a line from 1,1 to 18,20 causes three bytes to be written to - in no particular geometric order - and the last byte at 6076 remains at FF, no matter what I do to change it in the RS232_debugger.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 04:47:56 pm
Okay, so a single-pixel write at location 1,1 causes a write to GPU address 6015, value FF.  As the RS232_debugger confirms, it looks as though the base memory address is set slightly higher than 6000.

1,1 is not 0,0.
Also, why is you screen width an odd number like 15 instead of 16.

This means that at line 1 (IE +15) and pixel 1 (IE+1) + shave off the LSB, wait hold on, are some figures here decimal and others hex and you are mixing the 2?

Also when you plot on a screen, you need to match the MAGGIE's pixel width count, NOT the byte count which we use in the MAGGIE HW control register unless it is an 8 bit 256 color screen where these 2 figures will match.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 04:50:56 pm
YOU DIRTY RAT BASTARD.  You know I don't have a Z80 to fix this problem:
[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 05:09:39 pm
YOU DIRTY RAT BASTARD.  You know I don't have a Z80 to fix this problem:
(Attachment Link)

Fix it high and it'll be fine.  :-+  It's not a feature I use (at the moment - it may be useful later), it was just something I added to test IO writes early on.

Okay, so a single-pixel write at location 1,1 causes a write to GPU address 6015, value FF.  As the RS232_debugger confirms, it looks as though the base memory address is set slightly higher than 6000.

1,1 is not 0,0.
Also, why is you screen width an odd number like 15 instead of 16.

This means that at line 1 (IE +15) and pixel 1 (IE+1) + shave off the LSB, wait hold on, are some figures here decimal and others hex and you are mixing the 2?

Also when you plot on a screen, you need to match the MAGGIE's pixel width count, NOT the byte count which we use in the MAGGIE HW control register unless it is an 8 bit 256 color screen where these 2 figures will match.


Yeah, fair point. I've gone back to the MAGGIE settings for the image and have corrected the width and height - they should be 74 and 91 pixels respectively.  That'll teach me to use ballpark figures.

I've just tried plotting to 2,2 and got a write to 6003, when the sim says it should be 6028.  I'm going to keep testing though to rule out user error.  ::)

I've also been contending with a problem with accessing GPU RAM.  It seems the GPU doesn't like the Z80 doing block writes - i.e. I've tried to clear a block of RAM (erase the image) using LDIR and it results in some very... interesting... behaviour.  The Z80 reads the RAM and sees all zeroes, as it should be, but the RS232_debugger sees some zeroes and mostly FFs.  I have to power-off the whole thing and restart to be able to write to RAM properly again.  Odd.  Has anything changed with regard to the Z80_bridge bus timings or something?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 05:39:25 pm
Is the bit order backwards?  Plotting to 1,0 changes the first byte from FF to FC in 2-bits per pixel.  Even then, it's still out by 1 bit-pair - it should be zeroing bits 5 & 4, not 1 & 0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 05:40:52 pm
Ok, I've done this.  I'm only getting the first 5 out of 10 pixels, but, they are correct except for the endian error.

Take a look at photo 1 for the commands I sent to the GPU.

Take a look at photo 2 for the memory before executed draw line.

Take a look at photo 3 for after the line draw.  (Ignore endian error)

Endian patch coming in 10 minutes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 06:12:40 pm
Here is the output after the endian patch.

I've attached the new quartus project.

For some reason, the geo unit seems to freeze after 5 pixels are drawn.

Need to create a simulation test bench with all 3 modules tied together.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 06:32:30 pm
For some reason, the geo unit seems to freeze after 5 pixels are drawn.

Need to create a simulation test bench with all 3 modules tied together.

Could this be related to the GPU RAM issues I'm experiencing as well, perhaps?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 06:45:19 pm
Nope, I've just done a complete geometry simulation.
Take a look at the blue like once the pixel writer fifo is full and it tells the rest of the system to wait.
It hangs there after the 5th pixel.

Give me a few minutes to debug...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 07:11:57 pm
Freeze fixed.  Every pixel now comes out, see:

Give me 10 minutes to compile & check that the FMAX is still good, then prepare the .zip.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 07:39:28 pm
All fixed.  Get the attached .zip below.

I also added 1 parameter which allows you to adjust the geometry input fifo margin which signals the 'fifo_cmd_busy' that many commands prior to the fifo being full.  This is so you do not need to check the 'fifo_cmd_busy' before every byte being sent.  Instead, check once before sending a block of up to 32 commands.  Or, for instance, just check once before sending a complete triangle which takes around 8 commands in a row.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 08:09:42 pm
Seems to be working just fine now.  :-+

From humble beginnings...  ;D

[attachimg=1]

I'll have more time tomorrow to check the rectangle functions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 08:48:12 pm
Geo tests in this order,

Line_0,0-9,9-255.png
Box_0,0-9,9-17.png
Box-Fill_0,0-9,9-102.png

I'll leave it to you to check for all the different color modes and higher resolutions.
Once verified, we will finish the pixel copy & paste/paste_mask function.

Then, back to the geometry_xy_plotter to add some missing function commands, then final drawing shapes, then a copy blitter function.  We got only 2 weeks left to finish this.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 09:04:57 pm
Could this be related to the GPU RAM issues I'm experiencing as well, perhaps?  ???

What GPU Ram issues?
This is important as the Z80 r/w supposed to get immediate overriding priority over the geometry unit's access.
Even with the geo freeze bug, the Z80 should still work fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 13, 2020, 09:28:32 pm
What GPU Ram issues?
This is important as the Z80 r/w supposed to get immediate overriding priority over the geometry unit's access.
Even with the geo freeze bug, the Z80 should still work fine.

This one:

I've also been contending with a problem with accessing GPU RAM.  It seems the GPU doesn't like the Z80 doing block writes - i.e. I've tried to clear a block of RAM (erase the image) using LDIR and it results in some very... interesting... behaviour.  The Z80 reads the RAM and sees all zeroes, as it should be, but the RS232_debugger sees some zeroes and mostly FFs.  I have to power-off the whole thing and restart to be able to write to RAM properly again.  Odd.  Has anything changed with regard to the Z80_bridge bus timings or something?

I'll try to shed some more light on it tomorrow when I have time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 09:44:55 pm
What GPU Ram issues?
This is important as the Z80 r/w supposed to get immediate overriding priority over the geometry unit's access.
Even with the geo freeze bug, the Z80 should still work fine.

This one:

I've also been contending with a problem with accessing GPU RAM.  It seems the GPU doesn't like the Z80 doing block writes - i.e. I've tried to clear a block of RAM (erase the image) using LDIR and it results in some very... interesting... behaviour.  The Z80 reads the RAM and sees all zeroes, as it should be, but the RS232_debugger sees some zeroes and mostly FFs.  I have to power-off the whole thing and restart to be able to write to RAM properly again.  Odd.  Has anything changed with regard to the Z80_bridge bus timings or something?

I'll try to shed some more light on it tomorrow when I have time.

Careful if you are in edit mode (RED BORDER) in the RS232 debugger when using the Z80 to write to the GPU ram.  What may be happening is that you successfully did the block write and read, however, the RS232 debugger may be overwriting the same memory with it's 256 byte cache.  This only happens when the hex editor has the 'RED BORDER' on.  Otherwise, it is in passive read mode when the border is green.  I'm assuming that this is not the problem.

Are you saying that access to the GPU ram goes silent?  And you need to power-cycle the GPU?
We may need to adjust the # of clock cycles for a write in the Z80_bridge_v2, however, that module should not be able to lock-up.

Once frozen, before cycling power, does the RS232 debugger still work?

Also, does pressing CTRL-R (send internal soft reset) in the RS232 debugger regain access to the ram?

Do block reads work properly?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 10:08:02 pm
Awww, thanks to you, I just found a minor bug in the RS232 Hex editor viewer.  Get the V1.2 patch here:

https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/msg3187578/#msg3187578 (https://www.eevblog.com/forum/fpga/verilog-rs232-uart-and-rs232-debugger-source-code-and-educational-tutorial/msg3187578/#msg3187578)

This has nothing to do with your Z80 block write freeze.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 13, 2020, 11:23:05 pm
As you can see, the geometry unit works fine on 4 color layers as well without a single pixel defect:
Layer size = 76x92, 4 colors.
box-fill, then line, then box.

(This is your Zilog layer 2x zoomed moved to the center of the screen)

By the way, it is safe to go from 5 layers to 6 layers so you get that Zilog IC on your power-up screen.
I haven't tried anything higher because your logic is 86% full at 6 layers.  Adding more layers will increase compile time to a point where it just won fit into your FPGA...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 05:28:07 am
Ok, here is the almost complete pixel writer. 

Pixel Writer with copy, paste, paste_mask & set_RGB legend (see photo):

A = Reset both collision counters.

B = Copy pixel @0x0ABC-2, 16 color = '0xB'

C = Paste_mask 16 color pixel '0xB' to 0x0111-1.
    Since pixel @0x0111-1 wasn't 0x0 to begin with, collision_rd +1.
    Since color '0xB' was written into 0x0111-1 which wasn't 0, collision_wr +1.

D = Copy pixel @0x0ABC-3, 16 color = '0x0'.

E = Paste_mask 16 color pixel '0x0' to 0x0111-1.
    Since pixel @0x0111-1 wasn't 0x0 to begin with, collision_rd +1 again.
    Since color '0x0' is transparent, 0x0111-1 kept the earlier '0xB'color
    and collision_wr stayed the same.

F = Normal paste 16 color pixel '0x0' to 0x0111-1.
    Since pixel @0x0111-1 wasn't 0x0 to begin with, collision_rd +1 again.
    Normal paste means the color '0x0' was written into 0x0111-1 and since
    the pixel was originally '0xB', the collision_wr +1.

G = Paste_mask 16 color pixel '0x0' to 0x0111-1.
    Since pixel @0x0111-1 is 0x0 to begin with, the collision_rd stayed the same.
    Since color '0x0' is transparent, 0x0111-1 kept the earlier '0x0'color
    and collision_wr stayed the same.

H = set_rgb = This passes the first 16 bits in the command bus directly into
    the copy pixel buffer so you may write 16 bit true color RGB pixels
    using the pixel_paste command afterwards.

New 'Pixel_writer' Quartus simulation attached.

Also, new 'Geo_Writer' Quartus simulation project attached which contains the entire geometry processor simulation path from command to ram access.  It needs the 'Pixel_writer' project to function.

Your going to need to read all my code and add your own comments and documentation yourself as I have some basic info in there with some mistakes as this was rushed.  You'll need to post your commented versions of the code for verification you understand what's going on.  For now, wait for finalization of the pixel writer.  The address generator looks complete.  And you know we need to make the filled triangles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 05:36:08 am
New main GPU build with the latest pixel writer supporting copy, paste, mask, both collision counters & set_rgb functions.  6 MAGGIE layers enabled.

Only the color conversion feature which allows you to select new colors from low color source images to different higher color values when copying & pasting onto a high color bitmap is missing.  Currently, the color is only copied verbatim.


Open up a 320x200 x 16 color screen.  You have enough ram for it.  Make a random point-point, random color lines all over the screen and see how fast it's running.  Assuming your Z80 can generate random numbers that fast.  I remember my Atari 800 was slow with RNG.  Video the results.

Also do the same with box-fills.  These eat up a magnitude more pixel write commands unless the Z80 is fast enough to keep up with the line drawings.

I wonder if you could successfully get the 'fifo_cmd_busy' to trigger.  Your only prayer may be setting up a box-fill to 320x200 x 16 color, then just continuously writing the box-fill command again and again non-stop.  It may be valuable to attempt this and report/time the speed of how many box-fills as this size can be drawn per second.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 10:28:20 am
Careful if you are in edit mode (RED BORDER) in the RS232 debugger when using the Z80 to write to the GPU ram.  What may be happening is that you successfully did the block write and read, however, the RS232 debugger may be overwriting the same memory with it's 256 byte cache.  This only happens when the hex editor has the 'RED BORDER' on.  Otherwise, it is in passive read mode when the border is green.  I'm assuming that this is not the problem.

Are you saying that access to the GPU ram goes silent?  And you need to power-cycle the GPU?
We may need to adjust the # of clock cycles for a write in the Z80_bridge_v2, however, that module should not be able to lock-up.

Once frozen, before cycling power, does the RS232 debugger still work?

Also, does pressing CTRL-R (send internal soft reset) in the RS232 debugger regain access to the ram?

Do block reads work properly?

I can't replicate the issue today in the latest build - I didn't pay too much attention to it yesterday as I didn't want to sidetrack away from getting the drawing to work, and I figured I could just look at it today in more detail and give you more information on it.   I've just done block writes and reads to GPU RAM with no errors or artefacts at all just now, so it could have been user error on my part - I'm aware of the issues caused by the RS232_debugger being in edit/write mode when the Z80 accesses the RAM, but can't remember if it was in edit mode or not when I was having the issues yesterday.  It probably was, as it's all working now (without the RS232_debugger attached).  I'll draw a line under this one unless it crops up again.  :phew:

New main GPU build with the latest pixel writer supporting copy, paste, mask, both collision counters & set_rgb functions.  6 MAGGIE layers enabled.

Wow. Thank you. (I'm gonna need a bigger FPGA...)  ;)

Open up a 320x200 x 16 color screen.  You have enough ram for it.  Make a random point-point, random color lines all over the screen and see how fast it's running.  Assuming your Z80 can generate random numbers that fast.  I remember my Atari 800 was slow with RNG.  Video the results.

Yeah, the old 8-bit computers weren't built for speed.  I did briefly look at RNG HDL to see if the FPGA could do it on behalf of the Z80 - but I'll use a quick pseudo-random generator based on the R register for the graphics test program.

Also do the same with box-fills.  These eat up a magnitude more pixel write commands unless the Z80 is fast enough to keep up with the line drawings.

I wonder if you could successfully get the 'fifo_cmd_busy' to trigger.  Your only prayer may be setting up a box-fill to 320x200 x 16 color, then just continuously writing the box-fill command again and again non-stop.  It may be valuable to attempt this and report/time the speed of how many box-fills as this size can be drawn per second.

I've got my work cut out - I'll be back when I have some video footage. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 12:33:32 pm
I can't replicate the issue today in the latest build - I didn't pay too much attention to it yesterday as I didn't want to sidetrack away from getting the drawing to work, and I figured I could just look at it today in more detail and give you more information on it.   I've just done block writes and reads to GPU RAM with no errors or artefacts at all just now, so it could have been user error on my part - I'm aware of the issues caused by the RS232_debugger being in edit/write mode when the Z80 accesses the RAM, but can't remember if it was in edit mode or not when I was having the issues yesterday.  It probably was, as it's all working now (without the RS232_debugger attached).  I'll draw a line under this one unless it crops up again.  :phew:

Can confirm - no issues encountered so far and I'm doing lots of block writes to the GPU RAM.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 12:57:16 pm
I seem to be having some trouble setting a base memory address of 0x1200.

I've hit the simulator to work out what's happening, and as best I can see, it looks like when the DSTRWIDTH is called, the bit-order on the high byte is reversed?

i.e:

    Sending 255 as the low byte, 1 as the high byte should result in an address of 01FF being passed to the pixel_writer.  Instead I see 10FF.
    Sending 0 as the low byte, 6 as the high byte should result in an address of 0600 being passed to the pixel_writer.  Instead I see 6000.

Am I going mad or is this is a bug that we've missed by pure chance so far?

EDIT:
Hmm... maybe not reversed, but some odd behaviour (in the simulator at least).  I've just entered (LOW) 200 (HI) 1 and got an address of 10C8.  So it would appear the highest address I can reference in any block of 1000 addresses is the first 256?

Changing the HI byte to 02 changes the address output to 20C8.  Changing HI byte to 20 changes the address output to 140C8.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 02:40:54 pm
Remember, for some reason, in the simulator we chose showing decimal for the CMD inputs.
Here, I changed it to hex and here is how the address is sent.

Since we wanted 24 bits and the CMD uses 4, then sending 12 bits to the X&Y, the final X&Y were stacked together and transmitted as the final address.  See here:

H command byte                                      L command byte
(CDM 4bit)   +   (4 top bits of X[n]/Y[n])    (Bottom 8 bits of X[n]/Y[n])

Base address out
Y[n][12],X[n][12]
X holds the least significant 12 while Y holds the most.

Note this is still in flux and we can make changes...
See attached image.
[attach=1]

(OPTIONAL CHANGE) If you will never be going above 20 bits, it would be much easier to use:
Y[n][12],X[n][8] - a sum of 20 address bits only.
This way, you only feed the lower address 8 bits into X and feed the upper address 8 bits into Y[7:0] and for above 64k, send the next 4 bits into the lower 4 bits of CMD when setting Y where you feed Y[11:8]. Much less fragmentation like this way.  This may or may not also be of benefit when using the set_rgb function for setting a 16 bit color.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 03:56:42 pm
 :o

I was able to correctly set the address thanks to the image you included in your reply - the ABCDE address gave it away.  :-+

Hmm.. okay, so I'm probably making a stupid mistake as I've just tried to draw a line and it's just appeared as a load of scattered dots on the screen.  I'm not confident I really know what's going on with YINC_ADDR_L/H, for starters - anywho, here's the setup:

I've set up MAGGIE0 like this:

0x000010 - 00 10 00 10  - HV triggers
0x000060 - 0A 00 00 00 12 00 01 00 01 40 00 C7 01 01 00 00 - 256 colours, 320x200, scaled 2x2

Here's my assembly setup (send_gpu just sends HL's low byte L to port 246, then the high byte H to 247), so the setup should mirror what we've done previously:

Code: [Select]
; set GPU base_addr for graphics
LD HL,0F001H ; set Y[3] to 01
CALL send_gpu
LD HL,0B200H ; set X[3] to 200
CALL send_gpu
LD HL,7F00H ; send cmd 127 to set destination base address
CALL send_gpu
; set raster width (H) and bit depth (L)
LD HL,0B140H ; set X[3] to 320
CALL send_gpu
LD HL,7102H ; set dest raster width to X[3] and bpp to 2
CALL send_gpu
; set X & Y limits
LD HL,8140H ; set X[0] to 320
CALL send_gpu
LD HL,0C0C8H ; set Y[0] to 200
CALL send_gpu
LD HL,5F00H ; set max X & Y to X[0],Y[0]
CALL send_gpu

;------------------------------------------------------------------------------
; drawLine
;
; Draws a line - what else?
;------------------------------------------------------------------------------
drawLine:
LD HL,8000H ; set X[0] to 0
CALL send_gpu
LD HL,0C000H ; set Y[0] to 0
CALL send_gpu
LD HL,90DCH ; set X[1] to 220
CALL send_gpu
LD HL,0D096H ; set Y[1] to 150
CALL send_gpu
LD HL,01FFH ; draw white line X[0],Y[0] to X[1],Y[1]
CALL send_gpu
RET

It's also writing into the symbol table as well, as some characters have artefacts in them, so I'm doing something wrong.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 04:05:57 pm
Bpp of 2 is invalid unless you are translating something...

Code: [Select]
LD HL,0B140H ; set X[3] to 320
CALL send_gpu
LD HL,7102H ; set dest raster width to X[3] and bpp to 2

bpp 0 = 1 bit color, 2 colors
bpp 1 = 2 bit color, 4 colors
bpp 3 = 4 bit color, 16 colors
bpp 7 = 8 bit color, 256 colors
bpp 15 = 16 bit color, 65536 true colors

(we can change these numbers to bpp 0,1,2,3, & 4, or even match the maggie color settings as they are look up table driven.)

Your maggie must match the number of color bits as well.  But remember, it's setting orientation may be different.

Also, in the maggie, when you have 4 bit color, it's screen bytes/line setting isn't 320, it's width setting is set in bytes/line.  Since each line is 320 pixels and there are 2 pixels in a byte, then the maggie bytes/line should be set to 180.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 04:26:23 pm
0x000060 - 0A 00 00 00 12 00 01 00 01 40 00 C7 01 01 00 00 - 256 colours, 320x200, scaled 2x2

0x000060 - 0A 00 00 00 12 00 00 A0 01 40 00 C7 01 01 00 00 - 16 colours, 320x200, scaled 2x2

0x00A0 bytes per 320 pixel line of video when in 4 bit color mode.

This layer begins at memory address $1200, ie 4608 bytes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 04:34:05 pm

Code: [Select]
; set raster width (H) and bit depth (L)
LD HL,0B140H ; set X[3] to 320
CALL send_gpu
LD HL,7102H ; set dest raster width to X[3] and bpp to 2
CALL send_gpu


It's also writing into the symbol table as well, as some characters have artefacts in them, so I'm doing something wrong.  :-//

You didn't set Y[3] to 0 in advance.  The geometry unit can address screens widths up to 65535 pixels wide.  12 bit width of X[3] alone is not enough and you previously set Y[3] with a value when setting the address earlier.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 04:44:06 pm
That's sorted it.  Thank you. :-+

I should have taken better notes back when we built BART and MAGGIE...

Will update shortly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 04:59:10 pm
https://www.youtube.com/watch?v=7qXboFXc2_Y (https://www.youtube.com/watch?v=7qXboFXc2_Y)

Okay, random line drawing test is done. 

It's not the fastest as I've got a keyboard input check going on every time a line is drawn, so I can quit back to CP/M if I want, and it's checking the line colour before it's drawn to exclude the two blacks in the palette.  :-+

Oh, my RNG only goes up to 255 as well, hence the full screen isn't used.  ;)

Artefacts at the bottom of the screen are from a previous run of the program - I'm obviously not clearing the full GPU RAM area at startup.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 05:44:14 pm
Mixed lines, rectangles and filled rectangles. (https://www.youtube.com/watch?v=tZojsin_pKE)

Each loop now draws a random line, rectangle and filled rectangle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 06:05:38 pm
Arrrgg, I don't even think your flexing the geometry at all.
How about just adding 3,7x5,9 to 8 bit only xy,xy coordinates, and add 1 on color with the line or box fill and plot all in an assembly loop with nothing else.  No os or kb scans.  Or loop for 255 draws, then do 1 assembly hw kb to check for a character to break, if not, then do another 255.

Who cares about the 2 black colors, let them draw.

I need to see this thing swing...

I'm trying to keep everything in 8 bit and only do adds or inc.

I think I could do better with a PIC16C54 microcontroller from the mid 1990s.

We might need to store graphic programs on the GPU to do any real work.
However, with the current rate of development, this would take forever.

Do you have any 20MHz Z80s?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 07:03:59 pm
Full-screen (320x200) rectangle fills, random colours each time, no input checks whatsoever - the loop is just the rectangle command, repeated infinitely.

https://www.youtube.com/watch?v=QMgRiJ4Vrp0 (https://www.youtube.com/watch?v=QMgRiJ4Vrp0)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 07:32:35 pm
That RND takes too long, just do the super fast test I mentioned 2 posts up.

You still haven't maxed out the GPU.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 07:55:11 pm
There's no RND in that code.  Here's the main loop:

Code: [Select]
MAINLOOP:
CALL drawFRect
JP MAINLOOP

drawFRect:
CALL full_params
LD HL,0AFFH ; draw filled rectangle X[0],Y[0] to X[1],Y[1]
LD L,A
CALL send_gpu
RET

full_params:
LD HL,8000H ; set X[0] to 0
CALL send_gpu
LD HL,0C000H ; set Y[0] to 0
CALL send_gpu
LD HL,9140H ; set X[1] to 320
CALL send_gpu
LD HL,0D0C8H ; set Y[1] to 200
CALL send_gpu
recol:    ; Cycle colours
INC B
LD A,B
CP      16
RET C    ; RETurn if < 16
LD A,2
LD B,A ; Otherwise, set colour to 2
RET

I could tighten it up by not setting the X/Y parameters every loop...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 08:03:09 pm
Who cares about the 2 black colors, let them draw.

I need to see this thing swing...

Okay, I'll remove the check for the two black colours.  Could I get away with setting up X[0]/Y[0] and X[1]/Y[1] once at the start, then just running draw command in the loop without setting those registers again?  That'd speed the loop up a lot.

I'm trying to keep everything in 8 bit and only do adds or inc.

I think I could do better with a PIC16C54 microcontroller from the mid 1990s.

We might need to store graphic programs on the GPU to do any real work.
However, with the current rate of development, this would take forever.

Do you have any 20MHz Z80s?

No, 8 MHz is the fastest I have (well, 10 MHz chip running at 8 MHz) - it would cause me real headaches trying to change existing hardware in the system to run at faster speeds.  The alternative, I guess, is to run the lot in the FPGA itself if you're after real performance.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 14, 2020, 08:14:29 pm
Optimised the loop some more:

https://www.youtube.com/watch?v=7HcgeBjebnM (https://www.youtube.com/watch?v=7HcgeBjebnM)

Not seeing a lot of difference?

Here's the code:

Code: [Select]
CALL full_params     ; Set rectangle coordinates
LD HL,0AFFH ; draw filled rectangle X[0],Y[0] to X[1],Y[1]
MAINLOOP:
LD L,A
INC A
AND 0FH ; restrict A to 0-15
CALL send_gpu
JP MAINLOOP

drawFRect:
CALL full_params
LD HL,0AFFH ; draw filled rectangle X[0],Y[0] to X[1],Y[1]
LD L,A
CALL send_gpu
RET

full_params:
LD HL,8000H ; set X[0] to 0
CALL send_gpu
LD HL,0C000H ; set Y[0] to 0
CALL send_gpu
LD HL,9140H ; set X[1] to 320
CALL send_gpu
LD HL,0D0C8H ; set Y[1] to 200
CALL send_gpu
RET

send_gpu:
PUSH AF
LD A,L
OUT (CMD_LO),A
LD A,H
OUT (CMD_HI),A
POP AF
RET
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 08:15:59 pm
Maybe you are hitting the input FIFO's limit and not knowing.  Do you occasionally check the status flag?
However, seeing colors broken part way down the screen should means that you are filling the entire screen with a new color faster than the video is coming out.  I see 20 bars, meaning 20 fills in 1/60th of a second.  Or, 1200 full screen fills per second.  That's (320*200*20*60) = 76.8 million pixels written per second.  Really close to the predicted figure.

Writing 4 adjacent pixels in a fill takes (2+1+1+1+1) 125Mhz clocks for 6 clocks.  125Mhz / 6 clocks * 4 pixels = 83 million rendered pixels per second.

Without any cache, you would only fill 41 million pixels a second.  The cache acceleration is even more than doubled with a copy-blit function as you need to do a pixel read, then a write which has that initial read as well making a 4 pixel copy go from taking 20 clocks down to 8 clocks.  IE, copy 25 million pixels a second no cache VS 62 million pixels a second with caching.

In 1 bit color, writing 16 adjacent pixels = (2+16) 125Mhz clocks for 18 clocks.  125Mhz / 18 clocks * 16 pixels = 111 million rendered pixels per second.


Ok,
As for the line demo, doing it with my simple addition would be a hell of a lot more impressive, or any other type of addition to make spiral-graph type patterns I used to generate on my Atari800, except, on steroids...

It's ok, don't stress yourself, you wont really get any further.

I'll touch up the copy color transformation feature and your can make sure all the rest of the features like the collision detectors and soft reset works.

Next, we will look at filled triangles.

Also, you can try a 640x400 hi-res 2 color B&W mode.  The lines should look very sweet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 14, 2020, 08:29:09 pm
Code: [Select]
CALL full_params     ; Set rectangle coordinates
LD HL,0AFFH ; draw filled rectangle X[0],Y[0] to X[1],Y[1]
MAINLOOP:
LD L,A
INC A
AND 0FH ; restrict A to 0-15
CALL send_gpu
JP MAINLOOP

drawFRect:
CALL full_params
LD HL,0AFFH ; draw filled rectangle X[0],Y[0] to X[1],Y[1]
LD L,A
CALL send_gpu
RET

full_params:
LD HL,8000H ; set X[0] to 0
CALL send_gpu
LD HL,0C000H ; set Y[0] to 0
CALL send_gpu
LD HL,9140H ; set X[1] to 320
CALL send_gpu
LD HL,0D0C8H ; set Y[1] to 200
CALL send_gpu
RET

send_gpu:
PUSH AF
LD A,L
OUT (CMD_LO),A
LD A,H
OUT (CMD_HI),A
POP AF
RET

Arrrg, it's 0 to 319 and 0 to 199.  This is a coordinate system on graph paper.

Since we hit the 76.8 million pixels written per second, your Z80 is probably overfilling the geometry's input fifo sending out over 1200 box-fills a second.

The line would be more difficult to flood the input fifo as they have so few pixels, even though pure vertical lines would render pixels at around half speed due to all the cache-miss.  The box fills will mostly generate cache-hits rapidly accelerating the fill.

If you went to 2 or 1 bit color, the cache hits doubles or quadruples.  In 1 bit color, the box fills should achieve a pixel write speed close to 111million pixels a second.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 15, 2020, 11:38:04 am
I'll touch up the copy color transformation feature and your can make sure all the rest of the features like the collision detectors and soft reset works.

Next, we will look at filled triangles.

Also, you can try a 640x400 hi-res 2 color B&W mode.  The lines should look very sweet.

Okay, working on B&W hi-res mode test right now as I've got half an hour to spare.  Not sure what I can get done this weekend, going to be busy, but hoping to get the tests done you've mentioned above.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 15, 2020, 06:04:00 pm
Uh. :-[ What am I doing wrong with the MAGGIE setup here?  I'm trying to draw a grid in 640x480x2.  I'm getting the grid drawn in memory, but with the current MAGGIE settings I can't see anything. ???

MAGGIE HW register settings:
Code: [Select]
08 00 00 00 12 00 00 50 7F 02 DF 01 00 00 00 00
If I change the first byte to 9, I can see the grid on the screen, but obviously distorted as it's the wrong bpp setting (I think? Bits 2-0 all low should be 1 bit per pixel in the BP2Rast_cmd byte, right?)

Here's my GPU settings:
Code: [Select]
    ; set GPU base_addr for graphics
    LD      HL,0F001H       ; set Y[3] to 01
    CALL    send_gpu
    LD      HL,0B200H       ; set X[3] to 200
    CALL    send_gpu
    LD      HL,7F00H        ; send cmd 124 to set destination base address
    CALL    send_gpu
    ; set raster width (H) and bit depth (L)
    LD      HL,0F000H       ; reset Y[3] to 0
    CALL    send_gpu
    LD      HL,0B27FH       ; set X[3] to 639
    CALL    send_gpu
    LD      HL,7100H        ; set dest width to Y[3]X[3] and bpp to 0 for 2 colours
    CALL    send_gpu
    ; set X & Y limits
    LD      HL,827FH        ; set X[0] to 639
    CALL    send_gpu
    LD      HL,0C1DFH       ; set Y[0] to 479
    CALL    send_gpu
    LD      HL,5F00H        ; set max X & Y to X[0],Y[0]
    JP      send_gpu
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 15, 2020, 07:22:30 pm
A) 08 00 0F 00 12 00 00 50 02 7F 01 8F 00 00 00 00

 :palm: Your boot up values were already correct except for the character in blue which changed the text column address repeat mode to regular graphics.

Don't forget you need to set the background(pen0) and foreground(pen1) colors with the 'green' colored settings.  Otherwise everything will be black and transparent.

Remember the color settings?
This is how you assign the position of both colors into the chosen palette color.
Or, on a 4 color screen, it assigns the missing upper 6 bits for that maggie layer.
How do you think we are able to assign dedicated palettes to each layer's colors when they have less than 256 colors?

You have a github account for this project.  Let's see you current manual for using the MAGGIE.  I'm sure the color palette assignment bits were in my documentation.

In other words: Where is the MAGGIE manual?
MAGGIE has been finished for over 6 months.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 15, 2020, 11:15:03 pm
The manual is in docs/Microcom GPU Manual.docx.

There's been a fair bit of editing with the learning I've done over the last few days, I've yet to update that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 15, 2020, 11:28:35 pm
The manual is in docs/Microcom GPU Manual.docx.

There's been a fair bit of editing with the learning I've done over the last few days, I've yet to update that.
I'm just teasing.
But now, you have a geometry processor and enough ram for 640x480 if you change the font to 8x8 and we move the HW registers outside the first 512 bytes to the end of memory.

Big update on the GPU core coming.
I got rid of the 4word 0latency fifo and changed it for my own 2word FWFT fifo.
It saved 10% on the logic cell count and it's easier to hit the crucial 125MHz FMAX.
I've also added 2 XOR color transformations on the CopyPixel and PastePixel commands.

Now all that's left the the geometry plotter's ellipse, filled triangle & a rectangle copy from graphic ram A to B, size (X,Y).

Then your done.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 16, 2020, 06:17:35 am
Here is a test GPU project.  I've changes all the 3/4 word fifos into a new 2 word fifo.  Verify everything works.
We've gone from 90% utilization to 79%.  With a few compiler setting changes, we can possibly get this same project down to 72%.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 16, 2020, 11:07:35 pm
Been busy with other stuff for the last 24 hours - tomorrow probably the same as well - but I grabbed an hour or so to have a look at your latest update just now and I can't really test it properly.

Well, it seems to work fine as far as I can tell, but when I ran my graphics test program which draws a grid on the screen (each cell 10x10 pixels) with a single red cursor (drawn with a single filled rectangle), the image was corrupted - the vertical lines were no longer regularly spaced (or every third vertical line is missing and they aren't aligned with the start and end of the screen), and the red 'cursor' that should fill a cell spills into adjacent cells.

I've tried two previous versions of the GPU project as well as your new version and the results are the same.

I added some random lines to the mix and the attached image is what I get.  Now I'm not really sure what's going on - I'm just hoping that it's a simple error I've made in my test code, but I can't see anything.

Before you start tearing the HDL apart, I just thought I'd post the pics in case it's an obvious issue that you can identify straight away.  Otherwise, I'll have to put together another test program to see if the same thing happens again or if it's some stupid bug I've introduced to the original test program somehow.  The lines and the red rectangle are making me wonder if it's not my test code, though.  There's no way I'm aware of that a mistake in my code (MAGGIE settings or geo_unit setup) could produce broken lines or rectangles like that.  :-//

... but text mode is working absolutely fine - I'm not detecting any errors or artefacts in the symbols or text mode in general, even after running the test program above - so that points the finger back at the MAGGIE/geo_unit settings again...

[attachimg=1]

I'm really short on time at the moment, otherwise I'd dig into this a lot more before posting, but it's late here and I have to hit the sack.  This is worrying me though, as it's done the same thing on three different versions of the project.

The only other thing I'm worried about is if something has broken in the FPGA, but I've no real reason to think that.

Second image is 640x480 mode - same grid with random lines.  I haven't been able to get the grid to display properly in 640x480, despite your recent posts with revised MAGGIE settings, so the distorted grid is 'normal', but the broken lines are showing up in this mode too.

The Z80 seems to be able to read and write the GPU RAM just fine - I can load in new character sets from CP/M so block reads/writes to GPU RAM are working fine.  :-\

Any ideas?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2020, 12:19:38 am
Maybe in the latest update, I overwrote the wrong 'data_mux_geo.sv'.

Yup, just checked, overwrote the 'data_mux_geo.sv' with an older one in the last update.
I'm making a new clean 'GPU' project now.
Until I upload it, you may swap out the 'data_mux_geo.sv' with the gpu_xxx_endianfix.zip upload which has the correct .sv version inside.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2020, 02:09:48 am
Ok, I completely cleaned and rebuilt your 'GPU_EP4CE10'.
This means rename or backup-delete whatever folder you have now and begin this new one alone.

Two thing you need to do.
A) You have 2 IO pins in your design which still have no IO pin assignment.  It's been like this awhile.
B) You need to change your PS2 keyboard decoder for a synchronous one.  The one you have which crosses 3 clock domains is messing up the timing report and the compiler's efforts to rank how to optimize it's location in the FPGA fabric.  You other choice is to learn how to setup and define cross domain clock correlation timing restrictions.

As the design is 83% full and we have some spaghetti logic, achieving the FMAX is becoming difficult as we are close to the edge.  Without providing assignments to the compiler to give it clues on where to layout the logic, or having the full subscription version of Quartus & progressively fitting the design withe the much more powerful logic-lock functions, we are left with adding pipeline buffers and trying the let the compiler work out how to deal with the design optimization on it's own.  Also, for now, defining where to locate logic on the fpga would all become useless if you change fpga size or go to another vendor.

I've made some additional changes, so let me know if this latest version works fine & let me know if you can switch to a better all synchronous PS2 keyboard interface.

(You can see you had a lot of useless residue in the older uploads as this .zip is ~1/2 size for the complete project.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 17, 2020, 10:00:51 am
Ok, I completely cleaned and rebuilt your 'GPU_EP4CE10'.
This means rename or backup-delete whatever folder you have now and begin this new one alone.

Awesome, thank you - all working fine now.

Two thing you need to do.
A) You have 2 IO pins in your design which still have no IO pin assignment.  It's been like this awhile.

Done this now - have assigned the tx/rx LED outputs for the rs232_debugger module in the pin planner.  Seem to still be getting the 'some pins have incomplete assignments' message, though?  How do I view the I/O Assignments Warnings report?  I can't seem to find out how to view it online..

B) You need to change your PS2 keyboard decoder for a synchronous one.  The one you have which crosses 3 clock domains is messing up the timing report and the compiler's efforts to rank how to optimize it's location in the FPGA fabric.  You other choice is to learn how to setup and define cross domain clock correlation timing restrictions.

I'll work on this this week.  :-+

I've made some additional changes, so let me know if this latest version works fine & let me know if you can switch to a better all synchronous PS2 keyboard interface.

It's all good.  :-+  Will try to find another PS2 interface module, or start converting the existing one to SystemVerilog and synchronous logic.  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 17, 2020, 11:04:39 am
Before I start investing precious time working this new file into the project and getting it to work with the Z80 interface, do you think the attached PS2 module would be an improvement?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2020, 09:06:19 pm
Ok, here is an enhanced cleaned up version which has a ton of wiggle room on the FMAX for the geometry unit at the limiting factors right now isn't even the geometry processor, but the Z80 bridge and vid_osd_generator.  Download the new attached Quartus project.  Make sure you older one is renamed so there is no chance some Quartus compile settings wont migrate between versions.

Though we are at 84% device utilization now, it is better than the 90% we were at last week.

My replacement of the 4 word 0 latency fifo for the new 2 word FWFT fifo really made it possible and I don't think the geometry unit has suffered.  However, you need to test everything once again to make sure.  A speed test of the filled full screen boxes will tell you.  If you still get 20 vertical colored bars, then we are still at full pixel writing speed.

I also finished the pixel writer copy&paste color transformation feature to alter the color between source image and destination image.  Simulation illustration coming.

(My new 2 word FWFT elastic FIFO designed purely to increase FMAX in large processing designs located here: 2 Word FWFT FIFO (https://www.eevblog.com/forum/fpga/2-word-first-word-fall-through-(fwft)-fifo-fifo-style-elastic-buffer-for-speed/msg3191352/#msg3191352) )

(New slacks now attached in image.  Worst geometry now has 0.625ns clack and the system worst is 0.405ns slack instead of last week's version where the worst slack was 0.081ns and took 4.5 minutes to compile.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 17, 2020, 11:03:50 pm
Ok, here is an enhanced cleaned up version which has a ton of wiggle room on the FMAX for the geometry unit at the limiting factors right now isn't even the geometry processor, but the Z80 bridge and vid_osd_generator.  Download the new attached Quartus project.  Make sure you older one is renamed so there is no chance some Quartus compile settings wont migrate between versions.

Though we are at 84% device utilization now, it is better than the 90% we were at last week.

Wow, thanks - performance seems to have jumped as far as I can tell.  Just wondering if the compilation setting was right, though?  I'm sure I saw it prioritising area at the expense of timing?

My replacement of the 4 word 0 latency fifo for the new 2 word FWFT fifo really made it possible and I don't think the geometry unit has suffered.  However, you need to test everything once again to make sure.  A speed test of the filled full screen boxes will tell you.  If you still get 20 vertical colored bars, then we are still at full pixel writing speed.

Here's what I'm getting now - although I don't think the video (or my phone, more specifically) is up to the task any more...

https://www.youtube.com/watch?v=QtV0wiNAkBw (https://www.youtube.com/watch?v=QtV0wiNAkBw)

The bars are not as clear as they were previously - they're thinner - so it looks like the system is working faster.  The palette was slightly corrupted from a previous test, so some of the bars may be very similar colours, but I'm counting about 25?

I also finished the pixel writer copy&paste color transformation feature to alter the color between source image and destination image.  Simulation illustration coming.

(My new 2 word FWFT elastic FIFO designed purely to increase FMAX in large processing designs located here: 2 Word FWFT FIFO (https://www.eevblog.com/forum/fpga/2-word-first-word-fall-through-(fwft)-fifo-fifo-style-elastic-buffer-for-speed/msg3191352/#msg3191352) )

(New slacks now attached in image.  Worst geometry now has 0.625ns clack and the system worst is 0.405ns slack instead of last week's version where the worst slack was 0.081ns and took 4.5 minutes to compile.)

Okay, I need to focus on testing the collision timers and these new copy/paste commands.  Might get a little time tomorrow, hopefully.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2020, 11:57:32 pm
It looks all messed up.  It looks slower in your video compared to the earlier stable ones, or at least stability-wise.  Did you change your code?  This may be a bug on my end.  Try 1 or 2 earlier versions of the GPU.  Or, has you cell phone video capture slowed down?

You didn't need to video the bars, just count them.  Originally, your Z80 is clearly out-pacing the first 512 word geometry FIFO input, but you wont be able to see overshoot errors.  I see around 20 bars in your still image.  The question was not if it was going faster, but was it going slower.

What I needed to see was properly drawn lines.  An also, my recommendation for a simple line algorithm in assemble which just incremented in 8 bit the x0,y0 and x1,y1 coordinates by those odd numbers, plus add 1 to color for every line, only checking the keyboard after every 256 lines drawn.  All 8 bit single inc and odd opps to try and tax the line algorithm.

This would also prove a massively more impressive video as no Z80 could ever render so many screen size lines ever so fast before.  The screen fills only showed a final few percent of the filled rectangles.  However it is now clear, once we have the copy-blit function in geo unit, you will then be able to render your font, or multiple fonts on the bitmap screen with even proportional spacing as well as smoothly scroll the screen pixel-by-pixel in any direction without relying on the MAGGIE as a special layer function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 01:47:38 am
Wow, thanks - performance seems to have jumped as far as I can tell.  Just wondering if the compilation setting was right, though?  I'm sure I saw it prioritising area at the expense of timing?

There is something utterly messed up with that setting in Quartus Prime.  Anything I use has little effect on the performance.  However, in older Quartus -Non Prime- versions, there older Synthesis Optimization Technique, Speed, Balanced, Area, actually worked for your design.  So, I added this line in the assignment editor:

set_global_assignment -name CYCLONEII_OPTIMIZATION_TECHNIQUE SPEED

Low and behold, with some of my other code changes, it worked.  And yet, Quartus Prime doesn't even support 'CYCLONEII', yet, that setting is in the 'Advanced Settings (Synthesis)' in the compiler settings as plain old 'optimization technique.'  Now, if you want to contact Intel and find out why, be my guest.  I'm sure you can join their forum and post the question with your project stats.  Maybe there is a more modern and better way to achieve the same capability, but I do not know what it is.

By the way, changing this setting in the compiler yields:
Area - 78% full, 125Mhz
Balanced - 81% full, 127MHz
Speed - 84% full, 131MHz.

Yet that stupid Optimization Mode window with the 6 settings does diddly-squat.

(Edit, is some cases that Optimization Mode does work, however, it seems to only be adjusting the 'Fitter' controls, not the 'Synthesis' compiling work like the CycloneII Synthesis Optimization Technique.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 07:55:53 am
Before I start investing precious time working this new file into the project and getting it to work with the Z80 interface, do you think the attached PS2 module would be an improvement?  ???

Since I do not have a board to test this module, I cannot say anything about it's function.  However, it does seem to be a synchronous design and it also seems it can transmit something on the PS2 bus as well since it uses tristate ports for the PS2 IO.  I think you can control the keyboard LEDs with it.

Give it a try, but there is 1 line in it which Quartus is ignoring.  Take a look at line 652.  You'll  notice it is green/commented out.  You'll need to delete the last character on line 651 to make that line active code, or, just add an additional space at the end of line 651.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2020, 08:31:37 am
It looks all messed up.  It looks slower in your video compared to the earlier stable ones, or at least stability-wise.  Did you change your code?  This may be a bug on my end.  Try 1 or 2 earlier versions of the GPU.  Or, has you cell phone video capture slowed down?

Lighting was different, so the exposure setting on the camera lens may have been different.

You didn't need to video the bars, just count them.  Originally, your Z80 is clearly out-pacing the first 512 word geometry FIFO input, but you wont be able to see overshoot errors.  I see around 20 bars in your still image.  The question was not if it was going faster, but was it going slower.

What I needed to see was properly drawn lines.  An also, my recommendation for a simple line algorithm in assemble which just incremented in 8 bit the x0,y0 and x1,y1 coordinates by those odd numbers, plus add 1 to color for every line, only checking the keyboard after every 256 lines drawn.  All 8 bit single inc and odd opps to try and tax the line algorithm.

I'll have a go at this later this afternoon hopefully, but I'm not convinced I understand exactly what you're asking for.  It seems you want arbitrary-length lines that have 3,7 added to X[0],Y[0] and 5,9 added to X[1],Y[1] and their colour incremented every loop?  Is that right?  Not full-screen horizontal lines (I guess because they'd generate far more cache hits)?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2020, 08:39:30 am
Since I do not have a board to test this module, I cannot say anything about it's function.  However, it does seem to be a synchronous design and it also seems it can transmit something on the PS2 bus as well since it uses tristate ports for the PS2 IO.  I think you can control the keyboard LEDs with it.

Yes, I think that's the idea - it can control the status LEDs on the keyboard.

Give it a try, but there is 1 line in it which Quartus is ignoring.  Take a look at line 652.  You'll  notice it is green/commented out.  You'll need to delete the last character on line 651 to make that line active code, or, just add an additional space at the end of line 651.

That's the unescaped backslash character in the comment on line 651 causing that.  Interestingly, the code appears fine in my Quartus Prime editor window.  When I viewed the code in Notepad++ yesterday it had displayed the next line as 'commented out', the single backslash was confusing the text renderer, but Quartus appears to be coping with it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2020, 02:50:12 pm
I've updated the PS/2 interface to the Verilog-only version.  Have tweaked the original code a bit to get it sending break codes in the format I need for the Z80_bridge, and to cope with CTRL-C codes and CAPS LOCK.  Otherwise it's a pretty comprehensive module.

I've also stripped out some project files that are no longer used (including the old PS/2 VHDL stuff).

Compilation reports the following now:

I have a couple of questions on the project so far:

EDIT:  Okay, I've got Fmax back up to 133.21 MHz for clk[0] by adding a FF between the status output of the PS/2 module and the input of the Z80_bridge. Woot.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 04:21:01 pm
I have a couple of questions on the project so far:
  • Fmax has dropped again (see red above) - any tips/advice on how to find bottlenecks?
  • The pixel collision counters - why are they 8-bit and are they for detecting sprite collisions and/or something else?

1. Give me a sec.  For now, those figures are functional.  (YOU MODIFIED THE COMPILER SETTINGS...)

2a. I can switch them down to 1 bit (no collision, or yes, a hit) like a normal 8 bit computer if you like.
2b. We can also remove these collision counters completely since 8 bit computers since cant detect collisions when writing pixels in the first place. They have player missile and sprite collision detectors.  We have yet to add any collision detectors to the MAGGIE layers.  These are different.  Each layer will have a 16 bit register where each bit, 0 through total layer number which will go from 0 to 1 depending on a collision with each associated layer's pixel set to that bit#.  Once again, if you do not like this, we can make each layer have only a single bit collision detector telling you if it collided with anything at all like any 8 bit computer or Amiga.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2020, 04:54:52 pm
I have a couple of questions on the project so far:
  • Fmax has dropped again (see red above) - any tips/advice on how to find bottlenecks?
  • The pixel collision counters - why are they 8-bit and are they for detecting sprite collisions and/or something else?

1. Give me a sec.  For now, those figures are functional.  (YOU MODIFIED THE COMPILER SETTINGS...)

Hmmm.. maybe - I added in the CYCLONE II setting you'd mentioned.  Anyway, as per my edit in my previous post, I've got Fmax back up to 133 MHz now.  :-+

2a. I can switch them down to 1 bit (no collision, or yes, a hit) like a normal 8 bit computer if you like.
2b. We can also remove these collision counters completely since 8 bit computers since cant detect collisions when writing pixels in the first place. They have player missile and sprite collision detectors.  We have yet to add any collision detectors to the MAGGIE layers.  These are different.  Each layer will have a 16 bit register where each bit, 0 through total layer number which will go from 0 to 1 depending on a collision with each associated layer's pixel set to that bit#.  Once again, if you do not like this, we can make each layer have only a single bit collision detector telling you if it collided with anything at all like any 8 bit computer or Amiga.

I have no preference, really. I'll go with whatever you think is best.  :-+  They sound handy - I was just asking as I wasn't sure if they were for detecting sprite collisions or something else that I couldn't grasp.  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 06:35:34 pm
Here is the updated .zip.
Don't worry about how close the FMAX is, everything is set to area and you still have good clearance for the geometry unit with is the most mathematically intense part of your entire design.

I also patched the address generator back a revision as a simple 2 layer carry buffer was better than a FIFO.

The running plot line example I asked you for was to be able to send as many different line commands as possible.  The z80 is 8 bit, so, to send as many different x&y coordinates as possible, a simple add, 5 different add figures, 1 for each coordinate and 1 for a different color would plot a lot of different lines very quickly compared to generating 5 different random numbers for each line drawn.  This test would at least get you close to the speed of drawing geometry from cpu ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 06:37:00 pm

I have no preference, really. I'll go with whatever you think is best.  :-+  They sound handy - I was just asking as I wasn't sure if they were for detecting sprite collisions or something else that I couldn't grasp.  :o

Well, going down to a 1 bit collision counter will save 14 registers and a few gates on the FPGA.

The sprite collision detector needs to be done in the 'palette_mixer.sv' since that module receives all the different pixel layers in parallel before it chooses which dot from which layer ends up being the final pixel shown.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2020, 07:04:18 pm
Here is the updated .zip.
Don't worry about how close the FMAX is, everything is set to area and you still have good clearance for the geometry unit with is the most mathematically intense part of your entire design.

I also patched the address generator back a revision as a simple 2 layer carry buffer was better than a FIFO.

Runs fine.  I've updated the Z80_bridge and ps2_keyboard_interface with some changes I'd made today, so here's the latest project files at the end of the post.

The running plot line example I asked you for was to be able to send as many different line commands as possible.  The z80 is 8 bit, so, to send as many different x&y coordinates as possible, a simple add, 5 different add figures, 1 for each coordinate and 1 for a different color would plot a lot of different lines very quickly compared to generating 5 different random numbers for each line drawn.  This test would at least get you close to the speed of drawing geometry from cpu ram.

Okay, well I can give this a shot tomorrow perhaps.  I really need to start looking at these triangle and circle functions too.  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 09:47:22 pm
The 2 key settings to get the FMAX to the top for this design:  This increases the the design back to 84% utilization.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2020, 09:49:08 pm
Ready to go on the filled triangle.
Tell me what you have learned so far on the triangle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 19, 2020, 10:03:25 am
Ready to go on the filled triangle.
Tell me what you have learned so far on the triangle.

Setup is key.  Three line generators operate on three sets of coordinates in the registers X[0]Y[0] to X[2]Y[2].  The three lines need to be ordered vertically in the registers so that register set
There's some extra drawing to ensure lines meet and there's no empty pixels at the edges.

 :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 19, 2020, 07:34:53 pm
Take a look at the basic code and recount the line generators.
There are a few tricks buried in this.

Separate out the steps involved in setting up and running each of the line generators.
Remember, we don't want to just add more and more line generators to our design, we the minimum necessary, meaning, even when calling a simple line, box, or box fill, we want to use the exact line generators as the filled triangle, is only the order and setup in which we run those few line generators.  Logic space is at a premium here.

Yes, even when we get to the ellipse, it will be an addition to one of the line generators which will have a adapted arc radius, or, drawing a triangle with 1 rounded face, 4 of them rotated 90 degrees from each other with the inner face line just not drawn.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 19, 2020, 09:23:12 pm
Take a look at the basic code and recount the line generators.

D'oh.  There's only two.  One is re-used for the third line.  ;)

Separate out the steps involved in setting up and running each of the line generators.

1) Order the lines so that the two line generators run on the first and third lines, with one line stopping and that line generator then drawing the second line.
2) Each line is setup by calculating its bounding box's width and height
3) Signs are calculated for the stepping increments according to the direction of the line
4) Key values are assigned to magic, errd and is_done to allow the line generator to run
5) Line generators are run, filling in horizontal raster lines between the two lines being drawn if fill mode is on
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 19, 2020, 11:48:21 pm
Take a look at the basic code and recount the line generators.

D'oh.  There's only two.  One is re-used for the third line.  ;)

Separate out the steps involved in setting up and running each of the line generators.

1) Order the lines so that the two line generators run on the first and third lines, with one line stopping and that line generator then drawing the second line.
2) Each line is setup by calculating its bounding box's width and height
3) Signs are calculated for the stepping increments according to the direction of the line
4) Key values are assigned to magic, errd and is_done to allow the line generator to run
5) Line generators are run, filling in horizontal raster lines between the two lines being drawn if fill mode is on
Step #1 is more like the first linegen is the tallest vertical line.
Line #2 begins by touching the top of line #1.
Increment a Y pixel at a time for each line.
If there is empty space, draw a line (will be the linegen3 engine) between the X coordinates of linegen #1 and #2.
Loop around until lingen2 ends, the reset linegen2 with the lat 2 points on the triangle.

Currently, we have a dumb linegen3, but, we might as well replace it with a normal smart one.

Ok, what you said is ok, but, what we want is the order of operations before we start drawing, IE the setup, and what instructions to send to the linegens.

This organization step is important as with a variable setup and control, our triple linegen engine with the right setup controls will also replace our single linegen as well as out box, box-fill, 4 point polygon & fill, + ellipse.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2020, 12:14:08 am
I'm working on setting up your IO timing rules.  It's a mess as some buses cross IO banks and is f---ng things up.  I need to know what output pins you have set the led_rxd and led_txd.

When going to a higher pin count FPGA, you will need to read the datasheet and choose the IOs wisely, otherwise you wont get anywhere near good performance with external ram without a crap load of carry chains destroying the read-turn-around times.  And carry chains will not work if you have IO on opposite sides of the FPGA silicon or use the any one of the 4 slower IO banks out of the 8.

My biggest headache is with 4 IO which are dual purpose pins as they have also the ability to be a 'VREF' input, there are 4 of them.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2020, 06:33:53 am
Ok, this one took all day.  (Poor documentation from Altera/Intel)

I've setup your timing constraints.  To do so, I had to add additional delay pipe chains in the Z80 bridge, video out and a few other places, however now, Quartus is respecting the IO timings, core clock frequency & the Fast IO assignments now appear to function correctly.

It should now compile quickly & achieve the timing requirements filling the FPGA to only 76%.

If it were'nt for those 4 IOs on the vref pins, all your outputs would be within 300ps of each other.  Those 4 IOs are 1.3 ns slower than your slowest output.  Though, your DAC clk output is the fastest output at 25MHz.
Inputs are tight too except for the PS2 keyboard interface which wasn't engineered for speed.

I also changes the DAC CLK output to a synthesized 25MHz clock generated from the sync generators /5 of the 125MHz clk.

You'll need to test everything.  On my side, my DAC on my scaler wasn't designed to operate down to 25MHz, so I have a shaded bar on the left hand side of the screen.  Make sure you do not see this.

Let me know if everything works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 20, 2020, 09:38:05 am
I'm working on setting up your IO timing rules.  It's a mess as some buses cross IO banks and is f---ng things up.  I need to know what output pins you have set the led_rxd and led_txd.

Uh, looks like their pin assignments got lost with the project going back and forth over the last couple of days.  I'm actually not using them - may as well remove the output pins.  :-//

When going to a higher pin count FPGA, you will need to read the datasheet and choose the IOs wisely, otherwise you wont get anywhere near good performance with external ram without a crap load of carry chains destroying the read-turn-around times.  And carry chains will not work if you have IO on opposite sides of the FPGA silicon or use the any one of the 4 slower IO banks out of the 8.

I'm hoping I might have a little more flexibility in choosing which IOs to use in a BGA setup - or they'll all be as hard to route as each other - as the QFP package I'm using is fairly restrictive in terms of choice of IO pin due to their position on the package and what's physically near it on the PCB.

My biggest headache is with 4 IO which are dual purpose pins as they have also the ability to be a 'VREF' input, there are 4 of them.

Well I'm open to suggestions for the BGA iteration of the board.  I should steer clear of dual-purpose pins, then?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 20, 2020, 10:33:55 am
Ok, this one took all day.  (Poor documentation from Altera/Intel)

I've setup your timing constraints.  To do so, I had to add additional delay pipe chains in the Z80 bridge, video out and a few other places, however now, Quartus is respecting the IO timings, core clock frequency & the Fast IO assignments now appear to function correctly.

It should now compile quickly & achieve the timing requirements filling the FPGA to only 76%.

If it were'nt for those 4 IOs on the vref pins, all your outputs would be within 300ps of each other.  Those 4 IOs are 1.3 ns slower than your slowest output.  Though, your DAC clk output is the fastest output at 25MHz.

I'm not going to cry over 1.3ns unless it causes issues later, but this design has outgrown the EP4CE10 a lot faster than I thought it would - it really does appear that BGA is the way to go.

I had a look around at various packages and models in the Cyclone range last night.  I had pretty much decided on the EP4CE22F17 as the next step - though I'm wondering if the jump straight to an EP4CE40 might be worth it.  That's an FBGA-484 package, though - perhaps that should wait until I've developed some skill with the FBGA-256 first.

I guess I was just wondering what's in the ball-park of realistic home-DIY soldering (and PCB design)?  Is an FBGA-484 too much?  Then there's the Cyclone V range.  The smallest one appears to have over 150 KB of RAM and 40% lower power usage, and I can get it in FBGA-256 (5CEBA4F17 - https://uk.rs-online.com/web/p/fpgas/8303565/ (https://uk.rs-online.com/web/p/fpgas/8303565/)).

Talking of power usage, I've fitted a heatsink over the 1.2V regulator now.  It's still almost too hot to touch, but it makes me feel happier.  :o

You'll need to test everything.  On my side, my DAC on my scaler wasn't designed to operate down to 25MHz, so I have a shaded bar on the left hand side of the screen.  Make sure you do not see this.

Let me know if everything works.

It all works with no anomalies or glitching. None of the tests have thrown up issues, there's no shaded bar down the side of the screen, it all looks good.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2020, 11:32:57 am
I had a look around at various packages and models in the Cyclone range last night.  I had pretty much decided on the EP4CE22F17 as the next step - though I'm wondering if the jump straight to an EP4CE40 might be worth it.  That's an FBGA-484 package, though - perhaps that should wait until I've developed some skill with the FBGA-256 first.
Before jumping to really expensive FPGAs, look at this post here:

https://www.eevblog.com/forum/fpga/quartus-prime-18-1-cant-fit-design-in-device/msg3178780/#msg3178780 (https://www.eevblog.com/forum/fpga/quartus-prime-18-1-cant-fit-design-in-device/msg3178780/#msg3178780)

A little research might reveal what you are getting at what price.

Quote
I'm not going to cry over 1.3ns unless it causes issues later, but this design has outgrown the EP4CE10 a lot faster than I thought it would - it really does appear that BGA is the way to go.

No problem on this design as everything is slower than 40ns for VGA out, 125ns/2 for Z80_CLK.  But if you want 250MHz DDR ram, IE 500mtps, that 1.2ns on 1 or 2 specific pins in each IO bank would potentially be disastrous.  Or not using the dedicated PLL CLK & CLKn output pins to drive the memories CLK inputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2020, 04:51:41 pm
Ok, lets see your triple line drawing engine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 20, 2020, 07:34:54 pm
Ok, lets see your triple line drawing engine.

Hmmm well, my first question in writing this function is that as it uses two line drawing engines, how best do I utilise the existing line-drawing engine in the geometry_xy_plotter module?   Do I need to create it as a sub-module and instantiate it for use in the triangle function, or can I somehow re-use the existing function?

Code: [Select]
4'd1 : begin    // draw line from (x[0],y[0]) to (x[1],y[1])
 
case (geo_sub_func1)    // during the draw line, we have multiple sub-functions to call 1 at a time

4'd0 : begin

errd            <= dx + dy;
geo_sub_func1   <= 4'd1;                 // set line sub-function to plot line.

end // geo_sub_func1 = 0 - setup for plot line

4'd1 : begin

draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.

if ( ( geo_x >= 0 && geo_x <= max_x ) && (geo_y>=0 && geo_y<=max_y) )
draw_cmd_tx     <= 1'b1;            // send command if geo_X&Y are within valid drawing area
else
draw_cmd_tx     <= 1'b0;            // otherwise turn off draw command

if ( geo_x == x[1] && geo_y == y[1] ) geo_shape <= 4'd0;   // last pixel - step to last sub_func1 stage, allowing time for this pixel to be written
// On the next clock, end the drawing-line function
 
// increment x,y position
if ( ( errd << 1 ) > dy ) begin

  geo_x   <= geo_x + geo_xdir;
 
  if ( ( ( errd << 1 ) + dy ) < dx ) begin
 
geo_y   <= geo_y + geo_ydir ;
errd    <= errd + dx + dy   ;

  end else begin
 
errd    <= errd + dy   ;

  end
 
end else if ( ( errd << 1 ) < dx ) begin
  errd    <= errd  + dx       ;
  geo_y   <= geo_y + geo_ydir ;                           
end

end // geo_sub_func1 = 1 - plot line

endcase // sub functions of draw line
 
end // geo_shape - draw line
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2020, 08:22:45 pm
Ok, lets see your triple line drawing engine.

Hmmm well, my first question in writing this function is that as it uses two line drawing engines, how best do I utilise the existing line-drawing engine in the geometry_xy_plotter module?   Do I need to create it as a sub-module and instantiate it for use in the triangle function, or can I somehow re-use the existing function?

Code: [Select]
4'd1 : begin    // draw line from (x[0],y[0]) to (x[1],y[1])
 
case (geo_sub_func1)    // during the draw line, we have multiple sub-functions to call 1 at a time

4'd0 : begin

errd            <= dx + dy;
geo_sub_func1   <= 4'd1;                 // set line sub-function to plot line.

end // geo_sub_func1 = 0 - setup for plot line

4'd1 : begin

draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.

if ( ( geo_x >= 0 && geo_x <= max_x ) && (geo_y>=0 && geo_y<=max_y) )
draw_cmd_tx     <= 1'b1;            // send command if geo_X&Y are within valid drawing area
else
draw_cmd_tx     <= 1'b0;            // otherwise turn off draw command

if ( geo_x == x[1] && geo_y == y[1] ) geo_shape <= 4'd0;   // last pixel - step to last sub_func1 stage, allowing time for this pixel to be written
// On the next clock, end the drawing-line function
 
// increment x,y position
if ( ( errd << 1 ) > dy ) begin

  geo_x   <= geo_x + geo_xdir;
 
  if ( ( ( errd << 1 ) + dy ) < dx ) begin
 
geo_y   <= geo_y + geo_ydir ;
errd    <= errd + dx + dy   ;

  end else begin
 
errd    <= errd + dy   ;

  end
 
end else if ( ( errd << 1 ) < dx ) begin
  errd    <= errd  + dx       ;
  geo_y   <= geo_y + geo_ydir ;                           
end

end // geo_sub_func1 = 1 - plot line

endcase // sub functions of draw line
 
end // geo_shape - draw line

You can:
A) Make 1 module which runs on arrays.
B) Copy and paste the line to make 3 of them.
C) Make a new module which you can call 3 times.

Before all this, there is some mathematical prep work which needs to be taken care of.  One big part and FMAX killer is determining which arrays have equal X, or Y coordinates.  What are the array groups order from low to high on the Y  axis and also X axis.  Prep up these flags creating a status array so you know which line functions draw what and in what order.  Remember, you have 4 sets of coordinated to compare.  This should all be prepared in advance before the draw command is even being given since the any and all X&Y coordinates are being sent in advance of the draw command.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2020, 10:55:25 pm
I am talking about you making a module which takes in X[0..3] or Y[0..3] and returns all the point which are equal, greater than and less than in 3 arrays which can easily be checked/used to select which lingen should be used (IE: if all X & Y coordinates on the 3 vertices are equal, no lingen will be used, just draw a point), each of those linegen's source and destination X[?]&Y[?] coordinates and select whether to add or subtract the x&y counter (x&y dir) in each linegen module's arithmetic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 21, 2020, 01:29:07 am
I guess I was just wondering what's in the ball-park of realistic home-DIY soldering (and PCB design)?  Is an FBGA-484 too much?  Then there's the Cyclone V range.  The smallest one appears to have over 150 KB of RAM and 40% lower power usage, and I can get it in FBGA-256 (5CEBA4F17 - https://uk.rs-online.com/web/p/fpgas/8303565/ (https://uk.rs-online.com/web/p/fpgas/8303565/)).
The '5CEBA2F17C8N' may actually be identical to the 5CEBA4F17 just like the EP4CE6 is identical to the EP4CE10...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 21, 2020, 12:10:47 pm
I am talking about you making a module which takes in X[0..3] or Y[0..3] and returns all the point which are equal, greater than and less than in 3 arrays which can easily be checked/used to select which lingen should be used (IE: if all X & Y coordinates on the 3 vertices are equal, no lingen will be used, just draw a point), each of those linegen's source and destination X[?]&Y[?] coordinates and select whether to add or subtract the x&y counter (x&y dir) in each linegen module's arithmetic.

Hmm.. well, this is what I've got at the moment.  It's taken straight from the FreeBasic geo program to set up the order of lines to be drawn.  It's not what you're asking for though, by the looks of it.  It doesn't do the sign (x & y dir) yet, but I'm not sure I'm on the right path anway..... it sounds like you want a module that returns three arrays - equal, greater than and less than - with the coordinates ordered accordingly and a sign flag for the use of another module?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 21, 2020, 12:23:01 pm
I guess I was just wondering what's in the ball-park of realistic home-DIY soldering (and PCB design)?  Is an FBGA-484 too much?  Then there's the Cyclone V range.  The smallest one appears to have over 150 KB of RAM and 40% lower power usage, and I can get it in FBGA-256 (5CEBA4F17 - https://uk.rs-online.com/web/p/fpgas/8303565/ (https://uk.rs-online.com/web/p/fpgas/8303565/)).
The '5CEBA2F17C8N' may actually be identical to the 5CEBA4F17 just like the EP4CE6 is identical to the EP4CE10...

Right, so let me get this straight - the EP4CE6 and EP4CE10 are physically identical - it's the Quartus software that artificially limits the capabilities of the CE6 chip?  Potentially the only difference in the chips is the model identifier or some fuse setting? Interesting.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 21, 2020, 05:06:55 pm
Potentially the only difference in the chips is the model identifier or some fuse setting? Interesting.
No fuse identifier.  Didn't you not see the jtag scan of the chip in the last post.  Quartus could not tell whether the installed FPGA it was scanning was an EP4CE10, or a EP4CE6.  Look at the picture in the last post.  In fact, it also couldn't tell in that same FPGA was a CycloneIII EP3C5 or EP3C10.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 21, 2020, 05:24:58 pm
I am talking about you making a module which takes in X[0..3] or Y[0..3] and returns all the point which are equal, greater than and less than in 3 arrays which can easily be checked/used to select which lingen should be used (IE: if all X & Y coordinates on the 3 vertices are equal, no lingen will be used, just draw a point), each of those linegen's source and destination X[?]&Y[?] coordinates and select whether to add or subtract the x&y counter (x&y dir) in each linegen module's arithmetic.

Hmm.. well, this is what I've got at the moment.  It's taken straight from the FreeBasic geo program to set up the order of lines to be drawn.  It's not what you're asking for though, by the looks of it.  It doesn't do the sign (x & y dir) yet, but I'm not sure I'm on the right path anway..... it sounds like you want a module that returns three arrays - equal, greater than and less than - with the coordinates ordered accordingly and a sign flag for the use of another module?
The idea is ok, but you have not identified a lot of useful information.  Like which of the other lines go to which points.  Are any coordinates equal so you might not have to use a triangle but draw a single line.  What about drawing boxes or filled boxes and 4 sided polygons.

Like I said, first make a module to construct a cross comparison of a group of 4 coordinates.  I want to know equality, greater than and less than.

Try this.

Code: [Select]
input           logic           clk
input signed logic [11:0] in [0:3]
output         logic [15:0] in_a_eq_b
output         logic [15:0] in_a_gt_b
output         logic [15:0] in_a_lt_b

parameter bit CLOCK_OUTPUT = 0;

now, make the rest so that it will be possible to clock latch or run as combinational logic the following logic:

Code: [Select]
for (int i = 0 ; i<=15 ; i++) begin
in_a_eq_b[i] = (in[i[3:2]] == in[i[1:0]]);
in_a_gt_b[i] = (in[i[3:2]] > in[i[1:0]]);
in_a_lt_b[i] = (in[i[3:2]] < in[i[1:0]]);
end

Now, having 2 modules like this, one for all X[n] and one for all Y[n], you have the status 3 status 16 bit words which you can use to select how and what each line generator will be using and which direction they will be counting and it doesn't matter which shape you are trying to draw as you set IF selection just chooses to look only at the status bits required to construct the shape you are trying to draw.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 21, 2020, 10:27:14 pm
Potentially the only difference in the chips is the model identifier or some fuse setting? Interesting.
No fuse identifier.  Didn't you not see the jtag scan of the chip in the last post.  Quartus could not tell whether the installed FPGA it was scanning was an EP4CE10, or a EP4CE6.  Look at the picture in the last post.  In fact, it also couldn't tell in that same FPGA was a CycloneIII EP3C5 or EP3C10.

No, I missed that as I was looking at the linked posts on my phone.  Well, that's interesting if the Cyclone 5's two lowest devices are the same, as there's about £20 difference between them.  The A2 would be fine for what I need with ~170KB of RAM and 25,000 LEs, but if I could squeeze the extra 24,000 LEs and extra 132 KB of RAM out of it instead of buying an A4, that would be a win.  Either way, jumping up a generation to Cyclone V would appear to solve a lot of memory issues.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 23, 2020, 10:07:56 am
I'm falling behind badly - been a busy few days and there's no let up next week either.  :-\

I've completed the comparison module just now - code attached to make sure I've done it right - it compiles, which is a start.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 23, 2020, 06:01:01 pm
Just place it at the bottom of the 'geometry_xy_plotter.sv' module.
At the top, add in 2 instances, 1 for comparing the X[n] and one fore comparing the Y[n]

This line should read:

   input  signed [3:0][11:0] in,

   input  logic signed [11:0] in [0:3],

I am not sure the way you did the 'IF' and 'CLOCK_OUTPUT' will work without problems, but, we will see.


Next, the line gen modules.

We want to try to make 1 module to work in all situations.
A begin line which loads all the chosen X&Y variables.
A pass-through A input, this will pass the Ax,Ay coordinates right to the output and not engage any line drawing with the begin line function.
A pass-through B input. Same as above.
An input aX/Y and bX/Y for beginning and ending.
Has a smart pass through.  Meaning if the same beginning and ending point coordinates are at the inputs, just pass through the coordinates to write a single pixel and signal that the line is finished.
Has an enable option to draw until a specified Y coordinate has been reached.  (For raster fills on a chosen Y axis)
Has a 'Y stop' signed input to define that stopping Y coordinate.  This input is live and once changed during a stop, the linegen will continue until the new new Y coordinate has been reached or the line has reached it's end.  If we are on the last Y coordinate, to finish drawing the line, either the final Y coordinate may increase outside the Y drawing area or the Y stop enable flag may be turned off.

Outputs, X/Y coordinates.
Draw pixel data ready.
stopped on Y coordinate flag.
Finished drawing the line.

This should help you define our new line gen 'module'.
We will use 3 of them.  The first 2 line gens draw/generate the outer edge coordinates of our shape while the output of those 2 feed the coordinate inputs of the third lengen module so it may draw a line between the 2 source linegens.  With this setup, not only can we manipulate the line 3 line gens into drawing filled or un-filled triangles, but, boxes and 4 sided polygons as well just by setting up the starting conditions and when linegens 1&2 stop and go on new Y coordinates telling linegen 3 where and when to fill, or just run when 1&2 begin and finish creating an outline of a box instead of filling it.

Your compare module tells you before you begin either the draw point order for triangles, or if a vertical or horizontal line is being drawn so you do not need to do any filling.

Since we are in a crunch for time, we will do the blitter after this works.  You will need to solve the ellipse on your own after that.  The only thing I can offer is that you can make the linegens also generate ACRs, but if you are not comfortable, you can make a discrete module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 24, 2020, 10:05:35 am
Just place it at the bottom of the 'geometry_xy_plotter.sv' module.
At the top, add in 2 instances, 1 for comparing the X[n] and one fore comparing the Y[n]

Okay - any hints on what should be attached to the inputs / outputs yet, or does that depend on the next module being built?

This line should read:

   input  signed [3:0][11:0] in,

   input  logic signed [11:0] in [0:3],

I built the module in Quartus II and it threw errors if I used 'input logic signed', so I did some research online and arrived at 'input signed' instead.  It does appear that 'input logic signed' compiles with no errors in Quartus Prime, soo...  :-//

I am not sure the way you did the 'IF' and 'CLOCK_OUTPUT' will work without problems, but, we will see.

Me neither, but we'll see.  I'm hoping the compiler detects that the conditional is based on a compile-time setting and won't change during use, so it'll only synthesise the logic for one branch or the other.

I did have a quick look for conditional-compilation commands in SystemVerilog, but didn't find anything immediately obvious (probably because I should have been looking at Quartus, rather than SystemVerilog itself), but it compiles - I was expecting a 'signal has multiple drivers' error or something similar.

Next, the line gen modules.

We want to try to make 1 module to work in all situations.

So does this replace or part-replace the geo_xy_plotter module?  Seems I'll be removing some of the linegen stuff from geo_xy_plotter and moving it to this new module?

A begin line which loads all the chosen X&Y variables.
A pass-through A input, this will pass the Ax,Ay coordinates right to the output and not engage any line drawing with the begin line function.
A pass-through B input. Same as above.
An input aX/Y and bX/Y for beginning and ending.
Has a smart pass through.  Meaning if the same beginning and ending point coordinates are at the inputs, just pass through the coordinates to write a single pixel and signal that the line is finished.
Has an enable option to draw until a specified Y coordinate has been reached.  (For raster fills on a chosen Y axis)
Has a 'Y stop' signed input to define that stopping Y coordinate.  This input is live and once changed during a stop, the linegen will continue until the new new Y coordinate has been reached or the line has reached it's end.  If we are on the last Y coordinate, to finish drawing the line, either the final Y coordinate may increase outside the Y drawing area or the Y stop enable flag may be turned off.

Outputs, X/Y coordinates.
Draw pixel data ready.
stopped on Y coordinate flag.
Finished drawing the line.

So something starting like this?

Code: [Select]
module line_generator (

  input logic [3:0][11:0]   aX,
  input logic [3:0][11:0]   aY,
  input logic [3:0][11:0]   bX,
  input logic [3:0][11:0]   bY,
  input logic               raster_fill,
  input signed logic [11:0] Y-stop,

  output logic [3:0][11:0]  aX_passthru,
  output logic [3:0][11:0]  bX_passthru,
  output logic [11:0]       X_coord,
  output logic [11:0]       Y_coord,
  output logic              pixel_data_rdy

);

This should help you define our new line gen 'module'.
We will use 3 of them.  The first 2 line gens draw/generate the outer edge coordinates of our shape while the output of those 2 feed the coordinate inputs of the third lengen module so it may draw a line between the 2 source linegens.  With this setup, not only can we manipulate the line 3 line gens into drawing filled or un-filled triangles, but, boxes and 4 sided polygons as well just by setting up the starting conditions and when linegens 1&2 stop and go on new Y coordinates telling linegen 3 where and when to fill, or just run when 1&2 begin and finish creating an outline of a box instead of filling it.

Your compare module tells you before you begin either the draw point order for triangles, or if a vertical or horizontal line is being drawn so you do not need to do any filling.

Since we are in a crunch for time, we will do the blitter after this works.  You will need to solve the ellipse on your own after that.  The only thing I can offer is that you can make the linegens also generate ACRs, but if you are not comfortable, you can make a discrete module.

Sorry, I'm going to need more of a steer on this module - and the blitter after it - if I'm to get this done by the end of the week.  Trying to multitask between this and work just isn't working out for me that well.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 24, 2020, 04:50:47 pm
option #1
Code: [Select]
module line_generator (

  input logic           clk,
  input logic           reset,   // loads the numbers and begins drawing the line.

  input logic signed [11:0]   X [0:3],
  input logic signed [11:0]   Y [0:3],
  input logic           [1:0]   sel_a,     // selects which X&Y for the beginning of the line.
  input logic           [1:0]   sel_b,     // selects which X&Y for the ending of the line.  If sel_A&B are equal,
                                                   // or different but the stored coordinates match, no line drawn, just the
                                                   // output should immediately draw 1 pixel at those coordinates.

  input logic                  ena_stop_ypos,
  input logic signed [11:0]    stop_ypos,

  output logic signed [11:0]   X_coord,
  output logic signed [11:0]   Y_coord,
  output logic                 pixel_data_rdy,

  output logic        ypos_stopped,
  output logic        line_complete
);


option #2
Code: [Select]
module line_generator (

  input logic           clk,
  input logic           reset,  // loads the numbers and begins drawing the line.

  input logic signed [11:0]   aX,
  input logic signed [11:0]   aY,
  input logic signed [11:0]   bX,
  input logic signed [11:0]   bY,

  input logic                  ena_stop_ypos,
  input logic signed [11:0]    stop_ypos,

  output logic signed [11:0]   X_coord,
  output logic signed [11:0]   Y_coord,
  output logic                 pixel_data_rdy,

  output logic        ypos_stopped,
  output logic        line_complete
);

Go with option #2 please.
The module's inputs just have the 'SELA/B' at the input port.
This makes like easier to tie the top 2 linegens' outputs into the third linegen's single A/B inputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 24, 2020, 05:24:48 pm
Little addition:
Code: [Select]
module line_generator (

  input logic           clk,
  input logic           run_line,  // low=loads the numbers, high = begins drawing the line.
  input logic           pass_thru_a,
  input logic           pass_thru_b,

  input logic signed [11:0]   aX,
  input logic signed [11:0]   aY,
  input logic signed [11:0]   bX,
  input logic signed [11:0]   bY,

  input logic                  ena_stop_ypos,
  input logic signed [11:0]    stop_ypos,

  output logic signed [11:0]   X_coord,
  output logic signed [11:0]   Y_coord,
  output logic                 pixel_data_rdy,

  output logic        ypos_stopped,
  output logic        line_complete
);
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 25, 2020, 08:46:41 am
Right okay, so I need to strip out the linegen code from the geo_xy_plotter module and work it into this new module?

Code: [Select]
case (geo_sub_func1)    // during the draw line, we have multiple sub-functions to call 1 at a time

                     4'd0 : begin
                 
                        errd            <= dx + dy;
                        geo_sub_func1   <= 4'd1;                 // set line sub-function to plot line.
                           
                     end // geo_sub_func1 = 0 - setup for plot line

                     4'd1 : begin
                     
                        draw_cmd_func        <= CMD_OUT_PXWRI[3:0]; // Set up command to pixel plotter to write a pixel,
                        draw_cmd_data_color  <= geo_color;          // ... in geo_colour,
                        draw_cmd_data_word_Y <= geo_y ;             // ... at Y-coordinate,
                        draw_cmd_data_word_X <= geo_x ;             // ... and X-coordinate.

                        if ( ( geo_x >= 0 && geo_x <= max_x ) && (geo_y>=0 && geo_y<=max_y) )
                        draw_cmd_tx     <= 1'b1;            // send command if geo_X&Y are within valid drawing area
                        else
                        draw_cmd_tx     <= 1'b0;            // otherwise turn off draw command

                        if ( geo_x == x[1] && geo_y == y[1] ) geo_shape <= 4'd0;   // last pixel - step to last sub_func1 stage, allowing time for this pixel to be written
                                                                                 // On the next clock, end the drawing-line function
                         
                        // increment x,y position
                        if ( ( errd << 1 ) > dy ) begin
                       
                          geo_x   <= geo_x + geo_xdir;
                                         
                          if ( ( ( errd << 1 ) + dy ) < dx ) begin
                         
                              geo_y   <= geo_y + geo_ydir ;
                              errd    <= errd + dx + dy   ;
                             
                          end else begin
                         
                              errd    <= errd + dy   ;
                             
                          end
                         
                        end else if ( ( errd << 1 ) < dx ) begin
                          errd    <= errd  + dx       ;
                          geo_y   <= geo_y + geo_ydir ;                           
                        end

                     end // geo_sub_func1 = 1 - plot line
                     
                  endcase // sub functions of draw line
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 25, 2020, 04:30:24 pm
Correct.
The idea is to 3 running linegens, each where for the first 2, you can start and stop them when you like with which source X&Y for points A&B you like.  While the third one takes the output coordinates of linegens 1&2 as it's input A&B, and you can set it to pass through the A or B to plot those coordinates immediately, or you can run that third linegen to draw a line between the frozen captured output coordinates of linegens #1&2.

The output status flags tells you when you may start and run each module until it is time to switch to the next linegen module until all linegens have finished their initial line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 26, 2020, 02:47:17 pm
Just found some time to look at the line generator - I've integrated the line gen code from the geo_xy_plotter module into the new line_generator module.  Probably made quite a few mistakes as I'm rushing to make the most of the spare time I've got, so apologies if there's any glaringly obvious errors.

I've removed max_x and max_y checks as I guess they'll be done in the parent module?

When will pixel_data_rdy go high?  Constantly, I presume, once the line generator is running?

What about all the extra inputs and outputs for ena_stop_ypos, stop_ypos, ypos_stopped, etc?

I've just realised I've not done anything with line_complete.  I guess this should go high when draw_line goes low at the end of the line?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 26, 2020, 05:56:17 pm
Your doing good.  Try to wire in the module an make it function.

Yes you are correct about cheking for the max X&Y, they should only be checked once as the last and final step when sending out a write or paste pixel.

Don't forget to set the output flags.

Also, I was missing an input for the module.  A global 'enable' signal to run and stop the module tied to the ' !draw_busy ' input of the geometry_xy_plotter module.  This is the same for the clocked section of the comparator module ' tri_comp '.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 26, 2020, 08:01:35 pm
Don't forget to set the output flags.

Sooo... line_complete needs setting at the end of the line.  I'm not sure what to do about ypos_stopped though?  Is that an acknowledge signal for a check I need to add to see if the current Y_coord is equal to stop_ypos??  Best check the attached code to make sure I'm doing the right thing.

Also, I was missing an input for the module.  A global 'enable' signal to run and stop the module tied to the ' !draw_busy ' input of the geometry_xy_plotter module.

Ah - I'd added 'draw_line' because I thought I needed something like the 'draw_busy' signal, too.  ;D  I've kept draw_line as I don't want the line generator to carry on trying to draw a line if an end condition has been met.  Hopefully that's okay (line 62 in the code).

This is the same for the clocked section of the comparator module ' tri_comp '.

I need to add a 'draw_busy' input for the clocked part of the comparator module as well?  Why's that?  Can't the parent module just ignore those inputs if draw_busy is high?

Oh - also - is the pixel_data_rdy output the same signal as the internal 'draw_line' signal I'm using?  Couldn't I just do this each clock?
Code: [Select]
pixel_data_rdy <= draw_line ;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 26, 2020, 09:55:10 pm
Think through how you will be managing more than 1 line function.

You need to start a line, but, the line function takes an additional clock to initialize.
You don't want to draw a pixel during this step, but you still need to know the line command is busy and not finished yet.
Maybe a new busy output is also required.
Also, you want to make sure when you change the Y stop position, you can still see the linegen working up until it reaches that line.  Right now, the freeze would be forever.

The Y-stop counter will be generated in the main geometry_xy_plotter as it needs to synchronize 2 of the top tier linegens.

Remember, you will need a sequencer setting the controls for all 3 linegens in the geometry_xy_plotter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 27, 2020, 12:22:26 pm
Think through how you will be managing more than 1 line function.

You need to start a line, but, the line function takes an additional clock to initialize.
You don't want to draw a pixel during this step, but you still need to know the line command is busy and not finished yet.
Maybe a new busy output is also required.

Can this be handled with the pixel_data_rdy signal?  Pixel_data_rdy doesn't go high until valid coordinates are being output by the line generator.

Also, you want to make sure when you change the Y stop position, you can still see the linegen working up until it reaches that line.  Right now, the freeze would be forever.

Sorry, I don't follow.  Are you talking about if the Y-stop position is changed whilst the line generator is running?  I've latched the value in the first phase now.

The Y-stop counter will be generated in the main geometry_xy_plotter as it needs to synchronize 2 of the top tier linegens.

Remember, you will need a sequencer setting the controls for all 3 linegens in the geometry_xy_plotter.

Hmm.. might need a rough map of what that will need to look like.

Couple more questions:

1) What am I doing with the pass-throughs?  If pass_thru_a or _b are high, I'm just passing the value in aX/aY or bX/bY through to the X/Y_coord outputs, but am I also showing pixel_data_rdy as well?

2) When should I be passing those values through?  Constantly, or only when certain conditions are met (other than pass_thru_a/b being high)?

3) Is there any reason the geo_sub_func1 functions can't be performed as part of the reset stage, eliminating the need for geo_sub_func1 altogether?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 27, 2020, 05:40:36 pm
Think through how you will be managing more than 1 line function.

You need to start a line, but, the line function takes an additional clock to initialize.
You don't want to draw a pixel during this step, but you still need to know the line command is busy and not finished yet.
Maybe a new busy output is also required.

Can this be handled with the pixel_data_rdy signal?  Pixel_data_rdy doesn't go high until valid coordinates are being output by the line generator.

It's ultimately up to you how to code everything.  I'm only making useful recommendations.
How can you tell is the linegen has begun to work, yet the pixel data ready doesn't yet have the first pixel ready?
Quote

Also, you want to make sure when you change the Y stop position, you can still see the linegen working up until it reaches that line.  Right now, the freeze would be forever.

Sorry, I don't follow.  Are you talking about if the Y-stop position is changed whilst the line generator is running?  I've latched the value in the first phase now.
Look at our FreeBasic code.  We select a Y coordinate to stop on.  Then run linegen #1 until that Y coordinate.  Then run linegen #2 until that Y coordinate.  Then run linegen #3 between the output coordinates or linegen #1 and linegen #2 which should both be on the same Y coordinate.
Now, what happens next after linegen #3 draws a single horizontal line?
Quote

The Y-stop counter will be generated in the main geometry_xy_plotter as it needs to synchronize 2 of the top tier linegens.

Remember, you will need a sequencer setting the controls for all 3 linegens in the geometry_xy_plotter.

Hmm.. might need a rough map of what that will need to look like.

Couple more questions:

1) What am I doing with the pass-throughs?  If pass_thru_a or _b are high, I'm just passing the value in aX/aY or bX/bY through to the X/Y_coord outputs, but am I also showing pixel_data_rdy as well?

I guess the each pass through would also drive the pixel_data_rdy output at the same time.
Quote

2) When should I be passing those values through?  Constantly, or only when certain conditions are met (other than pass_thru_a/b being high)?
Only when either pass through signal is high.
Quote

3) Is there any reason the geo_sub_func1 functions can't be performed as part of the reset stage, eliminating the need for geo_sub_func1 altogether?

Take a look as what 'errd' equals.  It needs dx & dy to be ready.


Also, the '!draw_busy' in this block needs to encompass everything including the so called 'reset'.  Make it an 'IF' outside of everything else.
 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 28, 2020, 03:06:25 pm
It's ultimately up to you how to code everything.  I'm only making useful recommendations.
How can you tell is the linegen has begun to work, yet the pixel data ready doesn't yet have the first pixel ready?

Fair point - I've added a 'busy' output as well.

Look at our FreeBasic code.  We select a Y coordinate to stop on.  Then run linegen #1 until that Y coordinate.  Then run linegen #2 until that Y coordinate.  Then run linegen #3 between the output coordinates or linegen #1 and linegen #2 which should both be on the same Y coordinate.
Now, what happens next after linegen #3 draws a single horizontal line?

A check is made to see if linegen #1 needs to switch to the third line?

I'm still confused about what the issue is here.  :-//  My line generator module sets a flag to show the line is complete and that it has stopped at the specified Y-coordinate.  It clears several other flags but all of these flags are either reset (in the case of the Y-stop and line complete flags) or set again when the next line is specified to be drawn in the reset (now called start for clarity) function?
Code: [Select]
// Set latched registers, phase counters and flags
geo_sub_func1  <= 4'b0       ; // reset the phase counter
ypos_stopped   <= 1'b0       ; // reset ypos_stopped flag
line_complete  <= 1'b0       ; // reset line_complete flag
Y_stop         <= stop_ypos  ; // latch the Y_stop coordinate
stop_ypos_en   <= ena_stop_y ; // latch Y_stop enable
draw_line      <= 1'b1       ; // start drawing the line on the next clock cycle
busy           <= 1'b1       ;

// Initialise starting coordinates and direction for immediate plotting
X_coord        <= aX         ; // initialize starting X pixel location
Y_coord        <= aY         ; // initialize starting Y pixel location

Quote
3) Is there any reason the geo_sub_func1 functions can't be performed as part of the reset stage, eliminating the need for geo_sub_func1 altogether?

Take a look as what 'errd' equals.  It needs dx & dy to be ready.

Ah, missed that.

Also, the '!draw_busy' in this block needs to encompass everything including the so called 'reset'.  Make it an 'IF' outside of everything else.

Sorted.  Updated file attached.  Just need to write the reset function and fix any last issues (like the Y-stop thing?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 28, 2020, 05:47:43 pm
A check is made to see if linegen #1 needs to switch to the third line?

It's the second linegen, not the first.
Why do you think I told you to make 2 outputs, 1 which tells you when the linegen has stopped due to reaching the chosen Y coordinate VS if the linegen has finished it's current line.  Don't you think this flag may be of use as well?

Also, you have conditions where the pixel_data_ready gets set, but never cleared if the pass throughs are disabled and a reset comes next.


You need to proceed and simulate in these steps to make you life possible:

First, worry about getting a single line generator working and simulating in place of the original one.

Next worry about getting the linegen to recognize that the beginning and ending coordinates are on the same point bypassing everything else and just drawing the dot.

Then worry about controlling the linegens to step/advance a Y coordinate at a time with pre-sorted coordinates coming from the Z80.

Then worry about wiring 3 of them together and controlling them with pre-sorted coordinates from the Z80.

Then worry about enabling the fill.

Then worry about sorting the coordinates to the 3 triangles in the geometry unit.

Then worry about making the linegens process all other shapes except ellipses.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 29, 2020, 11:39:38 am
Why do you think I told you to make 2 outputs, 1 which tells you when the linegen has stopped due to reaching the chosen Y coordinate VS if the linegen has finished it's current line.  Don't you think this flag may be of use as well?

Okay, so the 1st linegen draws the longest line (to the lowest Y-coordinate) - this is set by the sorting function before the drawing starts.  The 2nd linegen draws the connected line from the topmost Y-coordinate, connected to the 1st linegen line, and (by definition as it's a triangle) stops at some point before reaching (or upon reaching) the end of the first line.

As I understand it, the two ending signals are for the following conditions:
The two linegens are run, set to stop at each Y-pixel so that the raster line can be filled if required - this is where ypos_stopped is used.  When linegen #2 signals line_complete, then the parent function sets up the third line to be drawn - or if it's the third line signalling complete, the triangle is complete.  Is that right?

Also, you have conditions where the pixel_data_ready gets set, but never cleared if the pass throughs are disabled and a reset comes next.

I've added a reset for pixel_data_rdy in the start phase.  Is there somewhere else I should be resetting it, or is it covered now?

You need to proceed and simulate in these steps to make you life possible:

First, worry about getting a single line generator working and simulating in place of the original one.

Next worry about getting the linegen to recognize that the beginning and ending coordinates are on the same point bypassing everything else and just drawing the dot.

Then worry about controlling the linegens to step/advance a Y coordinate at a time with pre-sorted coordinates coming from the Z80.

Then worry about wiring 3 of them together and controlling them with pre-sorted coordinates from the Z80.

Then worry about enabling the fill.

Then worry about sorting the coordinates to the 3 triangles in the geometry unit.

Then worry about making the linegens process all other shapes except ellipses.

No problem - will make a start on this and update when I have anything to report.

Again - thanks for all your help BrianHG. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 29, 2020, 03:19:44 pm
You got the basics of it.

Code: [Select]
                    if ( stop_ypos_en && Y_coord == Y_stop ) begin // reached Y_coordinate stop position and we want to stop on Y_pos
                   
                        draw_line      <= 1'b0 ; // last pixel - allow time for this pixel to be written by ending on next clock
                        line_complete  <= 1'b1 ; // set line_complete flag to let parent module know the line is done
                        ypos_stopped   <= 1'b1 ; // let the parent module know the line generator has stopped on ypos
                        pixel_data_rdy <= 1'b0 ; // reset pixel_data_rdy flag - no more valid coordinates after this clock
                        busy           <= 1'b0 ; // line generator is no longer busy
                   
                    end

The line isn't necessarily complete when Y stopped.
Also, Y-stopped needs to be cleared if the coordinates change or the feature is disabled.
You have no mechanism to do this.
Also, does the line engine actually stop?
A little more thought may be needed here.

As for the start, you should first compare is points A&B are equal.
If so, just pass thru point A to output.
In fact, you can actually do this as part of the first 'if ( pass_thru_a ) begin' bypassing the rest of the line draw algorithm.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 30, 2020, 04:22:10 pm
The line isn't necessarily complete when Y stopped.
Also, Y-stopped needs to be cleared if the coordinates change or the feature is disabled.
You have no mechanism to do this.

Why would the coordinates change or the feature be disabled in the middle of drawing a line?  :-//  (Unless you mean the Y-pos coordinates changing?)

Hmm.. the line generator stops on Y-pos, so the parent function can then fill in the raster line, but what causes the line generator to restart again?

.....Okay, my thinking is now going along these lines - I need to clear ypos_stopped when stop_ypos changes.  I also need to set draw_line, busy and pixel_data_rdy again to get the line generator running to the next stop_ypos.  Is that right?

Also, does the line engine actually stop?
A little more thought may be needed here.

Well, this is where I'm going with my thought process above.  The line generator currently is stopping on Y-pos and there's no way to start it again for the next Y-pos.  I think I'm finally getting how it works.  ;)

As for the start, you should first compare is points A&B are equal.
If so, just pass thru point A to output.
In fact, you can actually do this as part of the first 'if ( pass_thru_a ) begin' bypassing the rest of the line draw algorithm.

Have done that as below:
Code: [Select]
if ( pass_thru_a || ( aX == bX && aY == bY ) ) begin

pixel_data_rdy <= 1'b1 ; // valid coordinates at output
X_coord        <= aX   ; // pass-through aX value
Y_coord        <= aY   ; // pass-through aY value

if ( aX == bX && aY == bY ) begin

line_complete  <= 1'b1 ; // set line_complete flag to let parent module know the line is done

end

end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 30, 2020, 05:27:13 pm
It's time to insert with the main geometry_xy_plotter and first replicate drawing a single line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 02, 2020, 01:37:25 pm
Okay, I've done some tweaking to get it to work in the geometry_xy_plotter module, but I think it's okay...  The simulation is showing the correct pixels being output from the line_generator module and being passed to PAGET.  I just feel there's probably a much cleaner way of integrating the line_generator into the geo_xy_plotter module...

Anyhow, here's the simulation output:

[attachimg=1]

I've attached the line_generator and geo_xy_plotter modules at the end of this post too.

Maybe the timing could be tightened by a few clocks?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 02, 2020, 05:53:01 pm
I cannot see in your simulation the output coordinates at the address.  Choose a different base address and screen width to make this easy to decode on the waveform.
You also seem to be drawing an extra pixel at 6,5, or, is the flag I'm looking at mean something else?
I do not remember the old linegen changing pixel numbers after the line has finished.

Delays are due to fifo setup and pipe through time.
Give it a try with the Z80 constructing a few known shapes.
I say shapes so you know that the ends of the lines properly touch.
When testing with the Z80, first use the original line-gen, then, switch to this new one.
Make a program that uses something like 8-12 lines deliberate lines.
Speed is not important here.  It's coverage of the screen with odd angles and a few different colors at 320x200.

The output from both versions of the code should match.

If everything is ok, then go onto the next step which will only be simulate-able, making the smart point draw when point A= point B.  I say you can only simulate since it happens so fast that you could not tell with the Z80.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 03, 2020, 12:26:21 pm
Okay, so testing has thrown up a glitch.  I'm no professional, but it looks like it could be a FIFO thing going on, maybe?

I'm drawing a square, with a cross through it, but not drawing the very edge pixels of the square (in my mind it seemed like a good way to test for overrun etc).  One pic shows the normal GPU HDL drawing the image, the other shows the new line_gen code with the obvious errors.

I've included the geo_xy_plotter and line_generator modules for info, but I suspect it's probably a simple error I've made whilst integrating the new line_generator module.  It seems to simulate just fine and PAGET is throwing out addresses with no breaks, so I'm wondering if I've missed a busy check or something somewhere..  I note that there are more breaks in the horizontal lines than the other lines, maybe due to more cache hits and thus more misses (due to the faster pixel-write throughput) if PAGET's busy?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 03, 2020, 01:09:01 pm
Also, I'd tidied up the line_generator after it finishes, so it's not running on for another pixel.  Latest simulation results below.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 03, 2020, 05:04:50 pm
Your 2 pictures, are they a comparison between the old geometry unit's line gen and the new one, correct?
Ok, it looks like either what you said is true or just the pixel_write command may not be going high.
Though, the line being generated is still being fully generated, just not all the dots plotted on the screen.

Also:
Code: [Select]
last_run <= run ;

    if ( !draw_busy ) begin // draw_busy must be LOW or the line generator won't run

        if ( !run && ( latch_aX != aX || latch_aY != aY || latch_bX != bX || latch_bY != bY ) ) begin

Should be:
Code: [Select]
    if ( !draw_busy ) begin // draw_busy must be LOW or the line generator won't run

last_run <= run ;

        if ( !run && ( latch_aX != aX || latch_aY != aY || latch_bX != bX || latch_bY != bY ) ) begin

When the 'draw_busy' is high, everything must stop.
If fact, to be safe, I would also change line 205 in the geometry unit from:

Code: [Select]
    end else begin

to:
Code: [Select]
    end else if (!draw_busy) begin

Then down at line 430 change:
Code: [Select]
    end // reset
to:
Code: [Select]
    end else draw_cmd_tx <= 1'b0;  // !draw_busy

All the other '!draw_busy's inside the bulk should no longer be needed.
I will need to wait a few hours before I could investigate with a proper simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 03, 2020, 05:32:05 pm
Your 2 pictures, are they a comparison between the old geometry unit's line gen and the new one, correct?

Yes indeed.

Ok, it looks like either what you said is true or just the pixel_write command may not be going high.
Though, the line being generated is still being fully generated, just not all the dots plotted on the screen.

...

All the other '!draw_busy's inside the bulk should no longer be needed.
I will need to wait a few hours before I could investigate with a proper simulation.

Thanks.  I've made the changes you suggested and tried again, but have exactly the same output.   :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 03, 2020, 06:09:46 pm
Oh yes, something has gone completely haywire.
Take a look at this simulation with the integrated pixelwriter module.
Old geo xy plotter:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1059162)
New geo xy_plotter:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1059166)

As you can see, in the second sim, all the pixels are still being generated, but, pixels are being driven right through even though pixel_writer has told the geometry unit it was busy, so, STOP!

I've also attached all the needed sim files.
Geo_Writer = original linegen.
Geo_Writer_v2 = new linegen.
(Inside here, 'geo3.vwf' has the reference good simulation, 'geo3_v2.vwf' is the code you are working & simulating with)
pixel_writer = The 2 Geo_Writers require this to simulate.

All 3 projects are in the 1 attached Geo_Writer_V2.zip file.

I can only debug the code in a few hours from now, though, you can now see whats happening and take a crack at it yourself.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 03, 2020, 07:07:03 pm
 :scared: You have edited and changed an older version of geometry_xy_plotter.sv when you added the new linegen into it...  :palm:

Take a look at line 74 in the 'geometry_xy_plotter.sv' on your new linegen and take a look a line 74 in the last working version of the project.

This includes the address_generator...

Ok, I fixed and updated everything.
ALSO, take a close look at all the changes I've done to your Y-stop-ing function.  It latched things at start it shouldn't have and also would never recover from a stop if I left things the way they were.

Remember, you are taking new sources from this .zip
geometry_xy_plotter.sv
line_generator.sv
pixel_address_generator.sv
and
line_generator.sv
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 03, 2020, 07:35:24 pm
Now, how did I debug that one.

Flipping between the 2 simulations in quartus with the View & Zoom aligned, I saw this:

Zoom on old image was set to 340ns to 590ns.
Zoom on new image was set to 350ns to 600ns.

This was done sine the new code takes 1 additional clock before it starts drawing, so that 10ns offset aligns the output...

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1059218)

The green faded background was the good functioning algorithm.  The red arrow points to the draw_busy where the old code halted the output 'draw_cmd_rdy' immediately while the new code kept it high for 1 clock.

So, I knew that 'draw_cmd_rdy' should be searched for in both code revisions and that since in the working code it had an immediate effect, it also probably was something in a line of combinational code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 03, 2020, 08:12:32 pm
Place dates & revision numbers with a bug patch list at the top of each of your verilog cores...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 04, 2020, 07:15:40 pm
:scared: You have edited and changed an older version of geometry_xy_plotter.sv when you added the new linegen into it...  :palm:

Take a look at line 74 in the 'geometry_xy_plotter.sv' on your new linegen and take a look a line 74 in the last working version of the project.

This includes the address_generator...

Ok, I fixed and updated everything.
ALSO, take a close look at all the changes I've done to your Y-stop-ing function.  It latched things at start it shouldn't have and also would never recover from a stop if I left things the way they were.

Remember, you are taking new sources from this .zip
geometry_xy_plotter.sv
line_generator.sv
pixel_address_generator.sv
and
line_generator.sv

Uhh... darnit.  |O  This is what happens when I have three different versions of the same file in the main project and different test projects.  :-[

Right, so I missed the '!draw_busy` in the combinational logic (the wire assignment) in the geo_xy_plotter module on line 74.  I've been going round in circles trying to find the new code you're talking about, though... or even the fixed code... looks like the zip file has the last working code and my faulty code, rather than the fixed code?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 04, 2020, 07:34:17 pm
The '_patched.zip' version has all the fixes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 04, 2020, 08:06:26 pm
The '_patched.zip' version has all the fixes.

 ::)  It's been a long week.. 

[attachimg=1]

Works now. :-+ Will do some more testing tomorrow with more lines, but it's not likely to do anything different as all dx/dy directions are catered for in that square already.  Also, yes, schoolboy error with the ypos latching...  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 04, 2020, 08:19:40 pm
You need to proceed and simulate in these steps to make you life possible:

First, worry about getting a single line generator working and simulating in place of the original one.  DONE!

Next worry about getting the linegen to recognize that the beginning and ending coordinates are on the same point bypassing everything else and just drawing the dot. Simulate and test this one.

Then worry about controlling the linegens to step/advance a Y coordinate at a time with pre-sorted coordinates coming from the Z80. Next task...

Then worry about wiring 3 of them together and controlling them with pre-sorted coordinates from the Z80.

Then worry about enabling the fill.

Then worry about sorting the coordinates to the 3 triangles in the geometry unit.

Then worry about making the linegens process all other shapes except ellipses.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 05, 2020, 02:20:05 pm
Is this output good for a single pixel?

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 05, 2020, 02:34:03 pm
Do something like 5 of them to test.
Just add a few write pixel commands with a different color each, all adjacent.

When testing on the Z80, just place 2-4 dots on the screen in different places by different colors.

Then go onto the next stage.
The controlled Y position rasterizer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 05, 2020, 04:56:51 pm
The individual pixels are drawing fine.  :-+

Now for the next step.  This has me thinking as it's not as straightforward as inserting the line_generator module was.

I have two inputs to the line_generator:
Setting ena_stop_y HIGH tells the line_generator to stop on the specified Y-coordinate (set by stop_ypos as a 12-bit value).  Now, the FreeBasic version loops through every Y value from top to bottom, so that a raster fill line can be drawn between the two new points.  I'm wondering - wouldn't it be beneficial to be able to tell the line_generator to just stop on every new Y-value when it increments to it, instead of (or as well as being able to) stop at a specified Y-coordinate?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 05, 2020, 07:17:09 pm
The individual pixels are drawing fine.  :-+

Now for the next step.  This has me thinking as it's not as straightforward as inserting the line_generator module was.

I have two inputs to the line_generator:
  • ena_stop_y, and
  • stop_ypos
Setting ena_stop_y HIGH tells the line_generator to stop on the specified Y-coordinate (set by stop_ypos as a 12-bit value).  Now, the FreeBasic version loops through every Y value from top to bottom, so that a raster fill line can be drawn between the two new points.  I'm wondering - wouldn't it be beneficial to be able to tell the line_generator to just stop on every new Y-value when it increments to it, instead of (or as well as being able to) stop at a specified Y-coordinate?

What happens when the shorter face of the triangle ends and the new line begins there.
I guess it's your choice.
It sounds like it may be easier.
Ok, let's give it a try.

New rule on the Y stop input, whenever it's HIGH, on any Y increment, the line drawing engine will stop and wait for the Y_stop to go low.  The output Y_stopped will be high during this time.

Let's see what happens.


Also, for your multiplot of single pixel lines, please show me the simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 05, 2020, 07:33:20 pm
What happens when the shorter face of the triangle ends and the new line begins there.

The line_generator should show line_complete as well as the y_stop flag?

I guess it's your choice.
It sounds like it may be easier.
Ok, let's give it a try.

New rule on the Y stop input, whenever it's HIGH, on any Y increment, the line drawing engine will stop and wait for the Y_stop to go low.  The output Y_stopped will be high during this time.

Let's see what happens.

Will have a go at this tomorrow.  :-+

Also, for your multiplot of single pixel lines, please show me the simulation.

Ah, forgot to add that!  Here it is:
[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 05, 2020, 07:52:04 pm
Arrrg, all those wasted clock cycles...

Ok, I see there is a lot of cleanup work to do in the goemetry_xy_plotter.sv, lines 316...348, and, flush out lines 359...428.

Check back here before you start, I'll do a major overhaul getting rid of all that obsolete junk.

Just continue to work, I'll see if I can find time to clean up the obsolete junk tomorrow.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 06, 2020, 10:13:17 am
Two images below - both draw a diagonal line from 1,1 to 5,5.  The first image is without y_stop.  The second is with y_stop on for a pixel.

It looks like it's working, but I'm finding these simulation results hard to interpret, so you'll probably pick up on some problems.  :-//

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 06, 2020, 05:46:54 pm
Why not try wiring the Y-stopped output inverted back to the Y-stop input and see if there is a 1 clock cycle pause every Y increment.

Then try a stretched horizontal line at 22.5 degrees and see if the Y-stoppin only occurs once every 2 pixels for 1 clock.

You may disconnect the 'writer' section and go back just to the geo simulation to see things more clearly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 06, 2020, 06:05:02 pm
Why not try wiring the Y-stopped output inverted back to the Y-stop input and see if there is a 1 clock cycle pause every Y increment.

Then try a stretched horizontal line at 22.5 degrees and see if the Y-stoppin only occurs once every 2 pixels for 1 clock.

Okay, have done that - here's the output:

First image is 1,1 to 5,5 with the re-wired Y-stop output, as specified.

[attachimg=1]

Second image is 1,1 to 10,5 (22.5 degree angle), as specified.

[attachimg=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 06, 2020, 07:10:50 pm
How can the 'draw_cmd_rdy' be ready when the Y_stopped is stopped?

I guess I need to also see the 'Stop_on_next_Y_increment' input to help decipher things.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 06, 2020, 08:26:42 pm
How can the 'draw_cmd_rdy' be ready when the Y_stopped is stopped?

I guess I need to also see the 'Stop_on_next_Y_increment' input to help decipher things.

I won't be able to re-run the simulation until tomorrow now, but here's the source for geo_xy_plotter.sv.  Line #163 is where the 'stop_on_next_Y_increment' input is set - it's just the y_stopped output inverted, as you specified previously.

Actually, for it to be inverted, does !y_stopped work in that context, or should it be ~y_stopped?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 07, 2020, 11:09:26 am
Updated simulation with ena_stop_y signal shown (this is the signal to the line_generator module).

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 07, 2020, 01:49:15 pm
Ok, I've attached a version of the project with an enable/disable for the pixel_writer.

Take a look at the 'y_stop_1,1-10,5.png'.
The Y stop is cycling, but, you are always sending out 'pixel_cmd_rdy'.
When stopped, the pixel command shouldn't be ready.

Also, in 'point_1,1-1,1.png', there shouldn't be any delayed clock cycles.
A number of things need to be patched to correct this.  I guess I'll handle this one as we want to see this working really soon.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 07, 2020, 02:06:12 pm
A number of things need to be patched to correct this.  I guess I'll handle this one as we want to see this working really soon.

Uh, sorry.  :-[ No rush, I know you're busy.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 07, 2020, 03:32:20 pm
Ok, a bunch of patches have been made.
Take a look at 'Line-1,1-10,5_ystop.png'.
I fixed your 'pixel_cmd_ready'.

Also take a look at 'point_1,1-1,1.png', notice lack of additional delays when passing pixels through.

I also removed the additional clock cycles when the line begins when drawing a line as well.

No more box, or box-fill command as a removed a heap of junk from the code & once we have the 3 linegens in the code, you will be able to sequence them to generate the box/boxfill command as well as any 4 point / 4 face polygons.

Before this, you need to re-test the new attached project's line command, with and without the Y_stopped feature.  Once verified, we will add 2 additional linegens and generate your first triangle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 07, 2020, 04:09:34 pm
You need to proceed and simulate in these steps to make you life possible:

First, worry about getting a single line generator working and simulating in place of the original one.  DONE!

Next worry about getting the linegen to recognize that the beginning and ending coordinates are on the same point bypassing everything else and just drawing the dot. Done.

Then worry about controlling the linegens to step/advance a Y coordinate at a time with pre-sorted coordinates coming from the Z80. Simulate and test what I sent you...

Then worry about wiring 3 of them together and controlling them with pre-sorted coordinates from the Z80.  Time to do this one.

Then worry about enabling the fill.

Then worry about sorting the coordinates to the 3 triangles in the geometry unit.

Then worry about making the linegens process all other shapes except ellipses.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 08, 2020, 07:59:20 am
Before this, you need to re-test the new attached project's line command, with and without the Y_stopped feature.  Once verified, we will add 2 additional linegens and generate your first triangle.

Two pictures attached - first one is the new linegen with Y-stop disabled.  The second is with Y-stop enabled (as per the test bench, with ~y_stopped into the ena_stop_y input).  Both are identical.  :-+

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 08, 2020, 10:52:16 am
So, this is how I see it working:
I realise it's a compressed version of what's going on in geo.bas, it's more of an overview than anything else as it raises a big question in my mind; namely, point number 3. It's going to be expensive to have another set of 12-bit X/Y coordinate registers to pipe X[1]Y[1],X[2]Y[2] into them to feed linegen#2, then I'll lose a clock cycle when linegen#2 completes the second line and switches over to the third line, as the new coordinates are clocked into its registers.  Or maybe it's not expensive at all and it's a better option than having another linegen?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 08, 2020, 04:56:46 pm
So, this is how I see it working:
  • Run linegens #1 and #2 until next Y_stop
  • If fill enabled and empty pixels between the two lines, use linegen#3 to draw a raster line between the two points
  • If #2 has reached the end, reset it to draw from second point to the last point
  • Has #1 reached the end? No - loop back to No.1 above, otherwise triangle is complete
I realise it's a compressed version of what's going on in geo.bas, it's more of an overview than anything else as it raises a big question in my mind; namely, point number 3. It's going to be expensive to have another set of 12-bit X/Y coordinate registers to pipe X[1]Y[1],X[2]Y[2] into them to feed linegen#2, then I'll lose a clock cycle when linegen#2 completes the second line and switches over to the third line, as the new coordinates are clocked into its registers.  Or maybe it's not expensive at all and it's a better option than having another linegen?  :-//

Close, as in do not worry about the extra 2 clock cycles as linegen swaps from xy[0]-xy[1] to xy[1]-xy[2].

Ok, we have 3 coordinates. xy[0,1,2].
For now, we will always assume xy[0] has the lowest Y coordinate and, xy[2] has the highest Y coordinate.
This means our master first linegen #1 will run A-B from xy[0] to xy[2].
For now, hard wire these in.
Our second linegen #2 will run A-B from xy[0] to xy[1].
Once it has reached xy[1], then, it will run A-B from xy[1] to xy[2].
For now, hard wire linegen #2 A-B from xy[0] to xy[1].

The xy outputs of the first linegen #1 output coordinates will feed the third linegen #3's A coordinates while the xy outputs of the second linegen #2 coordinates will feed the third linegen #3's B coordinates input.

The third linegen #3's output coordinates will now drive the pixel_cmd_ready and the actual plotting xy coordinates.

Procedure order:
1. Wireup the basics.

2. Only get linegen #1 to draw a line like now, except, the 'line_dat_rdy' will now be driving the 'pass_thru_a' on the linegen #3 and you should be able to still simulate and draw lines on the screen, except the line will now go from xy[0] to xy[2], not xy[0] to xy[1].  (YStop disabled.)

3. Next, when calling the line, start linegen #1 and let it draw waiting for the next Y step, then, start linegen #2 and let it draw waiting for the next Y step, then go back to linegen #1, then #2 and cycle until linegen #2 is finished, then let linegen #1 finish it's line.  This will construct only 2 faces of the triangle.

4. Next, when linegen #2 ends, swap and re-run it's coordinates so that it begins again A-B now from xy[1] to xy[2].  Then once setup, let it run until it has a matching Y coordinate and now continue cycling linegens #1 & #2 until both finish their lines.  If you have completed this process properly, you should be rendering an outline of a triangle.  Test a few triangles on the Z80, following the rule that the Y in xy[0] is the smallest Y of the 3 coordinates and the Y in xy[2] has the largest coordinates.


BONUS: Then worry about enabling the fill....

5. Fill.  If the fill bit is in the draw command is enabled, the current linegen loop:
           Until linegens #1,#2 end, loop (y_wait #1,y_wait #2)

Will now change to:
           Until linegens #1,#2 end, loop (y_wait #1,y_wait #2, run linegen #3 from A-B until linegen #3 ends)

Running this should now render filled triangles.

     If you haven't noticed yet, because of the wiring, just by altering the sequence rules you can render a single line, or by changing the coordinates feeding linegen #1 & #2, you can render boxes, filled boxes, or any 4 sided polygons.  But not yet.  This comes after: Then worry about sorting the coordinates to the 3 triangles in the geometry unit. as the coordinate selection process for linegen #1&#2 with sequence order will be built into that coordinate selection logic based on which geometry shape has been selected meaning this processing block could generate any draw function/shape except ellipses.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 09, 2020, 11:21:58 am
Ok, we have 3 coordinates. xy[0,1,2].
For now, we will always assume xy[0] has the lowest Y coordinate and, xy[2] has the highest Y coordinate.
This means our master first linegen #1 will run A-B from xy[0] to xy[2].
For now, hard wire these in.
Our second linegen #2 will run A-B from xy[0] to xy[1].
Once it has reached xy[1], then, it will run A-B from xy[1] to xy[2].
For now, hard wire linegen #2 A-B from xy[0] to xy[1].

The xy outputs of the first linegen #1 output coordinates will feed the third linegen #3's A coordinates while the xy outputs of the second linegen #2 coordinates will feed the third linegen #3's B coordinates input.

The third linegen #3's output coordinates will now drive the pixel_cmd_ready and the actual plotting xy coordinates.

Okay, wired up as described above.

Procedure order:
1. Wireup the basics. DONE

2. Only get linegen #1 to draw a line like now, except, the 'line_dat_rdy' will now be driving the 'pass_thru_a' on the linegen #3 and you should be able to still simulate and draw lines on the screen, except the line will now go from xy[0] to xy[2], not xy[0] to xy[1].  (YStop disabled.)

Now I've hit a wall. |O  For some reason, I'm getting nothing out of the geo unit after the first pixel.  Initially I thought I'd got the wrong commands and X[2]Y[2] were empty, leading linegen#1 to end on the first pixel, but I've checked the commands and they seem to be okay.   As you can see in the attached simulation output, linegen#1 is working as draw_line is high, but it seems linegen#3 isn't happy about something - most probably I've made a silly wiring error, but I can't see it.

I'll keep looking and update if I fix it.  Latest versions of line_generator and geo_xy_plotter attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 09, 2020, 04:31:35 pm
Why are you toying with the perfect address generator?

You should concentrate on your issues with the 'geometry_xy_plotter.sv' and 'line_generator.sv'.

I would start with the fact that linegens #1 & #2 shouldn't even have the input pass-thru functions wired anywhere...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 09, 2020, 05:34:00 pm
Why are you toying with the perfect address generator?

You should concentrate on your issues with the 'geometry_xy_plotter.sv' and 'line_generator.sv'.

I would start with the fact that linegens #1 & #2 shouldn't even have the input pass-thru functions wired anywhere...

Sorry - no I haven't been toying with PAGET at all - don't know why I attached that file (other than doing three things at once and not concentrating on this one!)

I meant to attach the line_generator, not PAGET.  |O

EDIT: Have removed the inputs to the pass-thrus on linegens #1 and #2, and removed pass_thru_b on linegen#3.  No change in the output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 09, 2020, 06:23:41 pm
Pass thru shouldn't be dependent on a run commend...
Pass thru is a pass thru, not run a line from points A-B.

(on a few lines in line_gen)
 if ( run && ( pass_thru_a || ( aX == bX && aY == bY ) ) ) begin

Nor should it be stopped by any running Y function...
Same if both coordinates A&B are equal (only this one requires the 'run' but has no ystop action).  They should pipe through.

Also, in geometry line 232
linegen_3_start = linegen_1_start ; // necessary to allow linegen#3 to pass-through coordinates

Nope, make this 0 for now as this linegen module should only respond to passthrough commands.

Hopefully this should pass though linegen 1's commands.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 09, 2020, 07:19:34 pm
Aha - okay, sorted those issues now.  Here's the latest output - looks okay....??  ???

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 09, 2020, 08:02:30 pm
Why is the pixel_cmd_rdy staying high?

Let me guess, you forgot to clear it once the pass through A/or/B goes low, right?
Something looks upsidedown...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 09, 2020, 10:14:55 pm
Why is the pixel_cmd_rdy staying high?

Let me guess, you forgot to clear it once the pass through A/or/B goes low, right?
Something looks upsidedown...

Hmm.. I'm not sure what's going on.  Yes, I'd forgotten to clear pixel_cmd_rdy as you've said, but I added an edge-detect for when pass_thru_a goes low again to reset pixel_cmd_rdy, but it didn't seem to make a difference.  Seems draw_cmd_rdy and pixel_cmd_rdy is high shortly after reset clears, before any commands are sent at all (see attached output)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 10, 2020, 08:09:49 am
Okay, think I've fixed it.  Well, certainly the pixel_cmd_rdy being high all the time, anyway.  The offending code was line 92 in the line_generator module:
Code: [Select]
if ( pass_thru_a || ( aX == bX && aY == bY ) )begin
... should have been:
Code: [Select]
if ( pass_thru_a || ( run && ( aX == bX && aY == bY ) ) )begin
Also, I wasn't sure about line 230 in the line_generator module - looks like it would be setting pixel_data_rdy HIGH all the time if nothing else was being done...?
Code: [Select]
else  pixel_data_rdy <= 1'b1 ; // reset pixel_data_rdy flag - no more valid coordinates after this clock
Even the comment indicated it should RESET, not set... so I've changed that to 1'b0 instead.

Latest code and simulation output attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 10, 2020, 08:36:03 am
Ok, if the Z80 also creates a line on the screen, next make linegen 2 run after linegen 1 does a Y-stop.  Then once linegen 2 does a stop, go back to lingen 1.  Once linegen 2 finishes, continue linegen1 until it's finish.

You might as well make your logic so that if linegen1 finishes first, let linegen 2 finish.

Once working, make is so that when linegen2 finishes before linegen1, restart linegen2 with new coordinates and when it Y-stops, go back and forth finishing linegen1 & the new linegen2.  This should make a 3 face triangle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 10, 2020, 11:15:28 am
Works fine on the Z80.  Will push on with the next step.  It may be a couple of days before I can do anything.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 10, 2020, 01:09:49 pm
Hint: Choose 3 coordinates where you know what the results should look like on the simulation so it is easier to debug.

Like a vertical line for linegen1 and a 45 degree line, half height for linegen2...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 13, 2020, 04:08:28 pm
I've had very little time to sit and work on this at all - this is how far I have got.  Doesn't run currently, as I'm thinking about how to get linegen#2 to start, but not at the same time as linegen#1 (which is what happens at the moment thanks to the combinational logic section).

Would appreciate any thoughts on my current implementation (am I on the right track?) and how best to start the second linegen one y-stop after the first.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 13, 2020, 05:43:28 pm
Think in this always_comb section:
Code: [Select]
    linegen_1_start = !reset && ( !fifo_cmd_rdy_n && ~geo_run ) && ( command_in[7:5] == 3'd0 && command_in[2:0] == 3'd1 ) ;  // for now, only the draw line command
    linegen_2_start = linegen_1_start ; // start with linegen_1
Maybe say:
Code: [Select]
    line_gen_starter =  !reset && ( !fifo_cmd_rdy_n && ~geo_run ) && ( command_in[7:5] == 3'd0 && command_in[2:0] == 3'd1 ) ;  // for now, only the draw line command

    linegen_1_start = line_gen_starter && !line_gen_2_running && !line_gen_1_running ; //  initiate linegen1 when lingen2 is not running.
    linegen_2_start = line_gen_starter && y_stopped_1 && !line_gen_2_running ;          // initiate linegen2 after linegen1 has it's first stop

    y_stop_en_1 = !y_stopped_2 ; // once linegen2 has stopped, continue linegen1  These might need another term
    y_stop_en_2 = !y_stopped_1 ; // once linegen1 has stopped, continue linegen2

I'm sure there is a logic bomb here, but as you can see I forced you to make all those linegen flag outputs so you could sequence the 3 linegens with nothing more than 2 or 3 combinational logic equations, or if the different shape make an equation too complex, you can use a look-up table to trigger actions.

You will most likely use a look-up table when deciding which xy[ # ] are selected for which linegen# and A/or/B position based on the selected drawing shape and 'tri_comp' module's in_a_gt_b[] and in_a_eq_b[] outputs.
 
Also, when drawing other shapes, this sequence may need additional enable/disable/blocking.

I have not looked at any of the other code you have done.  If you have attempted to do what I have above, it may all be trashed.

Now, we can switch the logic so you may start linegen 1&2 at the same time, but, have the lingens stop and wait for you to signal their advance before beginning to draw....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 15, 2020, 12:33:27 pm
|O |O |O |O

I'm not giving up yet, but I've spent two days trying to get this to work and I'm getting nowhere with it, fast.

Linegen#1 should restart when linegen#2 stops after its first pixel.  I'm using an edge-detect on pixel_data_rdy from the other linegen to re-enable the y_stop and re-start the first linegen.  Doesn't seem to be working, though.

I've tried a couple of things, none of which work.  Any ideas where I'm going wrong?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 15, 2020, 05:15:38 pm
Please provide a copy of your full project so I can follow you...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 15, 2020, 05:36:23 pm
Haven't tested the !geo amendment yet, but here's the test project.  The only changes I've made are to geo_xy_plotter.sv and a slight change to line_generator to make reset_stop_y go HIGH for one clock when ena_stop_y goes HIGH..

Project attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 15, 2020, 06:20:26 pm
Try changing line 79 in line_generator.sv to this:

      if ( !ena_stop_y ) begin

The way you had it, once the line has stopped, it would never start.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 15, 2020, 09:11:08 pm
Try changing line 79 in line_generator.sv to this:

      if ( !ena_stop_y ) begin

The way you had it, once the line has stopped, it would never start.

Hmm.. okay, but the reset_stop_y that was in its place was supposed to go high for one clock when ena_stop_y transitioned from low to high, starting the line again.  Obviously that wasn't working.

Have attached simulation output with the change made as you've suggested.  Linegen#1 is now completing its line and y_stopping after each apparent change in Y coordinate (I say apparent, as I haven't tested it with multiple pixels on the same Y-coordinate yet).  However, it's only outputting the first pixel - none of the remaining pixels are sent to PAGET (pixel_data_rdy stays low after the first pixel).  As you can see, linegen#2 is stuck on the first pixel for some reason, but at least it keeps sending that pixel to PAGET.  I think this could be because busy and draw_line are going low before it finishes its line, so it's being reset each time it gets to draw a pixel?

Also, linegen#1 is not staying y_stopped whilst linegen#2 works, it just alternates between on and off each clock cycle once the first pixel is sent to PAGET.  Going to need to think about additional terms in the combinational logic for the y_stop_en signals, I think?

I'll try to have a closer look at this tomorrow.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 15, 2020, 09:40:25 pm
Look:
(http://)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 15, 2020, 10:03:34 pm
Oh for Pete's sake!  |O

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 16, 2020, 06:43:05 am
Ok, I removed a heap of a mess in both the linegen and geometry_xy_plotter.
Get the attached files below.

My added comments arent too detailed, so read up and add comments and ask me questions why while I still have a bit of time left.

Run and test a simulation.
If it looks good, then try it on the Z80.

If everything is of, move onto making linegen2 automatically continue to close the triangle.

Then, worry about making linegen3 do the raster fills.

I already passed everything through linegen3 and setup 4 pointers:

    lgen_1a = 0;
    lgen_1b = 2;
    lgen_2a = 0;
    lgen_2b = 1;

Which select the starting coordinates for the first 2 linegens.

Once the triangle fills, you will need to edit the command numbers. We will want these commands:
0 = do nothing.
1 = place a pixel.  (Currently a line, or the triangle we are debugging.)
2 = draw a line.
3 = draw a triangle.
4 = draw a box
5 = draw a quadrilateral
6 = draw an ellipse
7 = draw a spline    (spare, may be used for something else).

These shapes should only manipulate the lines 256-257 for how & when to start & stop + added lingen3 if necessary, lines 244-246 for what starts when & lines  250-254 to tell the linegens 1&2 which coordinates to use to draw a line.

See lines 422+ in geometry_xy_plotter for the fill/paste/mask flags.
(paste enables the copy blitter algorithm module which will replace lines 309-315.)
(IE disabled, the module will match lines 309-315 passing the plot through, enabled, the module will do a rectangular set width & height CMD_OUT_PXCOPY from the source address & CMD_OUT_PXPASTE/_M the destination address centered on the received destination gen_3_x,gen_3_y coordinates passing the mask (_M) setting if it is set.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 16, 2020, 11:59:32 am
Ok, I removed a heap of a mess in both the linegen and geometry_xy_plotter.
Get the attached files below.

My added comments arent too detailed, so read up and add comments and ask me questions why while I still have a bit of time left.

Run and test a simulation.
If it looks good, then try it on the Z80.

Hmm.. not sure what's going on, but it seems that (in the simulation at least), linegen#1 is repeating when I include the PAGET in the simulation.  :-//

I did this after I tried the HDL on the Z80 - the initial simulation (without PAGET) seemed to work just fine - but when I try to draw the two lines on the Z80, I'm only getting the second line (from x/y[0] to x/y[1]) drawn - there's no sign of the first line.  Just to cover myself, here's how I'm entering the coordinates:
Code: [Select]
    LD      HL,8001H        ; set X[0] to 1
    CALL    send_gpu
    LD      HL,0C001H       ; set Y[0] to 1
    CALL    send_gpu
    LD      HL,9004H        ; set X[1] to 4
    CALL    send_gpu
    LD      HL,0D004H       ; set Y[1] to 4
    CALL    send_gpu
    LD      HL,0A001H       ; set X[2] to 1
    CALL    send_gpu
    LD      HL,0E00AH       ; set Y[2] to 10
    CALL    send_gpu
    LD      A,15            ; Colour white
    CALL    GET_MASK
    CALL    drawLine

All I'm seeing is a line from 1,1 to 4,4.  So I went back to the simulation, included the PAGET and got the output I've attached below.  I'm not sure why the 1st line isn't drawn, unless I'm missing something in the simulation output.

The only changes I made to geo_xy_plotter.sv when I added it to the live project was to remove the two DEBUG pins and declare them in the code as LOGIC and removed the 'extended_cmd' on the geo_mask assignment (line 426 in attached module) as it was throwing errors (it should be command_in[5] if anything) and previously was just grounded.  I've done code tidying as well and changed the REG and WIRE declarations to LOGIC.

So - either my test code is wrong, I've messed up copy-pasting the geo_xy_plotter and line_generator modules from the test bench to the live project, or there's an issue with the HDL.  It's probably something I've done.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 16, 2020, 12:47:19 pm
First issue - time to bang you hear again:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1067870)

Try scrolling the sim waveform in the direction of the arrow...
Run the sim again without the pixel-write and just scroll to the right to 900ns and see what was always there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 16, 2020, 12:58:00 pm
Haha  ;D  I have to laugh otherwise I'd go mad. :palm:

Okay, so that sorts the simulation out.  Still have the problem with the Z80 not drawing the first line.  :-// 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 16, 2020, 01:18:02 pm
Ok, zooming into the simulation with the pixel writer enabled, looking at the bottom at the 'wr_ena' as a reference, you can see the 'ram_addr' just above writing that vertical line and 45 degree line, back and forth 1 pixel after another.  So, this looks good.

IE, 2 writes into 6010, then 6020, 6022, 6030, 6032, 6040, 6044, 6050, 6060,...60A0.
(6050 through 60A0 finishes the vertical white line)

Not only that, but you can count the 'wr_ena' clocks and it comes to 14, so, 14 pixels were written.

Are you sure you have the right source code in your Z80 build?
Seems you are drawing 1 single line from xy[0] to xy[1] like the old line program.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 16, 2020, 01:51:05 pm
Are you sure you have the right source code in your Z80 build?
Seems you are drawing 1 single line from xy[0] to xy[1] like the old line program.

Hmm, well I don't know what that was about, but it's working now.  I suspect the Windows CP/M emulator I'm using to compile the source into a .COM file (CP/M executable file) wasn't overwriting the original source, or something. :palm:  I've cleared out the cobwebs on the simulated drive and it's compiled the latest version now, as I'm getting two lines drawn on the Z80.  Onwards and upwards... :-+

That, or... well, when it wasn't working I'd programmed the FPGA directly via JTAG.  This time I've programmed the configuration ROM via AAS.  Wonder if that might have had something to do with it..
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 16, 2020, 01:59:18 pm
Okay, all is still not quite well..  On the FIRST run of the program since the uCOM is powered on, I get two lines drawn.  If I re-run the program, I only get one drawing from x/y[0] to x/y[2].  I suppose there's still work to be done around the state of the linegens after the two lines are drawn, as the function isn't yet complete?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 16, 2020, 04:03:30 pm
Okay, so getting linegen 2 restarted isn't proving easy.  I figured that using a register to track which set of coordinates linegen#2 is using would make sense, but I may be wrong there - so line_stage is a single-bit register.  In the combinational logic section, I'm setting the coordinate sets in current use as follows:
Code: [Select]
    // Starting and ending coordinate selection for Linegen#1
    lgen_1a              = 0 ; // default to starting at X[0],Y[0]
    lgen_1b              = 2 ; // default to   ending at X[2],Y[2]
   
    // Linegen#2's coordinate selection is a little more involved - needs to switch from 0-1 to 1-2 at first completion
    lgen_2a              = line_stage     ;
    lgen_2b              = line_stage + 1 ;
So linegen#2 uses set [ 0] to set [1] if line_stage is 0, or set [1] to set [2] if line_stage is 1.  That's the idea, anyway.

Line_stage is set in the asynchronous section:
Code: [Select]
        // If linegen#2 completes the first line, set its coordinates to the second line and restart it
        if ( line_2_done && !line_stage ) begin
       
            line_stage  <= 1'b1 ;
           
        end
The only issue is that it takes a clock for line_stage to update linegen#2 to the next set of coordinates - I'm sure there's a way I can do this instantly, I just don't know what it is currently.   I figure I need to do something with the y_stop_en_# assignments to restart linegen#2?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 12:28:26 am
Arrrrggg, damn FMAX... Changes coming...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 02:50:55 am
Ok, here we go, get the attached project.
It is your responsibility to document and update the revision numbers....

First big change, the drawing functions have been updated to these new ones:
Once the triangle fills, you will need to edit the command numbers. We will want these commands:
0 = do nothing.
1 = place a pixel.  (Currently a line, or the triangle we are debugging.)
2 = draw a line.
3 = draw a triangle.
4 = draw a box
5 = draw a quadrilateral
6 = draw an ellipse
7 = draw a Bezier Curve    (spare, may be used for something else).

Fills have yet to be done.

Changes in line_generator.sv:
1. 'line_complete' is now a single 1-shot after the line is finished.
    Enabling line 58 in the code and disabling the other instances in the code changes 'line_complete' into a 1-shot which is send during the final pixel output, meaning you shave 1 clock off when stringing one line command to the next in a sequence.  However, the FMAX will drop below 125MHz in the current setup.
2. 'ypos_stopped' now switches off immediately as the 'ena_stop_y' input goes low, IE it's now combinational logic saving a clock cycle.
3. Numerous other logic start and stop bugs cleaned up.


Changes in geometry_xy_plotter.sv:
1. New line setup Look Up Tables.  (LUT seem to slow down simulation by a big factor since I use large ones...Sorry)

A) This lookup table counts the number of sequences each linegen needs to run: 167-183
Code: [Select]
// This lookup table specifies the number of sequence cycles each linegen needs to run before completing the final shape
logic [2:0] LUT_LG_CMD_SEQ_SIZE[0:31] = '{ // Linegen 1, Linegen 2 sequence size
 0,0,   // Shape  0 = NOTHING
 1,0,   // Shape  1 = Pixel
 1,0,   // Shape  2 = Line
 1,2,   // Shape  3 = Triangle
 4,0,   // Shape  4 = Box
 4,0,   // Shape  5 = Quadrilateral
 0,0,   // Shape  6 = Ellipse
 0,0,   // Shape  7 = Bezier Curve
 0,0,   // Shape f0 = NOTHING
 0,0,   // Shape f1 = Pixel
 0,0,   // Shape f2 = Line
 0,0,   // Shape f3 = Triangle Filled
 0,0,   // Shape f4 = Box Filled
 0,0,   // Shape f5 = Quadrilateral Filled
 0,0,   // Shape f6 = Ellipse Filled
 0,0 }; // Shape f7 = Bezier Curve Filled

B) These 2 lookup tables tells which XY coordinates to use during each linegen sequence: 185-220
Code: [Select]
// These are the lookup tables to select which X/Y source for A,B
// The order is stage 0A,0B, 1A,1B,  2A,2B, 3A,3B, 4A,4B, 5A,5B, 6A,6B, 7A,7B
 logic [1:0] LUT_LG1_SEL_XY[0:511] = '{
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  1 = Pixel
 0,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  2 = Line
 0,0,2,2, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  3 = Triangle
 0,0,1,0, 1,0,1,1, 1,1,0,1, 0,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  4 = Box
 0,0,1,1, 1,1,2,2, 2,2,3,3, 3,3,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  5 = Quadrilateral
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  6 = Ellipse
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  7 = Bezier Curve
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f1 = Pixel
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f2 = Line
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f3 = Triangle Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f4 = Box Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f5 = Quadrilateral Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f6 = Ellipse Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; // Shape f7 = Bezier Curve Filled
 logic [1:0] LUT_LG2_SEL_XY[0:511] = '{
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  1 = Pixel
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  2 = Line
 0,0,1,1, 1,1,2,2, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  3 = Triangle
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  4 = Box
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  5 = Quadrilateral
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  6 = Ellipse
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape  7 = Bezier Curve
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f0 = NOTHING
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f1 = Pixel
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f2 = Line
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f3 = Triangle Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f4 = Box Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f5 = Quadrilateral Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,   // Shape f6 = Ellipse Filled
 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }; // Shape f7 = Bezier Curve Filled

These variables hold each linegen sequence position: 159-164
Code: [Select]
logic [2:0] lg1_seq       ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg2_seq       ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg1_seq_end   ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg2_seq_end   ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg1_nseq      ; // Sequence counter for geometric shapes with multiple lines
logic [2:0] lg2_nseq      ; // Sequence counter for geometric shapes with multiple lines

C) When a geometric shape is called, these lines initialize the linegen params: 538-551
Code: [Select]
                    // Depending on the selected draw command+fill bit, this sets the number of sequences to count down from for each linegen once each linegen finishes.
lg1_seq_end <= LUT_LG_CMD_SEQ_SIZE[{command_in[3:0],1'b0}];
lg2_seq_end <= LUT_LG_CMD_SEQ_SIZE[{command_in[3:0],1'b1}];
lg1_seq     <= 0;
lg2_seq     <= 0;

                    lgen_1ax <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00000}] ;
                    lgen_1ay <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00001}] ;
                    lgen_1bx <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00010}] ;
                    lgen_1by <= LUT_LG1_SEL_XY[{command_in[3:0],5'b00011}] ;
                    lgen_2ax <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00000}] ;
                    lgen_2ay <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00001}] ;
                    lgen_2bx <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00010}] ;
                    lgen_2by <= LUT_LG2_SEL_XY[{command_in[3:0],5'b00011}] ;

D) When the new one-shot 'line_complete' fires, it increments updates the following linegen settings here: 375-390
Code: [Select]
if ( geo_run ) begin // Decrement each line sequence counter once their line has completed.
if (line_1_done && (lg1_seq!=lg1_seq_end)) begin
                                             lg1_seq  <= lg1_nseq;
                                                         lgen_1ax <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b00}] ;
                                                         lgen_1ay <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b01}] ;
                                                         lgen_1bx <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b10}] ;
                                                         lgen_1by <= LUT_LG1_SEL_XY[{geo_shape[3:0],lg1_nseq,2'b11}] ;
                                             end
if (line_2_done && (lg2_seq!=lg2_seq_end)) begin
                                 lg2_seq  <= lg2_nseq;
                                                         lgen_2ax <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b00}] ;
                                                         lgen_2ay <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b01}] ;
                                                         lgen_2bx <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b10}] ;
                                                         lgen_2by <= LUT_LG2_SEL_XY[{geo_shape[3:0],lg2_nseq,2'b11}] ;
                                 end
end

E) This is the current sequence combinational logic for the linegens: 306-323
Code: [Select]
    // If any of the linegens or blitter are working, geo_run needs to go immediately HIGH to stop loading new commands
    geo_run              = (lg1_seq!=lg1_seq_end) || (lg2_seq!=lg2_seq_end) || line_gen_3_running ;

    // Line generator running logic
    line_gen_starter     = !reset && ( !fifo_cmd_rdy_n && !geo_run ) && ( command_in[7:5] == 3'd0 && command_in[2:0] != 3'd0 )    ; // for now, only the draw line command

    linegen_1_run        = line_gen_1_running  || (lg1_seq!=lg1_seq_end && !line_1_done)  ; // initiate linegen1 when linegen2 is not running
    linegen_2_run        = (line_gen_2_running || ( y_stopped_1 )) && !(line_2_done && (lg2_seq!=lg2_seq_end))       ; // initiate linegen2 after linegen1 has its first stop
    linegen_3_run        = 1'b0                                                                                      ; // not used at the moment
   
    // Starting and ending coordinate selection

    // Only release a stop once the opposite linegen goes from a non-y-stopped state to a y-stopped-state, or that linegen has completed a line
    y_stop_en_1          = ( !(y_stopped_2 && !last_y_stopped_2) ) && (lg2_seq!=lg2_seq_end) ;
    y_stop_en_2          = ( !(y_stopped_1 && !last_y_stopped_1) ) && (lg1_seq!=lg1_seq_end) ;

    lg1_nseq  = lg1_seq + 1; // prepare an array with the next sequence number
    lg2_nseq  = lg2_seq + 1; // prepare an array with the next sequence number

You now need to test the first 1..5 functioning commands.  Make sure they work on the Z80.  Make sure the simulation look good.  Update your comments.  Check that the Y position from linegen 1&2 stay synchronized with odd angle lines.  Make sure multiple lines works right.

Next you need to activate the 'Fill' commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 05:18:07 am
Your idea to not use the external Y-STOP counter to stop the linegens is making issues with a filled box and filled quadrilateral.  No problems with a filled triangle as the first pixel is a point and it doesn't need a a filled line between the 2 points.

Ohhh boy, you got a challenge now.

The problem is when a y_increment is ready to take place, y_stopped happens, but, the output coordinates for the next line also come out.  It's like the y_stopped skids 1 extra clock.

With my original idea where we externally mandate a Y-position which will prevent the linegen from doing anything at all if the core Y coordinates equal the externally supplied Y-position, your current code waits for a Y-inc to happen, then stops everything, but let's out the next y_position.

Still, we can start the module in a Y-stopped state, except when switching linegen2 in the middle creates an additional stop we do not want since the beginning and ending xy coordinates happen to match and we want to flush through that first set of numbers until the next Y coordinates only during that mid time, otherwise the Y position of linegen 1&2 loose sync.

This created a little mess.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 08:42:15 am
:wtf:  That's going to take some time to get my head around. :o  Thank you though.

So the first question that springs up when looking at the LUTs is this:

Code: [Select]
logic [1:0] LUT_LG1_SEL_XY[0:511] = '{
You've got one table for each of the first two linegens (LUT_LG1 and LUT_LG2), but I'm a little confused why they're declared as [1:0] LUT_name[0:511]?  There's 512 entries in the table, but what's the first index (1:0) for?

Also, for the box function, wouldn't it make sense to use both the linegens to draw the parallel lines simultaneously? ???  The second linegen looks seriously underused.  ;)

Your idea to not use the external Y-STOP counter to stop the linegens is making issues with a filled box and filled quadrilateral.  No problems with a filled triangle as the first pixel is a point and it doesn't need a a filled line between the 2 points.

Ohhh boy, you got a challenge now.

I hate it when you say that.  I'm not up to the non-challenging stuff, let alone the challenges.  :-[

The problem is when a y_increment is ready to take place, y_stopped happens, but, the output coordinates for the next line also come out.  It's like the y_stopped skids 1 extra clock.

Yeah, I'd noticed that previously.  I guess the only way to stop that would be to calculate the X & Y-coordinates internally and delay them by a clock before outputting them, so y_stopped can get out before the next Y-coordinate?

With my original idea where we externally mandate a Y-position which will prevent the linegen from doing anything at all if the core Y coordinates equal the externally supplied Y-position, your current code waits for a Y-inc to happen, then stops everything, but let's out the next y_position.

Still, we can start the module in a Y-stopped state, except when switching linegen2 in the middle creates an additional stop we do not want since the beginning and ending xy coordinates happen to match and we want to flush through that first set of numbers until the next Y coordinates only during that mid time, otherwise the Y position of linegen 1&2 loose sync.

This created a little mess.

Hmm.. did you see this coming a mile away when I first suggested stopping on every Y-coordinate? ;)

I guess we could add back the 'stop_y_coordinate' register and add a flag/signal to specify whether the linegen is to stop on every y-increment or at the specified y-coordinate?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 08:55:17 am
Ok, the fills are working, however, I haven't solved the above problem.
This means when rasterizing a triangle, the Y position from linegen1 to linegen 2 will slip at the halfway point.
This doesn't seem to be a serious problem as linegen3 will connect the uneven line between lingen 1&2 anyways.

Though I tried a few simple addon patches to fix the problem, non of them were really kosher.  I'll leave it up to you to fix.

Like the previous version, make sure you can simulate, and understand what the simulations are saying and why.
Make sure the FMAX can be reached as we are right on the line.  I had to remove a few optimization which shaved off occasional clock cycles between command transitions, but, your Z80 could never keep up and the pixel writer is the bigger bottleneck anyways.

In the line generator, line 149 reads:

                    ypos_stopped_int   <= 1'b1    ; // PREset ypos_stopped_int flag

The makes the linegen perform a y_stop after the first pixel output.  Disabling this corrects the Y-alignment error on the filled triangles.  However, the box fill and quadrilateral fill will be missing the first line between the first 2 coordinates.

I leave it up to you on if you want to re-engineer the way the y-stop works, or engineer a method to fix the triangle mid-point reset of lingen2 which adds an additional delay in y-coordinates generating that alignment error.

Test/simulate & Z80 test everything out, because I only did the basics.
Remember, we are not yet sorting the 3 coordinates withing the code, but, all the geometry shapes should now be working with and without fill.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 09:03:05 am
:wtf:  That's going to take some time to get my head around. :o  Thank you though.

So the first question that springs up when looking at the LUTs is this:

Code: [Select]
logic [1:0] LUT_LG1_SEL_XY[0:511] = '{
You've got one table for each of the first two linegens (LUT_LG1 and LUT_LG2), but I'm a little confused why they're declared as [1:0] LUT_name[0:511]?  There's 512 entries in the table, but what's the first index (1:0) for?
The first [1:0] means each table entry is a number between 0 and 3, IE: 2 bits wide, it's not an index...
Unlike parameter int's, this tells the compiler the size of the results so I may use the results inside indexed arrays and the compiler will simplify any values in the array down to a logic truth table.
Quote
Also, for the box function, wouldn't it make sense to use both the linegens to draw the parallel lines simultaneously? ???  The second linegen looks seriously underused.  ;)
Take a look at my new upload which supports box fills.
The box function is the same, but, the box_fill does use both linegens in parallel while the third linegen fills the space inbetween.

Same with the quadrilateral and quadrilateral fill.
(You can do freaky double triangles here if you cross up your a,b,c,d coordinates.  I would like to see what happens on the screen when you do so...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 10:06:27 am
Got to head out, but will continue testing when I get back.  Rects, lines and pixels are all working great though.  ;D :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 01:03:29 pm
Okay, here's some test images.  The code that draws them does so in this sequence:

I have 6 images attached, showing the graphics output from each of the above steps.

At the moment, the only error I can see is the missing pixel in the filled rectangle?  Otherwise, the box fill seems to be okay?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 01:35:25 pm
Quadrilateral checks out fine as well.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 02:41:26 pm
What's that missing dot in the purple triangle?
Also, try a weird quadrilateral where it is forced to make one side more pointed and stretched.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 02:42:37 pm
What's that missing dot in the purple triangle?

At the moment, the only error I can see is the missing pixel in the filled rectangle?  Otherwise, the box fill seems to be okay?

I'm not sure.  As soon as I get time, I'll try a few more triangles and see if it repeats, but it appears every time in that particular test.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 02:45:05 pm
In line generator, try this:
In the line generator, line 149 reads:

                    ypos_stopped_int   <= 1'b1    ; // PREset ypos_stopped_int flag

Change that to a 1'b0.
Should fix the triangle, but give you the reverse buf where the filled box and filled quad will be missing the first line.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 03:00:46 pm
That's interesting - yes, it gets rid of the missing pixel and also the top line of the rectangle and quad.  What I don't understand is how that would affect a single pixel in the middle of the triangle fill?

Shame though, it seemed like a good fix for the missing top-line issue.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 17, 2020, 03:09:07 pm
Extreme quad attached...  Same coordinates as before, except for X/Y[2] which I extended out around 250,250-ish.  As you can see, there's a fill error there - or I've got the coordinate order mixed up?

Here's the coordinates I used:

X/Y[0]: 32,40
X/Y[1]: 64,40
X/Y[2]: 236,246
X/Y[3]: 28,70
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 07:24:10 pm
That's interesting - yes, it gets rid of the missing pixel and also the top line of the rectangle and quad.  What I don't understand is how that would affect a single pixel in the middle of the triangle fill?

Shame though, it seemed like a good fix for the missing top-line issue.
RUN The simulation!!!
Watch what linegen 1,2, then 3 is doing in each case.
Predict what would happen in a large area fill.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 07:36:49 pm
For now, stuff the quads.
Show me what a triangle with a flat & near flat top and flat & near flat bottom looks like.

Extra:
If you go enough ram, go into 480x320x4 color so you can test the pixel writer's 4 color mode and larger filled surfaces.

I think we will switch over to a sequencer and just live with an extra clock cycle as new line parameters change.

Maybe we can get rid of the Y wait and just do a pixel wait and make a line fill every pixel advance from the first 2 linegens.  This would multiple repaint over many lines but the fills can be at any angle between both linegen outputs.  No clue if you would get pixel voids.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 17, 2020, 07:57:03 pm
Just so we are clear, stopping your linegen on a chosen Y position was easier and faster and fewer lines of code in the linegen than what you did which became a little isolated monsters which needs a taming...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 18, 2020, 09:51:18 pm
For now, stuff the quads.
Show me what a triangle with a flat & near flat top and flat & near flat bottom looks like.

Okay, image attachments as below:

image_1.jpg - Flat top
image_2.jpg - Near-flat top
image_3.jpg - Flat bottom
image_4.jpg - Near-flat bottom

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 19, 2020, 12:40:14 am
Black dot in first 2 images?
Which revision were you running?

Ok, I think we will need to redoo the entire system so linegen #2 stops on the same Y coordinates of linegen #1...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 19, 2020, 09:18:42 am
Black dot in first 2 images?
Which revision were you running?

Ok, I think we will need to redoo the entire system so linegen #2 stops on the same Y coordinates of linegen #1...

Right, yes, sounds like a plan.  Where do I begin?  I've added the input back to the line_generator module and in the geo_xy_plotter instances - also note that you'd already put the y_stop_coordinate check in the code in line_generator and commented it out previously, so I've un-commented it.

Latest versions of the modules attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 19, 2020, 11:48:44 pm
I don't know exactly what to say.  It looks like things need to be simplified down, otherwise in the futurem you will never be able to debug an issue.

I'm thinking the best strategy for you would be 1:

1. Get rid of the linegen3 and make a simple Horizontal line filling engine with pass-through  A & B, and, line from A to B.
2. Fix up linegens 1 & 2, get rid of pass-through A-B, but keep the smart.  Make an input increment enable.
3. Make a make a vertical line Ay-By counter with enable module.

Now, go back to old fashioned sequencing and when a triangle is called:
Set the vertical counter's start and stop to Y[0] and Y[2].

loop:
Run linegen 1 until the Y output = vertical counter's y output.  (Also plot the linegen's output)
Run linegen 2 until the Y output = vertical counter's y output.  (Also plot the linegen's output)
If lgX1<>lgX2, run Horizontal line filling engine.
If lg2 is finished, restart lg2 with a[1] to b[2]
If lg1 is not finished, increment vertical counter and loop

This matches exactly what the 'Free Basic' code is doing.
This has no coordinate sorting or tests to see if we are drawing a point, horizontal line, or vertical line.

This means getting rid of my LUT solution in place for a case statement with numerical sequences like an old fashioned Basic line numbering code except each line needs the goto to the next.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 21, 2020, 11:08:49 am
Okay, I have only done BASIC testing so far, but I've been experimenting with unique preset values of y_stopped_int for each line generator and I have fixed the alignment error introduced with the previous system of specifying y_stopped_int as the same value for each linegen.  :phew:

The line_generator module now has an additional 1-bit input - lineIndex - which is set to 1 or 0 when the line generator is instantiated in geo_xy_plotter.  Line 150 (previously 149) in the line_generator module now reads:

Code: [Select]
ypos_stopped_int <= lineIndex ;
I've found that setting lineIndex to 1 for linegen's 1 & 2 and 0 for linegen#3 removes the misalignment and draws rectangles and quads without error, and draws filled triangles with no missing pixels due to misalignment of the linegens.

I will do more testing with other triangle shapes later this afternoon, but currently the patch is looking good and a lot less hassle than effectively re-writing the geo_xy_plotter module to start again.  :-//

Lines and pixels are still drawn fine - I suppose if there's issues with any future functions (e.g. ellipses) then a LUT may be the answer, but currently it's working fine.  I'll probably change the name of lineIndex to something more descriptive shortly, but I'll wait and see if you shoot the fix down in flames because there's something I haven't spotted yet which means it breaks everything.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 21, 2020, 12:41:02 pm
Like I said, in the linegens, get rid of the pass-thru and the Y-inc stopped stuff.
Make a general -increment- enable.
Externally, you will  just compare the outpuy y position and decide to continue to increment or not.

Make that linegen -old-simple-stupid...

Too many little thing are going on inside it and you cant debug, or take control in the way you may like properly.

You will rely on code in the geometry_xy_plotter to make the linegens stop and go.

And you will rely on the next simple horizontal filler to select linegen1 or linegen 2 or draw a dumb horizontal line from linegen1 to linegen 2.

Get rid of my look-up tables and make a simple extension to the case statement to run your own sequences to generate each selected shape.  The only thing you want to keep is the output section with coordinates out of bounds check currently lines 395 through 407.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 21, 2020, 01:36:06 pm
Like I said, in the linegens, get rid of the pass-thru and the Y-inc stopped stuff.
Make a general -increment- enable.
Externally, you will  just compare the outpuy y position and decide to continue to increment or not.

Make that linegen -old-simple-stupid...

Too many little thing are going on inside it and you cant debug, or take control in the way you may like properly.

You will rely on code in the geometry_xy_plotter to make the linegens stop and go.

And you will rely on the next simple horizontal filler to select linegen1 or linegen 2 or draw a dumb horizontal line from linegen1 to linegen 2.

Get rid of my look-up tables and make a simple extension to the case statement to run your own sequences to generate each selected shape.  The only thing you want to keep is the output section with coordinates out of bounds check currently lines 395 through 407.

...but I don't want to do all that if I don't have to as I've got the existing system working?  :-//

Is there a big issue with what we've got at the moment (that I can't see) that will cause problems with ellipses?  I'm happy to rip it all up and start again if it really is unusable - there is, after all, still an issue with quads - but it seems silly to set myself back another couple of weeks whilst I rewrite the geo_xy_plotter for no good reason?

EDIT:  As for the quads issue - can't quads just be broken down into triangles by the geo_xy_plotter somehow?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 21, 2020, 05:58:35 pm
The system isn't working good.  If it was, you should have been able to fix it.

As for the quads,  we aren't doing it right now.  with that Y counter, out of the 4 coordinates, you once again make the Y counter go from the min Y to the max Y.

Then for linegens 1&2, pretend you are filling a perfect diamond shape:
What's the difference for linegen #1 when drawing that diamond instead of a triangle.
What's the same about linegen #2 when drawing that diamond and the triangle.

Also, ellipse and rotated ellipse are just quads with arcs instead of straight lines.  Again, the ellipse is a diamond shape with an addition to the linegens to generate a x2 arc.

However, you can try to patch up the current system.
Make sure empty pixels never come up anywhere.

I guess you should think about sorting the coordinates now for triangles and quads.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 21, 2020, 07:20:29 pm
The system isn't working good.  If it was, you should have been able to fix it.

I have fixed it. ???  I'm not getting missing pixels in triangles or misaligned fills in any shapes that I've tested so far.  I'll keep testing (especially larger shapes), but so far so good.  :-+

As for the quads,  we aren't doing it right now.  with that Y counter, out of the 4 coordinates, you once again make the Y counter go from the min Y to the max Y.

I was thinking of ordering the four points, then drawing a triangle with points 1, 2 and 3, then another triangle with points 2, 3 and 4.  That should cope with any shape of quad, unless you have a better idea?

However, you can try to patch up the current system.
Make sure empty pixels never come up anywhere.

That's what I've been saying, it seems I have patched the current system.  :-/O  I'll keep testing it, though.

I guess you should think about sorting the coordinates now for triangles and quads.

Righto - will make a start on that soon.  We already have a coordinate-sorting module, or part of one, with the tri_comp module, right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 21, 2020, 08:49:38 pm
Righto - will make a start on that soon.  We already have a coordinate-sorting module, or part of one, with the tri_comp module, right?

Yes, the tri_comp gives you a set of flags which you may simplify just the ones you need into a new logic array, and feed that into 4 LUTs whose results will give your the sort selection based on sequence number and shape type.

The sort should also work for the quads.

Quote
I was thinking of ordering the four points, then drawing a triangle with points 1, 2 and 3, then another triangle with points 2, 3 and 4.  That should cope with any shape of quad, unless you have a better idea?

Given my response, you should easily be able to adapt the current setup to do exactly as I described.
You are allowed any number of sequences for linegen #1 and #2.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 21, 2020, 10:31:24 pm
You can also do 2 triangles for the quad, but, it will be slower.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 07:50:35 am
You can also do 2 triangles for the quad, but, it will be slower.

That's the way that immediately sprang to mind when I thought about how to cater for any quad shape, as the current setup obviously doesn't work properly for all cases.   I figured it wouldn't be the quickest way, but in terms of my understanding it, I think I can do that myself once the point-sorting is running.

Modern graphics cards don't draw quads/polygons anyway?  Quads are a valid primitive in 3D graphics (they're used regularly in 3D software like Blender, Maya etc and game engines like Unreal Engine and Unity, for example), but I think polygons and quads are broken down into triangles by the driver (or perhaps even by the software 3D engine itself) before the GPU gets to run transform calculations on it?

I'm not sure I fully understand how your method of quad drawing will work.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 09:18:56 am
Just taking a look at tri_comp.

It provides three outputs, each a 16-bit composite value, where each bit is HIGH if that value's comparison is true - i.e. in_a_eq_b tests equality between the three 12-bit input values:
And these can be simplified down to:
Is that right?

Where do I go from there with it, though?  The flags output from tri_comp need to influence the LUT_LG#_SEL_XY lookup tables somehow, but I'm not sure how?  You mentioned using four LUTs:

Yes, the tri_comp gives you a set of flags which you may simplify just the ones you need into a new logic array, and feed that into 4 LUTs whose results will give your the sort selection based on sequence number and shape type.

Erm, so these LUTs will affect the LUT_LG#_SEL_XY tables or replace them?  I'm not sure how the new LUTs should look.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 10:46:03 am
Aaah dammit...  :'( |O :horse:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 22, 2020, 10:52:34 am
What's wrong?
What was that suppose to look like?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 11:11:07 am
What's wrong?
What was that suppose to look like?

It's not supposed to have the line of dots through the centre of the large triangle.  It seems my fix works for triangles where X[1] is greater than X[0], but not the other way around.  I'm just testing a fix for this case.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 22, 2020, 11:27:00 am
LUT Method:
Well, you need a LUT, right, 4 possible coordinates to set in the source lines.

There will be 2 sorting, 1 for triangles, 1 for quads.
The each sorting will have an output for first half or the triangle, then a second for the second half.

Feeding the compare module with Y[n], look at the  in_a_gt_b.

What's important is
y0>y1
y0>y2
y0>y3
y1>y2
y1>y3
y2>y3

That's 6 bitst for which shape, triangle or quad, so, make a 7 bit logic array:
Code: [Select]
y_cmp_sort = {in_a_gt_b[y2>y3],in_a_gt_b[y1>y3],in_a_gt_b[y1>y2],in_a_gt_b[y0>y3],in_a_gt_b[y0>y2],in_a_gt_b[y0>y1]} ;

Next, make a lut name:

Code: [Select]
logic [1:0]  LUT_SORT_SEL_LG  [0:511]  = '{  //  LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, COORD[1],COORD[0] } ]
// xy[3],xy[2],xy[1],xy[0],  xy[3],xy[2],xy[1],xy[0],
// Triangle  Quadra
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3],![y0>y2],![y0>y1] = 000000
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3],![y0>y2], [y0>y1] = 000001
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3], [y0>y2],![y0>y1] = 000010
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3], [y0>y2], [y0>y1] = 000011

.......  }; // Cross look up table.

Each 0,0,0,0 should have the new corresponding 0,1,2,3 filled in.

For you, it may be easier just to use the 'IF()' method.  IE, copy the basic code.

you should make an 4 12bit signed byte arrays:
sorted_x[ # ]
sorted_y[ # ]
And set them at line 553 in the latest geometry_xy_plotter code.

Code: [Select]
sorted_x[0] <= x[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd0 } ];
sorted_x[1] <= x[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd1 } ];
sorted_x[2] <= x[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd2 } ];
sorted_x[3] <= x[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd3 } ];
sorted_y[0] <= y[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd0 } ];
sorted_y[1] <= y[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd1 } ];
sorted_y[2] <= y[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd2 } ];
sorted_y[3] <= y[LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, 2'd3 } ];

Then in the 2 linegens:
Code: [Select]
  .aX             ( x[lgen_1ax]        ), // 12-bit X-coordinate for line start
  .aY             ( y[lgen_1ay]        ), // 12-bit Y-coordinate for line start
  .bX             ( x[lgen_1bx]        ), // 12-bit X-coordinate for line end
  .bY             ( y[lgen_1by]        ), // 12-bit Y-coordinate for line end
change those 2 into the 'sorted_x/y[ ... ]'

I hope this gives you ideas.
You may need to change the 'line_gen_starter' into a FF to delay the start by 1 clock for the new delayed 'sorted_xy[ # ]'s.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 11:53:34 am
What's wrong?
What was that suppose to look like?

It's not supposed to have the line of dots through the centre of the large triangle.  It seems my fix works for triangles where X[1] is greater than X[0], but not the other way around.  I'm just testing a fix for this case.

Okay, fixed that issue.  Turns out some shapes (rectangles) need to have delays on the linegens whilst others don't.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 03:30:49 pm
LUT Method:
Well, you need a LUT, right, 4 possible coordinates to set in the source lines.

There will be 2 sorting, 1 for triangles, 1 for quads.
The each sorting will have an output for first half or the triangle, then a second for the second half.

Feeding the compare module with Y[n], look at the  in_a_gt_b.

What's important is
y0>y1
y0>y2
y0>y3
y1>y2
y1>y3
y2>y3

That's 6 bitst for which shape, triangle or quad, so, make a 7 bit logic array:
Code: [Select]
y_cmp_sort = {in_a_gt_b[y2>y3],in_a_gt_b[y1>y3],in_a_gt_b[y1>y2],in_a_gt_b[y0>y3],in_a_gt_b[y0>y2],in_a_gt_b[y0>y1]} ;

Oookay... but why a 7-bit logic array to hold 6 bits of data? ???

Next, make a lut name:

Code: [Select]
logic [1:0]  LUT_SORT_SEL_LG  [0:511]  = '{  //  LUT_SORT_SEL_LG[ { y_cmp_sort , SHAPE_IS_QUAD, COORD[1],COORD[0] } ]
// xy[3],xy[2],xy[1],xy[0],  xy[3],xy[2],xy[1],xy[0],
// Triangle  Quadra
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3],![y0>y2],![y0>y1] = 000000
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3],![y0>y2], [y0>y1] = 000001
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3], [y0>y2],![y0>y1] = 000010
   0,0,0,0, 0,0,0,0,  // ![y2>y3],![y1>y3],![y1>y2],![y0>y3], [y0>y2], [y0>y1] = 000011

.......  }; // Cross look up table.

Each 0,0,0,0 should have the new corresponding 0,1,2,3 filled in.

Riiight.. okay, well I've completed the LUT structure, but have yet to populate all the order combinations.  Any chance you could let me know if I'm on the right track?  The new LUT starts at line 233 in the attached code.

For you, it may be easier just to use the 'IF()' method.  IE, copy the basic code.

Hmm, well as soon as I spot a pattern in the table, I'm sure filling out the LUT will speed up.  Otherwise, I've only done the first four lines so far.  :-+

EDIT:  Okay, so there's some weirdness going on here.  Some of the lines in the table are fine, but some are impossible and would (should?) never arise, unless some coordinates are exactly equal to each other, then all bets are off.

Take, for example, this case:

Code: [Select]
0,0,1,2, 1,2,3,0,  // ![y2>y3],![y1>y3],![y1>y2], [y0>y3],![y0>y2],![y0>y1] = 000100

The statement says that y3>y2, y3>y1, y2>y1, y0>y3, y2>y0, y1>y0 for a y_cmp_sort value of 000100.

How can y3 be greater than y2 when y0 is greater than y3, but y2 is greater than y0?  What should I be putting into the ordered coordinate values for lines like these?  Does it matter?  In theory, these cases will only arise when two sets of Y-coordinates are on the same line, so presumably it shouldn't matter in what order they go - except that it does for a quad?

Have I got the values the wrong way around as well? (i.e. the line above, should that be: 2,1,0,0 0,3,2,1 ?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 22, 2020, 05:46:49 pm
Yes, there are some impossible states.
Also, I go this backwards:
Code: [Select]
// xy[3],xy[2],xy[1],xy[0],  xy[3],xy[2],xy[1],xy[0],
It should be:
Code: [Select]
// xy[0],xy[1],xy[2],xy[3],  xy[0],xy[1],xy[2],xy[3],
So, flip everything around.
As for the lemmon states, just copy the best state which would still generate a valid output, or use 0,1,2,3.

Also for the triangle, I guess you can make xy[3] always equal 3 so it is passed through.

1 last thing, there is so much junk here, you can just engineer it as a module with an

Code: [Select]
input   clock
input   bypass            // makes output x_sort[0] to x_sort[3] = x_in[0] to x_in[3] no matter what.  Same for Y
input   shape_quad
input signed [11:0] x_in [0:3],
input signed [11:0] y_in [0:3],
output signed [11:0] x_sort [0:3],
output signed [11:0] y_sort [0:3],
output all_x_equal    // when drawing a triangle, only compare x0...x2, otherwise compare x0...x3
output all_y_equal    // when drawing a triangle, only compare x0...x2, otherwise compare x0...x3

Or you can make this part of the 'tri_comp' module.
This way if you want to change the lut_table to IF(a>b>c), you wont need to mangle the rest of the code.
The IF method compiles and simulates faster than the LUT and also eliminates those pesky dead conditions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 08:46:03 pm
1 last thing, there is so much junk here, you can just engineer it as a module with an

Code: [Select]
input   clock
input   bypass            // makes output x_sort[0] to x_sort[3] = x_in[0] to x_in[3] no matter what.  Same for Y
input   shape_quad
input signed [11:0] x_in [0:3],
input signed [11:0] y_in [0:3],
output signed [11:0] x_sort [0:3],
output signed [11:0] y_sort [0:3],
output all_x_equal    // when drawing a triangle, only compare x0...x2, otherwise compare x0...x3
output all_y_equal    // when drawing a triangle, only compare x0...x2, otherwise compare x0...x3

Wait, what?  We're sorting X-coordinates as well?  :o

The IF method compiles and simulates faster than the LUT and also eliminates those pesky dead conditions.

I suppose the IF method also doesn't use up valuable RAM - or are LUTs stored in some other way?

Must admit - the IF method is very tempting.  I've got 64 sets of 8 values to enter...  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 22, 2020, 08:57:28 pm
You are sorting based only the Y coordinates, but, remember, the coordinates come in pairs....
The IF method is easier to debug or swap output order as well.

Also add these 4 outputs:

signed [11:0] y-min
signed [11:0] y-max
signed [11:0] x-min
signed [11:0] x-max

If all Y coordinates are equal, then we sort based on the coordinates from x-min to x-max.
This is so you can generate an optimized horizontal only line, or vertical only line.
IE, run only 1 line generator once for the filled triangle or filled quadrilateral.

The IF() else IF() method would simplify down in gate much easier.

Remember, the module takes in the x/y 0,1,2,3, and spits out a new x/y 0,1,2,3 where the linegens always use those new outputs in the same order expecting the points to be ordered from low to high.

While the all_x_equal / all_y_equal tells the linegens section to skip a filled geometric shape and just draw 1 single line from min to max.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 22, 2020, 09:17:41 pm
Okay, so I'm ready to make a start on this in the morning, just want to clarify this point:

Aside from the x/y-min/max outputs, the IF...ELSE IF structure is going to replace the new LUT and it's 512 values based off of the y_cmp_sort value and instead I'll be doing something similar to this?

Code: [Select]
if ( ( Y[0] >=  Y[1] ) && ( Y[1] >= Y[2] ) ) begin
    sorted_x[0] = x[2] ;
    sorted_y[0] = y[2] ;
    sorted_x[1] = x[1] ;
    sorted_y[1] = y[1] ;
    sorted_x[2] = x[0] ;
    sorted_y[2] = y[0] ;
    sorted_x[3] = x[3] ;
    sorted_y[3] = y[3] ;
end else if ( etc...)

But I'd need to include Y[3] in the conditionals as well?

And this would replace the tri_comp module as well, wouldn't it?  Can't see a need for tri_comp if I'm doing all the IF..ELSE IF structure?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 22, 2020, 09:31:54 pm
Code: [Select]
always_ff @(posedge clk) begin

if (bypass) begin
for ( int i=0; i<=3 ; i++ ) begin
    sorted_x[i] <= x[i] ;
    sorted_y[i] <= y[i] ;
end
end else if (~shape_quad) begin // all triangle logic
    sorted_x[3] <= x[3] ;
    sorted_y[3] <= y[3] ;

if ( ( Y[0] >=  Y[1] ) && ( Y[1] >= Y[2] ) ) begin
    sorted_x[0] <= x[2] ;
    sorted_y[0] <= y[2] ;
    sorted_x[1] <= x[1] ;
    sorted_y[1] <= y[1] ;
    sorted_x[2] <= x[0] ;
    sorted_y[2] <= y[0] ;
end else if ( etc...)


end else begin // sorting for a triangle end, now sorting for a quadrilateral.

end

[/quote]

Finish this then we will worry about adding the IF ( y[0] == y[1] == y[2] ) at the top to sort the first linegen X min and X max as well as finish the all equal outputs.

Also, remember at the inputs,
input clk,
input enable,  // !pixel writer busy input...

I would also prefer feeding through this module the drawing function and drawing color as it should appear as a pipe in the command chain to the next lingen modules.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 23, 2020, 09:30:54 am
Okay, check out attached geo_xy_plotter module - line 684 onwards is the new poly_sort module.  Have done the triangle and quad sorting.

I would also prefer feeding through this module the drawing function and drawing color as it should appear as a pipe in the command chain to the next lingen modules.

Well this module is going to introduce a clock delay, so that makes sense I guess.  I'm just unsure how to feed the drawing function and colour through?  Should I be feeding geo_shape, geo_fill, geo_color etc into poly_sort, or passing in the fifo_cmd_in input from geo_xy_plotter, or...?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 23, 2020, 06:06:30 pm
Well this module is going to introduce a clock delay, so that makes sense I guess.  I'm just unsure how to feed the drawing function and colour through?  Should I be feeding geo_shape, geo_fill, geo_color etc into poly_sort, or passing in the fifo_cmd_in input from geo_xy_plotter, or...?

Check out line 412:
Code: [Select]
    line_gen_starter     = !reset && ( !fifo_cmd_rdy_n && !geo_run ) && ( command_in[7:5] == 3'd0 && command_in[3:0] != 4'd0 )    ; // for now, only the draw line command

Now you just need to delay the ' line_gen_starter ' by 1 clock and everything should be honky dory.
Now tell me where you will be moving that line to to that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 23, 2020, 06:19:39 pm
Check out line 412:
Code: [Select]
    line_gen_starter     = !reset && ( !fifo_cmd_rdy_n && !geo_run ) && ( command_in[7:5] == 3'd0 && command_in[3:0] != 4'd0 )    ; // for now, only the draw line command

Now you just need to delay the ' line_gen_starter ' by 1 clock and everything should be honky dory.
Now tell me where you will be moving that line to to that?

I've moved it into the asynchronous always_ff block and changed it to a register assignment:

Code: [Select]
line_gen_starter    <= !reset && ( !fifo_cmd_rdy_n && !geo_run ) && ( command_in[7:5] == 3'd0 && command_in[3:0] != 4'd0 ) ; // for now, only the draw line command
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 23, 2020, 06:53:48 pm
Ok, does the sorting work?
Did you not forget to remove the '!reset' from the line.
Is it inside the !draw_busy ?
Did you add a clear in the if(reset)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 23, 2020, 07:07:08 pm
Ok, does the sorting work?

Hang on a mo - am I wiring up the poly_sort module correctly?  I'm not sure the x_in and y_in inputs are right (or will work as expected), but I really don't know how to get four sets of values back out of the module.... what do I connect to x_sort and y_sort?

Code: [Select]
poly_sort sorter (
// inputs
    .clk           ( clk          ),
    .enable        ( !draw_busy   ), // !pixel_writer busy input
    .bypass        ( 1'b0         ), // pass x_in/y_in values straight to x_sort/y_sort - no sorting
    .shape_quad    ( geo_shape[2] ), // sorts y_in[0-2] (3 points) if LOW, y_in[0-3] (4 points) if HIGH
    .x_in          ( '{ x[0], x[1], x[2], x[3] } ), // values to sort
    .y_in          ( '{ y[0], y[1], y[2], y[3] } ), // values to sort
//outputs
    .x_sort        ( ), // sorted value output
    .y_sort        ( ), // sorted value output
    .y-min         ( ),
    .y-max         ( ),
    .x-min         ( ),
    .x-max         ( ),
    .all_x_equal   ( ), // tells the linegens to skip a filled geometric shape and just draw 1 single line from y-min to y-max
    .all_y_equal   ( )  // tells the linegens to skip a filled geometric shape and just draw 1 single line from x-min to x-max
);

Did you not forget to remove the '!reset' from the line.
Is it inside the !draw_busy ?
Did you add a clear in the if(reset)?

Yep.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 23, 2020, 09:07:52 pm
Have just connected the poly_sort module in a way where the outputs copied the format of the inputs, and it compiles.

Problem is, Fmax on clk[2] has dropped to 113.22 MHz.  :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 05:12:18 am
Have just connected the poly_sort module in a way where the outputs copied the format of the inputs, and it compiles.

Problem is, Fmax on clk[2] has dropped to 113.22 MHz.  :-BROKE
I cant compile your code.  I get:
Code: [Select]
Error: Port "lineIndex" does not exist in macrofunction "linegen_3"
Error: Port "lineIndex" does not exist in macrofunction "linegen_2"
Error: Port "lineIndex" does not exist in macrofunction "linegen_1"

Also, why:
Code: [Select]
poly_sort sorter (
// inputs
    .clk           ( clk          ),
    .enable        ( !draw_busy   ), // !pixel_writer busy input
    .bypass        ( 1'b0         ), // pass x_in/y_in values straight to x_sort/y_sort - no sorting
    .shape_quad    ( geo_shape[2] ), // sorts y_in[0-2] (3 points) if LOW, y_in[0-3] (4 points) if HIGH
    .x_in          ( '{ x[0], x[1], x[2], x[3] } ), // values to sort
    .y_in          ( '{ y[0], y[1], y[2], y[3] } ), // values to sort
//outputs
    .sorted_x      ( '{ x_sort[0], x_sort[1], x_sort[2], x_sort[3] } ), // sorted value output
    .sorted_y      ( '{ y_sort[0], y_sort[1], y_sort[2], y_sort[3] } ), // sorted value output
    .y_min         ( ),
    .y_max         ( ),
    .x_min         ( ),
    .x_max         ( ),
    .all_x_equal   ( ), // tells the linegens to skip a filled geometric shape and just draw 1 single line from y-min to y-max
    .all_y_equal   ( )  // tells the linegens to skip a filled geometric shape and just draw 1 single line from x-min to x-max
);
Why not:
Code: [Select]
poly_sort sorter (
// inputs
    .clk           ( clk          ),
    .enable        ( !draw_busy   ), // !pixel_writer busy input
    .bypass        ( 1'b0         ), // pass x_in/y_in values straight to x_sort/y_sort - no sorting
    .shape_quad    ( geo_shape[2] ), // sorts y_in[0-2] (3 points) if LOW, y_in[0-3] (4 points) if HIGH
    .x_in          ( x ), // values to sort
    .y_in          ( y ), // values to sort
//outputs
    .sorted_x      ( x_sort ), // sorted value output
    .sorted_y      ( y_sort ), // sorted value output
    .y_min         ( ),
    .y_max         ( ),
    .x_min         ( ),
    .x_max         ( ),
    .all_x_equal   ( ), // tells the linegens to skip a filled geometric shape and just draw 1 single line from y-min to y-max
    .all_y_equal   ( )  // tells the linegens to skip a filled geometric shape and just draw 1 single line from x-min to x-max
);

You will most likely need to create a command path from:

the output fifo function and command parameters

Into 'poly_sort'

command parameters and sorted coordinates out

Into a either the linegens or a new module which takes in the commands and runs the linegens.

Out of that module and into the blitter

out of the blitter to the output of the geometry_xy_plotter's output port into the address generator.

Each module having a clock delay, or in the case of the last 2 modules multiple clock delays.

This is the only way we can get a grip on improving the FMAX and if necessary in the future, adding an additional clock latency.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 07:19:28 am
Have just connected the poly_sort module in a way where the outputs copied the format of the inputs, and it compiles.

Problem is, Fmax on clk[2] has dropped to 113.22 MHz.  :-BROKE
I cant compile your code.  I get:
Code: [Select]
Error: Port "lineIndex" does not exist in macrofunction "linegen_3"
Error: Port "lineIndex" does not exist in macrofunction "linegen_2"
Error: Port "lineIndex" does not exist in macrofunction "linegen_1"

Sorry, you haven't got the latest line_generator.sv with the fix for the de-synched linegens.  Will take a look at rest of your post shortly.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 09:57:44 am
Here's my current test bench with the latest versions of line_generator and geo_xy_plotter.

I've got the cmd_data pipe set up from the FIFO, through poly_sort and into the linegens currently (best I can tell it simulates okay).  Quartus II is quoting an Fmax of 104.41 MHz.

If I'm reading anything correctly from the compilation report, it seems that the sort in poly_sort is causing the issue - does the IF structure need to be simplified or expanded further?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 12:56:42 pm
Ok, it's the quadrilateral sorting creating too much logic as when I remove it and just use the triangle sort, your FMAX's limiting factor is in the linegens instead.  It needs to be sorted in 2 steps.

Also, we need to fix up the command pipe as all it's functions like bypassing the sort and the geo-shape and color are not being used by the next function.

AND, the command pipe pass through (lines 643-644) also needs to be after line 646.....

I recommend keeping the triangle sort as the first stage in the pipe, then for the second stage, if a quad it selected, only if y[2] >= y[3], swap xy[2] & xy[3], or, if y[0] >= y[3], then swap xy[0] and xy[3].
Remember, the middle 2 coordinates don't need their y sorting if they 3 have already been sorted on the previous clock.

I'm assuming you are sorting y[0] minumum, y[3] maximum.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 01:22:11 pm
Also, we need to fix up the command pipe as all it's functions like bypassing the sort and the geo-shape and color are not being used by the next function.

How do you mean?

AND, the command pipe pass through (lines 643-644) also needs to be after line 646.....

Ah, okay, done.  I thought that it should be passing through cmd_data whether poly_sort is enabled or not though?

I recommend keeping the triangle sort as the first stage in the pipe, then for the second stage, if a quad it selected, only if y[2] >= y[3], swap xy[2] & xy[3], or, if y[0] >= y[3], then swap xy[0] and xy[3].
Remember, the middle 2 coordinates don't need their y sorting if they 3 have already been sorted on the previous clock.

Okay... so... pipelining the sort into a two-stage process...  :o

So instead of if (~shape_quad) begin starting off the triangle sorting, instead it'll be if ( !step ) begin, where step alternates between 0 and 1 each clock. Then the quad sort is done when step is 1?  Is there a better way?

Also, I'll need to increase the cmd_data pipeline by another step to delay it by 2 clocks if a quad is being sorted?

I'm going to need some sort of output to let the linegen's (or geo_xy_plotter) know that there is valid data?

I'm assuming you are sorting y[0] minumum, y[3] maximum.

Yep.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 01:35:17 pm
You have the first triangle sort,

cmd_in -> cmd_mid_pipe &
in -> tri-sort

then continue

cmd_mid_pipe -> pipe_out &
tri-sort -> quad sort.

Dont forget the the first bypass if gets its decision from the cmd_in
and the trisort->quadsort bypass gets its bypass decision from the cmd_mid_pipe.

You are also need to input and operate based on a execute command ready and a reset input which only needs to clear the command stages.  Don't worry about all the xy[ # ] mid stages in the reset.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 02:30:11 pm
120.32 MHz Fmax. :(  (Assuming I've pipelined the sorting correctly.)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 02:37:11 pm
How is that a pipe?
you are going straight from in to sorted & in to sorted again?

what happened to going from in to sort stage #1, then sort stage #1 to sorted output?

Also, in the reset, reset the output command & output cmd_ready...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 03:02:56 pm
How is that a pipe?
you are going straight from in to sorted & in to sorted again?

what happened to going from in to sort stage #1, then sort stage #1 to sorted output?

Oh yeah. ::)  Must have attached the module to the post before I'd finished it.  ;)

Okay, Fmax is up over 128 MHz but the simulation output doesn't look too good.  I'm doing something wrong somewhere.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 05:40:37 pm
You have structural command problem throughout lines 664-680.

Like, why do you still have a bypass.
And why are you beginning a sort instead of a bypass if the command shape to be drawn is anything else other than a FILLED TRIANGLE, or a FILLED QUADRILATERAL.  And in the second case, only a filled QUADRILATERAL.

Also, if the y[0] to y[2] are all equal in filled triangle, or, y[0] through y[3] are all equal if quadrilateral, think about changing the command into a DRAW LINE, and make x[0] the lowest x[ # ] in the coordinates and make x[ # ] the highest x in the used coordinates.

Also, same if all X [ # ] are equal.  Change the command into a DRAW LINE and make y[0] the lowest used Y and make y[1] the highest Y.  This one may be simplified by making xy[0] the lowest Y and xy[1] the highest Y by default and changing the coordinate order in the line drawing engine.

Next, you also need to take care of 570-591 as these need to be part of a new line drawing module as they need to receive commands and what functions to draw after this sorting module.  This module will now initiate the linegens driving code and output a pixel ready plus XY coordinates + color + command.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 06:11:44 pm
You have structural command problem throughout lines 664-680.

Like, why do you still have a bypass.

And why are you beginning a sort instead of a bypass if the command shape to be drawn is anything else other than a FILLED TRIANGLE, or a FILLED QUADRILATERAL.  And in the second case, only a filled QUADRILATERAL.

Also, if the y[0] to y[2] are all equal in filled triangle, or, y[0] through y[3] are all equal if quadrilateral, think about changing the command into a DRAW LINE, and make x[0] the lowest x[ # ] in the coordinates and make x[ # ] the highest x in the used coordinates.

Also, same if all X [ # ] are equal.  Change the command into a DRAW LINE and make y[0] the lowest used Y and make y[1] the highest Y.  This one may be simplified by making xy[0] the lowest Y and xy[1] the highest Y by default and changing the coordinate order in the line drawing engine.

Okay, fair bit for me to be getting on with here.  So I need to get rid of the bypass input and replace its IF conditional for one that checks for line conditions?

Only filled triangles and filled quads to be sorted?

Next, you also need to take care of 570-591 as these need to be part of a new line drawing module as they need to receive commands and what functions to draw after this sorting module.  This module will now initiate the linegens driving code and output a pixel ready plus XY coordinates + color + command.

So this will be the module that sits between the poly_sort and blitter in the cmd pipeline?  The LUTs will need to be moved into this new module as well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 06:17:57 pm
correct, the bypass was originally to be decoded outside the module from the command which was never sent through.  This is no longer the case and you need to evaluate 2 different commands at 2 different stages in the pipe.

Correct on number 2 as well.
#2 will also receive the command and pipe them through to generate it's output.
#2 also now generates the geometry 'running' command to pause everything else in the pipeline until the shape it is working on is complete.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 24, 2020, 09:14:56 pm
Okay, if I have any time I'll have a go at this tomorrow afternoon.  This sorting feature seems to be a bit of a bottomless rabbit hole, though!  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 24, 2020, 09:50:48 pm
Okay, if I have any time I'll have a go at this tomorrow afternoon.  This sorting feature seems to be a bit of a bottomless rabbit hole, though!  :o
It not that it is a bottomless hole.  You are adding logic & you need to space/step thing out in steps which can keep the FMAX at the top.  It is good practice for you as I did the same thing in the address generator for you awhile back.

Learning to compartmentalize and sequence your functions as such removes dead clock cycles when done right.
You are now creating a geometry graphics pipeline with stand alone modules, forwarding the command instruction as each draw command feeds through.  This will allow you to sequentially add in more functions into that command pipe as time goes on.

We did this with the 15 port ram where we fed through the bitplane/palette color mixing settings and sub-pixel selection with those auxiliary ports in parallel with the read address.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 26, 2020, 03:48:29 pm
Maybe you misunderstand, just make the 2 stage sort with proper command pass thru first.
The added command interpretation and change to line is used to optimize flat filled triangles and flat filled quads.
I told you all this so you code the module expecting to add this optimization.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 26, 2020, 04:51:45 pm
I know I've been silent for a day or so - have been busy with work and haven't been able to get anything done.  Here's where I'm at currently (latest geo_xy_plotter module attached).

Lines 662-671 have been updated to remove the old bypass value check and changed to only bypass the sorting if the shape is not a triangle or filled quad.

When I get a sec, I'll make a start on the next bit - optimising to line drawing if all points in an axis are identical.

What I meant with the 'rabbit hole' comment was that what started out as a simple sorting function seems to have turned into a multi-stage, command pipeline-editing optimiser  that probably should be in a module file all of its own.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 27, 2020, 01:18:19 am
Ok, here we go:

Lines 662 to 669:
You cannot bypass/skip a clock cycle from in to out.

Line 672, you all of a sudden should not to decide to register the cmd_rdy_in if earlier you didn't for the pass-through which are still legitimate commands, just the coordinates arent sorted.

Line 740,  This isn't an else.  What happens if 2 sequential commands come in, once one goes through the first stage, then through the second but there is also another command ready at the first, this second stage will be ignored.

Ok, I'll re-write this in a way which will actually allow you to add additional processing steps at will without the confusing labels and middle sequences.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 28, 2020, 05:34:30 am
Redone!

Well, almost, I just need to add the raster-fill.
Please test these new units as all the draw commands without a fill should work.

I'll add the raster fill tomorrow.

Things done:
Reverted the line generator to a simple dumb one with nothing more than a 'pause' feature.
Made the input command sort, sort everything and now it also sets the sequence size for each linegen.
FMAX (geometry processor related) should no longer be a problem.
Made provisions for inserting the copy pixel blitter for completion on Tuesday.

***CHANGE: I made the max X&Y coordinate limiter = only pixel coordinates below the max setting are written to GPU ram, it is no longer the top pixel coordinate allowed.  This way, if max X&Y is set to 0, the geometry plotter cannot perform a pixel write protecting your GPU ram from any writes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 28, 2020, 10:10:36 am
Wow! Thank you.  ^-^  Seems to work just fine on the hardware  :-+, buuut.... I had a look at the compilation report to see what the new Fmax would be for clk[2] and got this:

[attachimg=1]

clk[2]'s Fmax is down to 104.6 MHz?  Is that right or have I got a compiler setting that needs changing again? (I haven't changed anything - just copy-pasted the new line gen and geo_xy_plotter modules into the existing GPU project.)

I've attached the Worst-Case Timing Paths report in case it's any use.  From my interpretation, it looks like Pixie's FIFO output to the poly_sort module isn't happy.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 28, 2020, 05:27:27 pm
How strange, this is what I get:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1076828)

Take a look at the attached project.
(Backup your previous work or save it under a new name)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 28, 2020, 06:01:32 pm
Must be a compiler setting then as the version of the project you uploaded compiles with exactly almost the same Fmax results as you're getting.  How odd - I was sure I hadn't changed anything but the results speak for themselves.  :-//

EDIT:

I'm getting clk[0] Fmax = 125.94 MHz, clk[2] Fmax = 130.72 MHz.  Not quite the same as what you're getting.  Is that usual or is the Fmax sensitive to the host computer the project is compiled on?  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 28, 2020, 06:44:34 pm
Must be a compiler setting then as the version of the project you uploaded compiles with exactly almost the same Fmax results as you're getting.  How odd - I was sure I hadn't changed anything but the results speak for themselves.  :-//

EDIT:

I'm getting clk[0] Fmax = 125.94 MHz, clk[2] Fmax = 130.72 MHz.  Not quite the same as what you're getting.  Is that usual or is the Fmax sensitive to the host computer the project is compiled on?  :o
The slight change in FMAX was because I forgot a change which forced the filled shapes to draw as outlines.
The change lowered the FMAX slightly.  But no problem.  I'm now finishing the raster fill.  Update in an hour or so.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 03:00:29 am
Here you go, V5 with fill, all shapes except ellipse.
Please test everything.
I've included the final project EP4CE10 & simulation test bench Geo_Writer_V5.
Some optimization sacrifices were made to make the code editable by you.  For this, the odd additional clock cycle happens during line generation.

Test everything as I'll add the blitter next.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 08:56:17 am
Initial testing is throwing up a problem.  I'm using the identical test that I've been using for the last couple of weeks.

Looks like the bottom line of the filled rectangle isn't getting drawn and there's an issue with certain orders of triangles?

Line renderer seems to be working:

[attach=1]

However, the multi-shape test is showing that the bottom-most horizontal line of filled and frame rectangles isn't being drawn.  Weirdly, neither are the two pixels in either of the bottom corners.  I have checked the output of previous GPU versions and they are there normally. Also, there should be two more triangles on the screen after the first one, which is draw as both filled and frame just fine, but the next one that should overlap it slightly below it, isn't drawn properly.  You might see the black pixel at the bottom of the first triangle where the second one starts and overlaps it slightly.  No quad is drawn, either.

[attach=2]

Drawing random filled/frame rectangles shows up a strange error in their rendering too:

[attach=3]

I have to reset the hardware after the rectangles are drawn, otherwise I can't get any graphical output at all if I run the tests again - seems the geometry engine is locking up somewhere?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 09:04:15 am
Only proceed onto the this code once you fully verify the previous code.
Well too late.  I need to see why you are getting those errors.
Just ry this code, without using the blitter, the errors will probably be identical.


Here is the code with a fully functional blitter.  Here are the blitter functions:

1.  Functions 0x78ZZ,0x79ZZ,0x7AZZ,0x7BZZ
Like the pixel write base address commands 0x7C-0x7F, this tells the blitter pixel copy command where in memory the source image is located.  The address taken from the contents of regs x/y[0-3].

2.  Functions 0x70ZZ and 0x72ZZ:
Like the write raster width & bitplane depth commands 0x71 and 0x73, this tells the blitter pixel copy command the source image width and source image bitplane depth.  The width is taken from registers x/y[3 & 2] (I know this 1 control is reversed order compared to all other commands.  You never asked to switch this.) and the bitplane depth is taken from the 'ZZ'.

3. Functions 0x74ZZ & 0x75ZZ:
This function sets the blitter width and height box size to be copied +1.  This means a setting of 7x, 7y will copy a box of 8 pixels by 8 lines.  The width and height are taken from regs x/y[ 2 & 3 ].  (This one is in proper order.)

4. Functions 0x76ZZ & 0x77ZZ:
This function sets the source image offset.  The copy read position offset are taken from regs x/y[ 2 & 3 ].  (This one is in proper order.)

5. Function 0x00ZZ:
This sets the blitter function.  It is controlled by the contents of the lower command byte 'ZZ'.  Here are the bit functions:

Code: [Select]
//************************************************************************************************************************************************
// p_blit_features bitmask features:
// 0 = Enable blitter       1 = run biltter copying source to output coordinates, 0 = Simple pixel write command
// 1 = Enable paste mask    1 = Pasting pixels with transparency mask, 0 = Always paste pixels even if the source has the selected transparent color
// 2 = Enable center paste  1 = Offset the paste up and to the left by half of blit_width/height, 0 = Use the paste coordinates as the top-left
//************************************************************************************************************************************************

6. Function 0x08ZZ:
This one sets a color transformation on the blitter pixel copy command.  This means the read pixel is XORed with the contents of 'ZZ'.  Since when using the mask feature, the transparent color is '0x00', XORing the read pixels with a custom number here other than '0x00' will change the read color which will simultaneously change what color will become transparent when a paste/write pixel is done with mask enable.

Blitting: All draw commands will blitt.  This mean if you use command '0x01ZZ', the paste will begin at coordinates x/y[0], or be centered shifted depending on set width & height when 'Enable center paste' is enabled.  If you use the line command '0x02ZZ', the blitter will paste a new copy of the source image for every single pixel in the source line coordinates x/y[0] - x/y[1].

The chosen drawing 'ZZ' color will perform a second XORing of the first XORed pixel copy, then allow you to change the color once again before the pixel is written.  So, if your source image is monochrome 1 bit color and your destination screen is 4 bit 16 colors, you can XOR a number like 0x04 which make to output color 0x04 and 0x05 instead of 0x00 and 0x01.  Careful not to choose an XOR number larger than the available colors on the destination screen, otherwise garbage will bleed into adjacent pixels.

Things you need to test:
A)
Keep using your current 16 color screen.
Set the source raster width to 8 pixels and 1 bit color depth with the base memory address set to your font memory address.
Set the blitter width and height to 8x16.
Now, keeping the source image offset X at 0, choose a character by setting the source offset Y to 16 X ASCII char #.
Blitt a copy onto a chosen screen coordinates using a command 0x01ZZ, pixel write.
Blitt multiple letters all over the place.
Test the mask enable feature.
Try changing test colors & invert the transparency making negative outline colors.

B) Attempt emulating carriage return of the bottom of the screen by using the biltter to copy begining 16 lines down, all the way to the bottom of the display, copied up to the first line of video, then draw a black box on the bottom 16 lines of video.

C) Attempt a smooth vertical scroll carriage return by making the above routine blitter copy beginning 1 line down, all the way to the bottom, pushing the image up only 1 line, waiting for a vsync, then doing this again 16 times in a row.

D) Attempt drawing a line/triangle/box/quad with a thick pen by making a 1 bit small monochrome circle 8x8 pixels.  Then turn on the blitter and mask and center offset correction, and draw the shape.  Your geometry lines should be painted with the circle pen you created, with it's color changes to the XORed 'ZZ' color setting.

I've attached the V6 geo blitter test bench and full EP4CE10 project.  Your FPGA is >90% full.  Going to a bigger chip will make achieving the FMAX easier, though right now, it will take almost 5 minutes to compile.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 09:11:37 am

Drawing random filled/frame rectangles shows up a strange error in their rendering too:


Ok, see the filled rectangle bug.
I need to vertically sort the Y coordinates.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 09:13:24 am
Initial testing is throwing up a problem.  I'm using the identical test that I've been using for the last couple of weeks.

Looks like the bottom line of the filled rectangle isn't getting drawn and there's an issue with certain orders of triangles?

Line renderer seems to be working:


Need to analyze, I did not verify your code which sorts these triangles vertices...

In the meantime, work on the blitter as it will still work and you have a number of things to test.

The other problems seem to be that the command system isn't stopping immediately once the drawing has begun.  At least I think so...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 09:25:16 am
Only proceed onto the this code once you fully verify the previous code.
Well too late.  I need to see why you are getting those errors.
Just ry this code, without using the blitter, the errors will probably be identical.

Yes, same errors on this version too.

Here's another pic - this one is the grid test, showing the line generators seem to be working fine but the red filled rectangle that normally jumps from cell to cell when I move it isn't drawing properly.  Doesn't seem to be missing the bottom row this time, but the top row is either missing or drawing to the edge of the screen.  You can see artefacts in previous cells where the red rectangle has been.

(Basically when the rectangle 'moves', it is overdrawn with a black filled rectangle, then the red filled rectangle is drawn in the next cell.)

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 09:29:03 am
Yup, the new version only adds the blitter.  No other changes.
I need to sleep now.  I'll look at the bugs tonight.
For now, you can start playing with the blitter using simple plot pixel and line commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 11:02:20 am
Yup, the new version only adds the blitter.  No other changes.
I need to sleep now.  I'll look at the bugs tonight.
For now, you can start playing with the blitter using simple plot pixel and line commands.

I'll make a start looking at the blitter commands and see if I can get some text on screen with the graphics, but I'll document the new commands first. :-+  Oh, one other thing I noticed - Fmax is down to 119.77 MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 02:04:32 pm
Yup, the new version only adds the blitter.  No other changes.
I need to sleep now.  I'll look at the bugs tonight.
For now, you can start playing with the blitter using simple plot pixel and line commands.

I'll make a start looking at the blitter commands and see if I can get some text on screen with the graphics, but I'll document the new commands first. :-+  Oh, one other thing I noticed - Fmax is down to 119.77 MHz.

Were the timing analyzer results clock result RED?
Did the compiler say that timing constraints were not me?
Was that 119.77MHz limit result for CLK[0], the one which needs to be at least 125MHz?
Or was that CLK[2], your PS2 keyboard clock which is only running at 50MHz where the 119.77MHz limit is actually 2x fine and CLK[0]'s limit was >126MHz?

Remember, I fixed all the IO and core timing constraints, if the compiler doesn't make that section 'RED', then everything is ok.  That took hours to fix a month ago thanks to poor documentation on Intel's part.  Remember, the timing analyzer used to always light up red...

Your FPGA is 90% full, squeezing in any more logic and trying to maintain CLK[0]'s 125MHz minimum means other slower sections will begin to loose placement and routing priority dropping their top FMAX is there is clearance to do so.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 02:30:19 pm
Were the timing analyzer results clock result red?
Did the compiler say that timing constraints were not me?
Was that 119.77MHz limit result for CLK[0], the one which needs to be at least 125MHz?
Or was that CLK[2], your PS2 keyboard clock which is only running at 50MHz where the 119.77MHz limit is actually 2x fine?

Remember, I fixed all the IO and core timing constraints, if the compiler doesn't make that section 'RED', then everything is ok.

Uh, never mind, I'm having a bad day.  It was for clk[2], not clk[0].  :phew:

I've had a little free time to try and get a character to blit onto the screen, but having mixed results because I'm clearly making a mistake in setting the base source address or the offset or something.

What I'm trying to do to test the blitter is this:

1. Set the base memory address to the start of the font table (0x0200)
2. Set the source raster width to 8 pixels with 1-bit colour depth
3. Set blitter width/height to 8x16
4. Set source offset to 16xASCII char # - in this case, capital 'X' (0x58 x 0x10 = 0x580)
5. Turn on the blitter, with Paste Mask and Centre Paste turned off
6. Blit the character 'X' to 100,100 on the screen

The output I get is this:

[attach=1]

Two things are immediately obvious - it's not a capital X and there's a pixel missing at the very end.  I'd hesitate to call either of these an issue with the blitter just yet as I'm not 100% confident I'm setting it up properly, hence the rambling list above of commands I'm using to get this output.

EDIT:  Definitely something wrong with my base memory and offset address setup.  I'm getting the letter 'j' appear in 1-bit mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 02:37:18 pm
Your FPGA is 90% full, squeezing in any more logic and trying to maintain CLK[0]'s 125MHz minimum means other slower sections will begin to loose placement and routing priority dropping their top FMAX is there is clearance to do so.

I'm working on the schematics for the EP4CE22F17 version currently, after getting a little scared off by the potential power supply requirements for the Cyclone V and lack of reference designs anywhere I can make use of.

The only hints of schematics I've found use QFN power chips, which means there's more of a learning curve for me than just trying to solder a BGA, coupled with the extra power draw that my existing power board in my uCOM just won't keep up with - so I'd have to re-design and up-rate the power card first.  Seems the EP4CE22 should be okay though, and I have reference schematics I can use to confirm my design with.  I need some time to be able to make headway on its design though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 07:05:14 pm
Were the timing analyzer results clock result red?
Did the compiler say that timing constraints were not me?
Was that 119.77MHz limit result for CLK[0], the one which needs to be at least 125MHz?
Or was that CLK[2], your PS2 keyboard clock which is only running at 50MHz where the 119.77MHz limit is actually 2x fine?

Remember, I fixed all the IO and core timing constraints, if the compiler doesn't make that section 'RED', then everything is ok.

Uh, never mind, I'm having a bad day.  It was for clk[2], not clk[0].  :phew:

I've had a little free time to try and get a character to blit onto the screen, but having mixed results because I'm clearly making a mistake in setting the base source address or the offset or something.

What I'm trying to do to test the blitter is this:

1. Set the base memory address to the start of the font table (0x0200)
  • Send 0x200 to X[0] - command 0x8200
  • Send 0x00 to Y[0] - command 0xC000
  • Set base memory address - command 0x7800
2. Set the source raster width to 8 pixels with 1-bit colour depth
  • Set Y[2] to 8 - command 0xE008
  • Set raster width to Y[2] pixels and bpp to 1 - command 0x7200
3. Set blitter width/height to 8x16
  • Set X[2] to 7 - command 0xA007
  • Set Y[2] to 15 - command 0xE00F
  • Set copy width/height - command 0x7400
4. Set source offset to 16xASCII char # - in this case, capital 'X' (0x58 x 0x10 = 0x580)
  • Set X[2] to 0 - command 0xA000
  • Set Y[2] to 0x580 - command 0xE580
  • Set source image offset - command 0x7600
5. Turn on the blitter, with Paste Mask and Centre Paste turned off
  • Enable blitter, disable PM + CP - command 0x0001
6. Blit the character 'X' to 100,100 on the screen
  • Set X[0] to 100 - command 0x8064
  • Set Y[0] to 100 - command 0xC064
  • Plot a pixel in yellow (colour 0x0E) - command 0x010E

The output I get is this:

(Attachment Link)

Two things are immediately obvious - it's not a capital X and there's a pixel missing at the very end.  I'd hesitate to call either of these an issue with the blitter just yet as I'm not 100% confident I'm setting it up properly, hence the rambling list above of commands I'm using to get this output.

EDIT:  Definitely something wrong with my base memory and offset address setup.  I'm getting the letter 'j' appear in 1-bit mode.
Something weird is going on, it may be the pixel address generator.
It's also yellow?
The last pixel also looks missing.  OK, I see the bug.  Will fix tonight.

Try Character 01, IE offset Y=16.  This should generate the VGA font's happy face.
PAGET and Pixel Writer has never been tested with reading 1 bit color under strict scrutiny.
Or something's overwritten your font.
But, Yellow?  Unless you used a weird write paste color, maybe the Pixel Writer needs to be checked.

Try making the base address the screen memory, and raster width of 320 and match the 4 bit color.
Then copy, after painting your other test triangle and blue box.
Make copy blit width & height 160x200 and paste blit at 160,0.  A copy of the left half of the screen should appear on the right hand side.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 08:00:58 pm
Your FPGA is 90% full, squeezing in any more logic and trying to maintain CLK[0]'s 125MHz minimum means other slower sections will begin to loose placement and routing priority dropping their top FMAX is there is clearance to do so.

I'm working on the schematics for the EP4CE22F17 version currently, after getting a little scared off by the potential power supply requirements for the Cyclone V and lack of reference designs anywhere I can make use of.

The only hints of schematics I've found use QFN power chips, which means there's more of a learning curve for me than just trying to solder a BGA, coupled with the extra power draw that my existing power board in my uCOM just won't keep up with - so I'd have to re-design and up-rate the power card first.  Seems the EP4CE22 should be okay though, and I have reference schematics I can use to confirm my design with.  I need some time to be able to make headway on its design though.

Schematic 1.
https://software.intel.com/content/www/us/en/develop/articles/de10-nano-board-schematic.html (https://software.intel.com/content/www/us/en/develop/articles/de10-nano-board-schematic.html)
Another:
https://www.analog.com/media/en/technical-documentation/eval-board-schematic/c5_soc_devkit_c.pdf (https://www.analog.com/media/en/technical-documentation/eval-board-schematic/c5_soc_devkit_c.pdf)
Another:

Search for libraries.
For switching regulator DC-DC converters, try this guy: AOZ1284.
It's cheap and only requires an external 10uH SMD power inductor and 1 diode with a few resistors and caps.
4 amps output, no heatsink.
Adjustable voltage from 0.8v to beyond 5v.
http://www.aosmd.com/res/data_sheets/AOZ1284PI.pdf (http://www.aosmd.com/res/data_sheets/AOZ1284PI.pdf)

Also, TI's: Anything on this page will do:
https://www.ti.com/power-management/non-isolated-dc-dc-switching-regulators/step-down-buck/buck-converter-integrated-switch/products.html#p451max=3;4&p634max=5;90&p20min=1000;5700 (https://www.ti.com/power-management/non-isolated-dc-dc-switching-regulators/step-down-buck/buck-converter-integrated-switch/products.html#p451max=3;4&p634max=5;90&p20min=1000;5700)

Example 'TLV62090', 5v in, adjustable out... Only needs a 1uH inductor and delivers 3 amps, no heatsink.
'TLV62130A' up to 17v in, 0.9v and up adjustable output. 2.2uH inductor, also 3 amps.

'TPS563249' TI sells this one direct for only 62cents each. Also 3 amps.  That's cheaper than linear regulators...
https://www.ti.com/store/ti/en/p/product/?p=TPS563249DDCR&HQS=OCB-tistore-invf-storeinv-invf-store-findchips-wwe (https://www.ti.com/store/ti/en/p/product/?p=TPS563249DDCR&HQS=OCB-tistore-invf-storeinv-invf-store-findchips-wwe)
It's only downside is that it needs at least 4.5v in, but the Vin goes up to 17v.
For 3amp load @ 3.3v, I would power these with 6v - 12v in.
For 3amp load @ 1.8v, I 4.5v in would be fine.

The more expensive 'TLV62130A' @1$ can deliver the same full 3 amp current with a smaller Vin-Vout voltage gap, IE 4.5v to 3.3v.
I think Farnell/RS Components has stock of this one, but they jacked up the price compared to the TI store.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 08:08:53 pm
Something weird is going on, it may be the pixel address generator.
It's also yellow?
The last pixel also looks missing.  OK, I see the bug.  Will fix tonight.

Try Character 01, IE offset Y=16.  This should generate the VGA font's happy face.

This is what I get if i change X[2] to 0 (0xA000) and Y[2] to 16 (0xE010) and set the source image offset to that (0x7600):

[attach=1]

I'm blitting the character using this command - 0x010E.  So write pixel (0x01) and colour yellow (0x0E).  It seems whatever colour I choose, that colour replaces the transparent/0 bits in the copied image, and the next colour up (in this case 0x0F or white) replaces the 1-bits in the copied image.

The character hasn't changed, though, which was why I was thinking it was something to do with my base or offset addresses earlier.

PAGET and Pixel Writer has never been tested with reading 1 bit color under strict scrutiny.
Or something's overwritten your font.

Nothing has overwritten the font as far as I know.

But, Yellow?  Unless you used a weird write paste color, maybe the Pixel Writer needs to be checked.

As outlined above, I'm using yellow as the write pixel colour, but I haven't got paste mask on.

Try making the base address the screen memory, and raster width of 320 and match the 4 bit color.
Then copy, after painting your other test triangle and blue box.
Make copy blit width & height 160x200 and paste blit at 160,0.  A copy of the left half of the screen should appear on the right hand side.

[attach=2]

That didn't work as expected.  I'm still not 100% sure I'm setting up the blitter properly though.  For that last image, I did this:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 08:26:44 pm
Need to do a full sim tonight...
Arrrg, so many setup variables...
Except for the last missing pixel, the Blitter inside the geometry unit is generating the correct commands and read and write coordinates which are being sent to the address generator.  I need to see what's happening after inside the address generator.  The originally, the pixel writer did perform correct reads and writer when I did a simulation of it.  And, it could not draw proper geometry shapes on a 16 color screen if it weren't first reading GPU ram, then editing the correct bit mask, then doing a pixel write.  And the current screen copy shows a 0 color transform, going from 16 color to 16 color screen.

The destination being in the right screen location, but with stretched line images, I would bet the address generator isn't generating the right read address.  Probably a typo somewhere as the read address generation mirrors the write address which we knows it works.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 09:40:02 pm
Need to do a full sim tonight...
Arrrg, so many setup variables...
Except for the last missing pixel, the Blitter inside the geometry unit is generating the correct commands and read and write coordinates which are being sent to the address generator.  I need to see what's happening after inside the address generator.  The originally, the pixel writer did perform correct reads and writer when I did a simulation of it.  And, it could not draw proper geometry shapes on a 16 color screen if it weren't first reading GPU ram, then editing the correct bit mask, then doing a pixel write.  And the current screen copy shows a 0 color transform, going from 16 color to 16 color screen.

The destination being in the right screen location, but with stretched line images, I would bet the address generator isn't generating the right read address.  Probably a typo somewhere as the read address generation mirrors the write address which we knows it works.

I'd feel much happier if you were able to confirm that the commands I'm sending are correct before you go too far down the sim and bug-hunting route.  I'd hate for this to all be because I'm doing something wrong with the setup.  Wouldn't be the first time.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2020, 10:10:15 pm
Schematic 1.
https://software.intel.com/content/www/us/en/develop/articles/de10-nano-board-schematic.html (https://software.intel.com/content/www/us/en/develop/articles/de10-nano-board-schematic.html)
Another:
https://www.analog.com/media/en/technical-documentation/eval-board-schematic/c5_soc_devkit_c.pdf (https://www.analog.com/media/en/technical-documentation/eval-board-schematic/c5_soc_devkit_c.pdf)

Problem with those schematics is they're for the SoC version of the Cyclone V.  Whilst you're probably quite comfortable looking at those schematics and deciding what is needed and what isn't for a more stock (non-SoC) Cyclone V E, they just confuse the heck out of me.  The SoC requires more power rails, and there's a lot of stuff in there that I have no need for and doesn't translate directly to an E-version Cyclone V.  I'm stretching my understanding (and luck) designing for an E, without the complication of trying to translate the schematics for a SoC version. :scared:

Here's what I've been using as a guide - the DE0 Nano:
https://wiki.bu.ost.ch/infoportal/_media/fpga/boards/de0_nano/de0-nano-schematic.pdf (https://wiki.bu.ost.ch/infoportal/_media/fpga/boards/de0_nano/de0-nano-schematic.pdf)

Search for libraries.
For switching regulator DC-DC converters, try this guy: AOZ1284.
It's cheap and only requires an external 10uH SMD power inductor and 1 diode with a few resistors and caps.
4 amps output, no heatsink.
Adjustable voltage from 0.8v to beyond 5v.
http://www.aosmd.com/res/data_sheets/AOZ1284PI.pdf (http://www.aosmd.com/res/data_sheets/AOZ1284PI.pdf)

Hey, good spot! :-+  That looks to be a perfect replacement for the existing 7805 I have providing the 5V power rail on my uCOM currently.  It's probably going to be stretched to the limit with an EP4CE22, let alone anything larger.  It'd also replace my 3.3V rail AMS1117 which really isn't up to anything more than its current application (providing the EP4CE10 and I2C with 3.3V).

The more expensive 'TLV62130A' @1$ can deliver the same full 3 amp current with a smaller Vin-Vout voltage gap, IE 4.5v to 3.3v.
I think Farnell/RS Components has stock of this one, but they jacked up the price compared to the TI store.

So which is better - the TLV62130A or the AOZ1284?  I'd be using them to provide a 5V and 3.3V rail to the entire uCOM system, as well as the GPU - which would have more chips supplying the 1.2 and 2.5V rails from the 5V rail.  The uCOM draws about 120mA without the GPU.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 11:25:12 pm

That didn't work as expected.  I'm still not 100% sure I'm setting up the blitter properly though.  For that last image, I did this:
  • Set base memory address to 0x1200 - 0x8200, 0xC001, 0x7800
  • Set source raster width to 320 pixels, 4 bpp -??? not clearing 0xA000 ??? 0xE13F, 0x7202
  • Set blitter width/heigh to 160x200 - 0xA0A0, 0xE0C8, 0x7400
  • Set image offset to 0 - 0xA000, 0xE000, 0x7600
  • Blit - 0x80A0, 0xC000, 0x010E
4bpp is 0x7203, the screen width is larger than 12 bits.
And, 0xAxxx and 0xExxx, if I am not mistaken, you have the width set to $13F000?  1306624 X pixels?
Shouldn't it be $000140? X=320 pixels?  this explains some of the mess.
How did you set the screen width.  It should have the same  0xAxxx and 0xExxx values. IE 0xE000 & 0xA140.
And instead of 0x7203, you should have 0x7103 or 0x7303 depending on which XY regs you choose.

Ok, the 'ONE' fix in this code is just the missing last pixel.
I need to see blitts with the right settings before I go messing around in the pixel writer.

I'm working on the sorted coordinates and 'Filled' polygons now.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2020, 11:39:55 pm
So which is better - the TLV62130A or the AOZ1284?  I'd be using them to provide a 5V and 3.3V rail to the entire uCOM system, as well as the GPU - which would have more chips supplying the 1.2 and 2.5V rails from the 5V rail.  The uCOM draws about 120mA without the GPU.

The TI has far more suppliers, though it's double price the AOZ1284.  Use it only for the 3.3v & VCC 1.8v core.  The 2.5v PLL you may use a cheap linear 50ma regulator in sot23 package.  The VCC analog for the DAC you may also use a 100ma regulator.  The TI part doesn't require a diode on the output and it's inductor is far cheaper and smaller at 2.2uH 4 amp instead of the AOZ1284's required 10uH 5 amp inductor.

As for the Cyclone V, the smallest one is actually the next size up and you then get 49K logic cells and 3 megabits ram.  Your current design almost reaches 10k logic gates and, well, you know.  If not, the first one is 25K logic and 1.75 megabits ram.

If I were you, look into the latest KiCad.  It's public domain and it may already have the Cyclone V component in it's library, or online library.  This is the biggest hurdle for you if you are worried about mistakes.

The Cyclone V schematics I sent you will tell you how to hook up the JTAG/Active serial programming ports & configuration lines and filters for the analog PLL core voltages, unless you can find an existing online Cyclone V project which you can load and edit.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2020, 07:53:41 am

That didn't work as expected.  I'm still not 100% sure I'm setting up the blitter properly though.  For that last image, I did this:
  • Set base memory address to 0x1200 - 0x8200, 0xC001, 0x7800
  • Set source raster width to 320 pixels, 4 bpp -??? not clearing 0xA000 ??? 0xE13F, 0x7202
  • Set blitter width/heigh to 160x200 - 0xA0A0, 0xE0C8, 0x7400
  • Set image offset to 0 - 0xA000, 0xE000, 0x7600
  • Blit - 0x80A0, 0xC000, 0x010E
4bpp is 0x7203, the screen width is larger than 12 bits.

Hmm.. I need to clarify this setting then, as the only notes I have pertain to the MAGGIE settings in the hardware registers, where bits 2-0 of the BP2RAST_cmd are:

Bit 2  Bit 1  Bit 0   Video Mode
  0       0       0      1-bit colour
  0       0       1      2-bit colour
  0       1       0      4-bit colour
  0       1       1      8-bit colour
  1       0       0      16-bit, 8 pixels-per-word
  1       0       1      16-bit, 4 pixels-per-word
  1       1       0      16-bit, 2 pixels-per-word
  1       1       1      16-bit, true colour

I've been using these to set the bpp for the geo unit previously.  0x7203 should be 8-bit colour if I'm using the right table?

And, 0xAxxx and 0xExxx, if I am not mistaken, you have the width set to $13F000?  1306624 X pixels?
Shouldn't it be $000140? X=320 pixels?  this explains some of the mess.

I knew in my bones I'd made some mistakes. :(  I've spotted some more too (like not setting destination raster width for the letter blit, or the source raster width for the half-screen blit.  I blame my lack of concentration and being in the early stages of a cold.

Ok, the 'ONE' fix in this code is just the missing last pixel.
I need to see blitts with the right settings before I go messing around in the pixel writer.

I'm working on the sorted coordinates and 'Filled' polygons now.

Here's the latest image, with the updates mentioned above.

[attach=1]

Blitter is being enabled with 0x0001, and both blits are being done with 0x010E commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2020, 08:05:12 am
The half-screen blit with zero colour (0x0100 command instead of 0x010E).

[attach=1]

Looks like I've still got some work to do to sort out that character tile blit.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 30, 2020, 09:16:56 am

That didn't work as expected.  I'm still not 100% sure I'm setting up the blitter properly though.  For that last image, I did this:
  • Set base memory address to 0x1200 - 0x8200, 0xC001, 0x7800
  • Set source raster width to 320 pixels, 4 bpp -??? not clearing 0xA000 ??? 0xE13F, 0x7202
  • Set blitter width/heigh to 160x200 - 0xA0A0, 0xE0C8, 0x7400
  • Set image offset to 0 - 0xA000, 0xE000, 0x7600
  • Blit - 0x80A0, 0xC000, 0x010E
4bpp is 0x7203, the screen width is larger than 12 bits.

Hmm.. I need to clarify this setting then, as the only notes I have pertain to the MAGGIE settings in the hardware registers, where bits 2-0 of the BP2RAST_cmd are:

Bit 2  Bit 1  Bit 0   Video Mode
  0       0       0      1-bit colour
  0       0       1      2-bit colour
  0       1       0      4-bit colour
  0       1       1      8-bit colour
  1       0       0      16-bit, 8 pixels-per-word
  1       0       1      16-bit, 4 pixels-per-word
  1       1       0      16-bit, 2 pixels-per-word
  1       1       1      16-bit, true colour

I've been using these to set the bpp for the geo unit previously.  0x7203 should be 8-bit colour if I'm using the right table?

And, 0xAxxx and 0xExxx, if I am not mistaken, you have the width set to $13F000?  1306624 X pixels?
Shouldn't it be $000140? X=320 pixels?  this explains some of the mess.

I knew in my bones I'd made some mistakes. :(  I've spotted some more too (like not setting destination raster width for the letter blit, or the source raster width for the half-screen blit.  I blame my lack of concentration and being in the early stages of a cold.

Ok, the 'ONE' fix in this code is just the missing last pixel.
I need to see blitts with the right settings before I go messing around in the pixel writer.

I'm working on the sorted coordinates and 'Filled' polygons now.

Here's the latest image, with the updates mentioned above.

[attach=1]

Blitter is being enabled with 0x0001, and both blits are being done with 0x010E commands.

Maggie settings are different from the geometry settings, remember...
For setting up the geometry controls, the bit depth is number of bits per pixel -1.  Not the table you provided.

I would like to see the text working....
Try character 0 and character 1, that would be a blank square and the happy face...

0x010E would change the resulting colors on the output.

Almost done fixing the geometry unit.
It's given me a headache.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2020, 09:40:44 am
Maggie settings are different from the geometry settings, remember...
For setting up the geometry controls, the bit depth is number of bits per pixel -1.  Not the table you provided.

Yeah, that's where I've been going wrong.  Well, one of the places.  ;)

I would like to see the text working....
Try character 0 and character 1, that would be a blank square and the happy face...

It seems whatever I put into the image offset, I'm still just getting the '!!' double exclamation mark.  The weird thing is that if I load a new character set over the default one, which has thinner exclamation marks, I still see the same double exclamation mark on the screen in the GPU test.  :-//

I'm setting the image offset by setting X[2] to 0 (0xA000), Y[2] to 0x10 (0xE010), then command 0x7600.  Source base address is set with 0x8200 and 0xC000 to set X[0] to 200 and Y[0] to 0, then 0x7800.  Is that right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 30, 2020, 10:35:10 am
Ok, here is the fixed geometry unit.
You will need to test everything.

For the filled quadrilateral, you need to run them like this:
Set the 4 xy coordinates.

xy[0]   xy[1]

xy[2]   xy[3]

Then send 2 draw commands
0x0Bzz   - This draws a filled triangle coords xy[0,1,2] color zz
0x0Dzz   - This draws another filled triangle coords xy[3,2,1] color zz.

To draw an unfilled quad, draw command 0x05zz should work on it's own.

My head hurts, I'll look at your blitter question tonight.  You can always read the code in the geometry_xy_plotter.sv to double check.

Let me know how all the drawing commands work...
(I know the FMAX only reached 123MHz, just use it for now.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2020, 12:14:54 pm
My head hurts, I'll look at your blitter question tonight.  You can always read the code in the geometry_xy_plotter.sv to double check.

Have been reading the code - what is going on doesn't make sense.  The command appears to be correct, I'm setting the right register, but I'm getting odd stuff in the blit and it's not changing when I change the offset value.  This is confirmed in the test program (see attached image) - I'm blitting two character tiles, apparently from base memory address 0x1200 and offset 0 for the first one, offset 0x10 for the second, but they're both identical. :-//

Let me know how all the drawing commands work...
(I know the FMAX only reached 123MHz, just use it for now.)

Mixed bag, really.  Quite a few things going on:

1. Lines and triangles seem to be working fine again, as are quads.
2. Filled rectangles are missing their last filled line.
3. Non-filled rectangles aren't drawing at all.

In the test, it looks like whatever is happening with the missing last line fill is affecting subsequent drawing commands, as I'm not seeing any diagonals drawn in the rectangle, or the outline rectangle (as mentioned earlier), or the pixels in the four corners.  When the diagonals are supposed to be drawn, the only thing that happens is a single pixel in the top left corner of the rectangle.  It disappears in the next step where the outline rectangle should be drawn (but may be being drawn in the same colour as the fill, causing the pixel to 'disappear'.)  Then the next step is the filled triangle on the left side of the screen - when this is drawn, the single pixel in the rectangle reappears in mauve, the same colour as the filled triangle.

Later lines are drawn just fine in the quad, however.

The character tile blit is corrupt garbage - but then I'm wondering if it ever was displaying the '!!' character - it may have been a random chunk of memory that coincidentally looked like a valid character. :-//  The second character tile, which should be the smiley face character, is identical to the first one, which should be the blank/empty character.

The attached image shows the final output with paste mask disabled, blitting with yellow colour (otherwise the character blits are just black squares without PM enabled), and drawing the quad AFTER the blits.

[attach=1]

If I draw the quad before the blits, strange things happen and the half-screen blit is corrupted:

[attach=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 30, 2020, 04:37:38 pm
Please provide 2 adjacent subsequent commands which generate the missing triangle line.

Again, 2 subsequent command which generate the bad box/box fill.

Try to shrink the error so that is is small enough to fit in the simulation.
Like 6x6 pixels each face, or, up tp 12x12 pixels for un-filled objects.

For now, just test the blitter with the mask and offset disabled.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2020, 05:57:57 pm
Hmm.. okay, here's what the test program does (apologies for the potato-camera images, but they get the message across I think):

; Draw filled rectangle
Command 0x8020H        ; set X[0] to 32
Command 0x0C001H       ; set Y[0] to 1
Command 0x9024H        ; set X[1] to 36
Command 0x0D004H       ; set Y[1] to 4
Command 0x0CFFH        ; draw filled rectangle

[attach=1]

; 1st diagonal
Command 0x8021H        ; set X[0] to 33
Command 0x0C002H       ; set Y[0] to 2
Command 0x9023H        ; set X[1] to 35
Command 0x0D03H       ; set Y[1] to 3
Command 0x02FFH        ; draw line X[0],Y[0] to X[1],Y[1]

; 2nd diagonal
Command 0x8021H        ; set X[0] to 33
Command 0x0C003H       ; set Y[0] to 3
Command 0x9023H        ; set X[1] to 35
Command 0x0D002H       ; set Y[1] to 2
Command 0x02FFH        ; draw line X[0],Y[0] to X[1],Y[1]

[attach=2]

; Non-filled rectangle
Command 0x8020H        ; set X[0] to 32
Command 0x0C001H       ; set Y[0] to 1
Command 0x9024H        ; set X[1] to 36
Command 0x0D004H       ; set Y[1] to 4
Command 0x04FFH        ; draw rectangle

Attached images show the output of the FIRST filled rectangle block above, then the output after the first keypress (i.e. the diagonals) - although it all seems to have gone to rat food after the first rectangle.

There's obviously a couple of lines of code between setting the register coordinates and telling the GPU to draw the shape that I have missed out of the above - this just overwrites the 'FF' in the draw command to set a different colour and has worked fine all along, so I don't suspect anything wrong with that and have left it out for the sake of simplicity.

16-bit values starting with a letter have a leading zero in front because the assembler that I use, Z80ASM, requires it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 06:26:15 am
Ok, I've re-done it again.
This time, the way I like it instead of doctoring up older code.
You have a real X&Y counter for the raster fill with only 2 linegens operating just like the Freebasic code.
I've also documented it very well with illustrations.
It is now back down to 89% full, but since the new code is more efficient, the blitter is in there as well at that size.
The code is 33% smaller as well.

Now, I'm only queasy about the filled quad.  It has to do when one corner is on the same line as the other and the order of how the coordinates is sorted, but, give it a try.  Remember, to send a filled quad, you just repeat a filled triangle with the same color right after.  Well, you may use a different color to see the cross dividing line.

Give it a thorough test as I would like to put this code to bed if possible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 09:07:24 am
Something is happening between drawing a filled triangle and everything after it.  :-\

I've run my usual test which draws a rectangle first, then diagonals within it, then an outline, then plots pixels at its four corners.  Seems to work fine (but more on this later).

The next thing the program does is draw a filled mauve triangle on the left side of the screen, then draws a white outline of a triangle over it.  That white outline never gets drawn - in fact nothing gets drawn after the first filled triangle - even if I exit the test program and re-run it, there's no graphical output from the GPU.

I added another filled triangle immediately after the first one to see if maybe it was the outlined triangle that was causing the lockup, but the second filled triangle doesn't get drawn either - so there's an issue with filled triangles?

Lines draw fine in their own test (if no filled triangles have been drawn since last reset).

[attach=1]

Filled rectangles, however, are still showing artefacts in the grid test.  Not as bad as previously - the topmost line doesn't stretch to the right side of the screen anymore - but the attached image shows what is going on - the single red dots over the white lines are caused when the red box is moved right, the longer red lines are left behind when the red box moves left.  I have not changed any code in this test since the very start and it was working fine before the recent changes, but I'm confused as heck trying work out why the results are different based on the direction of travel of the rectangle - just doesn't make sense.  Moving up and down leaves no artefacts.

[attach=2]

Second image shows a close-up of the first rectangle in the main test - this seems to draw just fine - showing the output of filled rectangle, rectangle, line and pixel drawing functions.

[attach=3]

This last image is as far as the test gets - the filled triangle - before stopping all graphical output.  Exiting the test program reverts the GPU back to text mode and it works fine, but running the program again without a full reset leads to none of the tests outputting graphics, even if they worked fine before (like the linegen test).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 09:58:40 am
need the filled triangle & triangle sequence exact.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 10:10:38 am
Okay, I've translated my Z80 assembly into pseudo-code for ease of reading (but all values are unchanged).  This is the entire triangle test routine, but only the first triangle (up to the first 'wait for keypress') is drawn:

; Turn off blitter
Send command 0x0000H        ; Blitter, PM & CP disabled

; Draw filled triangle
Send command 0x8001H        ; set X[0] to 1
Send command 0x0C001H       ; set Y[0] to 1
Send command 0x9018H        ; set X[1] to 24
Send command 0x0D063H       ; set Y[1] to 99
Send command 0x0A003H       ; set X[2] to 3
Send command 0x0E064H       ; set Y[2] to 100
Send command 0x0BFFH        ; draw filled triangle

** wait for keypress  -- nothing after this point is drawn

; Draw filled triangle
Send command 0x8070H        ; set X[0] to 112
Send command 0x0C010H       ; set Y[0] to 16
Send command 0x9088H        ; set X[1] to 136
Send command 0x0D023H       ; set Y[1] to 35
Send command 0x0A073H       ; set X[2] to 115
Send command 0x0E06CH       ; set Y[2] to 108
Send command 0x0BFFH        ; draw filled triangle

** wait for keypress

; Draw triangle
Send command 0x8001H        ; set X[0] to 1
Send command 0x0C001H       ; set Y[0] to 1
Send command 0x9018H        ; set X[1] to 24
Send command 0x0D063H       ; set Y[1] to 99
Send command 0x0A003H       ; set X[2] to 3
Send command 0x0E064H       ; set Y[2] to 100
Send command 0x03FFH        ; draw triangle

** wait for keypress

; Draw filled triangle
Send command 0x800AH        ; set X[0] to 10
Send command 0x0C064H       ; set Y[0] to 100
Send command 0x9030H        ; set X[1] to 48
Send command 0x0D080H       ; set Y[1] to 128
Send command 0x0A001H       ; set X[2] to 1
Send command 0x0E0C0H       ; set Y[2] to 192
Send command 0x0BFFH        ; draw filled triangle

** wait for keypress

; Draw big filled triangle
Send command 0x8136H        ; set X[0] to 310
Send command 0x0C00AH       ; set Y[0] to 10
Send command 0x900AH        ; set X[1] to 10
Send command 0x0D01CH       ; set Y[1] to 28
Send command 0x0A032H       ; set X[2] to 50
Send command 0x0E0C8H       ; set Y[2] to 200
Send command 0x0BFFH        ; draw filled triangle
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 10:59:28 am
 |O Stupid mistake on the freeze, try this:

If the filled rectangle still gives trouble, lets see if we can minimize and replicate the glitch down to an image with only around 100 pixels total plotted so I can do a simulation and track down where the pixels are being lost.

(Ignore the slight FMAX violation.  I'll send you better compiler settings to prevent this when editing code in the future.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 11:45:00 am
No freezing now - the test completes without locking up the GPU.  :)

However, :-\ there's still an issue with the triangles - seems the first point of the second (red) triangle is leaving a horizontal line:

[attach=1]

In the next image, you can see the topmost point of the third triangle is also leaving a line, but in the other direction now:

[attach=2]

The last image is a closeup of the quad, after it has drawn a filled (grey) quad, then diagonals between its corners, then a white outline quad and finally four pixels, one in each corner.  You can see that the filled quad isn't completely overwritten by the unfilled quad.

[attach=3]

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 12:15:01 pm
No freezing now - the test completes without locking up the GPU.  :)

However, :-\ there's still an issue with the triangles - seems the first point of the second (red) triangle is leaving a horizontal line:


In the next image, you can see the topmost point of the third triangle is also leaving a line, but in the other direction now:

Need sequence.  I'm assuming that the X fill begin/end address has the wrong coordinate at the top of the triangle.
Quote

The last image is a closeup of the quad, after it has drawn a filled (grey) quad, then diagonals between its corners, then a white outline quad and finally four pixels, one in each corner.  You can see that the filled quad isn't completely overwritten by the unfilled quad.

This may be due to the direction/orientation of the lines being drawn after a sort when drawing the filled shape.
The un-filled quad always draws lines xy[0-1,1-3,3-2,2-0].
When filled, the bottom & right side of the quad may be drawn in xy[1-3,1-2,2-3] if y[3] is below, a Higher value coordinate than y[2].  But if y[2] is below, a Higher value coordinate than y[3], the line direction changes to xy[1-2,1-3,3-2].  This order change needs to be replicate when drawing an outline quad so that the Bresenham's line algorithm places lines on the same dots.

It's the direction change of 1 line going from xy[3-2] in one case, then xy[2-3] in the other.  Bresenham's line algorithm will slightly shift the pixels horizontally on that 1 line being generated/drawn in the opposite direction.
In your test, try changing the height of point xy2[2] so it is below (Higher value) than the y in xy[3] and see if it fixes the problem.  If it does, then I know where to attack the problem.

  I will think of a solution.  Though, this wouldn't be an issue with a floating point line generator, my new code has all the coordinate sorting done in advance, it's just that depending on the height of the top 2 corners and bottom 2 corners, the line coordinates flip around.

(When drawing triangles, I always sort the vertices filled or non-filled since it makes no difference.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 12:26:49 pm
Need sequence.  I'm assuming that the X fill begin/end address has the wrong coordinate at the top of the triangle.

The sequence is identical to the one I posted earlier - no changes.

This may be due to the direction/orientation of the lines being drawn after a sort when drawing the filled shape.
The un-filled quad always draws lines xy[0-1,1-3,3-2,2-0].
When filled, the bottom & right side of the quad may be drawn in xy[1-3,3-2] if y[3] is a lower coordinate than y[2].  Bit if y[2] is a lower coordinate than y[3], the line direction changes to xy[1-2,2-3].  This order change needs to be replicate when drawing an outline quad so that the Bresenham's line algorithm places lines on the same dots.  I will think of a solution.  Though, this wouldn't be an issue with a floating point line generator, my new code has all the coordinate sorting done in advance, it's just that depending on the height of the top 2 corners and bottom 2 corners, the line coordinates flip around.

You just gave me an instant headache talking about floating point math...  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 12:28:38 pm
Need sequence.  I'm assuming that the X fill begin/end address has the wrong coordinate at the top of the triangle.

The sequence is identical to the one I posted earlier - no changes.

This may be due to the direction/orientation of the lines being drawn after a sort when drawing the filled shape.
The un-filled quad always draws lines xy[0-1,1-3,3-2,2-0].
When filled, the bottom & right side of the quad may be drawn in xy[1-3,3-2] if y[3] is a lower coordinate than y[2].  Bit if y[2] is a lower coordinate than y[3], the line direction changes to xy[1-2,2-3].  This order change needs to be replicate when drawing an outline quad so that the Bresenham's line algorithm places lines on the same dots.  I will think of a solution.  Though, this wouldn't be an issue with a floating point line generator, my new code has all the coordinate sorting done in advance, it's just that depending on the height of the top 2 corners and bottom 2 corners, the line coordinates flip around.

You just gave me an instant headache talking about floating point math...  ;)
Reread, I just edited the paragraph and I have a test for you to do...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 12:35:30 pm
Okay, with that change to Y[2] on the quad, the GPU's graphics output hangs after drawing the filled quad...

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 12:38:11 pm
Another edit, just fixed the order of the line draws.  But by now, you should get the idea.
Depending on the Y position of y[2] and y[3], I need to swap the line drawing direction of line xy[2-3].

Same goes for the top xy[1-2].  It just happens your current shape already has the proper orientation.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 12:40:23 pm
Okay, with that change to Y[2] on the quad, the GPU's graphics output hangs after drawing the filled quad...

(Attachment Link)

Ok, another bug.  Please send the coordinates of that quad and draw command order.
I also need the bad filled triangles since it may be a connected bug as the quad is just 2 back-back filled triangles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 01:05:31 pm
Ok, you missed your window of opportunity for me to fix the bug, though I believe I see the problem.
I'm off until later today.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 01:07:18 pm
Okay, the triangles haven't changed since last time:

; Turn off blitter
Send command 0x0000H        ; Blitter, PM & CP disabled

; Draw filled triangle THIS ONE DRAWS FINE
Send command 0x8001H        ; set X[0] to 1
Send command 0x0C001H       ; set Y[0] to 1
Send command 0x9018H        ; set X[1] to 24
Send command 0x0D063H       ; set Y[1] to 99
Send command 0x0A003H       ; set X[2] to 3
Send command 0x0E064H       ; set Y[2] to 100
Send command 0x0BFFH        ; draw filled triangle

; Draw filled triangle
Send command 0x8070H        ; set X[0] to 112
Send command 0x0C010H       ; set Y[0] to 16
Send command 0x9088H        ; set X[1] to 136
Send command 0x0D023H       ; set Y[1] to 35
Send command 0x0A073H       ; set X[2] to 115
Send command 0x0E06CH       ; set Y[2] to 108
Send command 0x0BFFH        ; draw filled triangle

; Draw triangle
Send command 0x8001H        ; set X[0] to 1
Send command 0x0C001H       ; set Y[0] to 1
Send command 0x9018H        ; set X[1] to 24
Send command 0x0D063H       ; set Y[1] to 99
Send command 0x0A003H       ; set X[2] to 3
Send command 0x0E064H       ; set Y[2] to 100
Send command 0x03FFH        ; draw triangle

; Draw filled triangle
Send command 0x800AH        ; set X[0] to 10
Send command 0x0C064H       ; set Y[0] to 100
Send command 0x9030H        ; set X[1] to 48
Send command 0x0D080H       ; set Y[1] to 128
Send command 0x0A001H       ; set X[2] to 1
Send command 0x0E0C0H       ; set Y[2] to 192
Send command 0x0BFFH        ; draw filled triangle

; Draw big filled triangle
Send command 0x8136H        ; set X[0] to 310
Send command 0x0C00AH       ; set Y[0] to 10
Send command 0x900AH        ; set X[1] to 10
Send command 0x0D01CH       ; set Y[1] to 28
Send command 0x0A032H       ; set X[2] to 50
Send command 0x0E0C8H       ; set Y[2] to 200
Send command 0x0BFFH        ; draw filled triangle

Here's the quad test routine:

; Turn off blitter
Send command 0x0000H        ; Blitter, PM & CP disabled

; Draw filled quad
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E041H       ; set Y[2] to 65
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x0BFFH        ; draw filled quadrilateral
Send command 0x0DFFH        ; draw filled quadrilateral

; Draw diagonals
Send command 0x8021H        ; set X[0] to 33
Send command 0x0C033H       ; set Y[0] to 51
Send command 0x9039H        ; set X[1] to 57
Send command 0x0D03BH       ; set Y[1] to 59
Send command 0x02FFH        ; draw line X[0],Y[0] to X[1],Y[1]

Send command 0x801DH        ; set X[0] to 29
Send command 0x0C036H       ; set Y[0] to 54
Send command 0x903FH        ; set X[1] to 63
Send command 0x0D029H       ; set Y[1] to 41
Send command 0x02FFH        ; draw line X[0],Y[0] to X[1],Y[1]

; Draw outline quad
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E037H       ; set Y[2] to 55
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x05FFH        ; draw quadrilateral

; Now draw some corner pixels
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x01FFH        ; draw pixel at X[0],Y[0]
;
Send command 0x8040H        ; set X[0] to 64
Send command 0x0C028H       ; set Y[0] to 40
Send command 0x01FFH        ; draw pixel at X[0],Y[0]
;
Send command 0x0801CH       ; set X[0] to 28
Send command 0x0C037H       ; set Y[0] to 55
Send command 0x01FFH        ; draw pixel at X[0],Y[0]
;
Send command 0x0803AH       ; set X[0] to 58
Send command 0x0C03CH       ; set Y[0] to 60
Send command 0x01FFH        ; draw pixel at X[0],Y[0]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 01:14:36 pm
I wanted the tiny small quad filled which freezes the gpu.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 01:27:15 pm
Test this blind shot...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 02:07:17 pm
I wanted the tiny small quad filled which freezes the gpu.

Have highlighted the quad code that hangs the GPU in red in my original response.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 04:17:25 pm
Sorry for delay - work has been hectic last few hours.  Okay, have tested the hotfix from your last post and the triangles (and rectangles) are drawing cleanly now.  ;D :-+

Still hangs on the quad, though.  :-\

EDIT: And the blit issues trying to get a character to blit, obviously.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 05:42:00 pm
Which quad?
I'm assuming that the vertical fill completes, but a linegen still may have horizontal pixels to draw.
There may be no closure in my code to handle this.
I need to see it happen in the sim to fix it.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 05:54:11 pm
Which quad?

The first quad drawn - the commands highlighted in red a previous post?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 07:40:50 pm
Ok, I did 4 things.

1. Fixed the hanging/frozen/un-finished linegen after a fill.  There is always a proper escape route now.
2. Cut the first linegen startup time by one clock cycle after each new command.
3. Removed the raster fill's final pixel from being plotted twice, once by the linegen generating it and then again by the raster fill algorithm itself.
4. Fixed Quartus compiler settings.  Achieving FMAX for now should no longer be a problem if the code isn't changed too much.

To do:
1. Make the outline Quad draw exactly on top of the same edge lines as a filled quad beneath it.  I need you online for this one since I cannot see the results and trying to decipher single dots at 2 different regions across a huge numerical sim time-line is near impossible and impractical.
2. Start testing the blitter more thoroughly.


Please generate me the quad filled, then quad outline example with a small shape and photo illustrating the lemon edge, then same script again modifying only the height of vertex xy[2] below/above xy[3] where the problem doesn't arise.  All other chords needs to be the same, just the y[2] vertex height difference should be opposite in relation to y[3]'s location.

Photograph both.  I will try to make the fix via simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 08:48:04 pm
Okay, initial testing is good - no problems found with any of the drawing functions (other than the quad issue we know about).  Pixels, lines, triangles, rectangles and quads are drawing nicely.  :-+

I'm not going to be available until tomorrow afternoon/evening, but if you're around then or over the weekend, let me know and I'll be online and ready to help.  :)

EDIT: Just the character tile blits not working, but we haven't really looked at them yet and I suspect it's my code that's at fault.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 09:15:10 pm
Please just send the coordinates of the grey quad with the white outline...
I don't know when I will have free time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2020, 09:18:27 pm
Please just send the coordinates of the grey quad with the white outline...

; Draw filled quad
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E041H       ; set Y[2] to 65
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x0BFFH        ; draw filled quadrilateral
Send command 0x0DFFH        ; draw filled quadrilateral

; Draw outline quad
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E037H       ; set Y[2] to 55
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x05FFH        ; draw quadrilateral

Is this what you're after?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2020, 10:05:03 pm
Please just send the coordinates of the grey quad with the white outline...

; Draw filled quad
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E041H       ; set Y[2] to 65
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x0BFFH        ; draw filled quadrilateral
Send command 0x0DFFH        ; draw filled quadrilateral

; Draw outline quad
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E037H       ; set Y[2] to 55
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x05FFH        ; draw quadrilateral

Is this what you're after?
Well, almost, the 2 y[2] coordinates are different.  Of course the outline wont sit ontop the quad.
I'm assuming you miss understood my instructions.

Which y[2] number, both drawn with the same coordinates generates the bug?

To tell, just do this:
; Draw filled quad and outline with a different color
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E041H       ; set Y[2] to 65
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x0BFFH        ; draw filled quadrilateral
Send command 0x0DFFH        ; draw filled quadrilateral
Send command 0x05FFH        ; draw quadrilateral

Visually inspect, the clear the screen and do this:

; Draw filled quad and outline with a different color
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E037H       ; set Y[2] to 55
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x0BFFH        ; draw filled quadrilateral
Send command 0x0DFFH        ; draw filled quadrilateral
Send command 0x05FFH        ; draw quadrilateral


Wait, without different colors on the outline, how do you know if the bug appears?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 02, 2020, 05:35:37 am
Ok, the non-filled quad automatically changes the direction of the edge lines to match the re-ordering that happens when using the filled quad due to the triangle sorting algorithm.

Also, I finished the blitter.  It now has a bunch or new features:

Code: [Select]
//************************************************************************************************************************************************
// p_blit_features bitmask features:
// 0 = Enable blitter         1 = run biltter copying source to output coordinates, 0 = Simple pixel write command
// 1 = Enable paste mask      1 = Pasting pixels with transparency mask, 0 = Always paste pixels even is the source has the selected transparent color
// 2 = Enable H-center paste  1 = Offset the paste to the left by half of blit_width, 0 = Use the paste coordinates as the beginning left
// 3 = Enable Mirror paste    1 = Mirror the output on the X axis.
// 4 = Enable V-center paste  1 = Offset the paste up by half of blit_height, 0 = Use the paste coordinates as the beginning top of the paste
// 5 = Enable Flip paste      1 = Flip the output on the Y axis.
// 6 = Enable Rotate 90 degree paste  1 = Swaps the X&Y coordinates on the paste.
// 7 = Enable Rotate 45 degree paste  1 = Increments/decrements the X&Y coordinates on the paste in unison.
//************************************************************************************************************************************************

As you can see, now I separated the center paste feature into separate H&V.
You also now have individual horizontal mirror and vertical flip function.
You also now get a 90 degree rotate.
It gets even better, you even get a 45 degree rotate.
Note that the 45 degree is experimental and you need to paste 2 adjacent pixels of the same image to fill in the checker board results.  You may use draw a line, from a-b by 1 x horizontal pixel to fill out the checkerboard.

You got to clean up you blitter Z80 code and get all the earlier tests done as well as the new ones as all the new flags can be combined.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 02, 2020, 04:59:26 pm
All seems to work fine so far.  :-+

; Draw filled quad and outline with a different color
Send command 0x8020H        ; set X[0] to 32
Send command 0x0C032H       ; set Y[0] to 50
Send command 0x9040H        ; set X[1] to 64
Send command 0x0D028H       ; set Y[1] to 40
Send command 0x0A01CH       ; set X[2] to 28
Send command 0x0E037H       ; set Y[2] to 55
Send command 0x0B03AH       ; set X[3] to 58
Send command 0x0F03CH       ; set Y[3] to 60
Send command 0x0BFFH        ; draw filled quadrilateral
Send command 0x0DFFH        ; draw filled quadrilateral
Send command 0x05FFH        ; draw quadrilateral


Wait, without different colors on the outline, how do you know if the bug appears?

I didn't bother posting my code that sets the colour of the object - it wasn't relevant so I left it out.  Although my post states, "Send command 0x05FFH", the low byte (FF) is overwritten with whatever colour I've chosen for that particular part of the test.

This issue hasn't reoccurred - it's either very picky or I genuinely did get a coordinate wrong in the test code (thought I'd copy-pasted them, but you never know..)  I'll keep an eye out for this later, but I'm not busting a gut worrying about it right now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 02, 2020, 07:40:45 pm
Character blitting fixed.  I'd made a mistake on setting the source raster width for the blitter, got X and Y mixed up.  :palm:

[attach=1]

Will get to doing proper testing of the blitter functions over the weekend with more character-based blitting, hopefully.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 02, 2020, 10:24:46 pm
Just spent ten minutes working on the character blitting.  Can now type into the graphics screen, but it's a long way from supporting DEL, CR, LF etc just yet.  Still promising though!

One question - it's probably just me, but I can't seem to change the colour of the blitted characters - they're all pale blue, no matter what I try, it seems.

[attach=1]

This next image shows 90-degree rotation active on the blits too:

[attach=2]

EDIT: Alternate fonts work as expected too:

[attach=3]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 02, 2020, 10:54:24 pm
I see the font translucency is working.
When calling the actual blit, IE draw dot, the chosen color get's it's value 'XOR' with the source image.

This means the source without a transparency mask is color 0 or 1.

If you XOR in a color number of 4, the output color becomes 4 or 5.

If the transparency mask is on, the '5' will be drawn while the '4' will be ignored.

If you changed the 'source copy mask color', draw command 08, since the source is 1 bit color, only 0 or 1 will work.  Using a value of 1 will invert the copy output 0 or 1, meaning that the font transparent color becomes 1, no longer 0.  The output would be plotting the voids in the front instead of the character lines.

You still need to choose a output color in the 'draw pixel' command to set/XOR the pasted color output.  IE the color chosen with the draw pixel/line/triangle/box/quad/ellipse command.  You cannot use an XOR color larger than the current number of colors on the paste bitmap side, otherwise, the output may get corrupted.

As for the 90 degree rotate, remember that the font is 16 pixels tall, not 8, so you need to shift the paste coordinates by 16 not 8.

Also, for your alternate font, don't forget to include an X increment table which has a different value for each character giving you proportional spacing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 02, 2020, 11:03:02 pm
I think there is a character in the font which is a 6x6 or 8x8 circle.  Use that character when drawing an outline of one of your triangles with blit enabled.  This should draw a thick outer border.

Just think, with the second tier Cyclone V, you could do this at 640x400 256 colors, or 640x480 at 16 colors with an additional shit load of space for quite a bit of blittable graphics.  Or, even double/triple buffered, or 3 playfield MAGGIE layers each at 320x240 at 256 colors, or all 8 layers at 16 colors, each with their own palette.  Or mix hardware font-tile layers with graphics layers and generate huge over-screen sized, multi-depth panoramic scrolling games.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 07:16:49 am
Ok, here is blitter V3, now with H&V zoom and shrink by floating point 'fractional' amounts.

Instructions:
Draw Command 0x09##.  The ## is a bit-field control.
Bit 0 = Set the source bitmap up-sample/zoom scale with regs x[0] and y[0].
Bit 1 = Set the paste bitmap down-sample/zoom scale with regs x[1] and y[1].

Since both settings use different regs, you may set both simultaneously by sending draw command 0x0903.

How to calculate a zoom:
Valid scale factor settings go from 1 through 2048.
Error values outside this range will default the setting back to 2048.

To enlarge the source bitmap, set the paste down sample to 2048.
The set the source up-sample using this ratio:
2048:(set x/y[0])

IE, if you want your image to be 1:1, then use a down sample setting of 2048 and an up sample setting of 2048.
If you want your image to be double size, 2:1, then use an up sample setting of 1024.
If you want your image to be 2.32992:1, then use an up sample setting of 879.

To shrink the destination bitmap, set the source up sample to 2048.
Then set the destination down-sample using this ratio:
(set x/y[1]):2048

If you want your pasted bitmap to be 1:1, then set the down sample setting to 2048.
If you want your image to be half size, IE 1:2, then use a down sample setting of 1024.
if you want your image to be 0.707:1, or, 1:1.41421, then use a down sample setting of 1448.  (See if you (Or anyone else here) could figure out why this magic down-sample figure is really important...)

You may mix different X&Y scale figures including zoom on X and shrink on Y, or, vice versa.
Note that the H&V center paste will not work properly with any zoom setting other than 1:1.
This is because to obtain the proper center offset based on the source width and height, we need to calculate the reciprocal of the source scale setting to determine the size of the final image which can give us the center offset of that image.  A reciprocal is long division and there is no more space in the current FPGA.

Remember you are dealing with paletted images, these scales are nearest neighbor only.  You need true-color and more gates if you want to generate a scaled image with bi-linear/bi-cubic filtering.  With the Cyclone V your switching to, you will have enough memory to do 320x240 16bit true color & with some big additions to the pixel writer, you could do anti-aliased rendering, both in blitter scale and with the geometry plotter.

You should also have enough gates in the Cyclone V to enable the other x/y[2&3] to define a quadrilateral shape which will render any perspective views of your source bitmap.  LOL, a Z80 will be able to do a 3D accelerated version of Doom I/II with this GPU.  Better than the original, though I wonder if the Z80 can keep up with the engine's 35fps.

Get the latest attached files...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 09:23:29 am
Just think, with the second tier Cyclone V, you could do this at 640x400 256 colors, or 640x480 at 16 colors with an additional shit load of space for quite a bit of blittable graphics.  Or, even double/triple buffered, or 3 playfield MAGGIE layers each at 320x240 at 256 colors, or all 8 layers at 16 colors, each with their own palette.  Or mix hardware font-tile layers with graphics layers and generate huge over-screen sized, multi-depth panoramic scrolling games.

That's just too tempting. :o  I need to stop wasting my time with the EP4CE22 and get developing the Cyclone V, then.  I guess the only real difference in the design is the cost if I get it wrong.  :-//

Had a little time to play this morning, now have multi-line text cycling through the palette as you write.  Will test more later.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 10:23:55 am
Ok, I doubled the quality of the scaling.  It now scales in fractions of 4096 instead of 2048.
To disable the scaling, just set the scale registers to 0 and the blitter scaler will take that value and change it to 4096.  All other integers from 1 to 4095 will be use as the 4096:scale for enlarge and scale:4096 for shrink.

I now fully documented the source code geometry_xv_plotter.sv.  You can now make head and tails of it all.
The only thing left is ellipse.  Generating a center ellipse is not too difficult.  But, making one rotated at any angle will take a little thought on how to best implement it.  There is just enough space left in the EP4CE10 to make it just fit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 12:57:04 pm
Hmm... seems blitting isn't working now?  I'm not getting the half-screen blit appearing at all, and character blits - if I'm lucky - I'm getting a single pixel.

Am I supposed to be turning the scaling off before blitting (didn't have to before this update) or is there a bug in the system?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 02:35:42 pm
Hmm... seems blitting isn't working now?  I'm not getting the half-screen blit appearing at all, and character blits - if I'm lucky - I'm getting a single pixel.

Am I supposed to be turning the scaling off before blitting (didn't have to before this update) or is there a bug in the system?
Weird, are you sure you 'arent' using the scale feature and you never called draw command 0x09xx?
Go backward 1 version for now & I'll double check tonight.
Please leave me a copy of your blitt setup.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 07:00:41 pm
Hmm... seems blitting isn't working now?  I'm not getting the half-screen blit appearing at all, and character blits - if I'm lucky - I'm getting a single pixel.

Am I supposed to be turning the scaling off before blitting (didn't have to before this update) or is there a bug in the system?
Weird, are you sure you 'arent' using the scale feature and you never called draw command 0x09xx?
Go backward 1 version for now & I'll double check tonight.
Please leave me a copy of your blitt setup.

No, no commands to 0x09xx are sent in the entire program.

Blit setup - note, this is pseudo-code - I haven't included code that specifies particular colours for the blit, or positions the blit according to row and column offsets. The code comments are intact, however:

Code: [Select]
; Set base memory address to start of font table ($0200)
Send command 0x8200H        ; set X[0] to 200
Send command 0x0C000H       ; set Y[0] to 0
Send command 0x7800H        ; set base memory address
; Set the source raster width to 8 pixels and 1 bit color depth
Send command 0x0A008H       ; set X[2] to 8
Send command 0x0E000H       ; set Y[2] to 0
Send command 0x7200H        ; set raster width to Y[2] pixels, 1 bpp
; Set the destination raster width to 320 pixels and 4 bit color depth
Send command 0x0A140H       ; set X[2] to 320
Send command 0x0E000H       ; set Y[2] to 0
Send command 0x7303H        ; set raster width to X[2] pixels, 4 bpp
; Set the blitter width and height to 8x16
Send command 0x0A007H       ; set X[2] to 7
Send command 0x0E00FH       ; set Y[2] to 15
Send command 0x7400H        ; set copy width/height to 8x16 pixels
; Turn on the blitter
Send command 0x0001H        ; Blitter enabled - blitter features are enabled in code not included, changing the 01 to 00-FF according to command-line parameters
; Keeping the source image offset X at 0, choose a character by
; setting the source offset Y to 16 x ASCII char #.
Send command 0x0A000H       ; set X[2] to 0
Send command 0x0E000H       ; set Y[2] to computed offset according to character to be displayed
Send command 0x7600H        ; set source image offset to Y[2]
; Blit character at screen coordinates (0 + offset),100
Send command 0x8000H        ; set X[0] to 0 + horizontal offset
Send command 0x0C064H       ; set Y[0] to 100 + vertical offset
Send command 0x010EH        ; blit single character
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 07:20:54 pm
Found the bug:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1081910)

See the purple arrows, I was comparing the output coordinates, a 24 bit value with the screen maximum X&Y size coordinates which are a 12 bit value.  That IF() protects writes outside screen memory.  I was only supposed to compare the integer part, the upper 12 bits only.  So the paste coordinates were always outside the screen coordinates since the results were seen as being multiplied by 4096.  I guess pixel 0x0 made it through.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1081914)

Also, I accidentally made the screen offset (red arrows) 24 bit, but they were only supposed to be an integer 12 bit number.

See, I make blunders as well.  I've attached the corrected code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 07:36:05 pm
 |O Hang on, 1 more error...  See, the problem existed twice...  I've attached the fix...

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1081920)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 07:45:57 pm
See, I make blunders as well.  I've attached the corrected code.

Not as many as I do.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 08:00:31 pm
Blitting all good again.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 09:11:27 pm
Ok, here is a minor enhancement.  It should not affect your current work.  All it does is originally, when the blitter paste coordinates where outside the max_x&y allowable bitmap area, it would skip both copy and paste commands, but it would still cycle each process meaning each new coordinate in that copy and paste would still eat 2 clock cycles even though no commands where being sent to the pixel writer.
     The new enhancement will skip one of those clock cycles if the paste pixel coordinates would end up located outside the max_x&y allowable bitmap area making off screen blitter coordinates process through twice as fast.
     The outside screen coordinates still need to be counted in the blit since zooming bitmaps, or rotating the output by 45 degrees may land pixels off screen, but we still want to compute the relative offset and continue onto the next line which may still have pixels on valid screen coordinates.

     I've included the source and built project in case you arent achieving FMAX where I turned up the compiler fitter's effort level to achieve the FMAX.  (Arrrg, 5 minute compile time.)

     If the scale works, and it now seems to fully simulate properly, all we have left is to give the 2 linegens the ability to generate arcs / fixed radius bezier curves, where running the 2 linegens each twice for the 4 quadrants will generate a rounded quadrilateral, in other words, an ellipse.  For the filled quadrilateral, only the linegen drawing the hypotenuse will have the bezier curve.

Updates attached below...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 09:59:28 pm
 :o Can you just clarify the scaling feature?  Is it just part of the blitter's rotate function, or is it an entirely separate function that can be used?  If so, how is it set?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 10:17:52 pm
Ok, here is blitter V3, now with H&V zoom and shrink by floating point 'fractional' amounts.

Instructions:
Draw Command 0x09##.  The ## is a bit-field control.
Bit 0 = Set the source bitmap up-sample/zoom scale with regs x[0] and y[0].
Bit 1 = Set the paste bitmap down-sample/zoom scale with regs x[1] and y[1].

Since both settings use different regs, you may set both simultaneously by sending draw command 0x0903.

How to calculate a zoom:
Valid scale factor settings go from 1 through 2048.
Error values outside this range will default the setting back to 2048.

To enlarge the source bitmap, set the paste down sample to 2048.
The set the source up-sample using this ratio:
2048:(set x/y[0])

IE, if you want your image to be 1:1, then use a down sample setting of 2048 and an up sample setting of 2048.
If you want your image to be double size, 2:1, then use an up sample setting of 1024.
If you want your image to be 2.32992:1, then use an up sample setting of 879.

To shrink the destination bitmap, set the source up sample to 2048.
Then set the destination down-sample using this ratio:
(set x/y[1]):2048

If you want your pasted bitmap to be 1:1, then set the down sample setting to 2048.
If you want your image to be half size, IE 1:2, then use a down sample setting of 1024.
if you want your image to be 0.707:1, or, 1:1.41421, then use a down sample setting of 1448.  (See if you (Or anyone else here) could figure out why this magic down-sample figure is really important...)

You may mix different X&Y scale figures including zoom on X and shrink on Y, or, vice versa.
Note that the H&V center paste will not work properly with any zoom setting other than 1:1.
This is because to obtain the proper center offset based on the source width and height, we need to calculate the reciprocal of the source scale setting to determine the size of the final image which can give us the center offset of that image.  A reciprocal is long division and there is no more space in the current FPGA.

Remember you are dealing with paletted images, these scales are nearest neighbor only.  You need true-color and more gates if you want to generate a scaled image with bi-linear/bi-cubic filtering.  With the Cyclone V your switching to, you will have enough memory to do 320x240 16bit true color & with some big additions to the pixel writer, you could do anti-aliased rendering, both in blitter scale and with the geometry plotter.

You should also have enough gates in the Cyclone V to enable the other x/y[2&3] to define a quadrilateral shape which will render any perspective views of your source bitmap.  LOL, a Z80 will be able to do a 3D accelerated version of Doom I/II with this GPU.  Better than the original, though I wonder if the Z80 can keep up with the engine's 35fps.

Get the latest attached files...

Blitter copy stage.
Set x[0] to enlarge the width of the source during the copy.
Set y[0] to enlarge the height of the source during the copy.
0=off, 4095=little bigger, 4094=little bigger, 2731=50% bigger, 1.50x size, 2048 = 2x larger.

Blitter paste stage:
Set x[1] to shrink the width of the source (enlarged or not) being pasted.
Set y[1] to shrink the height of the source (enlarged or not) being pasted.
0=off, 4095=little smaller, 4094=little bit smaller, 3072=0.75x size, 2048 = 0.5x size.

Just set all 4 and use draw command 0x0903 to transfer the 4 values to the blitter.
These just scale the bitmaps.  If is completely separate of everything else.  All other rotate & flip functions work fine simultaneously.
Only the 'center paste' feature will not properly center the output on your draw pixel command when the scaling isn't set to off.

Let's see a video of you smoothly with smooth steps zooming a letter 'A' from a chosen font from the top left corner of the screen all the way up to a full screen image.
IE redrawing the 'A' from the font again and again while increasing the magnification from 1:1 all the way up to 12:1.
Or, maybe better looking, fix the magnification to 12:1 so the A is larger than full screen, but set the output shrink to divide the image down by 12:1, then slowly decrease that divide down factor down to 1:1 making it appear to zoom/enlarge.  (This takes more blitter clock cycles, but, you get far more refined scale steps when the image 12x large due to a multiply, then divide.  You may play with other ratios to get the zoom refinement you like which cutting down on blitter clock cycles, but, the blitter is so F--KEN fast, your Z80 would have to run 2700 such combo scales a second for it to over-run the blitter.  That's painting (8x16x12x12)=18432 pixels per blit while the pixel writer will do better than 50Million copy&paste combos per second in this instance.)

 |O (Shit, I just thought of a way to almost double this speed in the case where you zoom the source image...  With more than 2:1 on the source zoom, make that 50% faster, with a zoom of 10:1, make that almost 100% faster, IE 2x speed.  I wont bother tackling it until you confirmed the current code, the ellipse is done and if I have time since it will eat more gates.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 10:25:57 pm
Latest project working with no bugs I can see with basic testing. :-+  If I have time tomorrow, I'll try to push the blit testing further.

I've included the source and built project in case you arent achieving FMAX where I turned up the compiler fitter's effort level to achieve the FMAX.  (Arrrg, 5 minute compile time.)

Took 4m30secs to compile here - it's not the end of the world.  Gives me time to go make a mug of tea. ;) clk[0] Fmax is 125.47 MHz.

Is this expected, though (the next bit)?  I know you mentioned chequer-boarding earlier, so I'm just checking:

When I do a 45 degree rotation:

[attachimg=1]

And the half-screen blit:

[attachimg=2]

Ok, here is blitter V3, now with H&V zoom and shrink by floating point 'fractional' amounts.

Sorry, I must have completely missed that post!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 10:47:18 pm
See the 45 degree angle hatchet...
Also notice the letters are larger...

Remember my line: 0.707:1, or, 1:1.41421 ... (See if you (Or anyone else here) could figure out why this magic down-sample figure is really important...)

Remember this A2 + B2 = C2...

The checker board issue, the letters being larger, my fancy numbers, and that Pythagorean, and the right scaling settings can be setup to solve the 45 degree issue perfectly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2020, 10:52:03 pm
See the 45 degree angle hatchet...
Also notice the letters are larger...

Remember my line: 0.707:1, or, 1:1.41421 ... (See if you (Or anyone else here) could figure out why this magic down-sample figure is really important...)

Remember this A2 + B2 = C2...

The checker board issue, the letters being larger, my fancy numbers, and that Pythagorean, and the right scaling settings can be setup to solve the 45 degree issue perfectly.

Ah, of course.. If the image being blitted has dimension AxB, when it's rotated 45 degrees its side A will be 1.41421 times longer due to good old Pythagoras and his squared hypotenuse.  Okay, no worries, I'll just need to downscale the blits by 0.707 to 1 to remove the chequer-boarding and make them less overweight.  ;)

Hitting the sack now - will hopefully have more time tomorrow.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2020, 10:55:04 pm
See the 45 degree angle hatchet...
Also notice the letters are larger...

Remember my line: 0.707:1, or, 1:1.41421 ... (See if you (Or anyone else here) could figure out why this magic down-sample figure is really important...)

Remember this A2 + B2 = C2...

The checker board issue, the letters being larger, my fancy numbers, and that Pythagorean, and the right scaling settings can be setup to solve the 45 degree issue perfectly.

Ah, of course.. If the image being blitted has dimension AxB, when it's rotated 45 degrees its side A will be 1.41421 times longer due to good old Pythagoras and his squared hypotenuse.  Okay, no worries, I'll just need to downscale the blits by 0.707 to 1 to remove the chequer-boarding and make them less overweight.  ;)

Hitting the sack now - will hopefully have more time tomorrow.

I predict that making the source scaler set to 2x the source image size, then shrinking the output image size to 0.5x will fill in the checker board, but, the final picture size still be 1.4x the size, but perfectly dot-dot rendered.  The output size will need to be set to 0.3535x, ie (0.707/2).  That scale will make the output look the right size.  The 2x source ensures oversampling of every pixel from the source, but I may be wrong.  using 1x and a down-sample of 0.707x may properly fill in the checkerboard without missing a dot saving 1/4 the pixel processing clocks.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2020, 10:38:31 am
Still getting blit corruption if I draw the quad before I run the blit tests.  The character blits are fine after the quad is drawn now, but the half-screen blit is still badly corrupted.

Could this be due to an error in my test code, or something still needs to be tied up with the quad function in HDL?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2020, 10:48:23 am
Default font, 45 degree rotation, paste mask enabled, up-scaled 2x (0x8800 & 0xC800), down-scaled 0.3535x (0x95A8 & 0xD5A8):

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2020, 11:08:29 am
Still getting blit corruption if I draw the quad before I run the blit tests.  The character blits are fine after the quad is drawn now, but the half-screen blit is still badly corrupted.

Could this be due to an error in my test code, or something still needs to be tied up with the quad function in HDL?
That corruption looks like a bad screen address & bitmap width setting.
Remember, reading a font or copying a half screen uses a different source address and bitmap width + a copy width and height.  Like before when the text was corrupt, you may have missed or got one of these settings backwards.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2020, 12:08:00 pm
Still getting blit corruption if I draw the quad before I run the blit tests.  The character blits are fine after the quad is drawn now, but the half-screen blit is still badly corrupted.

Could this be due to an error in my test code, or something still needs to be tied up with the quad function in HDL?
That corruption looks like a bad screen address & bitmap width setting.
Remember, reading a font or copying a half screen uses a different source address and bitmap width + a copy width and height.  Like before when the text was corrupt, you may have missed or got one of these settings backwards.

Most likely, I just can't see it at the moment.  I'm setting the source address and width for the blit okay - it works after the character blitting, just doesn't play after the quad is drawn. Anyway, here's a video:

https://www.youtube.com/watch?v=IdpLQUGMJMM (https://www.youtube.com/watch?v=IdpLQUGMJMM)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2020, 12:21:16 pm
Nice vid...

Remember, when you edit a quad, you are using all x&y[ #s ].
When you set a blitter address width, it uses both x&y to set the viewport width since the viewport width control is 16bits wide, not 12bits wide.
Rendering a quad means every X&Y has been filled with data.
Setting the blitter bitmap width & depth only setting the 'X' and not clearing the 'Y' means you may have set the width to something like 16k pixels per line.  This was done to allow really wide viewports which can go up to 64k pixels wide.

The copy width and height is limited to 4096x4096 at a time as it is only 12 bits wide and height.
The offset and destination coordinates are from -2048 to +2047 as these registers operate in signed mode as all the geometry x&y plotting controls are signed.

If this doesn't help, please send me a minimal quad plus minimal blit which messes up and I will simulate check it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2020, 06:45:51 pm
Just had another little play - looks like sending command 0x0900 isn't turning off scaling?

When I run the test initially, all is fine.  The X scales, program exits, great.  When I run the test again immediately after, the character blits are all scaled by 25x, despite turning off scaling before the test program exits, and when the test program starts... (command 0x0900).  Any ideas?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2020, 07:25:00 pm
Just had another little play - looks like sending command 0x0900 isn't turning off scaling?

When I run the test initially, all is fine.  The X scales, program exits, great.  When I run the test again immediately after, the character blits are all scaled by 25x, despite turning off scaling before the test program exits, and when the test program starts... (command 0x0900).  Any ideas?  :-//
No, 0x0900 does nothing.  You need to sen 0x0903 so that all the xy[0/1] regs take effect.  You need to put the 0's into the xy[1/2] regs, then send a 0x0903 so both regs [0/1] are passed to the scaler controls.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2020, 08:08:40 pm
Just had another little play - looks like sending command 0x0900 isn't turning off scaling?

When I run the test initially, all is fine.  The X scales, program exits, great.  When I run the test again immediately after, the character blits are all scaled by 25x, despite turning off scaling before the test program exits, and when the test program starts... (command 0x0900).  Any ideas?  :-//
No, 0x0900 does nothing.  You need to sen 0x0903 so that all the xy[0/1] regs take effect.  You need to put the 0's into the xy[1/2] regs, then send a 0x0903 so both regs [0/1] are passed to the scaler controls.

Ahaahh! My misunderstanding then - I thought 0x0900 turned off the X & Y scaling.  So to "turn them off", I need to set XY[0] and XY[1] to appropriate values to set scaling to 1:1.  No problem.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2020, 08:18:42 pm
As my province is now back on emergency quarantine, we I have a little time to finish ellipse, so, I setting up a freebasic tester for the current linegen to render a diamond based on mouse coordinates with the framework to allow you to play with a second parallel linegen which will be used to generate the arcs of the ellipse.  Give me 30-45 minutes to upload it.

Again, the coding will need to easily translate to the current Verilog linegens.  Once done, there wont be much left to do with the limitations of you current FPGA.

Though, you can drop the MAGGIE layers from 6 down to 5 or 4 to release a bunch a free space.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2020, 08:40:21 pm
I'm thinking you should change the command structure into 2 byte, 3 byte and 4 byte commands.

Commands 0-127 would send 2 byte controls like now.

Commands 128-191, 3 bytes would just directly change a 16 bit integer setting, directly feed any control, or set the x/y[ # ] instead of piping everything through the XY regs.  Now the XY regs, room for up to 64 of them will be 16bit each instead of 12bit.  (IE Z80 sends 3 bytes total.)

Commands 192-160 would send 24 bit integer commands. (IE Z80 sends 4 bytes total).
Commands 161-255 would send 32 bit integer commands. (IE Z80 sends 5 bytes total).


You will no longer need to convert all your 16 bits into 12bit + shift part of the remainder into the command's LSB's or the next Y register for the 24 bit ints.

This way, you may increase all the 12bit regs to 16bit, making your new XY coordinates go from -32768 to 32767, as well as a scaler which would have a 16bit scales of N:65536, 16x the current 4096 division steps.

Also, you will now have access to many more x/y regs than just 4 if you need them.

With room for 64x 16 bit integer regs and even 32 x 32 bit integers,it is now feasible to implement a 32bit ALU, full multiply/divide & add/sub between the regs with so many spare commands in the first 128 to direct things like holding offset and scale factors for the line drawing engines making high quality accelerated geometry graphics possible.

The 32 32bit integers will allow for true floating point accelerated geometry.  Though, we are getting into the realm of how can a Z80 feed all of this.  Though, you can feed this command pipe from memory contents of the GPU ram itself.


Maybe just use 2 byte and 4 byte command modes since the FIFO pipe and GPU ram is organized in 16 bits.
To send a 32 bit word, you would need to transmit 2x 4 byte commands, or we can scrap 32 bit ALU and just use 24 bit limiting use to +/- 8million range integers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2020, 10:31:47 pm
Ok, I setup the attached freebasic attached code to feed the coordinates for the Bresenham Bézier curve located on this page:

http://members.chello.at/easyfilter/bresenham.html (http://members.chello.at/easyfilter/bresenham.html)

Right at the bottom of the code, you need to change the 'drawLine_arc' from the current drawline into the Bézier curve just like we did before, but, make it so that it can be easily translated into verilog.  The final code should look almost identical to the existing draw line, just the added +/- arc curve correction will be added.

PLUS- at the end of the Bresenham Bézier curve on that website has a final 'plotLine(x0,y0, x2,y2)' which we will need to make part of the curved linegen code itself.

My basic code allows you to scroll the mouse to manipulate the curve settings.
Press 'ESC' to quit.

Once it works the way we like, we will replace our existing line_generator.sv into this new generator which has a third input coordinate for making the arcs.  Then to make a straight line, all we need to do it match P1&P2 when starting a line.  When drawing an ellipse, we just need to use the correct x&y offset depending on which quadrant is being drawn as our existing geometry_xy_plotter code is already setup to do.  (Just look at drawing a box & quad command inside our latest code...)
 
To rotate on the arc means calculating a rotation transform for determining point P1 based on X&Y coordinates (which are now separate instead of tied to a center axis) of P0&P2, or letting the Z80 compute the P1.  This could not be done with your normal ellipse command.

Touch up the 'Geoarc.bas' and post it back.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2020, 09:58:01 am
Right at the bottom of the code, you need to change the 'drawLine_arc' from the current drawline into the Bézier curve just like we did before, but, make it so that it can be easily translated into verilog.  The final code should look almost identical to the existing draw line, just the added +/- arc curve correction will be added.

Err.... well, it might look like the existing code if I could get it to work.  I'm having trouble translating the C example code to something FreeBasic will run in a coherent form.  i.e. I have no idea what this line evaluates to: y1 = 2*err < dx; and I can't seem to find anything online that'll help me out.  It looks like (to me) it should assign y1 to either TRUE or FALSE, which doesn't make sense as y1 is an integer value (coordinate position) supplied to the function in the first place.

There's multiple assignments to the same value that I'm not sure I've translated correctly too.  All I'm getting in the output window is a part-diamond shape with one edge going mad and making a fish tail before shooting off as a straight line to infinity if I'm not careful with the mouse pointer.  I'm trying random things now, so I've stopped as I clearly have no idea what's wrong or how to fix it.  :horse:

Touch up the 'Geoarc.bas' and post it back.

Yeah.  Erm... here's my broken mess.  :'(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2020, 10:38:09 am
As my province is now back on emergency quarantine, we I have a little time to finish ellipse, so, I setting up a freebasic tester for the current linegen to render a diamond based on mouse coordinates with the framework to allow you to play with a second parallel linegen which will be used to generate the arcs of the ellipse.  Give me 30-45 minutes to upload it.

Won't be long before lockdown kicks in again here - think it's just a matter of time.  :(

Again, the coding will need to easily translate to the current Verilog linegens.  Once done, there wont be much left to do with the limitations of you current FPGA.

Though, you can drop the MAGGIE layers from 6 down to 5 or 4 to release a bunch a free space.

Yes, we could always do that - I'm not using more than 2 at a time whilst testing anyway.  Starting to think more about the hardware (Cyclone 5) design now than the software as the CE10 has become the bottleneck.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2020, 10:57:27 am
I'm thinking you should change the command structure into 2 byte, 3 byte and 4 byte commands.

Commands 0-127 would send 2 byte controls like now.

Commands 128-191, 3 bytes would just directly change a 16 bit integer setting, directly feed any control, or set the x/y[ # ] instead of piping everything through the XY regs.  Now the XY regs, room for up to 64 of them will be 16bit each instead of 12bit.  (IE Z80 sends 3 bytes total.)

Commands 192-160 would send 24 bit integer commands. (IE Z80 sends 4 bytes total).
Commands 161-255 would send 32 bit integer commands. (IE Z80 sends 5 bytes total).


You will no longer need to convert all your 16 bits into 12bit + shift part of the remainder into the command's LSB's or the next Y register for the 24 bit ints.

This way, you may increase all the 12bit regs to 16bit, making your new XY coordinates go from -32768 to 32767, as well as a scaler which would have a 16bit scales of N:65536, 16x the current 4096 division steps.

Also, you will now have access to many more x/y regs than just 4 if you need them.

With room for 64x 16 bit integer regs and even 32 x 32 bit integers,it is now feasible to implement a 32bit ALU, full multiply/divide & add/sub between the regs with so many spare commands in the first 128 to direct things like holding offset and scale factors for the line drawing engines making high quality accelerated geometry graphics possible.

The 32 32bit integers will allow for true floating point accelerated geometry.  Though, we are getting into the realm of how can a Z80 feed all of this.  Though, you can feed this command pipe from memory contents of the GPU ram itself.

Sounds like a big improvement in capability, especially as we're going to be able to leverage that extra capability when I get a Cyclone V board up and running.  :-+

Funny you should mentioned an ALU.  I've been wondering about an FPU core.  At the moment I have no idea how an FPU integrates and is utilised by the old processors like the 68020 etc, but I wonder if it would be a benefit to the Z80?  There were a couple of 3D (wireframe) games for the old 8-bit computers (Elite (https://en.wikipedia.org/wiki/Elite_(video_game)), Starglider (https://en.wikipedia.org/wiki/Starglider) to name but two), and they managed that all on the Z80 processor.  Having hardware that could perform the floating point maths and matrix transformations would surely be a big boost?

Maybe just use 2 byte and 4 byte command modes since the FIFO pipe and GPU ram is organized in 16 bits.
To send a 32 bit word, you would need to transmit 2x 4 byte commands, or we can scrap 32 bit ALU and just use 24 bit limiting use to +/- 8million range integers.

No issue with sending 32-bit words, but I'm probably going to have to move from the current method of communicating with the GPU via IO ports to loading the commands/data into GPU RAM and letting the GPU off the leash to work on the command list.  Interacting with the GPU via IO is expensive time-wise due to the extra WAIT-state the Z80 inserts and it can only send a byte at a time.  A memory interface would speed things up slightly, I guess.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2020, 03:44:53 pm
So which is better - the TLV62130A or the AOZ1284?  I'd be using them to provide a 5V and 3.3V rail to the entire uCOM system, as well as the GPU - which would have more chips supplying the 1.2 and 2.5V rails from the 5V rail.  The uCOM draws about 120mA without the GPU.

The TI has far more suppliers, though it's double price the AOZ1284.  Use it only for the 3.3v & VCC 1.8v core.  The 2.5v PLL you may use a cheap linear 50ma regulator in sot23 package.  The VCC analog for the DAC you may also use a 100ma regulator.  The TI part doesn't require a diode on the output and it's inductor is far cheaper and smaller at 2.2uH 4 amp instead of the AOZ1284's required 10uH 5 amp inductor.


If I were you, look into the latest KiCad.  It's public domain and it may already have the Cyclone V component in it's library, or online library.  This is the biggest hurdle for you if you are worried about mistakes.

The Cyclone V schematics I sent you will tell you how to hook up the JTAG/Active serial programming ports & configuration lines and filters for the analog PLL core voltages, unless you can find an existing online Cyclone V project which you can load and edit.

Okay, I've spent a little time researching and designing the power rails for the Cyclone V E board using the TI part you recommended.  If you have five seconds spare, would really appreciate your thoughts. I'll make a start on the clock, configuration and JTAG/AS interface next.

I've never got on with KiCAD - found its UI to be a brick wall to learning more about how to use it, so I started out with DipTrace which spoiled me, really.  It's free for up to 500 pin designs, so I quickly outgrew it and moved on to EasyEDA (as you know), which is my go-to design tool now (and probably not too dissimilar from KiCAD, so I'm aware of the irony!)  It has Cyclone V parts on it already, fortunately.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2020, 08:05:08 pm
Okay, I've spent a little time researching and designing the power rails for the Cyclone V E board using the TI part you recommended.  If you have five seconds spare, would really appreciate your thoughts. I'll make a start on the clock, configuration and JTAG/AS interface next.

I've never got on with KiCAD - found its UI to be a brick wall to learning more about how to use it, so I started out with DipTrace which spoiled me, really.  It's free for up to 500 pin designs, so I quickly outgrew it and moved on to EasyEDA (as you know), which is my go-to design tool now (and probably not too dissimilar from KiCAD, so I'm aware of the irony!)  It has Cyclone V parts on it already, fortunately.

So far so good.  Remember, the C8 variant is the cheapest, see here:
https://lcsc.com/product-detail/CPLD-FPGA_Altera-5CEBA2F17C8N_C568996.html (https://lcsc.com/product-detail/CPLD-FPGA_Altera-5CEBA2F17C8N_C568996.html)

Just remember, reserve the high-speed IO banks for wiring to DDR3 ram & to directly drive HDMI out.  Everything else is almost do as you please, but still, I would sector off sections for Z80, Analog VGA, (make it close to a high speed IO bank containing the HDMI outputs).  Look in the data sheet, the 2 top & 2 bottom IO banks are high speed and the  2 left and 2 right ones are the slower ones.  DDR3 ram requires that IO bank to be on a lower supply voltage and that bank needs a PLL differential dedicated output in that IO bank to drive the PLL clock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2020, 08:11:16 pm
I'm thinking you should change the command structure into 2 byte, 3 byte and 4 byte commands.

Commands 0-127 would send 2 byte controls like now.

Commands 128-191, 3 bytes would just directly change a 16 bit integer setting, directly feed any control, or set the x/y[ # ] instead of piping everything through the XY regs.  Now the XY regs, room for up to 64 of them will be 16bit each instead of 12bit.  (IE Z80 sends 3 bytes total.)

Commands 192-160 would send 24 bit integer commands. (IE Z80 sends 4 bytes total).
Commands 161-255 would send 32 bit integer commands. (IE Z80 sends 5 bytes total).


You will no longer need to convert all your 16 bits into 12bit + shift part of the remainder into the command's LSB's or the next Y register for the 24 bit ints.

This way, you may increase all the 12bit regs to 16bit, making your new XY coordinates go from -32768 to 32767, as well as a scaler which would have a 16bit scales of N:65536, 16x the current 4096 division steps.

Also, you will now have access to many more x/y regs than just 4 if you need them.

With room for 64x 16 bit integer regs and even 32 x 32 bit integers,it is now feasible to implement a 32bit ALU, full multiply/divide & add/sub between the regs with so many spare commands in the first 128 to direct things like holding offset and scale factors for the line drawing engines making high quality accelerated geometry graphics possible.

The 32 32bit integers will allow for true floating point accelerated geometry.  Though, we are getting into the realm of how can a Z80 feed all of this.  Though, you can feed this command pipe from memory contents of the GPU ram itself.

Sounds like a big improvement in capability, especially as we're going to be able to leverage that extra capability when I get a Cyclone V board up and running.  :-+

Funny you should mentioned an ALU.  I've been wondering about an FPU core.  At the moment I have no idea how an FPU integrates and is utilised by the old processors like the 68020 etc, but I wonder if it would be a benefit to the Z80?  There were a couple of 3D (wireframe) games for the old 8-bit computers (Elite (https://en.wikipedia.org/wiki/Elite_(video_game)), Starglider (https://en.wikipedia.org/wiki/Starglider) to name but two), and they managed that all on the Z80 processor.  Having hardware that could perform the floating point maths and matrix transformations would surely be a big boost?

Maybe just use 2 byte and 4 byte command modes since the FIFO pipe and GPU ram is organized in 16 bits.
To send a 32 bit word, you would need to transmit 2x 4 byte commands, or we can scrap 32 bit ALU and just use 24 bit limiting use to +/- 8million range integers.

No issue with sending 32-bit words, but I'm probably going to have to move from the current method of communicating with the GPU via IO ports to loading the commands/data into GPU RAM and letting the GPU off the leash to work on the command list.  Interacting with the GPU via IO is expensive time-wise due to the extra WAIT-state the Z80 inserts and it can only send a byte at a time.  A memory interface would speed things up slightly, I guess.

Instead of command port & a command structure, we can make every word and control a memory address, but, you will no longer have an input fifo.  Every sent command will need to wait for the last draw command to complete before you can touch any variables.  This will slow down the Z80 when drawing multiple large screen elements and blits.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2020, 07:51:30 am
So far so good.  Remember, the C8 variant is the cheapest, see here:
https://lcsc.com/product-detail/CPLD-FPGA_Altera-5CEBA2F17C8N_C568996.html (https://lcsc.com/product-detail/CPLD-FPGA_Altera-5CEBA2F17C8N_C568996.html)

That's not a bad price at all - I've been looking at sourcing the A4 variant from Mouser (https://www.mouser.co.uk/ProductDetail/989-5CEBA4F17C8N), which is over £37 and not something I want to buy for an untested board or process (would be an expensive way to learn to solder BGA if I'm going to make mistakes!)

I suppose the A2/A4 versions of the Cyclone V are interchangeable on the same board if it's designed with that in mind?  (EDIT: Yes, they are.) Thinking back to previous comments about the Cyclone IV CE6/CE10, I wonder if the A2/A4 are physically identical dies, just marketing spin?  ???

[attach=2]

Just remember, reserve the high-speed IO banks for wiring to DDR3 ram & to directly drive HDMI out.  Everything else is almost do as you please, but still, I would sector off sections for Z80, Analog VGA, (make it close to a high speed IO bank containing the HDMI outputs).  Look in the data sheet, the 2 top & 2 bottom IO banks are high speed and the  2 left and 2 right ones are the slower ones.  DDR3 ram requires that IO bank to be on a lower supply voltage and that bank needs a PLL differential dedicated output in that IO bank to drive the PLL clock.

Yes, I'll try to focus more on grouping IO within the same banks this time - the IO layout of the Cyclone IV version was dictated entirely by the physical IO-pin placement on the board and which 245 level converter it was closest to, and thus which Z80 bus it was physically nearest to.  There'll still be a bit of that in the consideration for the Cyclone V version, but on a bank-basis rather than an individual pin-basis this time.

Question re: the video output from the FPGA:
I've got the VGA circuit, am happy with that and have upped it to a full 24-bit bus from the FPGA.  I've also added a DVI/HDMI (I know there's a difference, including expensive licensing, but if I mention HDMI by accident I mean DVI) output as well using a TFP410 (https://www.ti.com/lit/ds/symlink/tfp410.pdf).  I assume that it would be okay to share the 24-bit bus from the FPGA to the ADV7125 (VGA DAC) with the TFP410?  My reasoning being that the TFP410 will be driving the DVI output, whilst the ADV7125 drives the VGA 'bus', so the current draw should be negligible from the FPGA's 24 colour output IO pins?

Or is there a better way to do the DVI output?  I haven't really considered how difficult it would be to run 24 lines to one chip and fork them to another yet, but it's not sounding that bright.  ???

EDIT: Seems the ADV7513 (https://www.analog.com/media/en/technical-documentation/data-sheets/ADV7513.pdf) does HDMI and also incorporates audio into the data stream...?  Page 21 of the DE10-Nano schematic (https://software.intel.com/content/dam/develop/external/us/en/documents/de10-nano-schematic.pdf) shows one being used, with an I2S connection (which I know nothing about - yet).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2020, 07:57:55 am
Instead of command port & a command structure, we can make every word and control a memory address, but, you will no longer have an input fifo.  Every sent command will need to wait for the last draw command to complete before you can touch any variables.  This will slow down the Z80 when drawing multiple large screen elements and blits.

Unless we implement a FIFO in the memory?  Would just require a little routine on the Z80 to check for space in memory before adding the next command on the rare occasion that it's waiting for the GPU to clear some space in the list?

But either way I don't really mind - I don't think there'll be much time saved switching from the IO method to the memory method, probably no noticeable difference practically, as each method has its own overheads (not least if the Z80 wants to access the GPU's memory, I have to switch memory banks about which introduces IO calls anyway, so probably best to just stick with the IO method we have currently).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2020, 11:07:16 am
Schematic attached for configuration, clock and programming interfaces.  This is based entirely off of the official Intel/Altera datasheets and manuals.  :-/O

I'm putting these schematics up for anyone to offer feedback on or make use of for their own nefarious purposes.  Once I'm happy there's no obvious errors, I'll post the design in its entirety.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2020, 08:43:03 pm
So far so good.  Remember, the C8 variant is the cheapest, see here:
https://lcsc.com/product-detail/CPLD-FPGA_Altera-5CEBA2F17C8N_C568996.html (https://lcsc.com/product-detail/CPLD-FPGA_Altera-5CEBA2F17C8N_C568996.html)

That's not a bad price at all - I've been looking at sourcing the A4 variant from Mouser (https://www.mouser.co.uk/ProductDetail/989-5CEBA4F17C8N), which is over £37 and not something I want to buy for an untested board or process (would be an expensive way to learn to solder BGA if I'm going to make mistakes!)

I suppose the A2/A4 versions of the Cyclone V are interchangeable on the same board if it's designed with that in mind?  (EDIT: Yes, they are.) Thinking back to previous comments about the Cyclone IV CE6/CE10, I wonder if the A2/A4 are physically identical dies, just marketing spin?  ???

(Attachment Link)


Looking at the bootprom .rbf file size being identical for the 2, I would say that the A2 is an A4 and Quartus is just limiting you available features and sizes just because you told Quartus that you had an A2 in your circuit.  It's how Intel makes more profit by faking a smaller size and cheaper price VS getting those who step over that artificial limit to pay more for an A4.

Yes, you can wire the TFP410 and dac in parallel with using any IO.  You are just driving 25MHz.  Trace length and via count is irrelevant at these speeds.

Yes, £13.81 for the A2 variant which may be an A4 anyways, either way, it is half price of Mouser's A2 list price, never mind the A4.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 07, 2020, 07:40:44 am
Okay, so DDR3 memory (I was looking at DDR for some reason) - could I stick a chip on the back of the PCB somewhere?

What about this ADV7513 (https://www.analog.com/media/en/technical-documentation/data-sheets/ADV7513.pdf), though?  It seems like it would be an excellent replacement for the TFP410 to output video and states it does HDMI which incorporates audio into the data stream.  That would be a big win for me if I could use one of those (I could scrub audio DACs from the BOM and at least 10 IOs as I could just output audio to the TV via I2S) - but the datasheet is short on information regarding using it; do I need to get a licence for HDMI or is the licence more to do with tx-ing protected data (which I have no interest in doing)?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2020, 06:38:42 pm
Okay, so DDR3 memory (I was looking at DDR for some reason) - could I stick a chip on the back of the PCB somewhere?

What about this ADV7513 (https://www.analog.com/media/en/technical-documentation/data-sheets/ADV7513.pdf), though?  It seems like it would be an excellent replacement for the TFP410 to output video and states it does HDMI which incorporates audio into the data stream.  That would be a big win for me if I could use one of those (I could scrub audio DACs from the BOM and at least 10 IOs as I could just output audio to the TV via I2S) - but the datasheet is short on information regarding using it; do I need to get a licence for HDMI or is the licence more to do with tx-ing protected data (which I have no interest in doing)?
The ADV7513 requires I2C commands to work plus an HDMI license to get access to the full datasheet, I think.  Make sure you can get access to the full I2C datasheet before you select that chip.

You will probably want to add an MCU to handle the I2C unless you want to make one inside the FPGA.

As for DDR3, it may be too fast for your needs, unless the Cyclone V can handle at least 300MHz, 600mtps on it's DDR DQ port.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2020, 09:38:58 pm
Notes on Bresenham line and ellipse, explained and source in floats and integer versions.
It covers theory of operation and how this code compares to others.

Page 27 of 68 is the integer version and it's coded to easily convert to verilog.
https://cs.brown.edu/research/pubs/theses/masters/1989/dasilva.pdf (https://cs.brown.edu/research/pubs/theses/masters/1989/dasilva.pdf)

Though the paper has a general ellipse (rotate-able), it only has a floating point version.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2020, 09:55:20 pm
Another very compact all integer midpoint ellipse on page 8 of this .pdf.

https://pdfs.semanticscholar.org/b3af/aff55ea9d5271e4d31abd4f0dd6e60be28d7.pdf (https://pdfs.semanticscholar.org/b3af/aff55ea9d5271e4d31abd4f0dd6e60be28d7.pdf)

All we care about is the 'void ellipseMidpoint (int xCenter, int yCenter, int Rx, int Ry)'.
With region 1 & 2.

Still, no center ellipse with rotate.
Still looking...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2020, 10:08:22 pm
All integer, axis aligned ellipse and general ellipse (angled)

Though the code is given in parts.
https://www.geometrictools.com/Documentation/IntegerBasedEllipseDrawing.pdf (https://www.geometrictools.com/Documentation/IntegerBasedEllipseDrawing.pdf)

It's basically showing you how to calculate the 8 zones in the arc.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 10, 2020, 09:56:22 am
I have been extremely busy the last couple of days, hence no activity here unfortunately, and my time is limited this weekend as well.  I got up hoping to make some progress on this today, but I'm getting nowhere and have spent my time staring at quadratic equations and code examples that I can't translate into FreeBasic for some reason or other.  Can you just clarify exactly what we're trying to achieve with the next step please?  I've got to write a Bezier curve function in FreeBasic that's easily translatable into HDL?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 10, 2020, 08:36:25 pm
Ellipse or Bezier, your choice on how to attack the problem.

If you use the center aligned ellipse in the above papers, the easy one which has it in 2 simple for loops for the 2 half of the arc is one way to go.  However, you will have a separate ellipse/arc generator next to your line generator.  No problem doing this remembering that the above code would be modified to output sequences compatible with the pixel pipe and optional X filling engine.

Generating an integer Bezier means to create a circle or ellipse, your center 'pulling' point is the outer square box coordinates of the Bezier.  To make a straight line instead, that center point only needs to be on the begging or ending point of the line.  You are basically making 1 linegen algorithm which can perform the duties of line, ellipse (ie calling it 4 times, or since you have 2 of them, calling it 2x2 times), and the bonus of a bezier, or at least one where the sign of the arc cannot change.  However, this is a tricky thing to implement especially since I asked you to make it act as if it were part of the linegen.

Ok, what I have done is make the current linegen generate arcs by just adding 3 lines.
Now, the arcs do not close properly, but, you can see that the error is not tuning the arc & delta x/y properly, but you can see how simple it would be to add this to our existing verilog code is only the proper setup was used to make this work, as well as are direction.  Yes, there is a little more involved as a proper are generator supposed to flip the X&Y angle sign half way through as you have seen in the ellipse generators.



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 12, 2020, 09:58:02 am
I would be more than happy with just a circle generator tbh, but am happy with a separate ellipse function that can do circles and ellipses.  My mind is melting with all this math - not that it's particularly deep in its original form, but that we're looking at highly optimised routines in a variety of source languages that make no sense to me.  That, or I'm just crap at this stuff and I need a holiday.  :-\

I usually know when I'm lost in the software because I start to focus more on the hardware instead - have made some progress on the Cyclone 5 design recently as a result. :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2020, 10:22:30 am
Okay, it's been a busy week and next it's just getting busier.  I don't have the time to sit and work out how to massage the Bezier code into something compatible with FreeBasic or HDL, so I'm going with the ellipse code:

Code: [Select]
Sub drawEllipse(ByVal x0 As Integer, ByVal y0 As Integer, ByVal x1 As Integer, ByVal y1 As Integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)
   Dim As Integer a = Abs(x1-x0), b = Abs(y1-y0), b1, x : Rem values of diameter
   Dim As Integer dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a : Rem error increment
   Dim As Integer errd = dx + dy + b1 * a * a, e2 : Rem error of 1.step

   b1 = b And 1

   if (x0 > x1) then
       x0 = x1
       x1 = x1 + a : Rem if called with swapped points
   End If
   if (y0 > y1) Then
       y0 = y1 : Rem .. exchange them
   End If
   y0 = y0 + (b + 1) / 2
   y1 = y0 - b1 : Rem starting pixel
   a = a*(8*a)
   b1 = 8*b*b

   While (x0 <= x1)
      draw_pixel(x1, y0, colour) : Rem   I. Quadrant
      draw_pixel(x0, y0, colour) : Rem   II. Quadrant
      draw_pixel(x0, y1, colour) : Rem   III. Quadrant
      draw_pixel(x1, y1, colour) : Rem   IV. Quadrant
      If (filled) Then
        For x=x0 to x1
            draw_pixel (x, y0, colour)
            draw_pixel (x, y1, colour)
        Next x
      EndIf
      e2 = 2*errd
      If (e2 <= dy) Then
        y0 = y0 + 1
        y1 = y1 - 1
        dy = dy + a
        errd = errd + dy : rem  y Step
      End If
      If (e2 >= dx Or 2*errd > dy) Then
        x0 = x0 + 1
        x1 = x1 - 1
        dx = dx + b1
        errd = errd + dx : rem x Step
      End If
   Wend
 
   While (y0 - y1 < b)  : Rem too early stop of flat ellipses a=1
       draw_pixel(x0 - 1, y0, colour) : Rem -> finish tip of Ellipse
       y0 = y0 + 1
       draw_pixel(x1 + 1, y0, colour)
       draw_pixel(x0 - 1, y1, colour)
       y1 = y1 - 1
       draw_pixel(x1 + 1, y1, colour)
   Wend

End Sub

It works fine in FreeBasic, so if you have no objections I'll start translating this into Verilog as a separate function, though it's likely to take a while due to work.

I've also attached my first version of the schematic for the Cyclone V GPU card for comment if anyone is interested.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Gribo on October 20, 2020, 06:01:40 pm
Check page 27 of the TFP410 datasheet, you might not have enough decoupling capacitors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2020, 06:31:11 pm
Okay, it's been a busy week and next it's just getting busier.  I don't have the time to sit and work out how to massage the Bezier code into something compatible with FreeBasic or HDL, so I'm going with the ellipse code:

Code: [Select]
Sub drawEllipse(ByVal x0 As Integer, ByVal y0 As Integer, ByVal x1 As Integer, ByVal y1 As Integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)
   Dim As Integer a = Abs(x1-x0), b = Abs(y1-y0), b1, x : Rem values of diameter
   Dim As Integer dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a : Rem error increment
   Dim As Integer errd = dx + dy + b1 * a * a, e2 : Rem error of 1.step

   b1 = b And 1

   if (x0 > x1) then
       x0 = x1
       x1 = x1 + a : Rem if called with swapped points
   End If
   if (y0 > y1) Then
       y0 = y1 : Rem .. exchange them
   End If
   y0 = y0 + (b + 1) / 2
   y1 = y0 - b1 : Rem starting pixel
   a = a*(8*a)
   b1 = 8*b*b

   While (x0 <= x1)
      draw_pixel(x1, y0, colour) : Rem   I. Quadrant
      draw_pixel(x0, y0, colour) : Rem   II. Quadrant
      draw_pixel(x0, y1, colour) : Rem   III. Quadrant
      draw_pixel(x1, y1, colour) : Rem   IV. Quadrant
      If (filled) Then
        For x=x0 to x1
            draw_pixel (x, y0, colour)
            draw_pixel (x, y1, colour)
        Next x
      EndIf
      e2 = 2*errd
      If (e2 <= dy) Then
        y0 = y0 + 1
        y1 = y1 - 1
        dy = dy + a
        errd = errd + dy : rem  y Step
      End If
      If (e2 >= dx Or 2*errd > dy) Then
        x0 = x0 + 1
        x1 = x1 - 1
        dx = dx + b1
        errd = errd + dx : rem x Step
      End If
   Wend
 
   While (y0 - y1 < b)  : Rem too early stop of flat ellipses a=1
       draw_pixel(x0 - 1, y0, colour) : Rem -> finish tip of Ellipse
       y0 = y0 + 1
       draw_pixel(x1 + 1, y0, colour)
       draw_pixel(x0 - 1, y1, colour)
       y1 = y1 - 1
       draw_pixel(x1 + 1, y1, colour)
   Wend

End Sub

It works fine in FreeBasic, so if you have no objections I'll start translating this into Verilog as a separate function, though it's likely to take a while due to work.

I've also attached my first version of the schematic for the Cyclone V GPU card for comment if anyone is interested.

Ok, for the verilog, what we will do here is use xy[0] for the X&Y center.  xy[1] for the width and height. x[2] for which quadrant to draw, 0 through 3 meaning draw only 1 quadrant per draw command.  For the fill enable, the command will only draw from the output arc x position to the x[0] center.

This way, you may draw ellipses and 90 degree arcs at 4 different corners to construct boxes with rounded corners.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2020, 06:49:29 pm

I've also attached my first version of the schematic for the Cyclone V GPU card for comment if anyone is interested.

Change your audio dac to a PCM5101A.
https://www.ti.com/store/ti/en/p/product/?p=PCM5101APWR&HQS=OCB-tistore-invf-storeinv-invf-store-findchips-wwe (https://www.ti.com/store/ti/en/p/product/?p=PCM5101APWR&HQS=OCB-tistore-invf-storeinv-invf-store-findchips-wwe)

PCM5100A is also compatible, little lower quality, but, Farnell currently has stock of this one.

Use the dac supply with filter choke for the analog 3.3v & use optionally use vccio 3.3v for the digital.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2020, 07:19:36 pm
If you get your PCB made by JLPCB, they will place the components for you if the parts are available at https://lcsc.com/ (https://lcsc.com/) , the place where I found your Cyclone V for 18$.

Also, for your caps, use 10uf XR7 1206 or 1210 ceramic.  For 22uf, just use 2x10uf in parallel.
Do not use 0805 10uf ceramic.  Their capacitance really drops with voltage.

As for the DAC filter and boot caps, might as well use the same 10uf unless you do not want to consolidate parts.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2020, 08:56:10 pm
Check page 27 of the TFP410 datasheet, you might not have enough decoupling capacitors.

Thanks Gribo - initially I added in loads of decoupling caps and was more careful about using different supply rails, but found I was running out of room very quickly on my board and I haven't even done the traces to the FPGA yet.  I've since found a working schematic and PCB design using the layout/decoupling setup I'm using here.  In fact, it uses less decoupling caps than I'm using.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2020, 09:10:54 pm

I've also attached my first version of the schematic for the Cyclone V GPU card for comment if anyone is interested.

Change your audio dac to a PCM5101A.
https://www.ti.com/store/ti/en/p/product/?p=PCM5101APWR&HQS=OCB-tistore-invf-storeinv-invf-store-findchips-wwe (https://www.ti.com/store/ti/en/p/product/?p=PCM5101APWR&HQS=OCB-tistore-invf-storeinv-invf-store-findchips-wwe)

PCM5100A is also compatible, little lower quality, but, Farnell currently has stock of this one.

Use the dac supply with filter choke for the analog 3.3v & use optionally use vccio 3.3v for the digital.

The MAX5101 is in stock with Mouser (my preferred supplier if I'm not buying from China, which I won't be for this board) and it looks a lot simpler to use - it'll just require a small interface from the AY-3-891x HDL module to send the A/B/C channel data to the right register at the right time; something even I should be able to manage.  ;)

What's the improvement using the PCM5101A?  I haven't got time to look tonight, but a quick glance at the datasheet indicates it uses I2S and doesn't look quite as straightforward as the MAX part?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2020, 11:31:19 pm
What's the improvement using the PCM5101A?  I haven't got time to look tonight, but a quick glance at the datasheet indicates it uses I2S and doesn't look quite as straightforward as the MAX part?
I2S is a serial shift out protocol.  How hard is it to got from parallel to serial inside the FPGA?
The max part doesn't provide a 2 VRMS AC signal, IE output goes from -3v to +3v.  The PCM5101A has a built in negative voltage generator for it's internal output op-amps.
If you feed it a 48KHz audio, it has built in oversampling so you do not get aliasing on the audio output.
It's also 32bit per channel so you may have a software/firmware volume.
At 8 bit, the MAX part at low volume will have an undesirable broken bitstream sound to it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2020, 11:51:50 pm
Okay, it's been a busy week and next it's just getting busier.  I don't have the time to sit and work out how to massage the Bezier code into something compatible with FreeBasic or HDL, so I'm going with the ellipse code:

Code: [Select]
Sub drawEllipse(ByVal x0 As Integer, ByVal y0 As Integer, ByVal x1 As Integer, ByVal y1 As Integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)
   Dim As Integer a = Abs(x1-x0), b = Abs(y1-y0), b1, x : Rem values of diameter
   Dim As Integer dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a : Rem error increment
   Dim As Integer errd = dx + dy + b1 * a * a, e2 : Rem error of 1.step

   b1 = b And 1

   if (x0 > x1) then
       x0 = x1
       x1 = x1 + a : Rem if called with swapped points
   End If
   if (y0 > y1) Then
       y0 = y1 : Rem .. exchange them
   End If
   y0 = y0 + (b + 1) / 2
   y1 = y0 - b1 : Rem starting pixel
   a = a*(8*a)
   b1 = 8*b*b

   While (x0 <= x1)
      draw_pixel(x1, y0, colour) : Rem   I. Quadrant
      draw_pixel(x0, y0, colour) : Rem   II. Quadrant
      draw_pixel(x0, y1, colour) : Rem   III. Quadrant
      draw_pixel(x1, y1, colour) : Rem   IV. Quadrant
      If (filled) Then
        For x=x0 to x1
            draw_pixel (x, y0, colour)
            draw_pixel (x, y1, colour)
        Next x
      EndIf
      e2 = 2*errd
      If (e2 <= dy) Then
        y0 = y0 + 1
        y1 = y1 - 1
        dy = dy + a
        errd = errd + dy : rem  y Step
      End If
      If (e2 >= dx Or 2*errd > dy) Then
        x0 = x0 + 1
        x1 = x1 - 1
        dx = dx + b1
        errd = errd + dx : rem x Step
      End If
   Wend
 
   While (y0 - y1 < b)  : Rem too early stop of flat ellipses a=1
       draw_pixel(x0 - 1, y0, colour) : Rem -> finish tip of Ellipse
       y0 = y0 + 1
       draw_pixel(x1 + 1, y0, colour)
       draw_pixel(x0 - 1, y1, colour)
       y1 = y1 - 1
       draw_pixel(x1 + 1, y1, colour)
   Wend

End Sub

It works fine in FreeBasic, so if you have no objections I'll start translating this into Verilog as a separate function, though it's likely to take a while due to work.

I've also attached my first version of the schematic for the Cyclone V GPU card for comment if anyone is interested.

You cheated!  That old code was already there and it is not a center ellipse, it is drawing an ellipse inside a box!

I'm curious as to why you didn't use this code:
Code: [Select]
*************Part1

int a2 = a*a , b2 = b*b , fa2 = 4*a2 ;
int x, y, sigma;

for ( x = 0, y = b, sigma = 2*b2+a2*(1-2*b) ; b2*x <= a2*y ; x++)
{
     DrawPixel ( xc+x , yc+y ) ;
     DrawPixel ( xc-x , yc+y ) ;
     DrawPixel ( xc+x , yc-y ) ;
     DrawPixel ( xc-x , yc-y ) ;

     if ( sigma >= 0 )
     {
          sigma += f a 2 *(1-y ) ;
          y--;
     }
     sigma += b2*(4*x+6);
}

*************Part2

int a2 = a*a , b2 = b*b , fb2 = 4*b2 ;
int x, y, sigma ;

for ( x = a, y = 0, sigma = 2*a2+b2*(1-2*a) ; a2*y <= b2*x ; y++)
{
     DrawPixel ( xc+x , yc+y ) ;
     DrawPixel ( xc-x , yc+y ) ;
     DrawPixel ( xc+x , yc-y ) ;
     DrawPixel ( xc-x , yc-y ) ;

     if ( sigma >= 0 )
     {
          sigma += fb2 *(1-x ) ;
          x--;
     }
     sigma += a2*(4*y+6);
}

From the document in my above post ' https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267128/#msg3267128 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267128/#msg3267128) '.  It doesn't have that pesky flat ellipse issue.  And since it separates the are into 2-45degree segments, you can make my 90 degree bot corners into 45 degree edges if you like.

This is not important.  And for flat ellipses, ignore that portion when coding the verilog.  There is a better place within my code to bypass the ellipse all together and go straight to the draw line function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2020, 07:26:28 am
Okay, it's been a busy week and next it's just getting busier.  I don't have the time to sit and work out how to massage the Bezier code into something compatible with FreeBasic or HDL, so I'm going with the ellipse code:

Code: [Select]
Sub drawEllipse(ByVal x0 As Integer, ByVal y0 As Integer, ByVal x1 As Integer, ByVal y1 As Integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)
   Dim As Integer a = Abs(x1-x0), b = Abs(y1-y0), b1, x : Rem values of diameter
   Dim As Integer dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a : Rem error increment
   Dim As Integer errd = dx + dy + b1 * a * a, e2 : Rem error of 1.step

   b1 = b And 1

   if (x0 > x1) then
       x0 = x1
       x1 = x1 + a : Rem if called with swapped points
   End If
   if (y0 > y1) Then
       y0 = y1 : Rem .. exchange them
   End If
   y0 = y0 + (b + 1) / 2
   y1 = y0 - b1 : Rem starting pixel
   a = a*(8*a)
   b1 = 8*b*b

   While (x0 <= x1)
      draw_pixel(x1, y0, colour) : Rem   I. Quadrant
      draw_pixel(x0, y0, colour) : Rem   II. Quadrant
      draw_pixel(x0, y1, colour) : Rem   III. Quadrant
      draw_pixel(x1, y1, colour) : Rem   IV. Quadrant
      If (filled) Then
        For x=x0 to x1
            draw_pixel (x, y0, colour)
            draw_pixel (x, y1, colour)
        Next x
      EndIf
      e2 = 2*errd
      If (e2 <= dy) Then
        y0 = y0 + 1
        y1 = y1 - 1
        dy = dy + a
        errd = errd + dy : rem  y Step
      End If
      If (e2 >= dx Or 2*errd > dy) Then
        x0 = x0 + 1
        x1 = x1 - 1
        dx = dx + b1
        errd = errd + dx : rem x Step
      End If
   Wend
 
   While (y0 - y1 < b)  : Rem too early stop of flat ellipses a=1
       draw_pixel(x0 - 1, y0, colour) : Rem -> finish tip of Ellipse
       y0 = y0 + 1
       draw_pixel(x1 + 1, y0, colour)
       draw_pixel(x0 - 1, y1, colour)
       y1 = y1 - 1
       draw_pixel(x1 + 1, y1, colour)
   Wend

End Sub

It works fine in FreeBasic, so if you have no objections I'll start translating this into Verilog as a separate function, though it's likely to take a while due to work.

I've also attached my first version of the schematic for the Cyclone V GPU card for comment if anyone is interested.

You cheated!  That old code was already there and it is not a center ellipse, it is drawing an ellipse inside a box!

I'm curious as to why you didn't use this code:
Code: [Select]
*************Part1

int a2 = a*a , b2 = b*b , fa2 = 4*a2 ;
int x, y, sigma;

for ( x = 0, y = b, sigma = 2*b2+a2*(1-2*b) ; b2*x <= a2*y ; x++)
{
     DrawPixel ( xc+x , yc+y ) ;
     DrawPixel ( xc-x , yc+y ) ;
     DrawPixel ( xc+x , yc-y ) ;
     DrawPixel ( xc-x , yc-y ) ;

     if ( sigma >= 0 )
     {
          sigma += f a 2 *(1-y ) ;
          y--;
     }
     sigma += b2*(4*x+6);
}

*************Part2

int a2 = a*a , b2 = b*b , fb2 = 4*b2 ;
int x, y, sigma ;

for ( x = a, y = 0, sigma = 2*a2+b2*(1-2*a) ; a2*y <= b2*x ; y++)
{
     DrawPixel ( xc+x , yc+y ) ;
     DrawPixel ( xc-x , yc+y ) ;
     DrawPixel ( xc+x , yc-y ) ;
     DrawPixel ( xc-x , yc-y ) ;

     if ( sigma >= 0 )
     {
          sigma += fb2 *(1-x ) ;
          x--;
     }
     sigma += a2*(4*y+6);
}

From the document in my above post ' https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267128/#msg3267128 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267128/#msg3267128) '.  It doesn't have that pesky flat ellipse issue.  And since it separates the are into 2-45degree segments, you can make my 90 degree bot corners into 45 degree edges if you like.

This is not important.  And for flat ellipses, ignore that portion when coding the verilog.  There is a better place within my code to bypass the ellipse all together and go straight to the draw line function.

 ???  I wasn't passing the function off as my own work.  I did wonder why you hadn't mentioned using this code previously.  I took another look at all the Bezier stuff yesterday and being away from it for a week just made it (and the ellipse stuff) even less intelligible to me. :-[

Then I remembered the code in the original geo.bas and wondered why we hadn't used that - it seemed to work fine so thought I'd use that?  Would be easy enough to tweak it to work from a centre point and radius, although I'd be fine with the current 'box' implementation.  Truth is, I haven't a flying clue what I'm supposed to be doing with this ellipse/Bezier stuff, I'm totally lost in it all.

It has given me an opportunity to make some headway on the hardware side, though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Gribo on October 21, 2020, 11:33:04 am
As much as I like being lazy, and copy stuff instead of actually doing it, the layout you posted will not pass a basic DFM review.
Have a look at the reference design, especially if you are going to try higher resolutions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2020, 11:44:25 am
If you get your PCB made by JLPCB, they will place the components for you if the parts are available at https://lcsc.com/ (https://lcsc.com/) , the place where I found your Cyclone V for 18$.

Yes, that's an option as I use JLCPCB for my boards.  I'm seriously considering it, even though it's expensive (e.g. I don't need five boards made up but that would be the minimum if I use their assembly process), but it would save me a LOT of headaches trying to solder BGA and QFN parts.  :-+

Also, for your caps, use 10uf XR7 1206 or 1210 ceramic.  For 22uf, just use 2x10uf in parallel.
Do not use 0805 10uf ceramic.  Their capacitance really drops with voltage.

As for the DAC filter and boot caps, might as well use the same 10uf unless you do not want to consolidate parts.

Okie dokie, will use them - I take it these 1210 XR7 MLCC (https://www.mouser.co.uk/ProductDetail/187-CL32B106KOJNNNE) caps are fine and replacing polar caps with non-polar ones won't cause any issues?

The 10uF and 22uF caps on the Power sheet are 3216 tantalum capacitors - these are the same as what I've used on the current GPU board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 21, 2020, 12:12:27 pm

Okie dokie, will use them - I take it these 1210 XR7 MLCC (https://www.mouser.co.uk/ProductDetail/187-CL32B106KOJNNNE) caps are fine and replacing polar caps with non-polar ones won't cause any issues?


Those are fine everywhere.
But just don't take it that the Cyclone V is cheaper at LCSC, so is everything else.  Take a look at the cap price there:

https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106KQHNNNE_C318761.html (https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106KQHNNNE_C318761.html)
https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106MOHNNNE_C730480.html (https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106MOHNNNE_C730480.html)

You are throwing out 8x the money...
Or 4x for the 1210s:
https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_SAMSUNG_CL32B106KAJNNNE_10uF-106-10-25V_C39232.html (https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_SAMSUNG_CL32B106KAJNNNE_10uF-106-10-25V_C39232.html)

Same goes for almost every part on your PCB.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2020, 12:29:45 pm
But just don't take it that the Cyclone V is cheaper at LCSC, so is everything else.  Take a look at the cap price there:

https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106KQHNNNE_C318761.html (https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106KQHNNNE_C318761.html)
https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106MOHNNNE_C730480.html (https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_Samsung-Electro-Mechanics-CL31B106MOHNNNE_C730480.html)

You are throwing out 8x the money...
Or 4x for the 1210s:
https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_SAMSUNG_CL32B106KAJNNNE_10uF-106-10-25V_C39232.html (https://lcsc.com/product-detail/Multilayer-Ceramic-Capacitors-MLCC-SMD-SMT_SAMSUNG_CL32B106KAJNNNE_10uF-106-10-25V_C39232.html)

Same goes for almost every part on your PCB.

Oh yes, I've spotted that already - must admit, I was a bit surprised that LCSC are cheapest (currently) for the Cyclone V.

As far as SMD assembly of the board goes, I'd only be buying and having the Cyclone V and power chips (QFN parts) assembled on the board, the rest I'd do myself.  Might consider the ADV7125 as part of the assembly too just to save me the hassle - seems they don't do the TFP410, though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 21, 2020, 12:36:08 pm
If you get your PCB made by JLPCB, they will place the components for you if the parts are available at https://lcsc.com/ (https://lcsc.com/) , the place where I found your Cyclone V for 18$.

Yes, that's an option as I use JLCPCB for my boards.  I'm seriously considering it, even though it's expensive (e.g. I don't need five boards made up but that would be the minimum if I use their assembly process), but it would save me a LOT of headaches trying to solder BGA and QFN parts.  :-+

Also, for your caps, use 10uf XR7 1206 or 1210 ceramic.  For 22uf, just use 2x10uf in parallel.
Do not use 0805 10uf ceramic.  Their capacitance really drops with voltage.

As for the DAC filter and boot caps, might as well use the same 10uf unless you do not want to consolidate parts.

Okie dokie, will use them - I take it these 1210 XR7 MLCC (https://www.mouser.co.uk/ProductDetail/187-CL32B106KOJNNNE) caps are fine and replacing polar caps with non-polar ones won't cause any issues?

The 10uF and 22uF caps on the Power sheet are 3216 tantalum capacitors - these are the same as what I've used on the current GPU board.

Are your IO optimized based on IO Bank and pin location for routing?
Or, will you do pin-swapping during layout?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2020, 02:31:53 pm
As much as I like being lazy, and copy stuff instead of actually doing it, the layout you posted will not pass a basic DFM review.
Have a look at the reference design, especially if you are going to try higher resolutions.

I had a go at the reference design initially, but I was using the wrong chokes/inductors and they were taking up far too much room on the PCB, so I was keen to use a design that took up less space.  I've gone back to the reference design, but updated inductors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2020, 02:59:12 pm
Are your IO optimized based on IO Bank and pin location for routing?
Or, will you do pin-swapping during layout?

I've tried to keep within banks, but as you can see from the schematics I've not been able to keep all functions to the same bank.  A lot of this is because of prioritising pin placement, but I've never routed a BGA package before and fully expect to do some pin-swapping once you see the PCB layout and I learn a little about how I'm going to connect all these BGA pads up.

At the speeds we're working with (i.e. 8 MHz address/data buses and pixel clock speeds for the video out) and the fact all banks are running at the same 3.3V, how much effort should I be putting into fitting functions into the same bank?

Oh, I've also been unable to fit a DRAM into the BGA-256 version of the Cyclone V.  It only has 128 IOs, which is a step up from the Cyclone IV QFP-144 I'm currently using, but not enough to add in a DRAM.  Perhaps a larger BGA package should be considered, but the PCB is getting cramped...

The attachment shows where I am with the PCB layout currently.  Note that it doesn't reflect the changes made to the audio DAC and TFP410 decoupling, and doesn't have the decoupling caps for the FPGA placed yet.

I've yet to work out how many layers the PCB will need - I'm guessing it's going to have to be 4 layers - but I'm not sure which layers will be which, so I've just connected up power, bus lines and outer traces, working my way inwards using just the top layer so far.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Gribo on October 21, 2020, 03:31:17 pm
 :-+
That's a nice looking board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 21, 2020, 07:31:11 pm
A single DDR2 dram will use 43 IOs, half will need to be in the top or bottom IO banks.
A single Hyperbus PSRAM will use 13 IOs, all in the top or bottom IO banks.  You will want 2 which means 26-2 = 24 IOs.
A single or dual ZBT Sync SRam will use 40 IOs, all in the top or bottom IO banks.

Choose your poison.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 21, 2020, 08:55:50 pm
A single DDR2 dram will use 43 IOs, half will need to be in the top or bottom IO banks.
A single Hyperbus PSRAM will use 13 IOs, all in the top or bottom IO banks.  You will want 2 which means 26-2 = 24 IOs.
A single or dual ZBT Sync SRam will use 40 IOs, all in the top or bottom IO banks.

Choose your poison.

Ah okay... well, I can scrape together 24 IOs across three banks, but I'm going to need to re-jig the top banks if I'm going to use a PSRAM.  The FPGA is rotated 90 degrees CW on the PCB.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 21, 2020, 11:18:24 pm
Remember, the ram needs access to the dedicated differential PLL outputs.
Also, you need to squeeze everything into 1 IO bank since it will be run at a lower voltage.  You need to check, the PSRAM may work on 2.5v when operated at 250MHz, otherwise, you will want 1.8v.
This means the same IO bank with the dedicated PLL outputs will also need to be at the lower voltage.

Make sure the other 11 data lines are on DDR-DQ IO pins.

First, find a 250MHz PSRAM hyperbus or similar ram chip.

Some hyperbus rams allow interleaving on 1 bus, for those, you only need 14 IOs total saving a bunch...
Look for those so everything can fit in 1 bank.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 23, 2020, 05:28:50 pm
Remember, the ram needs access to the dedicated differential PLL outputs.
Also, you need to squeeze everything into 1 IO bank since it will be run at a lower voltage.  You need to check, the PSRAM may work on 2.5v when operated at 250MHz, otherwise, you will want 1.8v.
This means the same IO bank with the dedicated PLL outputs will also need to be at the lower voltage.

Make sure the other 11 data lines are on DDR-DQ IO pins.

First, find a 250MHz PSRAM hyperbus or similar ram chip.

Some hyperbus rams allow interleaving on 1 bus, for those, you only need 14 IOs total saving a bunch...
Look for those so everything can fit in 1 bank.

Thought I'd have a quick look as I have a spare 5 minutes for these RAM chips you've mentioned, but damned if I can find anything relevant anywhere other than on DigiKey.   :-//

Do you mean something like this S27KL0642GABHI030 (https://www.digikey.co.uk/product-detail/en/cypress-semiconductor-corp/S27KL0642GABHI030/428-S27KL0642GABHI030-ND/11611410)?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2020, 06:15:04 am
Yup, this is the cheapest and it's available everywhere:

https://www.arrow.com/en/products/s27ks0642gabhi030/cypress-semiconductor (https://www.arrow.com/en/products/s27ks0642gabhi030/cypress-semiconductor)
Everyone has it, not just Digikey, see here:
https://www.findchips.com/search/S27KS0642 (https://www.findchips.com/search/S27KS0642)
NOTE: The S27KS0642xxx020 variant is usually cheaper and available at more distributers...  Use that one instead.  There will be slight firmware changes depending on how you write the controller.

200 MHz is the limit and that's fine since the Cyclone V has enough PLLs, however your core multiport ram clock is 250MHz and it would be nice to run these at 250MHz.  You will need to add a linear 1.8v regulator as they require this voltage.  Make it adjustable as I believe we will be running them at ~2v-2.25v to squeeze out that 250MHz error free.

8bit bus at 500MTPS = 16bit data at 250MHz, same width and speed of your core ram meaning a 1:1 transfer rate.

You will probably configure this ram as 8 or 16bit graphics background screen only.  Meaning the 15 MAGGIE layers will be above it's display while this ram will be Maggie layer 16.  You will be able to use the blitter for text on this layer and have 15 dedicated sprite layers which will have access to the core 350Kb.

Audio will also be stored on this ram.  You will have 16 megabytes to play with using 2 chips.

If you make a smart flash DMA controller, I do not know about the flash speed, but you should be able to fill this ram at around 50 megabytes a second.  This means uncompressed 320x240 16bit avi @60fps video with sound playback is possible so long as the flash can keep up.  Almost no CPU overhead.  30fps will be easy-peasy.


Looking at the numbers, with the worst possible delay, you will just make it clear to guarantee that Z80 access will never have any wait states no matter what else the ram will be doing in the system, however, just like the pixel writer, you will need to write an equivilant, not 1 word, but 1 burst smart cache of 32 bytes to ease things along.  And you will need one for every sub-section of access which will need integration into the current pixel writer as it is the most demanding access port second to the video display, DMA flash reader/writer, then sound system, then Z80, except, any Z80 read transactions will need to interupt and take immediate action on the next read cycle if the contents are not in the cache, otherwise a read error will take place, or we will need to implement Z80 wait states.  Avoiding this means the Z80 will have the equivilant of 16 megabytes of static ram.  Assembly code should run with perfect repetitious predictable timing.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 24, 2020, 08:16:15 pm
200 MHz is the limit and that's fine since the Cyclone V has enough PLLs, however your core multiport ram clock is 250MHz and it would be nice to run these at 250MHz.  You will need to add a linear 1.8v regulator as they require this voltage.  Make it adjustable as I believe we will be running them at ~2v-2.25v to squeeze out that 250MHz error free.

8bit bus at 500MTPS = 16bit data at 250MHz, same width and speed of your core ram meaning a 1:1 transfer rate.

There's some big figures there.  I'm going to have a headache working out how to get the IOs together for these chips, though - or placement headaches on the PCB, in any case.

You will probably configure this ram as 8 or 16bit graphics background screen only.  Meaning the 15 MAGGIE layers will above it's display while this ram will be Maggie layer 16.  You will be able to use the blitter for text on this layer and have 15 dedicated sprite layers which will have access to the core 350Kb.

So I could use the external RAM for the text screen (basically what I have now, but a higher resolution due to the extra RAM space) and use the internal RAM for sprites?

Audio will also be stored on this ram.  You will have 16 megabytes to play with using 2 chips.

My intention for the audio is to use an HDL synthesis of the classic AY-3-8910 PSG.  At least initially.  I guess having the flexibility to store samples and so on will just expand the possibilities.

If you make a smart flash DMA controller, I do not know about the flash speed, but you should be able to fill this ram at around 50 megabytes a second.  This means uncompressed 320x240 16bit avi @60fps video with sound playback is possible so long as the flash can keep up.  Almost no CPU overhead.  30fps will be easy-peasy.


Looking at the numbers, with the worst possible delay, you will just make it clear to guarantee that Z80 access will never have any wait states no matter what else the ram will be doing in the system, however, just like the pixel writer, you will need to write an equivilant, not 1 word, but 1 burst smart cache of 32 bytes to ease things along.  And you will need one for every sub-section of access which will need integration into the current pixel writer as it is the most demanding access port second to the video display, DMA flash reader/writer, then sound system, then Z80, except, any Z80 read transactions will need to interupt and take immediate action on the next read cycle if the contents are not in the cache, otherwise a read error will take place, or we will need to implement Z80 wait states.  Avoiding this means the Z80 will have the equivilant of 16 megabytes of static ram.  Assembly code should run with perfect repetitious predictable timing.

Yikes, it's looking like the RAM is a must-have rather than a nice-to-have with these possibilities.  So, assume I will be using the DRAM chips we've identified above - I'll need two of them, the 1.8V rail (variable to allow 'overclocking'), what sort of consideration will I need to make for IO selection, PCB placement etc?  I guess I'm going 4-layer, so I could use the space to the left and right of the FPGA as the address and data/control buses will pass the RAM chips in a signal layer beneath them?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2020, 08:45:04 pm
There's some big figures there.  I'm going to have a headache working out how to get the IOs together for these chips, though - or placement headaches on the PCB, in any case.

Hun? Read the datasheet, it's 13 IOs for 1 chip, 1 more IO for the second as everything is in parallel except for CS# pin.
Quote

So I could use the external RAM for the text screen (basically what I have now, but a higher resolution due to the extra RAM space) and use the internal RAM for sprites?

It will be accessible as any 1 MAGGIE layer tied into the ram address.  The only issue is for access time allocation, only 1 MAGGIE can address the DRAM at a time as you will need to implement a special read-ahead cache for the DRAM as the ram access is on the order of 10-20 125MHz clocks unlike the FPGA ram which is immediate.  How you use the memory is completely up to you.  The blitter wont have this restriction between the fpga ram and DRAM, and as you know, you can simulate fonts/tiles with it supporting multiple colors and odd sizes which don't divide into widths of 8.
Quote

My intention for the audio is to use an HDL synthesis of the classic AY-3-8910 PSG.  At least initially.  I guess having the flexibility to store samples and so on will just expand the possibilities.

It may be OK if you have functional HDL code already, however, I recommend reconstructing an advanced version of an Amiga Paula audio system.  It is half as complicated as the geometry unit, but you can expect 8 channel sound, each channel with stereo, each with a volume and pitch table samples, all 16 or 8 bit.
Quote

Yikes, it's looking like the RAM is a must-have rather than a nice-to-have with these possibilities.  So, assume I will be using the DRAM chips we've identified above - I'll need two of them, the 1.8V rail (variable to allow 'overclocking'), what sort of consideration will I need to make for IO selection, PCB placement etc?  I guess I'm going 4-layer, so I could use the space to the left and right of the FPGA as the address and data/control buses will pass the RAM chips in a signal layer beneath them?

Begin with the IO.  To get the 500MTPS, you must use a top or bottom IO bank on the FPGA.  It must have PLL output pins to feed the CLK & CLK# signals.  It needs to be 1 IO bank since you need to change the VCCIO for that bank to 1.8v.  I already looked at your current layout.  You have 1 obvious choice and it will be an easy swapping of only a few IOs in your current design as soon as you clear up your schematic which seems to have a few unused additional labels.

For the regulator, you will add a small SMD trimpot tuned with an output range from 1.7v to 2.3v.  If there are no errors during tests at 1.7v, then you know you can keep running it at 1.8v.  I do not expect the entire 1.8v side to consume more than 80ma max when over-clocked.  So, you may relax and feel safe with the same linear regulators you are currently using.

You have other minor errors in your schematic, but I'm waiting until you finish things up.
1 thing, for the DAC's audio output DC filter caps, please change them to the 10uf non-polarized ceramic ones.  Remember, part consolidation...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2020, 09:23:17 pm
No matter how you slice it, if you use a tiled MAGGIE text front layer, this will make the fastest text output no matter what for the Z80 as only 2 bytes are needed for each character.  You can even use the blitter to perform a screen carriage return and screen clear on the text data memory space.

Using the biltter to emulate ASCII text may be faster than the Z80 can write down 2 bytes, however, there are a few additional controls the Z80 must set and check every time it paints 1 letter.  You need to decide due to case use, if you want blitter text which offers a lot of fancy features and possibilities VS old fashioned dumb text mode.  Remember, you are still running at a max res of 640x480, it's just that the blitter text allows for any foreground/background color instead of 16fg x 16bg colors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2020, 08:25:22 pm
Okay, it's been a busy couple of weeks for me and I've not had any time other than a couple of hours today to look at the schematic and your previous replies.  I've done what I can.  I've had to remove a lot of decoupling for the TFP410 because I don't think I'll have the room for it all, to be honest.  I'm happy to give the setup a try without the reference design power supply isolation and decoupling, especially as it has been used the way I've done it (in fact, with even less decoupling) to good effect in other published designs.

I've re-jigged some of the FPGA connections to get the two DRAMs onto the board - hopefully I've done what you had in mind.  The schematic is updated but I haven't yet connected up the 1.8V power supply to the FPGA's IO bank for the DRAMs.  I also haven't designed the variable-voltage output from the AMS-1117 (U19) for the DRAM yet.  I'd be happy for some more info on that before I try - I guess I'll be using an SMD potentiometer in series with one of the resistors that sets the output voltage, but I'd probably be guessing at values at this stage without taking a closer look and spending some more time on that part of the schematic.

I've also updated the DAC to the suggested one and tucked its circuit up in the corner by the headphone socket to keep it out of the way as much as possible.  Believe it or not, I know even less about analogue electronics than I do digital, so I've just gone with the reference schematic as close as possible from the datasheet.  I've connected it up to Bank 2A.

Quote
My intention for the audio is to use an HDL synthesis of the classic AY-3-8910 PSG.  At least initially.  I guess having the flexibility to store samples and so on will just expand the possibilities.
It may be OK if you have functional HDL code already, however, I recommend reconstructing an advanced version of an Amiga Paula audio system.  It is half as complicated as the geometry unit, but you can expect 8 channel sound, each channel with stereo, each with a volume and pitch table samples, all 16 or 8 bit.

I wouldn't have a clue where to begin with that and I'm mindful that I'm highly dependant on your help when your time is very restricted.  :-// I do have an HDL version of the AY-8910 already that would work with my existing software in CP/M, so in theory it's just a case of adding an interface in the Z80_bridge and an interface from the 3-channel output of the HDL AY-8910 to the DAC.  In theory I should be able to manage that myself - so I'll give that a shot first before starting on something like the Paula chip.

Begin with the IO.  To get the 500MTPS, you must use a top or bottom IO bank on the FPGA.  It must have PLL output pins to feed the CLK & CLK# signals.  It needs to be 1 IO bank since you need to change the VCCIO for that bank to 1.8v.  I already looked at your current layout.  You have 1 obvious choice and it will be an easy swapping of only a few IOs in your current design as soon as you clear up your schematic which seems to have a few unused additional labels.

Well, I've added the memory chips - not sure about the CLK & CLK# output pins - have picked pins marked 'p and 'n on the pin planner - so I'm hoping I've got that right.

For the regulator, you will add a small SMD trimpot tuned with an output range from 1.7v to 2.3v.  If there are no errors during tests at 1.7v, then you know you can keep running it at 1.8v.  I do not expect the entire 1.8v side to consume more than 80ma max when over-clocked.  So, you may relax and feel safe with the same linear regulators you are currently using.

Excellent.  Well, 1.8v power supply is in the schematic - you won't see it on the PCB design as it's out of shot because I haven't placed it yet, I'm waiting to finish the variable output design first.

You have other minor errors in your schematic, but I'm waiting until you finish things up.

There's probably loads of errors - I do the best I can, but I really rely on everyone's help here to spot the obvious errors I sneak in to test you all.  :-DD

1 thing, for the DAC's audio output DC filter caps, please change them to the 10uf non-polarized ceramic ones.  Remember, part consolidation...

That was for the old DAC - the new one pumps out a proper AC signal so there's no need for DC filters, hence you won't find any polarised caps in the new design.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 31, 2020, 03:39:51 am
Bugs part #1.

Audio DAC - Place those 10uf or 22uf ceramics back in place and place 100k or 47k pull-downs on the headphone jack.
You never know when bad firmware or bad coding will drive DC out of the DAC.  The series caps will protect your DAC and audio hardware from that.

U19, change that to the adjustable version and add a trimpot.  You want the pot on the output - resistor - feedback pin, then feedback pin - resistor - GND.
Resistor calculator : https://circuitdigest.com/calculators/lm317-resistor-voltage-calculator (https://circuitdigest.com/calculators/lm317-resistor-voltage-calculator)
Make R2 = 560 Ohm, make R1 a 560Ohm resistor + a 1K pot in series.
This will allow adjustment from 1.7v to 2.5v.

Micro-SD Card: 2 of those resistors are 'BOGUS'.

DDR-RAM - Place the DDR_CKp and DDR_CKn IOs onto the dedicated PLL outputs.
It's written there right on the IO bank labels.
Remember, these 2 pins cannot be moved around, they must be on the PLL outputs.
You may only swap the 'n' & 'p'.

Add another RS232 header with 4 wire protocol/handshaking.  Make it compatible with a 3.3v TTL USB-RS232 header which has DTR & CTS, see attached image.  Do not connect the VCC.  Unless you want a DB9 and want a generic full RS232 port, not just a PC interface for the Z80 separate of the debugger.

Also expect to draw out a few unused IOs as emergency/surplus features.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on October 31, 2020, 09:22:47 am
You should maybe consider placing 2-4 resistors in series instead of a potentiometer, and using a jumper to short out resistors, reducing the total resistance, therefore different output voltage.
Set the 1.8v as default (no jumpers needed), adding jumpers raises in 0.1v increments or something like that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 31, 2020, 02:01:13 pm
Audio DAC - Place those 10uf or 22uf ceramics back in place and place 100k or 47k pull-downs on the headphone jack.
You never know when bad firmware or bad coding will drive DC out of the DAC.  The series caps will protect your DAC and audio hardware from that.

Okie dokie, have added non-polarised 10uF caps back in there and 100K pull-downs at the headphone jack.

U19, change that to the adjustable version and add a trimpot.  You want the pot on the output - resistor - feedback pin, then feedback pin - resistor - GND.
Resistor calculator : https://circuitdigest.com/calculators/lm317-resistor-voltage-calculator (https://circuitdigest.com/calculators/lm317-resistor-voltage-calculator)
Make R2 = 560 Ohm, make R1 a 560Ohm resistor + a 1K pot in series.
This will allow adjustment from 1.7v to 2.5v.

That's done.  I do like mariush's suggestion of using a set of resistors to provide preset values, but I'm not sure I'll have the room for something like that on the PCB.  I haven't checked to see where I'll put the trim pot or additional resistors yet, but I'm expecting a lot more movement on the PCB before I hit the final layout.

Micro-SD Card: 2 of those resistors are 'BOGUS'.

As soon as you mentioned them I thought, "no, surely I wouldn't have", but I had. ::)  Well spotted.  :-+

DDR-RAM - Place the DDR_CKp and DDR_CKn IOs onto the dedicated PLL outputs.
It's written there right on the IO bank labels.
Remember, these 2 pins cannot be moved around, they must be on the PLL outputs.
You may only swap the 'n' & 'p'.

Okay, no problem - I was rushing yesterday to get something done in the time I had.  Hopefully using the right pins now.

Add another RS232 header with 4 wire protocol/handshaking.  Make it compatible with a 3.3v TTL USB-RS232 header which has DTR & CTS, see attached image.  Do not connect the VCC.  Unless you want a DB9 and want a generic full RS232 port, not just a PC interface for the Z80 separate of the debugger.

Ah okay, that's a good use for some of the remaining free IOs.  Is there any way the configuration ROM could be updated via that serial connection, I wonder?

Also expect to draw out a few unused IOs as emergency/surplus features.

I'll add some of them in at the very end when I know I've definitely got spares.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 01, 2020, 01:21:13 pm
Fixes, part 1B...

Ok, the VCCPGM going to the FPGA is all messed up.
You should have IO and PGM separate,

On trimpot R51, swap pin 1&3 so the rotating counter-clockwise lowers voltage and clockwise increases voltage.

Disconnected VCCA from VCCIO and connect it to 3.3VA.  Or, make a 2 pin header jumper to select between the 2.

Do you have 3.3v protection diodes for the 4x PS2_xxx signals?  I recommend using 4 single or 2 dual schottky diodes tied to VCCIO.  If you want full VCCIO & GND protection, then use 4 dual diodes.

For the MSEL#, maybe it would be good to make them config jumpers, or resistors...

I don't know about the Cyclone5, but, you can make code which will self-program the boot prom.  I've done so on the CycloneIII.
You would need to verify that the nCSO, DATA0-3 & DCLK can be configured into regular IOs.  If not, then an IO tied to each one through series resistor with a DISABLE-Jumper (breaks the IO feeding DCLK) may be added to your design.  Then the Z80 or RS232-port/debugger may be used to change the firmware.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 01, 2020, 07:43:24 pm
Ok, the VCCPGM going to the FPGA is all messed up.
You should have IO and PGM separate,

But page 5 in the Cyclone V Device Datasheet (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/cyclone-v/cv_51002.pdf) specifies maximum voltages for VCCIO and VCCPGM as 3.90V, and the Cyclone V E Power Supply Sharing Guidelines (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/dp/cyclone-v/pcg-01014.pdf) states they can be shared if the same voltage:

[attachimg=1]

On trimpot R51, swap pin 1&3 so the rotating counter-clockwise lowers voltage and clockwise increases voltage.

Disconnected VCCA from VCCIO and connect it to 3.3VA.  Or, make a 2 pin header jumper to select between the 2.

All done.

Do you have 3.3v protection diodes for the 4x PS2_xxx signals?  I recommend using 4 single or 2 dual schottky diodes tied to VCCIO.  If you want full VCCIO & GND protection, then use 4 dual diodes.

No, I don't - the design works okay on the Cyclone IV board, but if you think I should add in some better protection, I can add in something like the BAT54S?

For the MSEL#, maybe it would be good to make them config jumpers, or resistors...

Perhaps, but I'm not likely to want to change these values, am I?  I've checked and double-checked the configuration section of the Cyclone V datasheet.  Will I need to be able to change these settings?

I don't know about the Cyclone5, but, you can make code which will self-program the boot prom.  I've done so on the CycloneIII.
You would need to verify that the nCSO, DATA0-3 & DCLK can be configured into regular IOs.  If not, then an IO tied to each one through series resistor with a DISABLE-Jumper (breaks the IO feeding DCLK) may be added to your design.  Then the Z80 or RS232-port/debugger may be used to change the firmware.

Hmmm, most of them seem to be bidirectional in the connection guide, but I'll need to look at the datasheet more closely to see if I can configure them as regular IO.  Something for me to research when I have more time, perhaps.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 02, 2020, 10:09:41 am
Ok, the VCCPGM going to the FPGA is all messed up.
You should have IO and PGM separate,

But page 5 in the Cyclone V Device Datasheet (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/hb/cyclone-v/cv_51002.pdf) specifies maximum voltages for VCCIO and VCCPGM as 3.90V, and the Cyclone V E Power Supply Sharing Guidelines (https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/dp/cyclone-v/pcg-01014.pdf) states they can be shared if the same voltage:

(Attachment Link)

If you are going to share the power, then use 1 power bus, do not feed an extra filtered 3.3v with separate caps for the FPGA section.  Consolidate that power section, otherwise, you have too many power buses all over the place messing with you power plane design.  Again, fix this....

MSEL J2 is not good.  Replace it with 4 series 0603/0402 resistors with optional shorts underneath, going to your mode selection GND/VCC???

BAT54s series is fine.

Power the TFP410 from the VCCIO.  It can withstand a little digital noise from before it's L1 filter and it draws a little too much current from the linear regulator.  DVDD may be unfiltered.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 02, 2020, 11:17:06 am
If you are going to share the power, then use 1 power bus, do not feed an extra filtered 3.3v with separate caps for the FPGA section.  Consolidate that power section, otherwise, you have too many power buses all over the place messing with you power plane design.  Again, fix this....

Always happy to reduce nets and components.  I haven't attempted to place decoupling caps yet and it's already looking like it's going to be a nightmare to route.

MSEL J2 is not good.  Replace it with 4 series 0603/0402 resistors with optional shorts underneath, going to your mode selection GND/VCC???

Okay, I've done it for MSEL0 and MSEL1.

Power the TFP410 from the VCCIO.  It can withstand a little digital noise from before it's L1 filter and it draws a little too much current from the linear regulator.  DVDD may be unfiltered.

So long as the TFP410 is happy, I'm fine with DVDD using the filtered input as it seems to give the simplest PCB routing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 02, 2020, 11:41:22 am
You are missing 100nf decoupling caps for every VCC_DDR pin.

What's happening with pin VCCPGM C6?

What do the 'VCCPD#B#A' pins do?

Aren't VCC_AUX and VCC_FPLL supposed to be separate?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 02, 2020, 12:18:00 pm
You are missing 100nf decoupling caps for every VCC_DDR pin.

What's happening with pin VCCPGM C6?

This is why I don't do this stuff for a living. ;D

Aren't VCC_AUX and VCC_FPLL supposed to be separate?

As far as I can tell, they don't have to be.  The Cyclone V documentation I'm using (Cyclone V Device Family Pin Connection Guidelines PCG-01014-2.8 (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjj8MeM6OPsAhWBiVwKHRKMBkcQFjAAegQIBRAC&url=https%3A%2F%2Fwww.intel.com%2Fcontent%2Fdam%2Fwww%2Fprogrammable%2Fus%2Fen%2Fpdfs%2Fliterature%2Fdp%2Fcyclone-v%2Fpcg-01014.pdf&usg=AOvVaw2T9RnmJ4OD7k04CXh2g1Vn)) indicates they can be shared:

[attachimg=1]

And here in this Altera dev board schematic:

[attachimg=2]

What do the 'VCCPD#B#A' pins do?

Oooooh.... how could I miss that?  :o  |O

[attachimg=3]

Okay, that poses a serious (I guess?) problem, as it means that Bank 7A must operate at 1.8V as well, as it shares VCCPD pins with Bank 8A and both must use compatible VCCIO voltages for the shared VCCPD voltage, if I'm reading that right.

So that means I have to clear out the 11 Z80 data and control signals from Bank 7A and move them to the few remaining spare IOs in Banks 2A and 4A?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 02, 2020, 12:40:55 pm
I believe both DACs and TFP410 can be run their DVDD at 1.8 through 2.5v as well.  This means you may pass the 24 bit video dac and audio I2S through bank 7 and one of bank 5.  This leaves everything else at 3.3v.
Careful, you will want a dedicated separate 3.3v copy of HS&VS to drive U4 sync boost.

If you are using bank 5B, you also get the dedicated PLL CLK output to clock the video data.


***Don't forget decoupling caps for VCC_DDR for the FPGA supply pines as well, not just the memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 02, 2020, 03:43:37 pm
I believe both DACs and TFP410 can be run their DVDD at 1.8 through 2.5v as well.  This means you may pass the 24 bit video dac and audio I2S through bank 7 and one of bank 5.  This leaves everything else at 3.3v.
Careful, you will want a dedicated separate 3.3v copy of HS&VS to drive U4 sync boost.

If you are using bank 5B, you also get the dedicated PLL CLK output to clock the video data.


***Don't forget decoupling caps for VCC_DDR for the FPGA supply pines as well, not just the memory.

This is causing me a headache.  Changing the DVDD supply to the PCM5101 isn't an issue, looks like it's fine with that according to the datasheet.  Where the problem arises is with the TFP410 and ADV7125 DACs.  Both use the 24-bit RGB bus, pixel clock and display enable from the FPGA - so that's 26 IO pins on the FPGA I'd need to make 1.8V, which is more than one bank.  I'd be losing more IO's to 1.8V than I am already right now?  That's without worrying about the HS and VS signals too - they'd need to be 1.8V for the TFP410 if it's running on a 1.8V bus?

What about if I use Bank 3A for the DRAM?  I can assign just Bank 3A to 1.8V as it has its own VCCPD pin, it doesn't share it with any other banks. It just means moving the SD card and low Z80 address pins to Bank 2A, or shuffling everything around a bit.  Would that work?  The only (possible) issue I can see immediately is that CLKUSR goes into Bank 3A, but that must be able to operate at 1.8V as well as at 3.3V?  I'd just need to change the supply to X1?

EDIT:  Bank 3A doesn't have FPLL_CLKOUT pins, though.  |O

EDIT 2: Bank 5B has its own VCCPD pin AND FPLL_CLKOUT pins, however.....?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 03, 2020, 05:00:18 am
Ok, you can use bank 5B.  CycloneV doesn't have the row VS column speed limitations like the older Cyclones.  In fact, it can do with wisely chosen pins and 303MHz/606MTPS using any soft core memory controller.  You will be running your controller at 250MHz max, IO 500MTPS, well within IO Bank 5B's speed.

You may want to rotate the chip and fix up the IO so the PSRAM end up in the same current space on your PCB.

And, you may want to update a version of your project to a CycloneV and enter the IO pins to see if it compiles...
Also, enter dummy pins for the PSRAM, and add the final IO pins for any other new IOs.  Just add them in the top block diagram & tie them to GND, or leave open if they are dedicated inputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2020, 08:26:05 am
And, you may want to update a version of your project to a CycloneV and enter the IO pins to see if it compiles...

I've tried that already so that I can use the Pin Planner.  It won't compile - something about the async RAMs. Thought I'd worry about that later, but I guess now is as good a time as any...

*loads up Quartus to check*

It doesn't like the RAM primitives - complains about bidir_dual_port using an unsupported value for parameter port_x_read_during_write_mode...

Code: [Select]
Error (14000): WYSIWYG RAM primitive "ram_block1a1" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a1" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a2" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a2" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a3" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a3" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a4" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a4" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a5" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a5" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a6" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a6" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a7" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a7" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a8" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a8" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a9" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a9" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a10" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a10" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a11" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a11" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a12" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a12" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a13" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a13" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a14" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a14" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a15" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a15" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a16" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a16" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a17" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a17" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a18" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a18" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a19" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a19" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a20" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a20" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a21" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a21" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a22" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a22" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a23" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a23" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a24" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a24" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a25" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a25" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a26" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a26" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a27" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a27" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a28" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a28" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a29" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a29" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a30" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a30" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a31" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a31" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a32" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a32" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a33" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a33" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a34" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a34" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a35" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a35" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a36" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a36" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a37" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a37" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a38" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a38" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a39" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a39" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a40" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a40" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a41" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a41" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a42" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a42" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a43" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a43" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a44" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a44" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a45" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a45" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a46" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a46" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a47" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_a_read_during_write_mode"
Error (14000): WYSIWYG RAM primitive "ram_block1a47" in operation mode "bidir_dual_port" uses an unsupported value for parameter "port_b_read_during_write_mode"
Error (12152): Can't elaborate user hierarchy "vid_osd_generator:inst9|sixteen_port_gpu_ram:gpu_RAM|gpu_quad_port_ram:gpu_RAM|gpu_dual_port_ram_INTEL:dual_port|altsyncram:altsyncram_component|altsyncram_hvr2:auto_generated"
Info (144001): Generated suppressed messages file G:/fpga/Projects/GPU/GPU_5CEBA2F17/output_files/GPU.map.smsg
Error: Quartus Prime Analysis & Synthesis was unsuccessful. 97 errors, 86 warnings
Error: Peak virtual memory: 4830 megabytes
Error: Processing ended: Tue Nov 03 08:22:00 2020
Error: Elapsed time: 00:00:28
Error: Total CPU time (on all processors): 00:00:50
Error (293001): Quartus Prime Full Compilation was unsuccessful. 99 errors, 86 warnings


Will reply to the rest of your post shortly, once I've had a look at the project and moved some pins about.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 03, 2020, 10:10:06 am
Patched the ram definition, see the attached .v file.

The change was in these 2 configuration lines, OLD:
Code: [Select]
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",
NEW:
Code: [Select]
altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",

Based on our design, these changes should not affect any functionality.
The change should be backwards compatible, IE safe to use in your CycloneIV code.  You should update your CycloneIV design with the new 2 lines to test.  Let me know if everything runs AOK.

(How I found the bug)
I basically added a new core-memory from the basic functions IP catalog and made an equivalent ram block, 2 read, 2 write dual port ram as identical to our core-Intel ram as possible.  This was the only new spec in the CycloneV ram which could not be selected as 'OLD DATA' after the don't care.  So I modified only those 2 lines in our existing code and it compiled fine with a CycloneV selected FPGA.  The CycloneV core memory doesn't support the 'OLD DATA' read data out during write data into ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2020, 03:24:54 pm
That seems to have cleared up the RAM issue, I'm now getting this bizarre set of errors:


Error (16722): The SEU internal scrubbing feature is only supported for select Cyclone V and Cyclone V SoC devices. Contact your Intel sales representative for information on these devices and access to the SEU internal scrubbing feature.
Error (11802): Can't fit design in device. Modify your design to reduce resources, or choose a larger device. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.


Analysis & Synthesis completes and the Flow Summary shows 24% logic utilisation and 11% of memory bits used, so I suspect the second error to be an error in itself.  The first one, though, is proving troublesome for me to find a solution to.  (Compilation fails on the Fitter (Place & Route) stage).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 03, 2020, 03:49:07 pm
Compiles fine on my system.  Using Prime 18.1 Lite Edition.
Though, I have not defined the IOs, so they are being automatically being randomly distributed...
Which CycloneV have you selected?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2020, 04:04:25 pm
Compiles fine on my system.  Using Prime 18.1 Lite Edition.
Though, I have not defined the IOs, so they are being automatically being randomly distributed...
Which CycloneV have you selected?

5CEBA4F17C8.  I've just switched to the 5CEBA2F17C8 and got the exact same errors.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2020, 05:23:03 pm
Here's my project - not sure what's going on and why I'm getting that error, but it's probably something wrong with the project settings.  Other than changing the device and setting some voltages, I don't think I changed anything else?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 03, 2020, 07:49:43 pm
Latest project update after rotating the FPGA and re-assigning IOs accordingly.  Hopefully I've not introduced any more errors.  The 'diagram' sheet in the spreadsheet shows the physical layout of the IOs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 03:21:08 am
That seems to have cleared up the RAM issue, I'm now getting this bizarre set of errors:


Error (16722): The SEU internal scrubbing feature is only supported for select Cyclone V and Cyclone V SoC devices. Contact your Intel sales representative for information on these devices and access to the SEU internal scrubbing feature.
Error (11802): Can't fit design in device. Modify your design to reduce resources, or choose a larger device. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.


Analysis & Synthesis completes and the Flow Summary shows 24% logic utilisation and 11% of memory bits used, so I suspect the second error to be an error in itself.  The first one, though, is proving troublesome for me to find a solution to.  (Compilation fails on the Fitter (Place & Route) stage).

Just turn off the 'The SEU internal' 'Enable Internal Scrubbing' feature in the 'Device and pin options' / 'Error detection CRC'.

Also, you need to define all the IO.
Also, that 250MHz for larger core ram will be a little difficult to obtain.  We'll need to add code.  Also, unfortunately, that timing is still tight, so I recommend using a -C7 even though you may be mounting a -C8.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 03:42:27 am
Latest project update after rotating the FPGA and re-assigning IOs accordingly.  Hopefully I've not introduced any more errors.  The 'diagram' sheet in the spreadsheet shows the physical layout of the IOs.

DDR pinouts:
Move DDR_D6 off of pin G12.
All the DDR_D# signals need to be on ####,DQ2R pins.
Place DDR_RWDS signal needs to be on a #####,DQS pin.
CS#, RST, can go anywhere.
Obviously, the CK# need to be on the PLL pins.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2020, 10:08:11 am
Just turn off the 'The SEU internal' 'Enable Internal Scrubbing' feature in the 'Device and pin options' / 'Error detection CRC'.

How did I miss that?  That 'Device and pin options' button is too easily missed. ::)  It compiles now. :-+

Also, you need to define all the IO.
Also, that 250MHz for larger core ram will be a little difficult to obtain.  We'll need to add code.  Also, unfortunately, that timing is still tight, so I recommend using a -C7 even though you may be mounting a -C8.

I just wanted to see if it would compile first - will assign all the IO to pins when we're comfortable with the layout, otherwise I'll be updating schematics, spreadsheets and the Quartus project for every pin change I make.

DDR pinouts:
Move DDR_D6 off of pin G12.
All the DDR_D# signals need to be on ####,DQ2R pins.
Place DDR_RWDS signal needs to be on a #####,DQS pin.
CS#, RST, can go anywhere.
Obviously, the CK# need to be on the PLL pins.

All done. :) I'd been focusing on trying to make the routing as simple as possible - well, relatively speaking.  I'm a little anxious about trying to get this all connected up. :o

That said, I'm also aware there I've got spare IOs left over - two in Bank 3B at the bottom edge, 1 in 8A on the top and 13 in 7A on the top edge (ignoring the two in 5B as they're 1.8V and that's dedicated to the DRAMs - I guess, in theory at least, I could add another two DRAMs using those last two IOs as chip selects).

Any ideas what I could use the remaining IO for?  (Bearing in mind I'm likely to have the Cyclone V assembled on the PCB at the factory, rather than do it myself, so I'm hoping I won't need spare IOs 'just in case'.)  Hmm... what about EEPROM, or some other non-volatile memory?  Could use that as a drive, or bootstrap ROM for a soft-core CPU.  It could then almost literally be a standalone system on a PCB (still needs power via the system bus). Hmmm...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 10:54:24 am
Again:
Place DDR_RWDS signal needs to be on a #####,DQS pin.

Also, find out why pin J16 is red.  You may not be able to place pin D4 on it...

Separate VCC_AUX and VCC_FPLL.  The VCC_AUX are digital power and the VCC_FPLL powers the analog PLL circuitry.

Also, the power to pin H14 is wrong.  Shouldn't it be going to VCC_DDR?

VCC_DDR needs another 3 100nf decoupling caps for the FPGA power pins.

Also, place CLKUSR to CLK10p/n on bank 7A.

Move DAC_CLK to a dedicated PLL CLK output pin.  Down 2-3 pins...

Are you sure you do not want to power your 245's with the VCCIO?

Also, why aren't you using SCK for the audio DAC?
You also hardwired the DAC features, are you sure this is what you want?

Next step, paint a grid of vias inbetween all the BGA pins, make 45 degree connections outwards to all pins.   This is unless you have a pre-made 'FAN-OUT' structure which draws out all the IOs on 4 layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2020, 12:35:48 pm
Again:
Place DDR_RWDS signal needs to be on a #####,DQS pin.

Also, find out why pin J16 is red.  You may not be able to place pin D4 on it...

Sorry, missed that.  As for J16, no idea why it's red, other than perhaps it needs configuration in Quartus to set its function as an IO?  It dual-purpose - I/O or a Configuration via Protocol status output.

Separate VCC_AUX and VCC_FPLL.  The VCC_AUX are digital power and the VCC_FPLL powers the analog PLL circuitry.

When you say 'separate', you mean want another linear regulator supply or some other (less traumatic) change? 

Also, the power to pin H14 is wrong.  Shouldn't it be going to VCC_DDR?

Apparently not.  I've checked and double-checked.  According to the Altera docs and pin connection guide, if a bank's VCCIO is below 2.5 volts, its VCCPD should be 2.5V.  So instead of connecting VCCPD5B to VCC_DDR, I've connected it to VCC_FPLL.  It should probably be connected to VCC_AUX instead, actually...

[attach=1]

Also, place CLKUSR to CLK10p/n on bank 7A.

Okay, done that - what's the thinking behind this move though?  CLKUSR was on the dedicated CLKUSR input pin.  I assume there won't be any issues with the 50 MHz clock input going in via the new pin in Bank 7A?

Move DAC_CLK to a dedicated PLL CLK output pin.  Down 2-3 pins...

Done.

Are you sure you do not want to power your 245's with the VCCIO?

Hadn't really thought about it to be honest.  I've got a 3.3V supply on the system bus, I was just making use of it.  I suppose from a power-rail-consolidation point of view, it'd be good to use VCCIO instead.  Or I could use VCCIO to power the two 245's on the right hand side of the board to save routing another 3.3V net across the board...

Also, why aren't you using SCK for the audio DAC?
You also hardwired the DAC features, are you sure this is what you want?

Not using SCK to save IOs (I made that decision before I knew that I'd have nearly a whole bank of free IOs) and to simplify the interface to the PCM5101.  Clearly, IO usage is not a problem now so if you think using SCK would make for an easier HDL interface, I'll add it in.

As for hardwiring the features - that was purely because I didn't think that I'd want to change features, or have room to add in lots of configuration links.

Next step, paint a grid of vias inbetween all the BGA pins, make 45 degree connections outwards to all pins.   This is unless you have a pre-made 'FAN-OUT' structure which draws out all the IOs on 4 layers.

Just normal through vias, yes?  What about the last row on the right and bottom?  I guess I'll get rid of vias around the edges where the first and maybe second rows into the FPGA can be connected on the surface?

[attachimg=2]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 01:23:26 pm
Again:
Place DDR_RWDS signal needs to be on a #####,DQS pin.

Also, find out why pin J16 is red.  You may not be able to place pin D4 on it...

Sorry, missed that.  As for J16, no idea why it's red, other than perhaps it needs configuration in Quartus to set its function as an IO?  It dual-purpose - I/O or a Configuration via Protocol status output.

Separate VCC_AUX and VCC_FPLL.  The VCC_AUX are digital power and the VCC_FPLL powers the analog PLL circuitry.

When you say 'separate', you mean want another linear regulator supply or some other (less traumatic) change? 

No, You have a LC filter on your power supply so the PLLs do not inject a signal backwards, or the digital won't send EMI back into the PLL power input.  Just use the 2 you supplies you already created.  You even labeled the 2 yourself.
Quote

Also, the power to pin H14 is wrong.  Shouldn't it be going to VCC_DDR?

Apparently not.  I've checked and double-checked.  According to the Altera docs and pin connection guide, if a bank's VCCIO is below 2.5 volts, its VCCPD should be 2.5V.  So instead of connecting VCCPD5B to VCC_DDR, I've connected it to VCC_FPLL.  It should probably be connected to VCC_AUX instead, actually...

[attach=1]
Ok.
Quote

Also, place CLKUSR to CLK10p/n on bank 7A.

Okay, done that - what's the thinking behind this move though?  CLKUSR was on the dedicated CLKUSR input pin.  I assume there won't be any issues with the 50 MHz clock input going in via the new pin in Bank 7A?

A CLK# input pin on bank A7...  I think CLKUSR is for a custom bootprom clock speed.
Quote

Move DAC_CLK to a dedicated PLL CLK output pin.  Down 2-3 pins...

Done.

Are you sure you do not want to power your 245's with the VCCIO?

Hadn't really thought about it to be honest.  I've got a 3.3V supply on the system bus, I was just making use of it.  I suppose from a power-rail-consolidation point of view, it'd be good to use VCCIO instead.  Or I could use VCCIO to power the two 245's on the right hand side of the board to save routing another 3.3V net across the board...

Use the VCCIO for all of them.  If the FPGA has no power and you send 3.3v to the 245, they will push voltage into the 'expensive' FPGA IOs.
Quote

Also, why aren't you using SCK for the audio DAC?
You also hardwired the DAC features, are you sure this is what you want?

Not using SCK to save IOs (I made that decision before I knew that I'd have nearly a whole bank of free IOs) and to simplify the interface to the PCM5101.  Clearly, IO usage is not a problem now so if you think using SCK would make for an easier HDL interface, I'll add it in.

As for hardwiring the features - that was purely because I didn't think that I'd want to change features, or have room to add in lots of configuration links.

Use SMD jumpers for the features...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 01:55:32 pm
Ok, for the PCB, take a look at the first image.  Here is what I want you to do.

Taking a look at my second image, this is also a 1mm BGA, except 484pin.  As you can see I started with the 'VIA Grid', then erased the signals I was able to feed out on the top layer alone while erasing the vias which were no longer needed.
Pay attention to the VIA properties.  Use the same & verify that JLPCB can build these with their basic bottom end 4 Layer technology.  I made the power & GND are using .25mm tracks while the signals use 0.101mm tracks.  As you can see, you can fit 2 tracks between pads with .101mm and only 1 with 0.25mm.

Looking at my third image, you can see the clearance constraints I used which should allow those 2- 0.101mm tracks between pads and also I use a larger spacing for the GND fill to ease PCB copper spacing where not needed.  Again verify with JLPCB.

I do not know if the smallest cheap PCB JLPCB tracks & spacing would allow for 3 tracks between pads, but if it does, this could simplify quite a bit.  But stretching for the tightest tolerances isn't always the best solution manufacture-ability or having the most sturdy design...

Note that the decoupling caps are 0402 on the bottom of the PCB.
Also, I do not have as many for the VCCINT as you have.
However, you will need to see your FPGA power layout to decide where to place these caps.
It may just be a decision on which 4 possible directions the VIAS go leaving a channel / room underneath for the 0402 caps to be lined up under the FPGA.  something like a + pattern through the middle and also a box around the outside of those core PWR/GND vias.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2020, 04:55:13 pm
Okay, so my takeaway from your post is to use vias and traces that are almost at the limits of what JLCPCB can do with a 4-layer PCB with a safety margin (I've used 5 mil to connect the BGA pads with the vias, but the vias are minimum size for the PCB manufacturing tech) and start routing the FPGA to the rest of the board.

Two questions - in terms of routing, is it best to start at the centre and work my way out?

Secondly, should I do the same thing with the DRAMs (with vias etc) or should I just route these on the top layer?

Third (bonus) question - I'm starting the routing on the top layer?  Currently the PCB design only has two layers.  I've used the top layer exclusively so far (except where two power traces cross).  I was considering using the top layer to route power and initial 5V signals from the bus headers, and maybe to route signals as far as I can?

I'm thinking this would be an okay PCB stack-up?

TOP:       Power/some signals
LAYER 2: GND
LAYER 3: GND
BOTTOM: Power/some signals

Attached is the base FPGA breakout plan on the PCB.  I've divided it into four quadrants, as per your example, and will start routing out in the next day or two.

In the meantime - is there anything I can do with the remaining IOs in Bank 7A?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 05:21:22 pm
I'm thinking this would be an okay PCB stack-up?
Use my first illustration as it creates that big + shaped void inside the FPGA once you remove the unused vias in the middle.  You can place core 0402 decoupling caps inside the + channel under the FPGA.  Also, once the unused outer vias around the center are removed, you can place more decoupling caps around that border.  You can change all the 100nf and 4.7nf to 100nf.  Your app wont need so much filtering + add a few 10uf 0603/0805 around the FPGA, like 4 of them.

TOP :       signals - maybe odd/single outer edge PCB power trace if needed to jump for 1 of the multiple internal power.
LAYER 2: GND, ALL GND
LAYER 3: Multiple Power, an odd data signal, best avoided.
BOTTOM: signals - maybe odd/single outer edge PCB power trace if needed to jump for 1 of the multiple internal power.

For the ram, you want the same VIA count for every signal going to and from the FPGA to both ram chips.
If this can be done all on the top layer without running rings around the ram, then fine.  I suspect you will need to go from the FPGA to the bottom layer once (or a mid layer), then, to the top layer once between the 2 chips.  The only signal you can get away with poor routing is the reset signal.  You want to keep everything short and equal number of vias between the FPGA and RAM so you will not need to do sophisticated time-delay corrections due to unusual signal paths.  You will be operating the ram at 250MHz max and we are just below the border where adding length corrections to each trace will become necessary.  Having 1 IO only feed 2 IC data IO have kept this short and sweet which will let you get away with this.  Without a good fast logic analyzer or scope on your side, you will be slave to simulation, simulation, simulation, tune PLL output CLK phase and tune PLL read CLK phase, adjusting voltages and temperature, re-tune the PLL CLK phase...

Remember, you still have a lot of pin-swapping to do to straighten out those ram signals.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 05:33:15 pm
In the meantime - is there anything I can do with the remaining IOs in Bank 7A?

You can add a second serial boot-prom, which is basically a gigantic flash ram.
Maybe use it as an onboard Z80 OS, or HD.
Power-up graphics & fonts for the GPU outside the 256kb inside-FPGA GPU ram.
Audio clips/fonts.
At 1-3$, it's kind of worth it.

Maybe, with some 74HC logic (parallel to serial and 8bit ADC to read the old Atari/Comodore style Joysticks), you can add 2-4 joystick ports.
Ok maybe find a USB host IC so you can attach simple HID devices like USB KB, Mouse, Game-pad.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2020, 07:35:51 pm
Remember, you still have a lot of pin-swapping to do to straighten out those ram signals.

Ah, I forgot to upload the latest schematic!

You can add a second serial boot-prom, which is basically a gigantic flash ram.
Maybe use it as an onboard Z80 OS, or HD.
Power-up graphics & fonts for the GPU outside the 256kb inside-FPGA GPU ram.
Audio clips/fonts.
At 1-3$, it's kind of worth it.

Maybe, with some 74HC logic (parallel to serial and 8bit ADC to read the old Atari/Comodore style Joysticks), you can add 2-4 joystick ports.
Ok maybe find a USB host IC so you can attach simple HID devices like USB KB, Mouse, Game-pad.

Well, that's what I was thinking - using a flash RAM or something as a drive of some kind.  I like the USB host IC idea though - a lot.  Any suggestions on what IC to look at for that functionality?

EDIT: MAX3421E (https://www.maximintegrated.com/en/products/interface/controllers-expanders/MAX3421E.html) looks good, if a little expensive.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2020, 08:33:57 pm
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1103100)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2020, 10:33:16 pm
 :palm:  Ah, that's what you meant by separating the FPLL and IO nets...  ;D

(Ignore the MAX3421E on the Peripherals page - I've not finished wiring it up and am not 100% I'll use it yet...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 05, 2020, 03:16:16 am
You cannot short the SDA and SCL of the HDMI & VGA port.  The 2 different EDID proms will interfear with each other.  Since you are only using 640x480, just ignore the VGA port's EDID lines.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 05, 2020, 03:52:52 pm
Your SDA & SCL also seem to go to the Z80 bus.  Careful, the EDID usually is handled through the HDMI transmitter.  And, if your HDMI TFP410 has an I2C port with controls in it, it may be a different SDA & SCL.  Especially if you need to set I2C controls for the TFP410, if should be driven by the FPGA and have no connection to the EDID lines as those are 5v signals and need protection.  If the TPF410 has no I2C controls and the SDA/SCL is intended for the HDMI port, then those need to be wired there exclusively.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 05, 2020, 08:53:42 pm
LOL It's been a while since I looked a this thread. But it turns out I was right that this is not going to be a "get it done and go home" kind of project, but rather perpetual WIP :-DD Too bad you're still choosing crappy Antel FPGA instead of real deals, which is what Xilinx devices are. But you will get there eventually >:D This will save you about 100500 pins and TFP410 because real FPGAs can drive HDMI out directly with no crutches required.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2020, 03:44:27 am
LOL It's been a while since I looked a this thread. But it turns out I was right that this is not going to be a "get it done and go home" kind of project, but rather perpetual WIP :-DD Too bad you're still choosing crappy Antel FPGA instead of real deals, which is what Xilinx devices are. But you will get there eventually >:D This will save you about 100500 pins and TFP410 because real FPGAs can drive HDMI out directly with no crutches required.
At 250MHz HDMI for VGA, so can the Intel.  Every single IO bank on the entry CycloneV has enough LVDS transmitters for HDMI up to 600-800MB/S, or 3-6gb/sec on fewer dedicated channels.  Nockieboy wants both analog VGA and HDMI (so, more pins, not less) and he doesn't want to debug any third party DVI transmitter code.  (Yes, Since Altera was bought by Intel, their devices have stagnated.  Soon, with AMD's purchase of Xilinx, they will slow down as well but remain ahead as Intel flounders.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2020, 11:28:50 am
Making slow progress - must admit, I'm having difficulty routing those DRAMs.  I've only done the basics so far, trying to stick to the top layer, but can't see how I can go further without going down to the bottom layer for crossing signal nets which - if I've understood previous posts correctly - means I have to do the same for ALL of the data lines?

[attach=1]

I've routed the Z80 data bus - that seems to be a success, hopefully.  I'm using 5mil traces at the moment, with 10mil traces for GND and all the VCC### nets.

[attach=2]

0402 caps? Can they even be hand-soldered?! :o  Looks like another opportunity to push the limits of my soldering skills (and I thought 0603 was small!)  :phew:

LOL It's been a while since I looked a this thread. But it turns out I was right that this is not going to be a "get it done and go home" kind of project, but rather perpetual WIP :-DD Too bad you're still choosing crappy Antel FPGA instead of real deals, which is what Xilinx devices are. But you will get there eventually >:D This will save you about 100500 pins and TFP410 because real FPGAs can drive HDMI out directly with no crutches required.

Intel/Altera was the first manufacturer of FPGAs (and the Cyclone range) that I became aware of when I learned of their existence shortly before starting this thread, as Grant Searle used one for his multicomp project.  That was then reinforced by the wealth of help and assistance on offer from BrianHG who clearly has a lot of experience using Cyclones, so I've stuck with them not for any reason other than (now) familiarity and they allow me to make the most of BrianHG's knowledge and support.

There are undoubtedly better FPGAs out there - even in the Intel\Altera lineup - but I'm not precious about squeezing every last feature and drop of power out of the best FPGA I can get my hands on.  I'm just happy with enough RAM for a frame buffer and everything else is a bonus.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 12:21:54 pm
At 250MHz HDMI for VGA, so can the Intel.  Every single IO bank on the entry CycloneV has enough LVDS transmitters for HDMI up to 600-800MB/S, or 3-6gb/sec on fewer dedicated channels.  Nockieboy wants both analog VGA and HDMI (so, more pins, not less) and he doesn't want to debug any third party DVI transmitter code.  (Yes, Since Altera was bought by Intel, their devices have stagnated.  Soon, with AMD's purchase of Xilinx, they will slow down as well but remain ahead as Intel flounders.)
Lol. 7 series can officially do 1250 Mbps on every single diff pair, and almost 1500 Mbps HDMI unofficially (I'm yet to see a device that can't actually do that, but it's beyond datasheet values), it's BRAM are faster, and DSP tiles are over 2 times faster. But it's also about software. What about free DDRx controller from Antel? DMA controller (with or without SG support)? Softcore (NIOS is only free it's most useless configuration, so it doesn't count)? What about other 100+ IPs which are available for free from Xilinx? :palm:
Sorry, but from my experience the only people who use Antel devices are those who never used 7 series. I've never met a designer that used Xilinx FPGA and then voluntarily went back to Antel. Xilinx devices are just better in every single possible way.
And I don't understand your passage about third party DVI transmitter code. Writing your own basic RGB24->HDMI for 7 series takes about 30 minutes from scratch, so there is no point in using someone else's code (unless you really want to).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 12:27:14 pm
Making slow progress - must admit, I'm having difficulty routing those DRAMs. 
Hyperbus clock line is a differential pair and must be routed as such. On your picture it looks like it's routed as two independent traces.
Also a bunch of long parallel traces so close to each other is crosstalk magnet. Try spreading them around.
Do you do your layout in KiCAD? If so, do you have your project published anywhere? I can take a look and help if necessary/desired. I love routing. It's my favorite part of the design process.

0402 caps? Can they even be hand-soldered?! :o  Looks like another opportunity to push the limits of my soldering skills (and I thought 0603 was small!)  :phew:
Don't worry, if you've got proper equipment (microscope), you can manually solder even 0201. I've done quite a bit of them, though I prefer reflowing.

Intel/Altera was the first manufacturer of FPGAs (and the Cyclone range) that I became aware of when I learned of their existence shortly before starting this thread, as Grant Searle used one for his multicomp project.  That was then reinforced by the wealth of help and assistance on offer from BrianHG who clearly has a lot of experience using Cyclones, so I've stuck with them not for any reason other than (now) familiarity and they allow me to make the most of BrianHG's knowledge and support.
That is consistent with the point I made above. The only people who choose Antel voluntarily are those who never used Xilinx 7 series. Once you do, you will never want to go back.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2020, 12:31:15 pm
Ok, some hints about the ram.  Since the ram has 5 columns across and you cannot squeeze more than 2 traces between pads and you need at least 4, you need to approach this differently.

Step 1, remove the traces you have.
Step 2, make the ram like the FPGA with a via-grid, removing the power pins vias and NCs.
Step 3, on the bottom layer, parallel the left side of the 2 rams.
Step 4, on the power layer, parallel the right side of the rams.
Step 5, (vias replaced for FPGA which you now have routed on the top of the PCB), route the left side of the rams to the FPGA through the bottom layer.
Step 6, Route the right side of the rams to the FPGA on the power layer.

Now, I know that only 1 trace can only fit between vias, this is why you need to use 2 signal layers.  Always use a via from FPGA to new layer, then new layer to ram chip so that each ram IO signal always goes through 2 vias from FPGA to each RAM IC pin.

Step 7, on top layer, wire the ram power and decoupling caps and associated VIAS which will be outside that small island of signal traces you had to make on the power layer.  Look at the FPGA as it also has 2 power pins shared with the ram.  Make sure you can route a thick trace for this, thick meaning 50-150mil.

I hope this helps.

EDIT: Yes, the differential clock trace pair needs to be parallel and equal length to maximize signal quality and integrity throughout the system.  These 2 signals may also be wired exclusively on the top layer if you like as well as the reset and RDWS signal.  This will help clear up the middle layers as there are only 9 traces left.  Everything else may now fit on the bottom layer.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2020, 01:37:29 pm
And I don't understand your passage about third party DVI transmitter code. Writing your own basic RGB24->HDMI for 7 series takes about 30 minutes from scratch, so there is no point in using someone else's code (unless you really want to).
Yes, me, if I had a board here and I built it, no problem.  I know how to work on these things.  Nockieboy has an analog 25MHz scope and a single computer monitor and FPGA code is a brand new type of development for him as he learned some bottom end basics through this project as it has now rocketed to a point he never imagined that not only he now has a blitter, but it can combine any mirror/flip/rotate 90 & 45 degrees while up-sampling and down-sampling the image with programmable transparency stencils, pixel collision counter and testers all with a geometry shape engine with support and smart testing & memory write protection for pixel areas off screen.  (Well, he still need to add the last shape, filled ellipse)

I did push awhile back for home-made DVI transmitter, but Nockieboy felt at better ease using the TFP410.
Look way back on this thread and I found a public domain HDMI transmitter with audio support written in Verilog for both Intel and Xilinx.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 01:51:49 pm
The way I like to do routing is as follows:
1. Fanout the chips into a bunch of parallel tracks close to the chip going in the general direction of the target.
2. Bring both bunches of tracks close to each other.
3. Utilize pin swapping to get those bunches to match each other and connect them together, starting from clock and DQS lines if present (as these are the most critical). If for some reason that is not fully possible - for example, there are some hardwired pins involved which can't be swapped around, you can typically see how do you need to change a fanout on one or both sides to get tracks to align.
4. Spread parallel tracks around a bit and do the length matching if required.

Clock (and DQS if present) lines usually needs to be the longest lines in a match group, so leave plenty of space for them. You can tighten up layout later if desired.

Now, I know that only 1 trace can only fit between vias, this is why you need to use 2 signal layers.  Always use a via from FPGA to new layer, then new layer to ram chip so that each ram IO signal always goes through 2 vias from FPGA to each RAM IC pin.
Isn't it 1mm pitch BGA? If so, and you guys plan to use JLCPCB to manufacture boards, you can easily fit two tracks between vias in a 1 mm grid. Use 0.2/0.45 via and 0.1 mm tracks/spacing, or - better yet - 0.09 mm tracks/spacing and center two tracks closer to the middle of the channel between vias, this way you will make manufacturing easier as even if drill misses a bit, there will be enough clearance between via and tracks to not cause any problems.

EDIT: Yes, the differential clock trace pair needs to be parallel and equal length to maximize signal quality and integrity throughout the system.  These 2 signals may also be wired exclusively on the top layer if you like as well as the reset and RDWS signal.  This will help clear up the middle layers as there are only 9 traces left.  Everything else may now fit on the bottom layer.
You will also need to calculate proper line dimensions (and gap size for diff. pairs) if you care about signal integrity. And at 200 MHz DDR, you probably should. Again, if you plan to use JLCPCB, they've got a calculator on their website. I recommend using their JLC2313 stackup as it's much better for high-speed designs (prepreg is thinner and so 50 Ohm impedance lines can be narrower).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 01:57:53 pm
Yes, me, if I had a board here and I built it, no problem.  I know how to work on these things.  Nockieboy has an analog 25MHz scope and a single computer monitor and FPGA code is a brand new type of development for him as he learned some bottom end basics through this project as it has now rocketed to a point he never imagined that not only he now has a blitter, but it can combine any mirror/flip/rotate 90 & 45 degrees while up-sampling and down-sampling the image with programmable transparency stencils, pixel collision counter and testers all with a geometry shape engine with support and smart testing & memory write protection for pixel areas off screen.  (Well, he still need to add the last shape, filled ellipse)
You will probably be surprised to hear that, but I've developed my very first DVI TX module that output 720p without any scope. And even now I only have a 200 MHz scope, which is utterly useless for debugging HDMI (1450 Mhz for data lines at FullHD). And that also was back in time when my experience with FPGAs was very rudimental. Now, I did have a formal training for HDLs back at university (about 15 years ago), so that helped in a sense that I was familiar with the design process, but I never had any formal training using FPGAs (we used ASIC tools back at UNI).

I did push awhile back for home-made DVI transmitter, but Nockieboy felt at better ease using the TFP410.
Look way back on this thread and I found a public domain HDMI transmitter with audio support written in Verilog for both Intel and Xilinx.
Do you happend to have a link? I would be curious to see the one for Antel devices.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2020, 03:30:04 pm
I did push awhile back for home-made DVI transmitter, but Nockieboy felt at better ease using the TFP410.
Look way back on this thread and I found a public domain HDMI transmitter with audio support written in Verilog for both Intel and Xilinx.
Do you happend to have a link? I would be curious to see the one for Antel devices.

Here are the only links I remember:
https://www.realdigital.org/doc/189f72e0ee822643d7946fb639754841 (https://www.realdigital.org/doc/189f72e0ee822643d7946fb639754841)
https://github.com/charcole/NeoGeoHDMI (https://github.com/charcole/NeoGeoHDMI)  Altera true 480P with embedded audio.
https://github.com/hamsternz/FPGA_DisplayPort (https://github.com/hamsternz/FPGA_DisplayPort)
https://github.com/hamsternz/DisplayPort_Verilog (https://github.com/hamsternz/DisplayPort_Verilog)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 05:16:26 pm
https://github.com/charcole/NeoGeoHDMI (https://github.com/charcole/NeoGeoHDMI)  Altera true 480P with embedded audio.
This is the only implementation for Antel, and it's using diagrams :palm: so I can't really see it. I do wonder though what "true" part means, 480p is the lowest resolution supported by HDMI without pixel repeats (as 25 MHz is the minimum allowed HDMI clock). Sounds kind of cheesy to me if I'm being honest ::) Are there any HDL-only implementations for Antels?
As for others, like I said, minimal DVI TX implementation is very trivial for Xilinx 7 series because it's got SERDES which support 10:1 DDR serialization mode, and its output buffers support TMDS IO standard directly, so there is no need for any voltage translation or other analog tricks and you can connect FPGA pins directly to HDMI connector, while it looks like Cyclone V does not support that (at least I was not able to find any mention of TMDS in CV datasheet), so you will need to use additional circuitry to implement HDMI connector. You can take a look at schematic of the board from my signature and you will see just how trivial it is to physically implement the port using 7 series.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2020, 05:38:20 pm
Do you do your layout in KiCAD? If so, do you have your project published anywhere? I can take a look and help if necessary/desired. I love routing. It's my favorite part of the design process.

No, I'm using EasyEDA (https://easyeda.com) which is - as best I can tell - very similar to KiCAD, but all online (though there is a desktop version as well).  Thanks for the offer of help, let me know if you feel you can get to grips with EasyEDA and I'll give you access to the project :) - but I'm not giving up just yet.  :-/O

0402 caps? Can they even be hand-soldered?! :o  Looks like another opportunity to push the limits of my soldering skills (and I thought 0603 was small!)  :phew:
Don't worry, if you've got proper equipment (microscope), you can manually solder even 0201. I've done quite a bit of them, though I prefer reflowing.

I don't have a microscope - I'm using a loupe where necessary, but that's about it.  What sort of microscope do you use?

That is consistent with the point I made above. The only people who choose Antel voluntarily are those who never used Xilinx 7 series. Once you do, you will never want to go back.

Okay, so I've just had a very quick look at the Spartan 7 series - am I reading it right in that it has about 520KB of RAM in it, not included distributed RAM?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2020, 06:28:48 pm
I did push awhile back for home-made DVI transmitter, but Nockieboy felt at better ease using the TFP410.
Look way back on this thread and I found a public domain HDMI transmitter with audio support written in Verilog for both Intel and Xilinx.
Do you happend to have a link? I would be curious to see the one for Antel devices.

Here are the only links I remember:
https://www.realdigital.org/doc/189f72e0ee822643d7946fb639754841 (https://www.realdigital.org/doc/189f72e0ee822643d7946fb639754841)
https://github.com/charcole/NeoGeoHDMI (https://github.com/charcole/NeoGeoHDMI)  Altera true 480P with embedded audio.
https://github.com/hamsternz/FPGA_DisplayPort (https://github.com/hamsternz/FPGA_DisplayPort)
https://github.com/hamsternz/DisplayPort_Verilog (https://github.com/hamsternz/DisplayPort_Verilog)

Just a note - the NeoGeoHDMI project was shown running from the smallest Cyclone II FPGA in the video.  Hardly the most recent of Antel products.

In fact, BrianHG, I have next to no recollection of having a conversation with you about direct HDMI or using a TFP410.  That's not to say it didn't happen, of course - I do have a memory like a sieve - but I'm wondering now if it wouldn't be a bad idea.  I've no reason to keep the VGA output if I can get HDMI up and running - doing so would save lots of IOs and routing headaches for me at the bottom of the PCB...  ;)

EDIT: Of course, when I say HDMI I mean DVI-D.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 06:39:14 pm
No, I'm using EasyEDA (https://easyeda.com) which is - as best I can tell - very similar to KiCAD, but all online (though there is a desktop version as well).  Thanks for the offer of help, let me know if you feel you can get to grips with EasyEDA and I'll give you access to the project :) - but I'm not giving up just yet.  :-/O
I think so as it supports length tuning as well. At the very least I'm hoping to provide some constructive feedback.

I don't have a microscope - I'm using a loupe where necessary, but that's about it.  What sort of microscope do you use?
I use relatively cheap x10/x20 stereo microscope (mostly in x10 mode for soldering) - AmScope SE410, it was about US$170 (+ delivery charge) at the time of purchase. If you browse ebay/aliexpress, you can find a ton of options if pretty much the same basic design as mine with all kinds of combinations of objectives, eyepieces and other accessories. One thing I would say from my experience - if I was to buy a brand new one today knowing what I know now, I would buy a version with double arm boom, as it allows more freedom in movement. But it would cost more than a single arm one that I use, so for occasional use single arm is just fine. Also now that I have the microscope, I use it in x20 mode to look at all kinds of fun and interesting things - from my own skin to biological samples (my wife is a biologist, so that makes it extra fun :D )

Okay, so I've just had a very quick look at the Spartan 7 series - am I reading it right in that it has about 520KB of RAM in it, not included distributed RAM?
That sounds about right for the S100 device, but keep in mind that BRAMs in 7 series are natively 72 bits wide (can be split into two independent 36 bits wide parts), so depending on whether your design actually uses these additional 8 or 4 bits for something (ECC or some other data like flags or whatever), you might end up having less actually available (because remember each BRAM is all-or-nothing, you either use it fully or you don't). That said, since these BRAMs are very fast (depending on the mode of operation and speed grade, it can go from low 400's well past 500 MHz) and can be configured as hardware FIFOs, they are often used as cache or scratch memory, while resorting to external memory for longer term storage. Since even the slowest speed grade supports DDR2/DDR3 memory running at least at 333 MHz (DDR3 can work at 400 MHz for most devices), you can have massive memory bandwidth and very high capacity ( a single MT41K256M16TW-107:P memory chip cost just US$5 and provides 512 MBytes of storage with 16 bit data bus). And since memory controller IP is provided free of charge, you can see that vast majority of 7 series boards have DDR2/3 memory onboard. The only downside is that x16 memory takes up a whole IO bank (50 pins), but if you use Artix in 1mm pitch 256 pin package, you will have 170 IO pins, so losing 50 of them for memory is not a big deal. Also, since 400 MHz is relatively slow for DDR3 (and tracks are typically very short), it's not super sensitive to proper layout and impedance matching. Again, if you care to look at the project in my signature, you will see that DDR2 there works just fine at 333 MHz (package limit) despite me taking several shortcuts in layout and having no termination for address and control lines (except for the clock signal, which is too important to skimp on).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 06:49:16 pm
In fact, BrianHG, I have next to no recollection of having a conversation with you about direct HDMI or using a TFP410.  That's not to say it didn't happen, of course - I do have a memory like a sieve - but I'm wondering now if it wouldn't be a bad idea.  I've no reason to keep the VGA output if I can get HDMI up and running - doing so would save lots of IOs and routing headaches for me at the bottom of the PCB...  ;)

EDIT: Of course, when I say HDMI I mean DVI-D.  ;)
If SERDESes in CV support 10:1 DDR mode, then implementing it will be a breeze as essentially it's nothing more than a very simple encoder connected directly to SERDES (x3 for R, G and B channels), with encoder accepting parallel color data, a video enable flag, and a pair of sync signals (hsync/vsync) for one of the color channels (I think it's a blue one). And of course you will need PLL to create pixel and symbol clocks from your system clock, and finally some sort of FIFO to transfer data from your system clock domain into symbol clock one.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 06, 2020, 07:12:16 pm

Okay, so I've just had a very quick look at the Spartan 7 series - am I reading it right in that it has about 520KB of RAM in it, not included distributed RAM?
That sounds about right for the S100 device, but keep in mind that BRAMs in 7 series are natively 72 bits wide (can be split into two independent 36 bits wide parts), so depending on whether your design actually uses these additional 8 or 4 bits for something (ECC or some other data like flags or whatever), you might end up having less actually available (because remember each BRAM is all-or-nothing, you either use it fully or you don't). That said, since these BRAMs are very fast (depending on the mode of operation and speed grade, it can go from low 400's well past 500 MHz) and can be configured as hardware FIFOs.
The current design operates based on using 1 gigantic chunk or simple dual-port ram divided down into 15 25MHz ports, 1 125MHz port.  Width is not a problem as a write-mask channel exists.  Only minor changes to the current pixel writer where you may want to change the current 16 bit width to 32 improving performance there.  You might be able to upgrade the current 125 MHz core system with 250MHz ram to 200MHz while running the ram at 400MHz.
You could also then widen the external PSRAM unless you want to go to a true DDR 32bit ram setup and run the core ram at 64 bits.  You do not need to stretch too much more here in speed, even if you want texture filled polygons as with this setup, you could fill above ~150 million 32 bit pixels a second compared to our current ~100 million 16 bit pixels a second.  (Read/modify/write for each pixel)  (Yes, better is possible, but a lot of code changes will need to be done and a lot of legacy graphics functions/modes used for small CPUs like Z80s would get pushed out of the way.)

Note that 1 smaller dual port 400MHz 1KB ram would still be need for the palette.
There is no other ram in the system except for a 512 word x16bit FIFO which can be worked around if nessary.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 06, 2020, 07:27:02 pm
No, I'm using EasyEDA (https://easyeda.com) which is - as best I can tell - very similar to KiCAD, but all online (though there is a desktop version as well).  Thanks for the offer of help, let me know if you feel you can get to grips with EasyEDA and I'll give you access to the project :) - but I'm not giving up just yet.  :-/O
I think so as it supports length tuning as well. At the very least I'm hoping to provide some constructive feedback.

Oh, I'm all for constructive feedback - let me know when/if you create an account with EasyEDA and I'll give you access to the project.  Or try to, anyway - I tried with BrianHG but I think he had to clone a copy of the project in the end.

I use relatively cheap x10/x20 stereo microscope (mostly in x10 mode for soldering) - AmScope SE410, it was about US$170 (+ delivery charge) at the time of purchase. If you browse ebay/aliexpress, you can find a ton of options if pretty much the same basic design as mine with all kinds of combinations of objectives, eyepieces and other accessories.

Will keep my eyes open for a decent one then, thanks. :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 08:10:22 pm
You could also then widen the external PSRAM unless you want to go to a true DDR 32bit ram setup and run the core ram at 64 bits.  You do not need to stretch too much more here in speed, even if you want texture filled polygons as with this setup, you could fill above ~150 million 32 bit pixels a second compared to our current ~100 million 16 bit pixels a second.  (Read/modify/write for each pixel)  (Yes, better is possible, but a lot of code changes will need to be done and a lot of legacy graphics functions/modes used for small CPUs like Z80s would get pushed out of the way.)
Since DDR3 has 8n-prefetch architecture, DDR3 controllers typically runs at 1:2 or 1:4 memory clock rate. Xilinx memory controller can be configured to run at either, but 1:4 mode lines up nicely with 8n prefetch such that each system clock cycle gives you (or writes out) entire 8x data burst (4 memory clocks * 2 xfers per clock). So for x16 physical data bus and 400 MHz memory clock rate you get 16*8=128 bits at 100 MHz, or 64 bits at 200 MHz for 1:2 mode. The total theoretical bandwidth of x16@400MHz DDR3 interface is 400M*2(DDR)*16(data bus)=12800 Mbit/s, so unless you think you will need higher BW, you can get away with x16 physical interface. Also - up to 256Mx16 interface fits entirely into a single IO bank, and you will only need a single x16 memory device, so you can get away without termination for address/data lines. This makes layout much more simple and forgiving as your tracks will be very short. If you want to use more than one memory device in the interface, you will have to do a fly-by routing of address/control lines, and I have my doubts that you will be able to get away without termination at the end of these lines (though we can do some simulations to see if it's possible/feasible).

Note that 1 smaller dual port 400MHz 1KB ram would still be need for the palette.
BRAMs in 7 series are 36 Kbits each (dividable into 2 independent block of 18 Kbits each), but of course you can configure each of two ports as 32K x 1, 16K x 2, 8K x 4, 4K x 9, 2K x 18, 1K x 36, or 512 x 72 for 36 Kbits blocks, or 16K x 1, 8K x2 , 4K x 4, 2K x 9, 1K x 18 or 512 x 36 for 18 Kbits blocks.

There is no other ram in the system except for a 512 word x16bit FIFO which can be worked around if nessary.
You can use BRAM for that as they have necessary hardware to be configured as FIFO.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 06, 2020, 08:19:20 pm
Oh, I'm all for constructive feedback - let me know when/if you create an account with EasyEDA and I'll give you access to the project.  Or try to, anyway - I tried with BrianHG but I think he had to clone a copy of the project in the end.
Thanks. I've seen your PM and will take a look at it once I get home. Will let you know if it worked out or not.

Will keep my eyes open for a decent one then, thanks. :)
Before I accidentally run into a video on YT showing it, I was under impression that these microscopes cost a fortune and were far out of reach for a common folks like me (who don't have few millions burning holes in the pocket), so I was really surprised to see that there are now affordable options out there. Granted, ~US$200 is not exactly cheap, but my typical 6 layer board runs not that far away from this amount once postage, taxes and dues are all included, so to me it was definitely money well spent. Now I assemble boards for my commercial customers with it, so it paid for itself many times over since purchase.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 07, 2020, 12:56:25 am
You could also then widen the external PSRAM unless you want to go to a true DDR 32bit ram setup and run the core ram at 64 bits.  You do not need to stretch too much more here in speed, even if you want texture filled polygons as with this setup, you could fill above ~150 million 32 bit pixels a second compared to our current ~100 million 16 bit pixels a second.  (Read/modify/write for each pixel)  (Yes, better is possible, but a lot of code changes will need to be done and a lot of legacy graphics functions/modes used for small CPUs like Z80s would get pushed out of the way.)
Since DDR3 has 8n-prefetch architecture, DDR3 controllers typically runs at 1:2 or 1:4 memory clock rate. Xilinx memory controller can ....

Just so we are clear, that 100 million pixels a second combines a read and write for each 16 bit pixel (ie 100 million random pixel read/write a second, 50 million 16bit blits a second, ~double for 8 bit or less), plus 15x simultaneous 16 bit display pixels per pixel (ie 375 million pixel reads a second) to construct a display.  In the current system, using the PSRAM, 1-2 of those 15x 16 bit displays (the other 13-14 are still available using on FPGA ram) + ~1/3 speed for the pixel writer + 8 voice stereo audio with pitch&amplitude modulation is the ball-park target.  (SD-CARD read write bursts and 32bit ALU math-co shares the pixel writer's port)  A single DDR3 can do triple that with a comfort zone other than some blits when using rotate will break page boundaries when writing every single pixel unless the writes are done to onboard FPGA ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 07, 2020, 01:42:29 am
A single DDR3 can do triple that with a comfort zone other than some blits when using rotate will break page boundaries when writing every single pixel unless the writes are done to onboard FPGA ram.
To help resolving the straddling pages issue, Xilinx memory controller allows remapping user addresses from default "bank-row-column" to "row-bank-column" order, in the latter case you will be straddling banks as opposed to rows, and since different banks can have different pages open at the same time, you won't end up having to constantly open and close adjacent rows, and instead will be working with two banks in parallel.
Another way to resolve this issue is to implement a cache for 2 pages used in a circular fashion. Initially you load in first page to the cache #1 and write your changes to the cache instead of DDR. As you get close to the end of the page in your processing, you asynchronously load in the second page into cache #2. At some point you will move far enough into the second page to not need the first page anymore so now you can asynchronously commit entire first page from cache #1 into DDR. As you get close the end of the second page, you bring in third page into cache #1. This process then repeats endlessly. You can also expand it to more pages if required. Each page in x16 DDR3 device is 2KB = 16 Kbits long, which fits nicely into one half of BRAM (18 Kbits one). You will only need to have some way of knowing when entire page is completed and can be safely written out to DDR, as well as enough of a head's up to when you will need the next page so that you can read it in before it will actually be required and as such completely hide memory access latency from you main process. Also since you will be reading/writing entire pages, this will also lead to better memory bandwidth utilization, as it was designed exactly for this kind of usage scenario (desktop CPUs access entire cache lines at a time as well).
Also since DDR3 has large capacity, you can do double or even triple buffering to avoid race conditions between your renderer and the output process that outputs the frame to a screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2020, 12:14:12 pm
I didn't think I was too bad at routing until I started on these DRAMs.  Have been staring at the layout for too long - it's time to ask for help, I think.

Latest attempt at wiring the DRAMs is attached. |O  Aside from being a complete mess already, I also need to add in two vias for each signal that is currently only on one layer so that the via count for those signals matches the ones that already have two vias?

Looks like I'm going to have to route the chip selects on a third layer to get to the top of the DRAMs.  It's funny how all those IOs on the FPGA look like they'd make routing easy, but once you start looking at the detail, you realise that actually you're really restricted in which IO you can use for which job.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2020, 12:30:02 pm
Arrrggggg..  Ok, if 'asmi' doesn't help you out there, I'll make time toward the end of the week to route the ram for you.  For now, try your best with everything else and just leave room for the ram and don't touch the power or GND plane for now.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 08, 2020, 03:55:30 pm
I'm trying to get to the grips with the tool. It looks like differential pairs need to have suffixes _P/_N in order for PCB editor to recognize them as such. Can you please rename all differential pairs so that they would have these suffixes at the end, and push this change into the board? I don't feel confident enough with the tool to do it myself yet.
Also - are you targeting JLCPCB's JLC2313 stackup? This is important to determine the trace geometry for differential pairs as well as for data lines (50 Ohm single-ended/100 Ohm differential).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2020, 04:49:46 pm
Arrrggggg..  Ok, if 'asmi' doesn't help you out there, I'll make time toward the end of the week to route the ram for you.  For now, try your best with everything else and just leave room for the ram and don't touch the power or GND plane for now.

Thanks.  :-[

Regarding the video output - I'm interested in the idea of driving HDMI directly from the FPGA, if it means I don't need to worry about a TFP410 and can drop the VGA connector (I'll drop it anyway in v.2 once I'm confident the DVI-D will work) - it means I'll have room for the USB connection.  The whole video output area of the board looks to be a complete routing nightmare at the moment and my confidence is a little shaken by my attempts at the DRAM.  ???

I'm trying to get to the grips with the tool. It looks like differential pairs need to have suffixes _P/_N in order for PCB editor to recognize them as such. Can you please rename all differential pairs so that they would have these suffixes at the end, and push this change into the board? I don't feel confident enough with the tool to do it myself yet.
Also - are you targeting JLCPCB's JLC2313 stackup? This is important to determine the trace geometry for differential pairs as well as for data lines (50 Ohm single-ended/100 Ohm differential).

Thanks asmi. :-+  Differential pairs can have _P/_N or +/-, so I've changed CKP and CKN to CK+ and CK- for brevity.  That was a mistake I made naming those nets - I meant for them to be compatible with the tool, just forgot to add the underscore.  ???  Have just tried the differential pair routing tool and it's working (although it's trying to do odd things when connecting to the first DRAM - there is guidance here (https://docs.easyeda.com/en/PCB/Route/index.html) about how to use the tool).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2020, 04:51:35 pm
Also - are you targeting JLCPCB's JLC2313 stackup? This is important to determine the trace geometry for differential pairs as well as for data lines (50 Ohm single-ended/100 Ohm differential).

Probably not as I was unaware of it.  I'll go take a look at it and see how it compares with the stackup BrianHG has specified and that I'm (trying) to work to.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 08, 2020, 10:59:12 pm
Probably not as I was unaware of it.  I'll go take a look at it and see how it compares with the stackup BrianHG has specified and that I'm (trying) to work to.
If you are planning to use JLCPCB for manufacturing, this is the best stackup to use for high speed designs as it allows using narrower tracks to reach 50 Ohm impedance. That is because the prepreg is thinner in that stackup.
This EDA is a serious test of my patience :( I don't know if it's my PC or what, but it's sooooo freaking laggy - sometimes I have to wait up to 10 seconds for my command to register! |O
I did connect both memory modules, now will need to connect them to the FPGA. What kind of pin swapping is allowed? I assume all data pins can be swapped around, but what about others? My work file is saved right next to original, since I don't want to screw up others' work.
Also I slightly adjusted positions of these memory chips to align them to a grid, as this makes routing easier. In the future I recommend always aligning parts to a grid.
Finally - how are you planning to assemble these boards? If using hot air gun, I suspect that memory chips are too close to FPGA. But maybe I'm wrong - it's been a while since I soldered BGAs with hot air gun.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 09, 2020, 12:58:10 am
Forgot to mention - just in case you guys don't know - Cypress has published HDL simulation models for their HyperRAM chips - this should help you in developing controller for them.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2020, 02:41:09 am
I did connect both memory modules, now will need to connect them to the FPGA. What kind of pin swapping is allowed? I assume all data pins can be swapped around, but what about others? My work file is saved right next to original, since I don't want to screw up others' work.
Just read a few posts up.  I write down exactly what pins you are allowed to swap and where within the IO bank.
Only the dedicated '###CLKOUTn/p####' output pins should drive the CLKn/p. (polarity don't care/swappable)
And all the data[7..0] should go to a ####,DQ## pins.
And the RDWS pin should go to a #####,DQS## pin.  (could be on a DQ pin as well since we are not using the DQS to time/clock/capture early half-clock reads like with DDR3 ram.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2020, 08:55:19 am
If you are planning to use JLCPCB for manufacturing, this is the best stackup to use for high speed designs as it allows using narrower tracks to reach 50 Ohm impedance. That is because the prepreg is thinner in that stackup.

Makes sense.  I really feel out of my depth with all this talk of impedence matching, prepreg thickness, return paths and loops etc.  I'm really out on a limb here as this is by far the most complicated and advanced PCB I've ever designed - have been looking for information online so that I can read up on this stuff.

This EDA is a serious test of my patience :( I don't know if it's my PC or what, but it's sooooo freaking laggy - sometimes I have to wait up to 10 seconds for my command to register! |O

I had exactly the same problem when I viewed your changes.  I think part of the issue was having a selection filter on - when I turned it off, the response time improved dramatically.  I guess it doesn't help that it's an online tool and runs mostly in your browser, so it's not going to be as sharp and snappy as a dedicated desktop program.  The desktop version they provide for download is basically the EasyEDA web software running in a container as far as I can tell, so may not provide much performance improvement.  My original PCB design file seems to work a lot faster, though - maybe use that instead.

I did connect both memory modules, now will need to connect them to the FPGA. What kind of pin swapping is allowed? I assume all data pins can be swapped around, but what about others? My work file is saved right next to original, since I don't want to screw up others' work.

Thanks asmi - I've copy-pasted your work into the original PCB which seems to run a lot faster than the work copy for some reason.  Feel free to work on the original rather than the copy - I'm not going near the DRAMs until you tell me it's safe to do so, and being online software designed with collaboration in mind, it shouldn't cause any issues.  I'm backing up the project regularly, just in case.  :-+

Finally - how are you planning to assemble these boards? If using hot air gun, I suspect that memory chips are too close to FPGA. But maybe I'm wrong - it's been a while since I soldered BGAs with hot air gun.

Believe it or not, this thought had crossed my mind too.  I think at the moment I'm going to get the FPGA SMT-assembled by JLCPCB when the PCB is manufactured.  LCSC don't stock the DRAMs we're using when I last checked, so I'll have to source them from elsewhere and hot-air solder them.  What's a safe distance to mount them at?  Or will I have to use some sort of heat shield to protect the FPGA whilst heating up the DRAMs?  Though I guess that won't help with the PCB heating up and stressing the BGA solder connections on the FPGA.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2020, 07:07:42 pm

Believe it or not, this thought had crossed my mind too.  I think at the moment I'm going to get the FPGA SMT-assembled by JLCPCB when the PCB is manufactured.  LCSC don't stock the DRAMs we're using when I last checked, so I'll have to source them from elsewhere and hot-air solder them.  What's a safe distance to mount them at?  Or will I have to use some sort of heat shield to protect the FPGA whilst heating up the DRAMs?  Though I guess that won't help with the PCB heating up and stressing the BGA solder connections on the FPGA.  ???

I medium nozzle and plenty of flux like the Louis Rossman videos I've attached should allow you to solder the BGA Ram easily even if it is close to the FPGA.  The ram, 5x5 ball, 1mm pitch with liquid flux will melt and center truly instantly compared to an adjacent dry FPGA 16x16 balls, 10 times the area.  The absolute worst is that a few balls on the FPGA right next to the ram may temporarily almost go liquid, but, you will not damage anything here or be able to dis-lodge the FPGA from it's secure mounting.  It you are really afraid, a small strip of kapton tape on the PCB going over the FPGA preventing the hot air and liquid flux from going under the FPGA will prevent enough heat from getting under the FPGA to melt any of it's balls.


Slowly warming the PCB on a hot plate will help with mechanical stresses, but I don't think this will become too much of a problem as melting a 5x5 ball IC will be close to a few seconds.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2020, 07:35:14 pm
Slowly warming the PCB on a hot plate will help with mechanical stresses, but I don't think this will become too much of a problem as melting a 5x5 ball IC will be close to a few seconds.

Good point, hadn't thought of that - it shouldn't take long to solder at all and, like you say, I can always use some Kapton tape for peace of mind. :-+

Whilst I was checking LCSC for the DRAMs earlier, I noticed that Winbond do a version of the HyperRAM chips (https://www.mouser.co.uk/datasheet/2/949/W956x8MBYA_64Mb_HyperBus_pSRAM_TFBGA24_datasheet_A-1760356.pdf) that seems to be identical to the Cypress Semiconductor part (https://www.cypress.com/file/498611/download) we'd selected previously.  As far as I can tell, there's no material difference between the two chips other than the Winbond one being 60% the price of the Cypress Semi chip.  Would that be a suitable alternative?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 09, 2020, 08:04:00 pm
Just make absolutely sure you choose the exact part number for 1.8v, 200MHz...

Hmm $4.12 at multiple vendors with stock VS $2.75 where only Mouser has stock.
https://www.findchips.com/search/W956D8 (https://www.findchips.com/search/W956D8)
At least they are compatible & I believe there is also 1 more manufacturer of HyperBus ram.

You can also change to 1 ram chip and use this part number:
https://www.mouser.com/ProductDetail/Winbond/W957D8MFYA5I?qs=YwPsRIUVAOfDQ6YTWk12AA%3D%3D (https://www.mouser.com/ProductDetail/Winbond/W957D8MFYA5I?qs=YwPsRIUVAOfDQ6YTWk12AA%3D%3D)
It's basically 2 hyper-ram in 1 chip package & @ $4.04, you are saving...

Scrap that, I don't think you can interleave within a single 128mb ram chip.  (Unless you place 2 of them for 32mb.)
Safer to use 2 chip and interleave commanding the 2 to maximize hyperbus activity and throughput.

Though, I guess you can just increase the burst size & use data write without initial latency & stick with 1 16mb ram chip.  Much easier to route.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 09, 2020, 10:23:19 pm
Just make absolutely sure you choose the exact part number for 1.8v, 200MHz...

Absolutely - the W956D8MBYA5I is the one I'd use; 1.8V and 200MHz interface.

Hmm $4.12 at multiple vendors with stock VS $2.75 where only Mouser has stock.
https://www.findchips.com/search/W956D8 (https://www.findchips.com/search/W956D8)
At least they are compatible & I believe there is also 1 more manufacturer of HyperBus ram.

ISSI is the third manufacturer of HyperRam, but they're as expensive as Cyprus chips and only go up to 166MHz.

You can also change to 1 ram chip and use this part number:
https://www.mouser.com/ProductDetail/Winbond/W957D8MFYA5I?qs=YwPsRIUVAOfDQ6YTWk12AA%3D%3D (https://www.mouser.com/ProductDetail/Winbond/W957D8MFYA5I?qs=YwPsRIUVAOfDQ6YTWk12AA%3D%3D)
It's basically 2 hyper-ram in 1 chip package & @ $4.04, you are saving...

Scrap that, I don't think you can interleave within a single 128mb ram chip.  (Unless you place 2 of them for 32mb.)
Safer to use 2 chip and interleave commanding the 2 to maximize hyperbus activity and throughput.

Though, I guess you can just increase the burst size & use data write without initial latency & stick with 1 16mb ram chip.  Much easier to route.

I'd like to pretend that I understand all that, but I don't. :o  Having one DRAM chip would reduce cost marginally, but the biggest benefit would be easier routing and soldering.  Whether those benefits are offset by worse performance due to lack of interleaving or increased burst size making the controller more complicated, I just don't know enough to determine and will have to be guided by your judgement on that one. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 01:56:58 am
128Mbit chips are dual-die, they only support fixed double latency (no variable one-two latency like 64Mbit).
Also I don't think you can extract more performance from HyperRAM by interleaving as they already allow very long bursts, which will amortize initial access latency. The only reason to put multiple chips on a single data bus is to increase memory capacity. And in this case it will make more sense to just use 128Mbit device, as it makes all those connects internally and there is no need to route anything.
If you do want higher bandwidth, you will need to wire these chips in parallel to two separate data buses. In this case, you will probably want to work with fixed 2 latency mode, as it will allow you to run memory chips in lockstep. You will need to make sure these two data buses are not substantially different in length, otherwise you might have timing issues, especially if you don't use RDWS signal as read clock (a-la DQS), which is how it's meant to be used.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 06:01:58 am
I had exactly the same problem when I viewed your changes.  I think part of the issue was having a selection filter on - when I turned it off, the response time improved dramatically.  I guess it doesn't help that it's an online tool and runs mostly in your browser, so it's not going to be as sharp and snappy as a dedicated desktop program.  The desktop version they provide for download is basically the EasyEDA web software running in a container as far as I can tell, so may not provide much performance improvement.
I decided to try desktop client, and it seemed a bit more reasonable as far as performance goes. As for selection filter - this is a tool that I use extensively in all eCADs as it makes me much more productive. Same goes for using colored nets - it makes routing easier as you clearly see which tracks need to go where.

Anyway, I've completed memory connections to the FPGA. I did some pin swapping, so please verify that this pinout will work. I tried to leave space for decoupling caps, but in my experience 0402 don't fit between 1 mm via grid, so you either will need to use 0201 (that is basically the only reason I use them), or get creative with placement to remove some vias and make room for decoupling caps. Once you complete placement, we will probably need to do a pass and match tracks length to minimize potential for timing issues. Since we're talking about 200 MHz DDR, bit time is 2.5 ns so even 10% tolerance is 250 ps, which is about 40 mm for outside tracks (signal speed is ~16.3 cm/ns). So we won't have to be very precise here, but still it's better to be conservative.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2020, 09:59:06 am
I tried to leave space for decoupling caps, but in my experience 0402 don't fit between 1 mm via grid, so you either will need to use 0201

This was the reason for the + channel and some space around the edges once you remove or change vias to adjacent unused ones.  Though, you will end up with fewer VCCint caps compared to what's in the schematic right under the FPGA, there should be a problem with this FPGA being the smallest one, or second one in the series.  After everything is done, I would still add 2-4 ceramic 10uf caps just outside the FPGA with 3-5 vias per pad to the GND & power plane to stiffen up the supply.

Interleaving 2 ram chips, meaning issue CMD for #1, then imediate CMD for #2, the reading or writing data from #1, then #2 means there is a empty command gap between each ram's previous and next command giving time for a blind refresh around read commands.  (need to double check this when running the ram at 200MHz...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 10, 2020, 02:01:03 pm
Anyway, I've completed memory connections to the FPGA. I did some pin swapping, so please verify that this pinout will work.

Thanks asmi. :-+  Not sure about DDR_D0, though?  It's the only data line not connected to a DQ2R pin (I'm assuming DDR_D5 is fine connected to a DQS2R pin?)

After everything is done, I would still add 2-4 ceramic 10uf caps just outside the FPGA with 3-5 vias per pad to the GND & power plane to stiffen up the supply.

I'll add four 10uF caps into the schematic then.  :-+

What about decoupling for the DRAMs?  1x100nF cap for each VCC_DDR pin?  I've added another 100nF cap into the schematic on the decoupling page as there's two VCC_DDR pins on the FPGA, looked like I was one cap down previously.  Do I need a larger cap for each DRAM as well?

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2020, 03:13:30 pm
Please move the VCCDDR on the top layer to the green layer.
You have space if you move the blue track horizontally and down a bit.
This also give you room to place the GND pad via next to the ram.

Move the RST to the bottom layer.

Now, you can place 1 decoupling cap above and 1 decoupling cap below each ram chip (top layer) going straight to the power pins with >25mil tracks.
You can also now place 1 decoupling caps on the left and right sides of each ram as well.

For the FPGA VCCDDR, you can place a 45 degree angle 0402 caps right under the FPGA between the VCCDDR and GND vias while the second one you have space to place it horizontally.  That's 8 caps at least, or preferably 10 decoupling caps for the VCCDDR.  I would also add a 10uf ceramic between the FPGA and ram.  (Another cap you don't have in your schematic.)

Everything else is perfect.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 04:00:13 pm
Thanks asmi. :-+  Not sure about DDR_D0, though?  It's the only data line not connected to a DQ2R pin (I'm assuming DDR_D5 is fine connected to a DQS2R pin?)
I have no experience with CV, which is why I'm asking you guys to verify if that pinout would work or not.

What about decoupling for the DRAMs?  1x100nF cap for each VCC_DDR pin?  I've added another 100nF cap into the schematic on the decoupling page as there's two VCC_DDR pins on the FPGA, looked like I was one cap down previously.  Do I need a larger cap for each DRAM as well?
0.1 uF 0402 is my go-to decoupling cap, unless chip vendor tells something else.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 04:05:06 pm
Please move the VCCDDR on the top layer to the green layer.
You have space if you move the blue track horizontally and down a bit.
This also give you room to place the GND pad via next to the ram.
NO! Signal traces need an unbroken reference plane. This is high-speed design 101. Create a planelet on the power layer which would connect everything, and would also cover entire area under/above data traces. For high speed designs forget that power traces even exist. Because they suck as their inductance will kill whatever good regulation that comes out of DC-DC converter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2020, 04:41:01 pm
Please move the VCCDDR on the top layer to the green layer.
You have space if you move the blue track horizontally and down a bit.
This also give you room to place the GND pad via next to the ram.
NO! Signal traces need an unbroken reference plane. This is high-speed design 101. Create a planelet on the power layer which would connect everything, and would also cover entire area under/above data traces. For high speed designs forget that power traces even exist. Because they suck as their inductance will kill whatever good regulation that comes out of DC-DC converter.
I think you miss-read, did not ask you to break or even severely extend the blue tracks in any way.  Perhaps you just aren't seeing the cleaner path.

As for the VCCDDR, unless you have direct access to the VCCDDR on the top layer, it is already broken onto the green layer.  What I asked was to make an un-broken direct path to the RAM's VCC/GND pins to a decoupling cap on the top layer as an option and to get rid of the unusual loop you created which is worse than the dedicated power plane.  I thought you were going to do a rectangular flood fill for the VCCDDR when you were done encompassing the ram and the corner of the FPGA to gain that power-plane to GND plane capacitance and low impedance.  Note that what you see there is the only 1.8v components in the entire design.

As for any other power supply filtering, the PSP should be filtered at it's source (since we may not have control over it's distance to this logic section) while the logic/memory should also be filtered to a point where it appears to be a low frequency modulating (we cant help this) DC load.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 05:10:34 pm
As for the VCCDDR, unless you have direct access to the VCCDDR on the top layer, it is already broken onto the green layer.  What I asked was to make an un-broken direct path to the RAM's VCC/GND pins to a decoupling cap on the top layer as an option and to get rid of the unusual loop you created which is worse than the dedicated power plane.  I thought you were going to do a rectangular flood fill for the VCCDDR when you were done encompassing the ram and the corner of the FPGA to gain that power-plane to GND plane capacitance and low impedance.  Note that what you see there is the only 1.8v components in the entire design.
That wasn't me. I didn't touch VCCDDR net at all, aside from dropping few vias for it so that I can route around them.
Like I said above, the way to go is to create a solid planelet covering entire area where DDR traces go, as they need a reference plane in order to have 50 Ohm impedance (otherwise it's going to be much more than that). Same goes for another plane - it needs to be solid at least above/over entirely of DDR traces.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2020, 05:37:38 pm
As for the VCCDDR, unless you have direct access to the VCCDDR on the top layer, it is already broken onto the green layer.  What I asked was to make an un-broken direct path to the RAM's VCC/GND pins to a decoupling cap on the top layer as an option and to get rid of the unusual loop you created which is worse than the dedicated power plane.  I thought you were going to do a rectangular flood fill for the VCCDDR when you were done encompassing the ram and the corner of the FPGA to gain that power-plane to GND plane capacitance and low impedance.  Note that what you see there is the only 1.8v components in the entire design.
That wasn't me. I didn't touch VCCDDR net at all, aside from dropping few vias for it so that I can route around them.
Like I said above, the way to go is to create a solid planelet covering entire area where DDR traces go, as they need a reference plane in order to have 50 Ohm impedance (otherwise it's going to be much more than that). Same goes for another plane - it needs to be solid at least above/over entirely of DDR traces.

Which is exactly what I was asking you to do....
I think we are just arguing about an incomplete photo where that VCCDDR net stood out as a mistake.

This is along the lines of what I was asking... Please excuse the paint software limitations.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 05:45:19 pm
Which is exactly what I was asking you to do....
I think we are just arguing about an incomplete photo where that VCCDDR net stood out as a mistake.
Yea probably.

This is along the lines of what I was asking... Please excuse the paint software limitations.
I left enough space for 0402 decoupling caps to be placed on the bottom right next to those pairs of Vcc/Gnd vias. See attached picture - light blue are pads for the caps on the bottom side (of course this is a Paint.NET art, real part footprints need to be placed there). These are spots for 4 caps, if you need more, you can move data traces a bit to create space for two more, or place those two on the top side of a board (and drop vias to the planes right next to them).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 10, 2020, 05:59:50 pm
Ok, that's fine except for the bottom red VCCDDR going from 1 ram chip to the other  around for quite a distance for that single VCC pin.
That one is a NO-NO...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 10, 2020, 06:13:29 pm
Ok, that's fine except for the bottom red VCCDDR going from 1 ram chip to the other  around for quite a distance for that single VCC pin.
That one is a NO-NO...
Yea. But that's what we are here for - to catch those typical novice's mistakes. I wasn't sure if you guys wanted more than 2 decoupling caps per device, which is why I only left space for two. But there is enough space on the bottom side to spread around DDR data traces to create enough room for two more decoupling caps and power vias. Hopefully I will have some time this evening to add these in.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 10, 2020, 11:29:50 pm
Please move the VCCDDR on the top layer to the green layer.
You have space if you move the blue track horizontally and down a bit.
This also give you room to place the GND pad via next to the ram.

Move the RST to the bottom layer.

Now, you can place 1 decoupling cap above and 1 decoupling cap below each ram chip (top layer) going straight to the power pins with >25mil tracks.
You can also now place 1 decoupling caps on the left and right sides of each ram as well.

Have done the best I can, not sure I fully understood what you meant by moving the blue track horizontally and down a bit, but here's the latest:

[attach=1]

For the FPGA VCCDDR, you can place a 45 degree angle 0402 caps right under the FPGA between the VCCDDR and GND vias while the second one you have space to place it horizontally.  That's 8 caps at least, or preferably 10 decoupling caps for the VCCDDR.  I would also add a 10uf ceramic between the FPGA and ram.  (Another cap you don't have in your schematic.)

Everything else is perfect.

Yes, asmi has done a good job there (thanks asmi!!!) ;D Have yet to do this decoupling, aside from the top and bottom caps which you'll see in the previous closeup of the DRAMs.

I've also moved the AS and JTAG programming headers, seeing as I had some room between the three parts of the Z80 address buses to put the headers there and simplify routing.  That leaves me with some useful space at the top of the PCB - perhaps might have room for a USB connector and host chip.

Can we discuss the DVI-D output?  If I can get away with driving the HDMI connector directly from the FPGA, I'm all for doing that as it'll save me the headache of routing that rat's nest and I could do away with the TFP410.  Would appreciate thoughts on the idea, as it seems to be a worthwhile goal to strive for.  Even the HDL (https://www.fpga4fun.com/HDMI.html) doesn't seem too hard for me to get my head around - in its basic form, at least.

Latest PCB design attached.  Note that I haven't reconnected VCCIO across the top from the reset button to the PCM5101 as I'm likely to be moving or getting rid of the reset button altogether.

EDIT: Ignore most of the above re: decoupling - I hadn't received notifications of new posts and wasn't aware of all that conversation since the post I was replying to here.  I'll take a closer look at the images and sort out the decoupling tomorrow (and the extra VCC_DDR trace down the bottom that needs removing).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 09:00:10 am
The VCC and GND on high speed ICs should not have any length to the power plane if possible.
There should be a via as close as possible to each power pin going down to the power plane. Same for the decoupling caps right at those vias below the IC's power pins.

If you are using 0402 100nf caps, do it the right way under the ram and under the FPGA by the 2 adjacent power vias.

When I said an optional 10uf cap between FPGA and ram, this cap was an optional addition which should be by itself with the 3 vias on each side like you have going to the power planes, however, it should not be connected to any IC pins in this section.  Also, 1 additional 10uf cap could also be placed to the right of the second ram chip as well with the same no direct connect rule.

For high speed low voltage ICs, these rules should be kept.  Everywhere else, you are operating at such low frequency and such low current using regular 3.3v 74HC cmos, you do not need to be as strict, but once a rule is learned, keep on using it.

Also remember the FPGA VCCint 1.1v is also considered high frequency, high current, so, same decoupling caps rules apply.

Each matched length short trace between every power pin and via to a direct power plane ensures minimal inductive ring to each power pin and power plane as well as prevent some power pins receiving a differently tuned inductive ring on their power supply wreaking havoc within the IC's die and IOs.  Remember, many of the power pins also do merge at different points on the IC's DIE and if each one has a different frequency EMI noise, this adds current loops within the IC as well as generating such reflections on the IO and gates themselves.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 11:09:35 am
DRAM update - have made changes based on previous feedback and included all the decoupling caps now.  It is especially tight for the VCC_DDR decoupling under the FPGA itself - would certainly appreciate a thumbs-up or thumbs-down on the current position of those two caps, though I'm not sure how/where else I can mount them.

Full PCB image included for context.
[attach=1]

Closeup of DRAMs, showing decoupling cap placement and how I've moved the signal traces to accommodate them.  C128 and C129 are 0603 10uF.  I might take them up to 0805 just to give me some easy soldering to do... I know I'm pushing my limits when 0603 parts look huge.  :o
[attach=2]

Another DRAM closeup, this time showing bottom traces more clearly.
[attach=3]

I've removed the VCC_DDR power traces altogether and replaced them with a power plane on the PWR layer.  I can't upload the image for some reason.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 11:49:40 am
That looks a lot better.

Can I see the schematic.  The DDR_CS# seem excessively roundabout.
The only signal I don't care timing critical for is the DDR_reset.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 11:58:42 am
Sure, here's the schematic.  I haven't touched the DDR pin assignments, but did raise a question regarding DDR_D0 a few posts back as it's connected to a non-DQ pin since asmi routed the DRAMs.  DDR_D5 is on a DQS pin too - not sure that'll make a difference?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 12:12:53 pm
Now that you know what the ram will look like, here is an example of tightening up the tracks on the bottom.
Not mandatory...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 12:23:12 pm
Sure, here's the schematic.  I haven't touched the DDR pin assignments, but did raise a question regarding DDR_D0 a few posts back as it's connected to a non-DQ pin since asmi routed the DRAMs.  DDR_D5 is on a DQS pin too - not sure that'll make a difference?

Errors...

DDR_D0 needs to be on DQ2R pin and preferably DDR_D5 as well.
DDR1_CSn & DDR2_CSn may be moved to pins F12, G12, E15, or H13  to free up 2 x DQ2R for D0 & D5.
DDR1_CSn & DDR2_CSn may also be routed on the top layer.

DDR_RWDS G13 and H13 may also be swapped.

DQ2R IO have a dedicated DFF input clock/clock enable wiring in the FPGA fabric from the DQS pins to the DQ2R input flipflops.  This allows the RAM to send a return clock it's data outputs on that DQ strobe matching the rise and fall times of the RAM's output drive.  Though, not mandatory to be used, to achieve the maximum ram clock frequencies and guarantee reading data without errors, especially above 200 MHz way into the GHz, this is the proper way to wire up DDR ram to the FPGA.  Think of the DQS pins when writing data, they become a dedicated clock/data enable output, when reading data, the switch into a dedicated clock/enable input hard wired direct to all the adjacent DQ pins so the ram chips will be sending the data clock back with the valid data.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 12:36:37 pm
Here's the trace tightening tweaks and (hopefully) the power plane image.

Errors...

DDR_D0 needs to be on DQ2R pin and preferably DDR_D5 as well.
DDR1_CSn & DDR2_CSn may be moved to pins F12, G12, E15, or H13  to free up 2 x DQ2R for D0 & D5.
DDR1_CSn & DDR2_CSn may also be routed on the top layer.

DDR_RWDS G13 and H13 may also be swapped.

No problem, will have a go at those later this afternoon.  Got one of those infamous Teams meetings coming up.  ::)  :blah:  :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 12:38:04 pm
Now that you know what the ram will look like, here is an example of tightening up the tracks on the bottom.
Not mandatory...
I did a loose layout on purpose to allow space for future length matching once we place and route everything else that needs to be in that part of a board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 12:42:30 pm
Can I see the schematic.  The DDR_CS# seem excessively roundabout.
I would swap around DDR1_CSN and DDR2_CSN. You should be able to fit the latter between DDR1_CSN via and DDR_D2 trace. This should better balance the layout.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 12:44:07 pm
Here's the trace tightening tweaks and (hopefully) the power plane image.

Errors...

DDR_D0 needs to be on DQ2R pin and preferably DDR_D5 as well.
DDR1_CSn & DDR2_CSn may be moved to pins F12, G12, E15, or H13  to free up 2 x DQ2R for D0 & D5.
DDR1_CSn & DDR2_CSn may also be routed on the top layer.

DDR_RWDS G13 and H13 may also be swapped.

No problem, will have a go at those later this afternoon.  Got one of those infamous Teams meetings coming up.  ::)  :blah:  :popcorn:

Arrrg, I hate fake polygon power planes.. You will need to shrink the clearance constraint for that layer so you get some copper filled meat around those adjacent vias...  Editing the outer diameter on all vias not connected on the power plane layers is a hassle, but this is usually done automatically on power planes in Protel/Altium which radically improves the power planes.  Don't worry, this PCB isn't at a level where you need to bother with this is a 10mil clearance will fill the power planes around those un-connected vias, though using the feature would double-triple the filled copper between the via drills when the unconnected via pad isn't there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 12:54:46 pm
Arrrg, I hate fake polygon power planes.. You will need to shrink the clearance constraint for that layer so you get some copper filled meat around those adjacent vias...  Editing the outer diameter on all vias not connected on the power plane layers is a hassle, but this is usually done automatically on power planes in Protel/Altium which radically improves the power planes.  Don't worry, this PCB isn't at a level where you need to bother with this is a 10mil clearance will fill the power planes around those un-connected vias, though using the feature would double-triple the filled copper between the via drills when the unconnected via pad isn't there.

I've just reduced the clearance for the VCC_DDR area on the power plane, no issues.  Set it to 6mil, but having reviewed JLCPCB's capabilities (https://jlcpcb.com/capabilities/Capabilities), I'm not convinced it's valid as I can't find an 'area to via' minimum clearance specified.  :-//

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 01:01:58 pm
Does that fill under the FPGA reach all the VCCDDR pins?
You can make the green more rectangle and cover all the IO pins under the FPGA as well.
Including making it a bit wider on the right of the ram to the regulator...

As for 6mil.  For a mid layer power-plane, 6mil is tight especially with so many vias all over the PCB, all that tight area.  Even if JLPCB can do 6mil trace/via clearance, for PCB manufacturing, when it comes to polygon fills, I like to at minimum add 2 mil, if not 4 mil to this figure allowing for some breathing room.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 01:11:53 pm
Does that fill under the FPGA reach all the VCCDDR pins?

It does, especially since I tightened the clearance, but it looks like I'll be widening that back to 10mil again after what you've said.  I had used a couple of traces to ensure the VCC_DDR pins were connected to the fill, despite the via clearances creating islands.

As for 6mil.  For a mid layer power-plane, 6mil is tight especially with so many vias all over the PCB, all that tight area.  Even if JLPCB can do 6mil trace/via clearance, for PCB manufacturing, when it comes to polygon fills, I like to at minimum add 2 mil, if not 4 mil to this figure allowing for some breathing room.

Okay, so too tight then.  Will return it to 10mil.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 01:25:37 pm
As for 6mil.  For a mid layer power-plane, 6mil is tight especially with so many vias all over the PCB, all that tight area.  Even if JLPCB can do 6mil trace/via clearance, for PCB manufacturing, when it comes to polygon fills, I like to at minimum add 2 mil, if not 4 mil to this figure allowing for some breathing room.
I've been doing 0.15 mm for a while for JLCPCB and they never had a problem with that. For WellPCB, which is more advanced fab that I use for 6 layer boards (as JLCPCB's 6 layer stackup sucks for high-speed designs), I've been using 0.1 mm clearance, and again had no problems whatsoever.
BTW - JLCPCB can do down to 3.5/3.5 mil trace/spacing. 6 mil traces is a stone age tech at this point.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 01:30:10 pm
As for 6mil.  For a mid layer power-plane, 6mil is tight especially with so many vias all over the PCB, all that tight area.  Even if JLPCB can do 6mil trace/via clearance, for PCB manufacturing, when it comes to polygon fills, I like to at minimum add 2 mil, if not 4 mil to this figure allowing for some breathing room.
I've been doing 0.15 mm for a while for JLCPCB and they never had a problem with that. For WellPCB, which is more advanced fab that I use for 6 layer boards (as JLCPCB's 6 layer stackup sucks for high-speed designs), I've been using 0.1 mm clearance, and again had to problems whatsoever.
BTW - JLCPCB can do down to 3.5/3.5 mil trace/spacing. 6 mil traces is a stone age tech at this point.

0.15mm makes life much easier as the fill will fully encircle any vias - saves me having to worry about adding 'floating' traces to connect isolated islands up to the main fill area.   :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 01:31:03 pm
Does that fill under the FPGA reach all the VCCDDR pins?

It does, especially since I tightened the clearance, but it looks like I'll be widening that back to 10mil again after what you've said.  I had used a couple of traces to ensure the VCC_DDR pins were connected to the fill, despite the via clearances creating islands.

As for 6mil.  For a mid layer power-plane, 6mil is tight especially with so many vias all over the PCB, all that tight area.  Even if JLPCB can do 6mil trace/via clearance, for PCB manufacturing, when it comes to polygon fills, I like to at minimum add 2 mil, if not 4 mil to this figure allowing for some breathing room.

Okay, so too tight then.  Will return it to 10mil.
No copper/meat between vias, go back to 6mil...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 01:34:55 pm
As for 6mil.  For a mid layer power-plane, 6mil is tight especially with so many vias all over the PCB, all that tight area.  Even if JLPCB can do 6mil trace/via clearance, for PCB manufacturing, when it comes to polygon fills, I like to at minimum add 2 mil, if not 4 mil to this figure allowing for some breathing room.
I've been doing 0.15 mm for a while for JLCPCB and they never had a problem with that. For WellPCB, which is more advanced fab that I use for 6 layer boards (as JLCPCB's 6 layer stackup sucks for high-speed designs), I've been using 0.1 mm clearance, and again had to problems whatsoever.
BTW - JLCPCB can do down to 3.5/3.5 mil trace/spacing. 6 mil traces is a stone age tech at this point.
You haven't been using 2oz copper in the mid layers, JLPCB cant do 3.5 clearance on a mid layer with 2oz copper.
OK, so a number of my PCBs have power & RF power on them & I do use thicker copper for lower impedance power & it's heat dissipation advantages.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 01:49:22 pm
You haven't been using 2oz copper in the mid layers, JLPCB cant do 3.5 clearance on a mid layer with 2oz copper.
But this one isn't 2oz copper. Or is it?
OK, so a number of my PCBs have power & RF power on them & I do use thicker copper for lower impedance power & it's heat dissipation advantages.
I never had to use anything more than 1oz copper in any of my designs as I've been always trying to design the most efficient PDS I can, this has a nice side effect of lowering heat dissipation. That said, I had to use heatsinks for FPGAs as some of those dissipate too much power to safely sink it all into PCB.

Also - thicker copper does not lower plane impedance due to skin effect. Which is why most high-speed designs use 1/2 Oz power planes as this allows for finer geometry. It does affect current carrying ability, but unless we're talking about really high-end FPGA or CPU which consume 30+ Amps of current, typical power planelet is usually more than enough.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 01:57:36 pm

Also - thicker copper does not lower plane impedance due to skin effect.
The skin effect is at the high/RF frequency range component of your load, not the low the frequency & DC load component...

Yes, 1/2oz if fine for this project.

And 1oz for me has proven useful and on those layers, the 3.5mil is too tight to get good best possible yield over thousands of PCBs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 02:37:29 pm
Yes, 1/2oz if fine for this project.

And 1oz for me has proven useful and on those layers, the 3.5mil is too tight to get good best possible yield over thousands of PCBs.

I'm using 1oz copper for this PCB - it's all I've ever used, to be honest.  I'm also hoping that the yield is sufficient for 5 PCBs, not so worried about thousands as I won't be mass-producing this design, I'm sure!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 02:54:27 pm
The skin effect is at the high/RF frequency range component of your load, not the low the frequency & DC load component...
Exactly, reducing impedance at high frequency is the most important goal because decoupling caps are not very effective at these frequencies due to their own ESL and inductance of traces and vias. At lower frequencies decoupling caps work just fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 03:24:40 pm
Yes, 1/2oz if fine for this project.

And 1oz for me has proven useful and on those layers, the 3.5mil is too tight to get good best possible yield over thousands of PCBs.

I'm using 1oz copper for this PCB - it's all I've ever used, to be honest.  I'm also hoping that the yield is sufficient for 5 PCBs, not so worried about thousands as I won't be mass-producing this design, I'm sure!  ;D
At low quantity, JLPCB does a flying probe test to ensure all your PCBs are perfectly fine.  Don't confuse my work where I'm shaving only a dollar or so for some large expensive PCBs which must also endure in the field where they regularly cycle between freezing and boiling temperatures on a regular basis.  The recommendations I make don't really apply to this PCB, but can still be considered cautious practice when such fine clearances of 3.5mil everywhere arent needed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on November 11, 2020, 03:30:59 pm
Reading the last 2-3 pages made me think ... have you thought if it wouldn't it be easier or cheaper to just put a sodimm ddr1 slot on the board? They're maybe a couple of dollars is small quantities and there's lots of 512MB - 1 GB sodimm sticks on eBay.
Only issue I see is sticks being 64 bit wide, but maybe you could wire only the bottom 24-32  bits and use a part of the sticks somehow?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 04:00:27 pm
Okay, I've swapped the IOs around for DDR_D0, DDR_D5, DDR#_CSn and DDR_RWDS to preferential, or in the case of the data lines - required - IOs on the FPGA.

Routing for the chip selects is a little roundabout - would appreciate thoughts on whether it's appropriate.  If it's not, though, then I'm lost as to how we're supposed to get DRAMs connected up to the FPGA.

The other issue is the highlighted green line in the image.  This is my preferred - and at the moment, only - method of routing the signal to its required IO pin.  Can I get away with passing a 5mil trace through an 0402 component?

If not, this whole DRAM is going to require more of a routing re-think on my behalf.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 04:20:38 pm
Okay, I've swapped the IOs around for DDR_D0, DDR_D5, DDR#_CSn and DDR_RWDS to preferential, or in the case of the data lines - required - IOs on the FPGA.

Routing for the chip selects is a little roundabout - would appreciate thoughts on whether it's appropriate.  If it's not, though, then I'm lost as to how we're supposed to get DRAMs connected up to the FPGA.

The other issue is the highlighted green line in the image.  This is my preferred - and at the moment, only - method of routing the signal to its required IO pin.  Can I get away with passing a 5mil trace through an 0402 component?

If not, this whole DRAM is going to require more of a routing re-think on my behalf.

I need to see the net labels.  However, the strategy I would use is cut all the blue traces off of the FPGA just to it's edge.  Only concern yourself with choosing the best D0..D7 signals.  Then route the RDWS and reset on the top layer if necessary or possible noting that you cannot touch the CLKn&p line.

Maybe a hires .pdf of the pcb will help.

I don't know about the spacing on the PCB, but, I might have personally rotated the rams 90 degrees just to make those clock lines look perfect straight.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 05:21:14 pm
Reading the last 2-3 pages made me think ... have you thought if it wouldn't it be easier or cheaper to just put a sodimm ddr1 slot on the board? They're maybe a couple of dollars is small quantities and there's lots of 512MB - 1 GB sodimm sticks on eBay.
Only issue I see is sticks being 64 bit wide, but maybe you could wire only the bottom 24-32  bits and use a part of the sticks somehow?
They are having hard time routing 13 tracks to the memory, and you're offering them to instead route 60+? That doesn't sounds like a sensible solution to me. If anything, I'd rather place a single x16 DDR3(L) module. It would give a ton of bandwidth with just about 50 pins, and would be easier to route than full SODIMM interface. But routing entire interface on a 4 layer board is not easy. Take a look at the project in my signature, there is 16bit DDR2 module routed on a 4 layer PCB, but the only reason I was able to do it was because the package pinout was designed very well for that kind of layout. On larger packages I wouldn't even think of doing this on a 4 layer PCB and would go straight to 6 layer one.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 05:23:40 pm
I don't know about the spacing on the PCB, but, I might have personally rotated the rams 90 degrees just to make those clock lines look perfect straight.
Clock lines needs to be the longest in a group, which is why I left a ton of space around it's path for future length matching.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 05:36:53 pm
Reading the last 2-3 pages made me think ... have you thought if it wouldn't it be easier or cheaper to just put a sodimm ddr1 slot on the board? They're maybe a couple of dollars is small quantities and there's lots of 512MB - 1 GB sodimm sticks on eBay.
Only issue I see is sticks being 64 bit wide, but maybe you could wire only the bottom 24-32  bits and use a part of the sticks somehow?
Nockieboy went for the cheap 17$ 256pin fpga, not a nice 484 pin one with enough IO for real ram + that Z80 interface & full external 24bit dac.  If so, I would have recommended 1 single 16bit wide DDR2/3 chip @ ~1$ with a guaranteed 500mtps, if not 600mtps running 3-4x circles in speed around this 13 wire hyperbus solution.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 05:40:33 pm
I don't know about the spacing on the PCB, but, I might have personally rotated the rams 90 degrees just to make those clock lines look perfect straight.
Clock lines needs to be the longest in a group, which is why I left a ton of space around it's path for future length matching.
When using the dedicated PLL outputs in my Cyclone designs, I've been setting the PLL to shift/delay it's output by ~ +/-0.2ns increments and calculating trace length.
If used, read DQS is a little more touchy.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 06:00:04 pm
Nockieboy went for the cheap 17$ 256pin fpga, not a nice 484 pin one with enough IO for real ram + that Z80 interface & full external 24bit dac.  If so, I would have recommended 1 single 16bit wide DDR2/3 chip @ ~1$ with a guaranteed 500mtps, if not 600mtps running 3-4x circles in speed around this 13 wire hyperbus solution.

Yup, I'm victim to my own lack of skill, knowledge and confidence - not just with FPGAs, but electronics in general.  There's no way I could justify blowing over $50 on an FBGA484 package when I've never soldered a BGA before.  QFP-144s gave me a headache, so forgive me if I'm a little reticent to jump into self-assembling a 6-layer PCB with a BGA484 FPGA.  Those kind of production costs don't sit well with what I'm doing being described as a 'hobby', either.  I'd need to start selling products to keep the boss happy.  ;)

I'm still not sure whether I should try soldering the FBGA-256 package myself, or get JLCPCB to do it.  It'd probably work out a lot cheaper if I did it myself, but a lot riskier in terms of success...

Have routed the DRAMs to the FPGA now, but I'm sure there's going to be some feedback on some of those route lengths.  I blame whoever designed the IO pin locations on the FPGA package - they clearly weren't concerned about how we're supposed to connect stuff up to them.

Reading the last 2-3 pages made me think ... have you thought if it wouldn't it be easier or cheaper to just put a sodimm ddr1 slot on the board? They're maybe a couple of dollars is small quantities and there's lots of 512MB - 1 GB sodimm sticks on eBay.
Only issue I see is sticks being 64 bit wide, but maybe you could wire only the bottom 24-32  bits and use a part of the sticks somehow?

I came across an old DDR2 stick of RAM on a shelf when I was clearing it out the other day and the thought did occur to me as well.  Then I matched the stick up to the uCOM's PCBs and it won't fit - the PCB is too small to fit the stick, let alone the connector/receptacle it fits into.  I scrubbed the idea at that point, without even getting to any of the other considerations that BrianHG and asmi have already raised.  Otherwise was a good suggestion.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 08:27:10 pm
Just in case anybody is curious, here is what layout for 16bit DDR2 module on a 4 layer PCB looks like.
And with that, let's go back to the task at hand :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 11, 2020, 09:46:20 pm
Nockieboy went for the cheap 17$ 256pin fpga, not a nice 484 pin one with enough IO for real ram + that Z80 interface & full external 24bit dac.  If so, I would have recommended 1 single 16bit wide DDR2/3 chip @ ~1$ with a guaranteed 500mtps, if not 600mtps running 3-4x circles in speed around this 13 wire hyperbus solution.

Yup, I'm victim to my own lack of skill, knowledge and confidence - not just with FPGAs, but electronics in general.  There's no way I could justify blowing over $50 on an FBGA484 package when I've never soldered a BGA before.  QFP-144s gave me a headache, so forgive me if I'm a little reticent to jump into self-assembling a 6-layer PCB with a BGA484 FPGA.  Those kind of production costs don't sit well with what I'm doing being described as a 'hobby', either.  I'd need to start selling products to keep the boss happy.  ;)
Your doing fine as this is your second PCB.  Back in 1983, my first PCB was done with a sharpie marker, a hobby drill bit with hand drill and it had only a few transistors on it...

To use a DDR2 chip like this one @2$: https://www.digikey.com/en/products/detail/winbond-electronics/W9751G8NB-25/11656260 (https://www.digikey.com/en/products/detail/winbond-electronics/W9751G8NB-25/11656260) (And we can guarantee 250MHz/500mtps support as that ram chip can go up to 800mtps & by every metric, the access on this ram chip will run circles around the HyperRam.)

To access all 64 megabytes, you would need another 19 outputs that what you are currently using.

You can only do this if you get rid of the analog VGA dac and run the TFP410 in 12bit DDR mode.  This means you free up 12 IOs immediately and you already have another >8 free to complete the DDR2 ram chip interface.  Really push it and instead of the x8 ram chip, you can use the x16 version of the ram chip (same price and size) and double your ram bandwidth.

Use this guy for 128 megabytes: https://www.digikey.com/en/products/detail/issi-integrated-silicon-solution-inc/IS43DR81280C-25DBL/6202050 (https://www.digikey.com/en/products/detail/issi-integrated-silicon-solution-inc/IS43DR81280C-25DBL/6202050)
Question, how long would it take an 8MHz Z80 to fill 128 megabytes?
Without the aid of the accelerated geometry processor...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 09:59:28 pm
You can only do this if you get rid of the analog VGA dac and run the TFP410 in 12bit DDR mode.  This means you free up 12 IOs immediately and you already have another >8 free to complete the DDR2 ram chip interface.  Really push it and instead of the x8 ram chip, you can use the x16 version of the ram chip (same price and size) and double your ram bandwidth.
Why do you need that TFP410 at all? Didn't you said that FPGA can directly drive HDMI out up to like 720p (~750 Mbps per diff pair)? I'd say get rid of it - this will free up a ton of pins for other purposes.
Also if going DDR, I'd rather go all the way to DDR3 as they provide larger capacity for the same price over DDR2 - for like $5-6 you can get a 512 Mbytes device!

Question, how long would it take an 8MHz Z80 to fill 128 megabytes?
Without the aid of the accelerated geometry processor...
This is what DMA is for. Create a DMA with small memory-mapped aperture so that CPU can program data transfers, kick them off and let CPU do more useful things that shuffling bytes around.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 11, 2020, 10:06:01 pm
Your doing fine as this is your second PCB.  Back in 1983, my first PCB was done with a sharpie marker, a hobby drill bit with hand drill and it had only a few transistors on it...

Thanks. :)  I just feel like I know nothing compared to you guys.

To use a DDR2 chip like this one @2$: https://www.digikey.com/en/products/detail/winbond-electronics/W9751G8NB-25/11656260 (https://www.digikey.com/en/products/detail/winbond-electronics/W9751G8NB-25/11656260) (And we can guarantee 250MHz/500mtps support as that ram chip can go up to 800mtps & by every metric, the access on this ram chip will run circles around the HyperRam.)

To access all 64 megabytes, you would need another 19 outputs that what you are currently using.

You can only do this if you get rid of the analog VGA dac and run the TFP410 in 12bit DDR mode.  This means you free up 12 IOs immediately and you already have another >8 free to complete the DDR2 ram chip interface.  Really push it and instead of the x8 ram chip, you can use the x16 version of the ram chip (same price and size) and double your ram bandwidth.

Use this guy for 128 megabytes: https://www.digikey.com/en/products/detail/issi-integrated-silicon-solution-inc/IS43DR81280C-25DBL/6202050 (https://www.digikey.com/en/products/detail/issi-integrated-silicon-solution-inc/IS43DR81280C-25DBL/6202050)

Right, well now we're getting into the big thing I wanted to discuss before I go much further with the PCB.  I can't remember why I opted for the TFP410 in the first place (and admittedly haven't bothered to go back to that part of the thread to find out), but if I can get a DVI-D interface up and running, I'll be dropping the VGA output like a stone.  If I can skip the TFP410 altogether and just drive an HDMI socket straight from the FPGA, then that would be the gold standard - it would free up more than 12 IOs... and presumably make the DDR2 chip a preferable alternative to the HyperRam chips.

I'd just need some persuading that the DVI output would work - but it's even simpler than the VGA output I've currently got, so I guess I'm happy to just go with that as an alternative to the TFP410 and ADV7125 mess I've currently got going on.

Question, how long would it take an 8MHz Z80 to fill 128 megabytes?
Without the aid of the accelerated geometry processor...

Probably a little longer than it would take me to work out the answer.  :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 11, 2020, 10:10:48 pm
Thanks. :)  I just feel like I know nothing compared to you guys.
That's OK. Don't feel bad about it. Nobody was born with this knowledge, so at some point we all were in your position. The important thing is your willingness to learn. If it's there, the rest is just a matter of time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: FenTiger on November 12, 2020, 03:26:13 am
If I can skip the TFP410 altogether and just drive an HDMI socket straight from the FPGA,

Watch out for backpowering.

I have an FPGA board (Digilent Zybo Z7-20) with an HDMI output, and the manual says

Quote from: Digilent Zybo Z7 Manual
The HDMI TX port does not include a buffer for improving signal integrity, but does include an HDMI multiplexer
configured as a simple switch. This device is used to prevent displays from back-powering the Zybo Z7, and
otherwise has no effect on functionality. The benefit this adds is to make it possible to power cycle the Zybo Z7
while a display is attached to HDMI TX, which was not possible on previous Digilent boards.

Maybe this won't be a problem for you but I'd suggest checking first to be sure you don't make the same mistake Digilent's engineers did!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 03:42:12 am
TFP410 pros

Pros:
Well, easy coding as you just need to add a DDR output buffer to your existing code and it will work saving you 12 IO.
You are pretty sure TI's example output will pretty much pass FCC/EMI regs with a clean PCB layout.
It is likely to work with any DVI display.
Your chosen CycloneV can output 1080p with the device.
Cons:
No audio.
It's an additional IC.  (You still need that DVI/HDMI protection IC and EDID voltage level converter.)

FPGA direct DVI pros:
Save an additional ~4 IOs compared to running the TFP410 in DDR mode bringing the total saved IOs to 16.
(Still need that DVI/HDMI protection IC and EDID voltage level converter as discussed earlier in this thread)
Can support HDMI embedded audio.

FPGA direct DVI cons:
Though you may have no trouble getting a picture on all your DVI/HDMI displays, this is no guarantee how it will operate in the field at large.  However, 480p is so low res and slow, I dont think this will be an issue.
With your CycloneV, though you probably can get 720p to work if you want using a simple DQ port, the spec is slightly outside your FPGA's soft-serializers by around ~15% (I uploaded a code here on another thread which makes a trick 10:1 soft-serializer using the DDR-DQs which seems to full-timing-simulate good up to 742.5MHz for 720p.  It will work fine for 480p).  1024x768 @60hz is within spec.
(I guarantee you wont pass any HDMI/DVI certifications no matter how perfect it works.  ;) )

You will have to ask asmi what voltage you will need to set that IO bank to (I haven't done a direct HDMI myself) and you will no longer have any analog video fallback to rely on.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 04:54:35 am
Like I said before, Xilinx FPGA's output buffers support TMDS standard directly, so no additional analog tricks are required. TMDS standard uses current drivers which need to terminate to +3.3V via 50 Ohm resistor. So in this case Vccio needs to be 3.3V. In my designs I use TPD12S521 chip as ESD protection for main data lines, also as voltage level translator for auxiliary HDMI signals (like Hot Plug Detect, or DDC channel which can be used to discover capabilities of connected display), and finally as overcurrent protection for HDMI power line. Look at the last page of my project's schematic on how to connect it: https://github.com/asmi84/kicad-projects/blob/master/S7_Min/S7_Min.pdf Check documentation for your FPGA to see if it supports TMDS, and what exactly needs to happen to use it.

If FPGA you've chosen does not support TMDS standard directly, you can use "regular" LVDS standard and a voltage translator/retimer like SN75DP149. In this case you will need to use whatever Vccio that your FPGA needs for LVDS standard. Since it's going to be AC-coupled to voltage translator, the DC reference level for LVDS doesn't matter. Also some LVDS drivers require 100 Ohm differential termination resistor, so you've got to watch out for this. Now I want to be clear that I only ever implemented the first approach, so you will need to do your own research if the second approach will be required. The way I typically approach this is by searching for schematics of FPGA devboards that have this implemented, and borrowing the part that interests me.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 04:55:45 am
(I guarantee you wont pass any HDMI/DVI certifications no matter how perfect it works.  ;) )
And you'd be totally wrong ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 05:15:09 am
(I guarantee you wont pass any HDMI/DVI certifications no matter how perfect it works.  ;) )
And you'd be totally wrong ;)
You do realize just the wrong spacing/location of the HDMI connector compared to other connectors will fail HDMI certification.
You also realize the wrong size and color combination of the HDMI logo printed on your device will fail certification.
You also realize not paying the annual fee leads to failure.
In fact the rule book is so large and complicated, you usually need to pay a third party to evaluate your design before you even attempt to apply for certification.
Even the HDMI connector itself needs to be a certified version and not a knock off for your product to get certified.

Like I said, I guarantee you wont pass any HDMI/DVI certifications no matter how perfect it works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: james_s on November 12, 2020, 05:24:43 am
One of my tasks at a former job was running some of the HDMI certification tests on settop boxes. It was indeed complicated, and the stuff I was doing was just testing the signal, handshaking and content protection. I'm not sure why anyone other than a big company selling a mass produced consumer product would bother.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 05:26:24 am
You do realize just the wrong spacing/location of the HDMI connector compared to other connectors will fail HDMI certification.
You also realize the wrong size and color combination of the HDMI logo printed on your device will fail certification.
You also realize not paying the annual fee leads to failure.
In fact the rule book is so large and complicated, you usually need to pay a third party to evaluate your design before you even attempt to apply for certification.
Even the HDMI connector itself needs to be a certified version and not a knock off for your product to get certified.
There is nothing you listed here that is impossible to satisfy using FPGA. Therefore...
Like I said, I guarantee you wont pass any HDMI/DVI certifications no matter how perfect it works.
You'd be totally wrong.
Oh, and also - DVI and HDMI are different things as far as certification is concerned. So you can't really say DVI/HDMI when we talking about certifications.

Finally, and I think most importantly, none of that matters for hobby designs, which is why I'm puzzled as to why have you even brought this up as an argument against using FPGA for implementation. This is absolutely irrelevant here. As long as the monitor(s) nockieboy will be using will display the video feed properly (and render audio if that's included into the stream, though that will force to use true HDMI standard as opposed to DVI), we should be good to go. And so far I have not encountered a monitor (or TV), which didn't work with my implementation of it, or many others founds online which are substantially similar.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 05:31:52 am
You do realize just the wrong spacing/location of the HDMI connector compared to other connectors will fail HDMI certification.
You also realize the wrong size and color combination of the HDMI logo printed on your device will fail certification.
You also realize not paying the annual fee leads to failure.
In fact the rule book is so large and complicated, you usually need to pay a third party to evaluate your design before you even attempt to apply for certification.
Even the HDMI connector itself needs to be a certified version and not a knock off for your product to get certified.
There is nothing you listed here that is impossible to satisfy using FPGA. Therefore...
Like I said, I guarantee you wont pass any HDMI/DVI certifications no matter how perfect it works.
You'd be totally wrong.
Oh, and also - DVI and HDMI are different things as far as certification is concerned. So you can't really say DVI/HDMI when we talking about certifications.

Finally, and I think most importantly, none of that matters for hobby designs, which is why I'm puzzled as to why have you even brought this up as an argument against using FPGA for implementation. This is absolutely irrelevant here.
Didn't you notice the "  ;)  " when I first commented...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 05:35:57 am
Didn't you notice the "  ;)  " when I first commented...
So let's leave this certification nonsense alone, and talk about the actual implementation. I'm certain that you know Cyclone V much better than I do, so can you tell us if its' output buffers support TMDS standard directly, or we will need to use retimer and LVDS drivers instead?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 05:43:39 am
Also I have a question for nockieboy: how many IO pins your project requires, excluding pins for the memory and video out interface(s)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 09:53:55 am
Didn't you notice the "  ;)  " when I first commented...
So let's leave this certification nonsense alone, and talk about the actual implementation. I'm certain that you know Cyclone V much better than I do, so can you tell us if its' output buffers support TMDS standard directly, or we will need to use retimer and LVDS drivers instead?
Directly driven, you can get on an IO bank of 4 clock aligned LDVS transmitters with a matching & jitter performance <+/-250ps.   You would have to make a crap PCB, and poorly filter the VCC_PLL swinging the temperature between coldest and hottest to achieve that poor performance worst case scenario.  @250 megabit for 640x480, or even double that, you will have a huge clean data EYE which any monitor or TV should be able to display directly driven from the FPGA.  You still need the ESD protection IC.  As for the proper termination, I would consult existing third party dev board which drive HDMI/DP directly to see what they use.

In the past, I've fed DVI/HDMI with spread spectrum clocks and it still works fine except for some old TVs back around 2005 which at the time were not engineered to support spread-spectrum HDMI.  Today, I doubt you could find a monitor which the Cyclone could not drive all on it's own to 480p @ 270MHz.

I've attached the required EYE (blue eye) for 720p, 742.5MHZ and it looks like the Cyclone can just make it there as well, 480p will be easy.

(source : R&S HDMI measurements, page 11, 742.5MHz 720p graph (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjcjtrB3vzsAhWEEVkFHYTjAj0QFjAAegQIAhAC&url=https%3A%2F%2Fcdn.rohde-schwarz.com%2Fpws%2Fdl_downloads%2Fdl_common_library%2Fdl_brochures_and_datasheets%2Fpdf_1%2FEye_Measurements_on_HDMI_signals.pdf&usg=AOvVaw1jY_y6_u948-x853lFihQk) )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2020, 12:13:15 pm
Also I have a question for nockieboy: how many IO pins your project requires, excluding pins for the memory and video out interface(s)?

Okay, let's see:

Z80 data bus - 8 + 2 IOs
Z80 addr bus - 24 + 2 IOs
Z80 ctrl bus   - 8 IOs

PS2 interface - 4 IOs
uSD interface - 6 IOs
Debug port    - 2 IOs
Serial port     - 4 IOs
Audio DAC     - 3 IOs
---------------------------
TOTAL:           63 IOs
---------------------------

That doesn't include the 24-bit RGB video output and 3 control signals (HS, VS and DE).  It also doesn't include any additional IOs I've used for LEDs (3, currently).

Directly driven, you can get on an IO bank of 4 clock aligned LDVS transmitters with a matching & jitter performance <+/-250ps.   You would have to make a crap PCB, and poorly filter the VCC_PLL swinging the temperature between coldest and hottest to achieve that poor performance worst case scenario.  @250 megabit for 640x480, or even double that, you will have a huge clean data EYE which any monitor or TV should be able to display directly driven from the FPGA.  You still need the ESD protection IC.  As for the proper termination, I would consult existing third party dev board which drive HDMI/DP directly to see what they use.

In the past, I've fed DVI/HDMI with spread spectrum clocks and it still works fine except for some old TVs back around 2005 which at the time were not engineered to support spread-spectrum HDMI.  Today, I doubt you could find a monitor which the Cyclone could not drive all on it's own to 480p @ 270MHz.

Okay, well I'm given confidence by projects like this one (https://github.com/charcole/neogeohdmi), where a Cyclone II is used to generate a 480p image via directly-driven HDMI/DVI.

TFP410 pros

Pros:
Well, easy coding as you just need to add a DDR output buffer to your existing code and it will work saving you 12 IO.
You are pretty sure TI's example output will pretty much pass FCC/EMI regs with a clean PCB layout.
It is likely to work with any DVI display.
Your chosen CycloneV can output 1080p with the device.
Cons:
No audio.
It's an additional IC.  (You still need that DVI/HDMI protection IC and EDID voltage level converter.)

FPGA direct DVI pros:
Save an additional ~4 IOs compared to running the TFP410 in DDR mode bringing the total saved IOs to 16.
(Still need that DVI/HDMI protection IC and EDID voltage level converter as discussed earlier in this thread)
Can support HDMI embedded audio.

Additional FPGA direct pros - easier routing and saving PCB space with no TFP410 or ADV7125 (and associated VGA socket) required.

Also, currently I've got the TFP410 set up for single-edge latching, so a full 24 IOs are required for the RGB bus, not 12.  My hand was forced here as I wanted to keep the VGA output and, as far as I can tell, the ADV7125 only latches data on the rising edge - it doesn't do DDR.

I guess I should just drop the VGA altogether, whether or not I go with the TFP410.  I'm just nervous as I haven't tested the DVI output method practically, whereas with VGA I had it set up and working on my dev board (albeit with a resistor-ladder rather than an ADV7125).

FPGA direct DVI cons:
Though you may have no trouble getting a picture on all your DVI/HDMI displays, this is no guarantee how it will operate in the field at large.  However, 480p is so low res and slow, I dont think this will be an issue.
With your CycloneV, though you probably can get 720p to work if you want using a simple DQ port, the spec is slightly outside your FPGA's soft-serializers by around ~15% (I uploaded a code here on another thread which makes a trick 10:1 soft-serializer using the DDR-DQs which seems to full-timing-simulate good up to 742.5MHz for 720p.  It will work fine for 480p).  1024x768 @60hz is within spec.

So, no real cons at all then?

720p would be useful - can always upscale the 640x480 image to 720p - and providing a proper 720p image would be more compatible with the displays' native resolutions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 02:23:39 pm

Okay, well I'm given confidence by projects like this one (https://github.com/charcole/neogeohdmi), where a Cyclone II is used to generate a 480p image via directly-driven HDMI/DVI.

:)

Just copy his PCB and we will double verify your IO selection and placement to ensure you also get the chance to achieve 720p with at worst having increasing the VCCint from 1.1v to ~1.15v/1.2v if it didn't already do the 720p out of the box.

From experience routing CycloneIII with tests on an older true 5gs/sec/channel scope with amplified 1.5GHz jfet low capacitance probes, your output jitter and EYE is well under the +/-250ps, much closer to the +/-150ps in practice and the PLL is designed to go up past 700MHz.

As for the DDR2/3, your cyclone is guaranteed to do 250MHz/500mtps by Intel.  I'm not sure about the lower frequency limit of DDR3, but if it can do 250MHz, then you can use it.  DDR2s are still readily available with 4 banks allowing you continuous streaming memory access providing at least 3x the speed of a Hyperbus ram when comparing with an 8bit DDR2/3.  Since your core internally is 250MHz 16bit, this means the ram would also run internally in 1:1 mode in clock and depth.  Sparing up a second 8bit IO bank for a 16bit DDR2/3 will give you 8x the speed of the current Hyperbus ram.  Though, you core pixel writer and other newer functions will probably never saturate that speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 03:29:08 pm
Just copy his PCB
Do you have a link to it? I couldn't find anything.

Overall I'm surprised that it's incredibly hard to find any schematics for direct HDMI out for Antel FPGAs, while there are tons of implementations using Xilinx devices. I spent about half an hour trying to find any schematic in the Google, but totally failed.

Maybe it's a good time to discuss moving to Artix/Spartan-7? Artix-7 in 1 mm BGA256 package has 170 user IO balls, so it should be enough for everything we've got + direct HDMI out up to 1080p@60 + x16 DDR2/3 memory module running at 400 MHz. This package also has a wide range of pin-compatible densities from 15K to 100K, so you can easily scale device up or down as required without any PCB changes aside from possibly minor changes in PDS. The top level device (A100T with 100K) requires a beefy DC-DC converter for Vccint rail as it can consume up to about 6 Amps@1.0 V, and it will need at least some glued-on or clipped-on heatsink. Smaller density devices can get away without heatsink.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2020, 03:58:13 pm
Just copy his PCB and we will double verify your IO selection and placement to ensure you also get the chance to achieve 720p with at worst having increasing the VCCint from 1.1v to ~1.15v/1.2v if it didn't already do the 720p out of the box.

From experience routing CycloneIII with tests on an older true 5gs/sec/channel scope with amplified 1.5GHz jfet low capacitance probes, your output jitter and EYE is well under the +/-250ps, much closer to the +/-150ps in practice and the PLL is designed to go up past 700MHz.

*deep breath*

Okay, I'm going to pull the trigger and remove the TFP410 and VGA gubbins from the board.  We're going full-throttle on a DVI-D-compatible 480p (maybe 720p later) video output by driving the HDMI connector directly from the FPGA.

I'll keep the 3.3VA supply at the bottom-right corner of the board to supply the PCM5101.

As for the DDR2/3, your cyclone is guaranteed to do 250MHz/500mtps by Intel.  I'm not sure about the lower frequency limit of DDR3, but if it can do 250MHz, then you can use it.  DDR2s are still readily available with 4 banks allowing you continuous streaming memory access providing at least 3x the speed of a Hyperbus ram when comparing with an 8bit DDR2/3.  Since your core internally is 250MHz 16bit, this means the ram would also run internally in 1:1 mode in clock and depth.  Sparing up a second 8bit IO bank for a 16bit DDR2/3 will give you 8x the speed of the current Hyperbus ram.  Though, you core pixel writer and other newer functions will probably never saturate that speed.

Let me get this straight - the existing HyperRam setup requires two BGA chips and will require some nifty HDL-ing to interface with it and push it up over its 200MHz rated limit.  Even then, it's only fast enough to give full-speed, no latency access to one MAGGIE?

However, if I strip that out and replace with a DDR2 or 3 chip, I'll only need one chip but a load more IOs (so I'll be setting two banks to 1.8V instead of that faff trying to find just the one for the HyperRam) - I could potentially use the entire bottom-right corner/quadrant of the FPGA for the DDR.  But all that aside, what benefit will the DDR2/3 bring?  Would it be a little closer to the internal RAM in terms of performance?  i.e. could more than 1 MAGGIE access it?  I'm just wondering if I could use it as the frame buffer....  that would unlock some serious resolutions and colour combos....

Just copy his PCB
Do you have a link to it? I couldn't find anything.

As far as I can tell from watching this linked video in the project's readme (https://www.youtube.com/watch?feature=player_embedded&v=bTamCo2C6kg), he's using a bog-standard Cyclone EP2C5T144 board, like this one (https://www.ebay.co.uk/itm/ALTERA-Cyclone-II-EP2C5T144-FPGA-Development-Board-Kits-EPROM-EPCS4/283036275758?epid=21021086409&hash=item41e646d42e:g:TjwAAOSwBrlbOdqo), and incidentally, exactly like one I've got sitting in a tin on my shelf that I was using when I started this thread...  Doesn't appear to be any fancy wiring, he's just connected the IOs to the HDMI connector, although I can't see if there's any discrete components on the connector PCB in the video. Jump to 1min50secs to see.

Overall I'm surprised that it's incredibly hard to find any schematics for direct HDMI out for Antel FPGAs, while there are tons of implementations using Xilinx devices. I spent about half an hour trying to find any schematic in the Google, but totally failed.

Maybe it's a good time to discuss moving to Artix/Spartan-7?

Well, I guess this is the elephant in the room now.  Am I using the right tool for the job?  Thing is, whilst I'd likely be as clueless with a Xilinx as I am with an Altera FPGA, I'm quite comfortable and familiar with the Cyclone dev chain.  That's not to say that Xilinx's 7-series isn't appealing - they seem to have more RAM than the equivalent Cyclones and that's a big factor in our current designs.  I do actually have a Spartan-6 dev board and programmer, still in their static bags, sitting around somewhere.

The biggest thing though, is that whether or not he'd like to admit it, BrianHG is critical to the success or failure of this project.  He's the only one who knows how to finish what we've started on the HDL-side (if nothing else, I have learned a lot about what I don't know about HDL so far), so I'll always be guided by his preference here.  And I'm sure that if we did move over to Xilinx, there'd be a lot of head-scratching as the HDL wouldn't just lay back and allow us to port it without causing issues.

Artix-7 in 1 mm BGA256 package has 170 user IO balls, so it should be enough for everything we've got + direct HDMI out up to 1080p@60 + x16 DDR2/3 memory module running at 400 MHz. This package also has a wide range of pin-compatible densities from 15K to 100K, so you can easily scale device up or down as required without any PCB changes aside from possibly minor changes in PDS. The top level device (A100T with 100K) requires a beefy DC-DC converter for Vccint rail as it can consume up to about 6 Amps@1.0 V, and it will need at least some glued-on or clipped-on heatsink. Smaller density devices can get away without heatsink.

At the end of the day, this GPU card sits on a stack of cards that all draw power from either a USB serial connection to my PC, or a DC jack connected to a 7805 regulator.  Yep.  Exactly.  I've been putting off redesigning the power card for a while, as the current GPU (Cyclone IV) works just fine on the USB (though I've just checked and it only draws 0.08A!).  I'm hoping that the Cyclone V will work without MAJOR issues - I might have to run it from the jack rather than the USB supply like I do now with the Cyclone IV, but then again it should actually be more power efficient than the IV.  I suspect that a Xilinx (certainly some of the ones you've described) may cause power issues.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 04:35:03 pm
Just copy his PCB
Maybe it's a good time to discuss moving to Artix/Spartan-7? Artix-7 in 1 mm BGA256 package has 170 user IO balls, so it should be enough for everything we've got + direct HDMI out up to 1080p@60 + x16 DDR2/3 memory module running at 400 MHz. This package also has a wide range of pin-compatible densities from 15K to 100K, so you can easily scale device up or down as required without any PCB changes aside from possibly minor changes in PDS. The top level device (A100T with 100K) requires a beefy DC-DC converter for Vccint rail as it can consume up to about 6 Amps@1.0 V, and it will need at least some glued-on or clipped-on heatsink. Smaller density devices can get away without heatsink.
LCSC only has stock of the ' XC7A35T-2FTG256C ' @ 16$, 26kle 1.8mbit ram.  + Learning curve.
The DDR3 will run max in mode 2:1 @ 350Mhz with 700mtps  compared to CycloneV 2:1 303MHz, 606mtps.
The DDR3 can also run in mode 4:1 @ 200Mhz with 800mtps.
(Table 16 in Xilinx da181_Artix_7_datasheet.)
It's LVDS can guarantee 720P performance.

Our core clock is 250MHz/125MHz for VGA, or it goes up to 270MHz/135MHz for broadcast 480p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2020, 04:56:21 pm
LCSC only has stock of the ' XC7A35T-2FTG256C ' @ 16$, 26kle 1.8mbit ram.  + Learning curve.
The DDR3 will run max in mode 2:1 @ 350Mhz with 700mtps  compared to CycloneV 2:1 303MHz, 606mtps.
The DDR3 can also run in mode 4:1 @ 200Mhz with 800mtps.
(Table 16 in Xilinx da181_Artix_7_datasheet.)
It's LVDS can guarantee 720P performance.

Our core clock is 250MHz/125MHz for VGA, or it goes up to 270MHz/135MHz for broadcast 480p.

The Cyclone IV can't handle 135MHz without some (serious, I'm guessing) work on the HDL.  I wonder if the Cyclone V will be any better?

Anyway, LCSC only have stock of the A2 variant of the Cyclone V, so product choice is restricted either way I guess.  The Xilinx part is $3 cheaper (exchange rate approximate).  :-//

Hmm... around 200KB of RAM though.  The Cyclone V A4 has about 300KB?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on November 12, 2020, 05:00:15 pm
Maybe also have a look at the recently released Efinix chips?

For example the T85 series : https://www.efinixinc.com/docs/trion85-ds-v1.2.pdf (https://www.efinixinc.com/docs/trion85-ds-v1.2.pdf)

BGA324 : https://www.digikey.com/en/products/detail/efinix-inc/T85F324C3/11591357 (https://www.digikey.com/en/products/detail/efinix-inc/T85F324C3/11591357)

Has built in ddr3 controller block, supports ddr3 / ddr3l up to 1066 mhz x16 (the 484 and  576 support x16 and x32) ,  519040 bytes of memory ... but the bga324 is in 0.65 pitch which may be small  (bga484 is in 0.8mm)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 05:44:21 pm
At the end of the day, this GPU card sits on a stack of cards that all draw power from either a USB serial connection to my PC, or a DC jack connected to a 7805 regulator.  Yep.  Exactly.  I've been putting off redesigning the power card for a while, as the current GPU (Cyclone IV) works just fine on the USB (though I've just checked and it only draws 0.08A!).  I'm hoping that the Cyclone V will work without MAJOR issues - I might have to run it from the jack rather than the USB supply like I do now with the Cyclone IV, but then again it should actually be more power efficient than the IV.  I suspect that a Xilinx (certainly some of the ones you've described) may cause power issues.
I said "up to" for a reason. That is almost absolute maximum it can consume if you reach near 100% utilization of it's resources. Given that currently your design fits into like 1/4 of resources A100T has, you won't get anywhere near that consumption. Infact, this device is going to be a massive overkill for this project as it is, but it's nice to have options for future growth. As it is, even A35T is going to be more than enough. And that device is available on Digikey and Mouser for about 35-40$, so you don't run the risk of it suddenly disappearing from stock (which is what tends to happen quite a bit on LCSC).
That said, the very same TLV62130 that you use on a current board can be used to step down any power brick voltage (up to 17 V I think), which I'm sure you have quite a bit of, like we all do, down to 5 V, and it can output up to 3 Amps and so 15 W of power, which is going to be more than enough for any of your boards even if you use A100T FPGA and somehow manage to fill it to the gills, all that while maintaining fairly good efficiency and so not getting too hot. I learnt very early that using USB for power is not the greatest idea, because the voltage on it can sag quite a bit during current bursts - even simple microSD card can consume up to 300 mA in certain situations. I actually had all kind of weird issues which were traced to insufficient power specifically with microSD cards.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 05:50:12 pm
Our core clock is 250MHz/125MHz for VGA, or it goes up to 270MHz/135MHz for broadcast 480p.
I've been wondering for a while now if it would be possible to duplicate (with perhaps some modifications, hopefully minor) your processing pipeline and run two (or maybe even more) of them in parallel instead of raising the frequency? So essentially is it possible to go wide instead of going fast, and double effective throughput this way? FPGA resources are relatively cheap nowadays, and running at lower frequencies makes closing timing much easier, it also allows you to get away with more things that you can while running at higher frequencies.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 05:58:35 pm
Maybe also have a look at the recently released Efinix chips?
I don't think go to what effectively is a noname vendor in this field is a great idea. At least with Xilinx you get the benefit of a ton of information publicly available for just about anything related to these devices, excellent documentation provided by the vendor, lots of helpful guides, tutorials, open source and open HW projects, etc. And the vendor itself is quite hobbyist-friendly with a lot of free IPs and access to quite wide range of their devices in free version of tools, and the tools themselves are full-featured, not some cut-down versions of a cut-down versions of products, which is what some other FPGA vendors are doing, I guess in the hope that if they cripple and annoy you enough, you might just pull the trigger and buy a commercial license.

BGA324 : https://www.digikey.com/en/products/detail/efinix-inc/T85F324C3/11591357 (https://www.digikey.com/en/products/detail/efinix-inc/T85F324C3/11591357)
324 package? That's at least 6 layer PCB for sure. No way you can get away with 4 layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 06:03:13 pm
Anyway, LCSC only have stock of the A2 variant of the Cyclone V, so product choice is restricted either way I guess.  The Xilinx part is $3 cheaper (exchange rate approximate).  :-//
Interesting - even Digikey only has two options for CV in 256 ball package - A2 and A4. While it's got entire family of Artix-7 in the same package from smallest A15 all the way up to A100, and most densities are available in multiple speed grades and temperature ratings. Well I guess that shows which devices are more popular ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 06:43:44 pm
Maybe also have a look at the recently released Efinix chips?

For example the T85 series : https://www.efinixinc.com/docs/trion85-ds-v1.2.pdf (https://www.efinixinc.com/docs/trion85-ds-v1.2.pdf)

BGA324 : https://www.digikey.com/en/products/detail/efinix-inc/T85F324C3/11591357 (https://www.digikey.com/en/products/detail/efinix-inc/T85F324C3/11591357)

Has built in ddr3 controller block, supports ddr3 / ddr3l up to 1066 mhz x16 (the 484 and  576 support x16 and x32) ,  519040 bytes of memory ... but the bga324 is in 0.65 pitch which may be small  (bga484 is in 0.8mm)
This one is really interesting @20$:
https://www.digikey.com/en/products/detail/efinix-inc/T85F484C3/11591358 (https://www.digikey.com/en/products/detail/efinix-inc/T85F484C3/11591358)
However, I never seen their tools or dev boards and Digikey seems to have exclusive stock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2020, 06:56:25 pm
Oh. My. Gawd.  |O

Xilinx isn't selling itself to me at the moment.  I've just spent the last hour trying to get the damn ISE software to install and load so that I might have a play with my Spartan-6 over the weekend.  I'll be damned if I'm uninstalling my Oracle VM software just so that the ISE can run its own (older version) VM environment.  WTH is that for, anyway?  Upshot is that I'm currently downloading an older version of the ISE in the hope it's the non-VM version.  Then I've got to apply a hack to get it to work in Windows 10. :wtf:

Be as critical as you want about Antel, but Quartus just works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 07:01:59 pm
Our core clock is 250MHz/125MHz for VGA, or it goes up to 270MHz/135MHz for broadcast 480p.
I've been wondering for a while now if it would be possible to duplicate (with perhaps some modifications, hopefully minor) your processing pipeline and run two (or maybe even more) of them in parallel instead of raising the frequency? So essentially is it possible to go wide instead of going fast, and double effective throughput this way? FPGA resources are relatively cheap nowadays, and running at lower frequencies makes closing timing much easier, it also allows you to get away with more things that you can while running at higher frequencies.
It is a pipeline right now at 10 dual channels = 20 channels, 15 for 15 layers and 1 fat channel for Z80 and GPU geometry.

Pixel clock = 25Mhz * 10 dual channels = 250MHz/125MHz core.
You can easily configure the pipeline to for example 8 dual channels = 16 channels, 12 for 12 layers and 1 fat channel for Z80 and GPU geometry.
In this configuration, 25MHz pixel = 25MHz * 8 dual channels = 200MHz/100MHz core.
You can go in the other direction as well, but it is not worth all the layers unless you change the layers to 12 dual channels, 1 for 12 layers and 2 fat channels to either make a double speed geometry unit (modifying just the pixel writer module would be easiest), or run 2 parallel geometry units.  (IE 300MHz/150MHz core)

You can also cut the layers in half and double the pixel clock output.  With a few calculations after seeing the FPGA's fabric's max performance, an optimum configuration may be chosen for 720p if interested.  Also, the DDR port may have a dedicated 1 or 2 layer channels in addition to the ones listed above which are more like full screen sprites and hardware accelerated tile/font/sprite/overlay screens memory.

Though it is easy enough to add 2 geometry units, this would only offer acceleration with solid polygons and there is no mechanism in place to split the work between them as painting some shapes may require 1 being painted on top of another.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 07:05:49 pm
This means with the current setup, Nockieboy can have 720P with the current core with 5 layers instead of 15 layers, ie 3x25MHz = 75MHz pixel clock.  The HeyperRam/DDR would add another 1/2 layers on top of the 5 since it will have a dedicated pipe to draw the background screen.

The bridge between the 2 will be the GPU geometry and blitter core.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 07:33:06 pm
Oh. My. Gawd.  |O

Xilinx isn't selling itself to me at the moment.  I've just spent the last hour trying to get the damn ISE software to install and load so that I might have a play with my Spartan-6 over the weekend.  I'll be damned if I'm uninstalling my Oracle VM software just so that the ISE can run its own (older version) VM environment.  WTH is that for, anyway?  Upshot is that I'm currently downloading an older version of the ISE in the hope it's the non-VM version.  Then I've got to apply a hack to get it to work in Windows 10. :wtf:

Be as critical as you want about Antel, but Quartus just works.
ISE was last updated like 10 years ago, and currently it's on a life support. So avoid it unless you have to support your old products using these things.

I was talking about 7 series devices (Spartan-7/Artix-7) - they are supported by modern Vivado (or Vitis as the combined HW-SW package is called now). Which not only "just works", but also offers a ton of additional stuff for free.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2020, 07:56:10 pm
Oh. My. Gawd.  |O

Xilinx isn't selling itself to me at the moment.  I've just spent the last hour trying to get the damn ISE software to install and load so that I might have a play with my Spartan-6 over the weekend.  I'll be damned if I'm uninstalling my Oracle VM software just so that the ISE can run its own (older version) VM environment.  WTH is that for, anyway?  Upshot is that I'm currently downloading an older version of the ISE in the hope it's the non-VM version.  Then I've got to apply a hack to get it to work in Windows 10. :wtf:

Be as critical as you want about Antel, but Quartus just works.
ISE was last updated like 10 years ago, and currently it's on a life support. So avoid it unless you have to support your old products using these things.

I was talking about 7 series devices (Spartan-7/Artix-7) - they are supported by modern Vivado (or Vitis as the combined HW-SW package is called now). Which not only "just works", but also offers a ton of additional stuff for free.

Yeah I know, I was just trying to get ISE set up so I could try out the Spartan-6 board I have.  It's a shame they aren't using the same software for both the 6- and 7-series - I'll get so far using the ISE for the Spartan-6 before I'd likely have to change up to Vivado for a Spartan-7.

It's just not a great marketing decision when you close off older products like the 6-series, which just happen to be cheap as chips for beginners to learn on, behind software that is difficult to install and run, and I was venting a little.  Don't get me wrong, they've done exactly the same thing with Quartus and the Cyclone series (amongst others), but the old software (and the new) just installs and works, simple as that, which reduces the hoops a beginner has to jump through.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 08:04:47 pm
@Nockieboy, you will need this IC for your HDMI port's ESD protection and 5v <> 3.3v conversion for the DDC I2C lines.
https://www.ti.com/product/TPD12S520 (https://www.ti.com/product/TPD12S520)
Thanks for Asmi, I had the wrong one... Here is Asmi's correction:
https://www.ti.com/product/TPD12S521 (https://www.ti.com/product/TPD12S521)

For the FPGA driving this chip, you will need a group of 8 series resistors.  You can use this resistor pack:
https://www.digikey.com/en/products/detail/yageo/YC248-JR-0733RL/1005206 (https://www.digikey.com/en/products/detail/yageo/YC248-JR-0733RL/1005206)
Or, 8 individual 0402 33ohm resistors.

@83 cents, getting rid of the TFP410, VGA dac & sync driver 74HC245 will cut costs on your PCB getting rid of a lot of junk and save PCB space and a routing nightmare.
Also, you will now have room for a full DDR2/3 ram chip.

The IO bank needs to be a normal 3.3v and have 8x ####DQ## pins for the video signal + 4 more cheap regular IOs for the DDC I2C, HPD sense & CEC.  (Go figure, 12 IOs total...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 08:14:08 pm
Yeah I know, I was just trying to get ISE set up so I could try out the Spartan-6 board I have.  It's a shame they aren't using the same software for both the 6- and 7-series - I'll get so far using the ISE for the Spartan-6 before I'd likely have to change up to Vivado for a Spartan-7.

It's just not a great marketing decision when you close off older products like the 6-series, which just happen to be cheap as chips for beginners to learn on, behind software that is difficult to install and run, and I was venting a little.  Don't get me wrong, they've done exactly the same thing with Quartus and the Cyclone series (amongst others), but the old software (and the new) just installs and works, simple as that, which reduces the hoops a beginner has to jump through.
Yea, I get the inconvenience, but the thing is 7 series is better in every way - it's much faster than S6, it's cheaper if you compare the same densities (at least in "official" channels like Digikey or Mouser), and Vivado is much more functional. Supporting legacy is always pain in the butt (and as a software developer I know this from my own experience), so they had to draw a line somewhere. Since first devices of a 7 series rolled out, they released two newer generations of FPGA (Ultrascale and Ultrascale+), but these are high-end parts which go from "simply expensive" to "insane" at over 100K$ per device!! There are few outliers like smallest Zynq Ultrascale+ SoCs (2/4 ARM64 cores + FPGA fabric in a single chip) which can be had for few hundred bucks, but in general they are priced at least in 4 figures. Don't get me wrong - these are great devices (high performance, insane amount of resources, some really cool HW features), they are just waaaay out of my price range.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 08:16:41 pm
@Nockieboy, you will need this IC for your HDMI port's ESD protection and 5v <> 3.3v conversion for the DDC I2C lines.
https://www.ti.com/product/TPD12S520 (https://www.ti.com/product/TPD12S520)
No, this chip is for the receiver port. For transmitter port use this one: https://www.ti.com/product/TPD12S521 (https://www.ti.com/product/TPD12S521) Few pages back I've posted connection schematic, but I took it straight from the datasheet.

For the FPGA driving this chip, you will need a group of 8 series resistors.  You can use this resistor pack:
https://www.digikey.com/en/products/detail/yageo/YC248-JR-0733RL/1005206 (https://www.digikey.com/en/products/detail/yageo/YC248-JR-0733RL/1005206)
Or, 8 individual 0402 33ohm resistors.
Were you able to find a connection schematic for CV driving HDMI directly? All that I could find was either using transceivers + retimer, or interface chip a-la TFP410.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 08:22:38 pm
The Cyclone IV can't handle 135MHz without some (serious, I'm guessing) work on the HDL.  I wonder if the Cyclone V will be any better?
The problem actually isn't with the 135MHz, when addressing that core ram it will be retaining the 270MHz let alone 250MHz.  The massive free gates on the CycloneV will give the compiler space to generate a 135MHz core easily.  To Achieve the 250/270MHz core dualport ram the entire size of the chip, we will probably need to add 1 additional clock cycle on the write data port, or read data port.  At absolute worst, on both sides.  This wont effect functionality as the core was already written to handle a 'PIPLINE' parameter which we have located in all the right places for easy accommodation.

The second choice is to switch from maximum 15 layers to maximum 12 layers where the core will now be 200/216MHz as I described a few posts back.  (IE 100/108MHz for the geometry engine)

Since with the DDR2/3 ram, you will get another 2 layers, you would be going from 17 layers to 14 layers.

Note that my old CycloneIII video scaler image processor had a 216MHz core, though, it processed 6 1080p video images, 3 in 2 out in parallel.  It also had 4GB or 128bit DDR2 ram on SODIMM modules.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 08:35:32 pm
For the FPGA driving this chip, you will need a group of 8 series resistors.  You can use this resistor pack:
https://www.digikey.com/en/products/detail/yageo/YC248-JR-0733RL/1005206 (https://www.digikey.com/en/products/detail/yageo/YC248-JR-0733RL/1005206)
Or, 8 individual 0402 33ohm resistors.
Were you able to find a connection schematic for CV driving HDMI directly? All that I could find was either using transceivers + retimer, or interface chip a-la TFP410.
Altera's LVDS signal levels and strengths can be configured to match an Artix6 LVDS IO port where I found an example HDMI direct transmitter which uses 33 ohm series resistors and the circuit expects the receiving display to have a 50ohm termination.

Though Intel does support HDMI/DP direct on the Cyclone 10 with a free HDMI transmitter megafunction, it pains me that they don't have any schematics laying around, yet, they do have scope shots and timing eye diagrams of the FPGA plugged into an analyzer.

By all counts, in theory, Nockieboy just needs to configure Intel's HDMI transmitter generator megafunction to the right IOs and PLL and it should make him an HDMI video signal from the GPU's parallel 24bit video data + syncs output port.  I did not read enough to see if it supported embedded audio.  If not, Nockieboy will need to code his own.  At least the standard 48KHz audio format will be compatible with the DAC he will be using when using 480p or 720p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 08:56:06 pm
Though Intel does support HDMI/DP direct on the Cyclone 10 with a free HDMI transmitter megafunction, it pains me that they don't have any schematics laying around, yet, they do have scope shots and timing eye diagrams of the FPGA plugged into an analyzer.
DisplayPort is different because it uses "normal" ac-coupled differential lines without any DC offset (like pretty much all other high-speed serial standards do - SATA, PCIE, USB 3.x and many others), and with 100 Ohm differential termination at the receiver side, while HDMI uses single-ended 50 Ohm termination to 3.3 V for both sides of a diff pair independently.
 
In Xilinx world TMDS is actually often used as a poor man's LVDS when you have no control over Vccio (say you have a devboard and can't change it), as "normal" LVDS requires 2.5 V Vccio, while TMDS is the only differential IO standard that works at 3.3 V Vccio - and vast majority of affordable devboards out there power Vccio with that voltage.

Xilinx has "UG471 - 7 Series FPGAs SelectIO Resources User Guide" which covers all supported IO standards, including available (or required as the case may be) termination schemes, additional parameters and stuff like that - basically it contains everything you will ever need to know about using IO cells and all modules that are contained into them (like SERDES, DDR cells or delay blocks). Does similar user guide exist for CV devices? If it does, that's where I'd go for details about TMDS implementation.

By all counts, in theory, Nockieboy just needs to configure Intel's HDMI transmitter generator megafunction to the right IOs and PLL and it should make him an HDMI video signal from the GPU's parallel 24bit video data + syncs output port.  I did not read enough to see if it supported embedded audio.  If not, Nockieboy will need to code his own.  At least the standard 48KHz audio format will be compatible with the DAC he will be using when using 480p or 720p.
Is this megafunction available for free, or you have to pay for it?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 09:22:50 pm
Yes, we will be using the cheap 3.3v powered IO bank trick for HDMI, though I bet 2.5v would also work since in the displays, there are adaptive cable length equalizers.

Section 5 here has the long version of the programmable IO specs:
https://www.intel.com/content/www/us/en/programmable/documentation/sam1403481100977.html#sam1403477508169 (https://www.intel.com/content/www/us/en/programmable/documentation/sam1403481100977.html#sam1403477508169)

If we wanted DP's AC coupling we might need to use onboard terminators.

Specific IO drive capabilities here:
https://www.intel.com/content/www/us/en/programmable/documentation/mcn1422497163812.html#mcn1419933398989 (https://www.intel.com/content/www/us/en/programmable/documentation/mcn1422497163812.html#mcn1419933398989)

After checking the above (Periphery Performance), I was wrong, the CV-7 is specified to clock out 740mbps on any true differential IO pair.  That's only a puny 2.5Mhz slower than 720p's 742.5mbps.  CV-6 can go up to  840mbps.  I believe 720p will work without issue.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 09:43:46 pm
Section 5 here has the long version of the programmable IO specs:
https://www.intel.com/content/www/us/en/programmable/documentation/sam1403481100977.html#sam1403477508169 (https://www.intel.com/content/www/us/en/programmable/documentation/sam1403481100977.html#sam1403477508169)
Thanks for the link - this is what I was looking for! Why it's so hard to find via google? Xilinx user guides almost always pop up on the first page of google results...

Yes, we will be using the cheap 3.3v powered IO bank trick for HDMI, though I bet 2.5v would also work since in the displays, there are adaptive cable length equalizers.
That's not gonna work - according to your link, all differential output drivers require Vccio of 2.5 V or lower, and I finally got my answer that TMDS indeed is not supported directly. That explains my lack of success in trying to find a schematic for direct connection... This sucks all around |O At this point I personally wouldn't risk spinning a board with "invented by me" solution until I built some kind of prototype using any existing devboard and seen it actually working and connected display actually showing something.
One more reason to jump the ship :horse:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 09:47:03 pm
By all counts, in theory, Nockieboy just needs to configure Intel's HDMI transmitter generator megafunction to the right IOs and PLL and it should make him an HDMI video signal from the GPU's parallel 24bit video data + syncs output port.  I did not read enough to see if it supported embedded audio.  If not, Nockieboy will need to code his own.  At least the standard 48KHz audio format will be compatible with the DAC he will be using when using 480p or 720p.
Is this megafunction available for free, or you have to pay for it?
It's available and I can enter it into Nickieboy's GPU.  I need to wire it to IO pins and compile it to see, but his current 144pin IC doesn't have enough differential IOs free.

On Intel's site, it points to 'Premier' which means pay.

Below, I found a Displayport adapter IO board for the -GX versions of the FPGA.  The are using only the 2 series resistors, but probably the IOs are configured and powered at 2.5v.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 12, 2020, 09:58:15 pm
It's available and I can enter it into Nickieboy's GPU.  I need to wire it to IO pins and compile it to see, but his current 144pin IC doesn't have enough differential IOs free.
You don't need to have an actual FPGA in hands to run P&R and see if it closes the timing. Just pick the device that it currently planned to be used on a new board, and see if you can fit everything and close timing.
Below, I found a Displayport adapter IO board for the -GX versions of the FPGA.  The are using only the 2 series resistors, but probably the IOs are configured and powered at 2.5v.
If my memory serves me DisplayPort specifies 1.62 Gbps per lane minimum bandwidth so that adapter has to use dedicated transceivers and not regular user IO pins, as none of the latter are fast enough.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 10:18:15 pm
If you want to re-buffer the LVDS from the CV, you can use this chip:
https://www.digikey.com/en/products/detail/texas-instruments/TDP158RSBR/7312817 (https://www.digikey.com/en/products/detail/texas-instruments/TDP158RSBR/7312817)

It also has the level I2C shifter and seems to not require and ESD module.

Still cheaper than the TFP410, but no longer 83cents.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 10:20:48 pm
You don't need to have an actual FPGA in hands to run P&R and see if it closes the timing. Just pick the device that it currently planned to be used on a new board, and see if you can fit everything and close timing.
Below, I found a Displayport adapter IO board for the -GX versions of the FPGA.  The are using only the 2 series resistors, but probably the IOs are configured and powered at 2.5v.
If my memory serves me DisplayPort specifies 1.62 Gbps per lane minimum bandwidth so that adapter has to use dedicated transceivers and not regular user IO pins, as none of the latter are fast enough.
Yup, it's the drive capability and the CV though slower can create the same differential voltage and current on it's 740mhz differential outputs.  Just not the same speed or rise and fall characteristics.

The above buffer chip will guarantee an HDMI compliant cable drive levels and the CV's differential output is fast and clean enough for 480p & 2.5mhz shy of 720p unless we use a CV-6 speed grade.

(*** But, it needs some I2C settings...)

There are probably cheaper HDMI buffer/translators since we only need regular 1080p performance.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 10:33:02 pm
Found one, dirt cheap, under 1$:
https://www.digikey.com/en/products/detail/nxp-usa-inc/PTN3366BSMP/5981060?s=N4IgTCBcDaIAoBUByBmFA2dIC6BfIA (https://www.digikey.com/en/products/detail/nxp-usa-inc/PTN3366BSMP/5981060?s=N4IgTCBcDaIAoBUByBmFA2dIC6BfIA)

We are now on-par with the 83cent ESD IC, except this NXP has an adaptive amp which only needs a 700mv swing from the source, AC coupled meaning it don't care about DC offset.  Well within CV's differential LVDS output drive capabilities.

Level shifter for DDC and HPD.

No controls other than a 2 bit fixed pre-emphasis gain control.
Straight traces to boot!

Actually now, VLF DC signals are bothering me...
Maybe the series DC filter caps may be omitted, or at least replaced with series resistors depending on the amp's internal 'input bias' voltage on it's internal termination resistors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 12, 2020, 11:01:45 pm
Found one, dirt cheap, under 1$:
https://www.digikey.com/en/products/detail/nxp-usa-inc/PTN3366BSMP/5981060?s=N4IgTCBcDaIAoBUByBmFA2dIC6BfIA (https://www.digikey.com/en/products/detail/nxp-usa-inc/PTN3366BSMP/5981060?s=N4IgTCBcDaIAoBUByBmFA2dIC6BfIA)

We are now on-par with the 83cent ESD IC, except this NXP has an adaptive amp which only needs a 700mv swing from the source, AC coupled meaning it don't care about DC offset.  Well within CV's differential LVDS output drive capabilities.

Level shifter for DDC and HPD.

No controls other than a 2 bit fixed pre-emphasis gain control.
Straight traces to boot!

Trying to catch up with the conversation, I'm like :scared:

So this won't need the terminating resistors, or the ESD protection?  Looks like another darn QFN to me, though. ::)  I think I'm more concerned about soldering those than the BGAs!  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 12, 2020, 11:10:10 pm
Found one, dirt cheap, under 1$:
https://www.digikey.com/en/products/detail/nxp-usa-inc/PTN3366BSMP/5981060?s=N4IgTCBcDaIAoBUByBmFA2dIC6BfIA (https://www.digikey.com/en/products/detail/nxp-usa-inc/PTN3366BSMP/5981060?s=N4IgTCBcDaIAoBUByBmFA2dIC6BfIA)

We are now on-par with the 83cent ESD IC, except this NXP has an adaptive amp which only needs a 700mv swing from the source, AC coupled meaning it don't care about DC offset.  Well within CV's differential LVDS output drive capabilities.

Level shifter for DDC and HPD.

No controls other than a 2 bit fixed pre-emphasis gain control.
Straight traces to boot!

Trying to catch up with the conversation, I'm like :scared:

So this won't need the terminating resistors, or the ESD protection?  Looks like another darn QFN to me, though. ::)  I think I'm more concerned about soldering those than the BGAs!  ;)
No term resistors.  See the data sheet, though, you will need 8 series 0402 caps.  Not a nightmare...

Same hot air + you can use a normal soldering irons to fix bad connecting pins.  It's actually easier than your current 144pin TQFP since you cannot damage any pins.  See here: https://youtu.be/BvhE16vBfX4 (https://youtu.be/BvhE16vBfX4)

Just make sure the PCB footprint you use has long pins like in the video.  Though, they do not need to be that long.

Even  Farnell element14 has the PTN3366BSMP dirt cheap.
And you know that amp IC will drive an HDMI cable at full length.
And with this setup, you should be able to drive a 720p signal through the cable if you like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 13, 2020, 02:35:58 am
That solution still kind of smells to me because of too many unknowns for my taste. If I would be doing it, I would build a quick prototype first with just that HDMI out circuit and connect it to one of my devboards to check that it will actually work, before committing to a full board. So I think you should consider laying out a quick prototype and check it up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2020, 07:56:14 am
That solution still kind of smells to me because of too many unknowns for my taste. If I would be doing it, I would build a quick prototype first with just that HDMI out circuit and connect it to one of my devboards to check that it will actually work, before committing to a full board. So I think you should consider laying out a quick prototype and check it up.

Not a bad idea.  Nockieboy does have a C-IV dev board (though traces aren't matched length to IO expander connectors) and a cheap 5$ 2 layer PCB with this, IC and HDMI connector & a few SMD caps would cost under 15$ total.
He just needs to generate simple color bars and sound, IE using his existing sync gen with hard-generated test pattern -> home coded HDMI encoder -> 10:1 serializer.
I know you shouldn't expect anything other than 480p to work under these un-matched trace length feeding the amp circumstances, but maybe even 720p might make it through with this buffer amp which will generate a balanced output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2020, 08:29:19 am
Yes I'd been thinking about putting a test PCB together to confirm that the solution works, I just didn't know if the unmatched, non-paired traces going through header pins on the dev board to a second PCB would create more problems.  If I can get 480p out of the dev board, then I'd be totally happy getting rid of the VGA output on the new GPU card.

It'll delay the actual GPU card production by a few weeks/month, but I think it's worth it for my peace of mind and will give me some time to focus back on finishing the ellipse drawing function.

Just need to confirm that the dev board has the right IOs available for the job, though.  Have attached the schematics for the dev board I'm using.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2020, 09:23:47 am
Yes I'd been thinking about putting a test PCB together to confirm that the solution works, I just didn't know if the unmatched, non-paired traces going through header pins on the dev board to a second PCB would create more problems.  If I can get 480p out of the dev board, then I'd be totally happy getting rid of the VGA output on the new GPU card.

It'll delay the actual GPU card production by a few weeks/month, but I think it's worth it for my peace of mind and will give me some time to focus back on finishing the ellipse drawing function.

Just need to confirm that the dev board has the right IOs available for the job, though.  Have attached the schematics for the dev board I'm using.

Look at FPGA pins -> Header P2 pins: (use 4 adjacent pairs for the HDMI digital data)
38p/39n -> 38/37
49p/50n -> 32/31
52p/53n -> 29/28
54p/55n -> 27/26
59p/60n -> 24/23
ARRRRGGGG, these IO also go to a SDRAM chip according to the schematic...  Maybe cut the traces or remove the ram chip...

You only need 4 of these pairs.  They are all located on header 'P2'.
The other signals, I2C & HPD and output enable control & gain signals may be wired to any other IOs.

I would make a narrow PCB which sits on the P2 Header itself.  Make sure you can make JLPCB's cheap 5$ for 5PCBs fit on that connector.  It may need to be a bit narrower which is why I listed all the possible matched N/P pairs.

Also, make sure you have the ability to change the dev-board's 3.3v regulator for a 2.5v since we will use want to use that IO voltage on the Cyclone V.  NXP's amplifier chip only requires a differential 300mv signal coming in to drive the full TMDS output.  It has auto level, auto gain and a 4 level set-able high frequency/edge enhancement boost capability set by 2 input pins.

Your test PCB should have the 8 series caps like in the schematic, but, it should also have 4 parallel load resistors just before the caps as an extra termination option.  Also, the HDMI TMDS outputs should have test points, even though garbled, at least your 25MHz scope should be able to see the TMDS pixel clock line which is also 25MHz.

All other IOs should be wired as shown in the NXP datasheet.

Note that CycloneV no longer has the lower/higher FMAX speed restrictions of some IO banks compared the CycloneIV, so, some of the n/p pairs we have chosen have a 500MHz limit unlike the higher 740MHz LVDS limit of every differential pair on the CycloneV, so our goal here is 250MHz 480p and audio.  720p is not expected to work here.

Check the actual layout of your dev board so you may choose the straightest traces.  You may also swap the n&p as in the FPGA, the buffer would be driven with negative logic.  The important thing here is that you are using the pairs.


Again, check JLPCB's maximum dimensions for that 5$ for 5pcb deal and check if you can make a PCB which will at least to pin 32 of header P2.  Any extra space should just have a header going off the edge of the PCB and you should get a female dual inline header with gold plated pins to plug your test PCB onto the dev board.


Prep this PCB quick, then we can get onto doing the HDMI encoder and you also have the filled ellipse to finish in the geo unit.

Once confirmed, you can then edit the new CV GPU to your liking.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2020, 10:22:01 am

Look at FPGA pins -> Header P2 pins: (use 4 adjacent pairs for the HDMI digital data)
38p/39n -> 38/37
49p/50n -> 32/31
52p/53n -> 29/28
54p/55n -> 27/26
59p/60n -> 24/23
ARRRRGGGG, these IO also go to a SDRAM chip according to the schematic...  Maybe cut the traces or remove the ram chip...

Do you have a good image of the dev board so I can see this layout.
You may get lucky and only have to razor cut 8 traces depending on layout.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2020, 12:20:01 pm
As a reference, here are the electrical IO characteristics/voltages & thresholds for the CV:
CycloneV datasheet (https://www.google.ca/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwj0kJe7vv_sAhUNHqwKHdZnBI8QFjAAegQIIRAC&url=https%3A%2F%2Fwww.intel.com%2Fcontent%2Fdam%2Fwww%2Fprogrammable%2Fus%2Fen%2Fpdfs%2Fliterature%2Fhb%2Fcyclone-v%2Fcv_51002.pdf&usg=AOvVaw1WFU-x9NVBGWh_cz97rOv0)

The termination connections for the different LVDS modes is in the normal CV handbook 1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 13, 2020, 01:02:49 pm
OK guys, since you liked my previous one, I have another proposal 8) Whenever I start working with new (for me) FPGA, I always design and build a simple breakout devboard with the bare minimum components to run the FPGA, and some memory (as you usually can't connect it via connectors) and just a couple of LEDs and buttons. Here is what one of those boards look like:
(https://i.imgur.com/RVsPWrIl.jpg)

This devboard contains 256Mx16 (512 Mbytes total) DDR3L memory device and a single dual-color LED. It also contains HDMI out because I had some spare FPGA and didn't want to leave them unused. But the most important feature of this devboard are those two connectors on the bottom. These are high-speed connectors designed specifically for differential signals, each connector contains 20 differential pairs rated for 6 Gbps and beyond (depending on stackup height), I use one pair for power, so 38 user IO pins total, which I implemented as 19 differential pairs per connector, and all of the pairs going to the same connector are length-matched. As you can see, because of the way it's wired, one of connectors only supports 1.8 V logic levels, while another one is configurable - the board gives options of 1.8 and 3.3 V via zero ohm resistor placement, but it's possible to connect external DC-DC converter with any Vccio.

As you can see, this devboard is quite versatile for prototyping despite it being very simple. These Samtec connectors are quite expensive, but they send out free samples to anyone - I requested a 10 pairs of those connectors and they sent them to me for free the next day, and even paid for express postage via UPS.

My proposal is for you to design and build a similar devboard for your FPGA of choice. Place the memory device on a board, and connect the rest of IOs to connectrors like the one I use. If you length match all lines going into a single connector, you can then build whatever addon boards with prototype circuits you need as this gives a lot of freedom. Also ensure at least one of those high-speed connectors has configurable Vccio voltage - again to add more versatility to the board. Since that devboard is going to contain the very minimal set of components, it shouldn't be very expensive to make, but I think it will prove itself useful many times over in the future - like did the devboard pictured in the beginning of this post. I understand that it's going to sidetrack this project even more, but again, I think it will be worth it at the end of the day.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2020, 10:49:13 pm
Here's attempt No.1 for the DVI output card.  Have done what I can with it, but there's probably loads of things wrong with the power layout.  The entire bottom layer will be ground plane, aside from a few power traces to connect nets.  All signals on the top layer.  I probably need to add more decoupling caps to the top and spread out some power planes on the top layer?

PCB layout also included, very rough draft and I know I can make it smaller.  Not overly concerned about keeping it under the $5 mark, to be honest.  I'll be paying more for postage than I will for the PCBs, no matter what.  Might add a few LEDs and a PCM5101 to make it even more useful.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 13, 2020, 11:03:20 pm
Do you have a good image of the dev board so I can see this layout.
You may get lucky and only have to razor cut 8 traces depending on layout.

Here's a couple of images.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 13, 2020, 11:37:03 pm
Do you have a good image of the dev board so I can see this layout.
You may get lucky and only have to razor cut 8 traces depending on layout.

Here's a couple of images.
Everything is fairly straight.
You should have no problems with 480p.  To attempt 720p, you would just need to remove the ram chip or cut the 8 traces to the ram.  Though, if 480p works, I wouldn't bother.

Just do as I said in the last post and start by making a PCB with the amp chip & a 3.3v regulator being fed from the 5v on the connector.

for each data pair, use this wiring:

   VCCIO
        |
      50Ohm 0603
        |
IOp ---> 0603 .1uf ---> NXPINp
IOn ---> 0603 .1uf ---> NXPINn
        |
      50Ohm 0603
        |
    VCCIO

(You may swap the n&p if it will keep the routing straight)

I checked the datasheets and differential driver & receiver's capabilities for both chips.  The above circuit covers the worst case scenario.
Most likely, you will test with the 0.1uf changed for jumpers or 50Ohm or 25Ohm resistors ignoring the other 2 50Ohm terminators to VCCIO as in DC mode, the NXP chip has built in 50ohm pullup terminators to it's own internal 1.8v reference.  The NPX chip is specified to support differential inputs with voltage swings anywhere from 0.3v through biased to 1.8v.

The 3.3v regulator will power the NXP amp.

The 3.3v VCCIO coming from the dev-board's connector will be used to power the VCCIO 50 ohm terminators.
When powering the CIV to 2.5v (make sure you purchase a 2.5v regulator for your dev board), this 3.3v will change with it.  This will be in proper spec for the CV differential output in  Differential SSTL-2 Class I & II & the NXP internal 50 Ohm terminator will be almost in spec with jumpers in place of the 0.1uf caps.  With 25ohm series resistors in place of the 0.1uf caps, the pull-up load of CIV's differential outputs will be completely within spec.  (SSTL-2 requires a 50ohm to 1.25v termination.  The NXP has a 50ohm to 1.8v termination.  The series 25 ohm lowers the pullup current on the CIV output driver to appear very close to as if a 50ohm was tied to 1.25v since now it will look like a 75 ohm tied to 1.8v)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 12:09:35 am
Here's attempt No.1 for the DVI output card.  Have done what I can with it, but there's probably loads of things wrong with the power layout. 
The ground connections between HDMI lines at connector are not good. Get rid of that trace, and instead add a via to the ground right next to each ground contact. And try getting into the habit of using a via with the shortest possible trace to it any time you need a connection to the ground (or power in case of 4+ layer boards). Long power/ground traces render decoupling capacitors useless as current can't get to device fast enough due to trace inductance.
Also try to make all HDMI lanes the same length. You've got a ton of space on a board, so that shouldn't be a problem at all. Unbroken ground plane under HDMI traces is a must.
Next, add a low dropout Shottky diode between connector's +5V line and the rest of the board to prevent backpowering of your board from the HDMI sink - it should let the current go from your board into connector, but should block reverse direction. As per HDMI spec the max. current through 5V line should not exceed 50 mA, so you don't have to add anything beefy.
Finally, it's usually not the greatest idea to connect a metal shroud of connector directly to the ground, instead do it via fat 1M resistor (I usually use 1206 size) and a high-voltage 1nF capacitor (again 1206 size) directly across that resistor. This will allow static charge to safely discharge into the ground via resistor, while shorting HF signals directly to the ground via capacitor.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 12:13:30 am
Yup, the bottom of that PCB should be all GND filled.
And each HDMI GND pin should have it's own VIA to that GND layer.

Make sure there are 100nf caps for each supply pin on the NXP IC and at least 3 for the 50 ohm pullup terminator resistors.

Also add 1 10uf for each supply rail.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 12:16:59 am
Also - I would consider going for 0.8 mm PCB instead of standard 1.6 mm if possible, that will bring HDMI traces' impedance closer to their spec of 50 Ohm single ended/100 Ohm differential impedance. Remember - the thinner the isolation between trace and a reference plane, the lower the impedance.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2020, 02:57:40 pm
Latest update on the DVI card.  Think I've taken into account all the advice above, with the exception of HDMI signal length matching.  Let me know if the power trace positioning on the bottom layer is okay.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2020, 03:08:08 pm
Everything is fairly straight.
You should have no problems with 480p.  To attempt 720p, you would just need to remove the ram chip or cut the 8 traces to the ram.  Though, if 480p works, I wouldn't bother.

That's great then - I don't want to be cutting traces on the dev board if I don't have to.  Never know if I might need to use the dev board to test out some DRAM interface...  ;)

Also, just had a quick look at the schematic for the dev board to see what negative affects swapping the 3.3V regulator for a 2.5V one would make - can't see any issues to my untrained eye, other than perhaps the 50MHz crystal getting 2.5V instead of 3.3V, but that shouldn't be an issue for the FPGA, hopefully.  I actually have some 2.5V AMS1117s somewhere, might swap that regulator this weekend and test to make sure it's all still working okay (with the exception of anything on the IOs that only works with 3.3V, obviously).

OK guys, since you liked my previous one, I have another proposal 8) Whenever I start working with new (for me) FPGA, I always design and build a simple breakout devboard with the bare minimum components to run the FPGA, and some memory (as you usually can't connect it via connectors) and just a couple of LEDs and buttons.

This is a good idea, asmi, but I'm really wanting to push forward on the GPU project.  I'll give this suggestion some serious thought once I've got a run of GPU cards and can start on the HDL side for the Cyclone V.  Seems like a good way to practice some BGA soldering - if I can make the dev cards small enough and cheap enough, it won't hurt to use them to get confident in BGA soldering.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 03:40:42 pm
Add these 4 Differential LVDS compliant 100 ohm resistors.
See photo.
Note that the Cyclone's differential IO's have software controlled series and parallel resistors and support many differential SSTL & LVDS modes.  The NXP seemed to be designed to take almost anything, even after a long cable and automatically amplify the signal into a DVI/HDMI TMDS compliant signal to drive through another cable.

With our test board, we will pick the cleanest functional solution, though, I do admit it would be a pluss if you had access to a 500MHz scope...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2020, 04:31:22 pm
Added the terminating resistors - is there a particular part I should be looking for on Mouser for these, or will any 0603 100 ohm resistors do?

With our test board, we will pick the cleanest functional solution, though, I do admit it would be a pluss if you had access to a 500MHz scope...

Yeah, wish I had one of those too.  Or the money for one.  They seem to range from $350 upwards on eBay.  My oscilloscope is only 20MHz by the way, not 25.  :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 04:33:11 pm
Added the terminating resistors - is there a particular part I should be looking for on Mouser for these, or will any 0603 100 ohm resistors do?
Any 0603 will do.  Also, for the 50ohm, 51ohm will also do if there is no stock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2020, 04:41:14 pm
Any 0603 will do.  Also, for the 50ohm, 51ohm will also do if there is no stock.

Marvellous.  All good then?  Happy with the design?  I'm going to be ordering parts for the main GPU card at the same time - minus the TFP410s and ADV7125s.  Any ideas on DDR RAM?  Would like to order that at the same time to save on shipping.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 05:05:51 pm
Marvellous.  All good then?  Happy with the design? 
Can you pls post latest schematics?

I'm going to be ordering parts for the main GPU card at the same time - minus the TFP410s and ADV7125s.  Any ideas on DDR RAM?  Would like to order that at the same time to save on shipping.
It depends if you want DDR2 or DDR3. Latter has more capacity for the same price, and it's always nice to have more memory, but on the downside it's going to require additional DC-DC converter because DDR3 is powered by 1.5 V (DDR3) or 1.35 V (DDR3L). The latter one is a bit more picky about layout, but it consumes less power, and even DDR3 is more power-efficient than DDR2. That said, I've personally never had any problems with DDR3L implementation, so maybe that "picky-ness" only manifests at much higher frequencies than I was running at, and lower power means memory device stays cooler. Also all DDR3L parts are 100% backwards compatible with DDR3 and can be ran at 1.5 V as well as 1.35 V.
For DDR2 I recommend MT47H128M16RT part (it's 128Mx16=256 Mbytes part, the maximum capacity available for DDR2), for DDR3 - MT41K256M16TW - this one is 256Mx16=512 Mbytes part. There are larger capacity DDR3 devices out there (8Gbit parts or even dual-die 16 Gbit ones), but they are disproportionally more expensive in my opinion.
Also keep in mind that you can always install smaller capacity memory device on a board designed for larger one - higher address lines just won't be used. So I always recommend to do a layout for the largest capacity possible, but use what you think is reasonable. This way if you will require larger capacity down the road, you can just install larger device onto the same PCB without making any changes to the board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 05:18:06 pm
This is a good idea, asmi, but I'm really wanting to push forward on the GPU project.  I'll give this suggestion some serious thought once I've got a run of GPU cards and can start on the HDL side for the Cyclone V.  Seems like a good way to practice some BGA soldering - if I can make the dev cards small enough and cheap enough, it won't hurt to use them to get confident in BGA soldering.  :-+
That's OK and of course it's your call. The reason I usually begin with such board is very simple - since nobody helps me with schematics, I need to make sure I did all basic connections right (things like PLL connection, flash memory, JTAG, etc - things you need to get right for FPGA to even work at all). And since the very first project on a new (for me) FPGA carries much higher than usual risk, I'd rather retire it on simpler board first, as it would be cheaper to respin it if I screw something up.

That said, you always need to be prepared for the fact that you will very likely need to do a one or two revisions before you get everything working as it should. This is unfortunate, but this has been my experience - in most my devboards the first revision is screwed up beyond repair as I got some major thing wrong, second revision kind of works (found more issues, but they are usually fixable via some bodging and cutting), and only third revision is perfrect and works 100% how it was intended. By now I have a dedicated "box of shame" where I store all my screwed up revision A boards as a reminder not to rush into production and instead check everyting many many times over. There are very things which are worse than finding a major flaw in your board just as it went into manufacturing and you already know it's going to be a fresh addition to the "box of shame" even though it doesn't even fully exist yet |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 05:42:14 pm
RAM table:
Code: [Select]
Example possibilities :

DDR2 - W9751G8NB-25     =  64mx8  - 1.8v - 60 ball BGA  2.80$
       W9751G6NB-25     =  32mx16 - 1.8v - 84 ball BGA  2.08$
DDR3 - W631GG8MB-12     = 128mx8  - 1.5v - 78 ball BGA  1.76$
       W631GG6MB-11     =  64mx16 - 1.5v - 96 ball BGA  1.00$

8 bit ram IO requires:
Requires (8bit data + DQSn/p bank + PLLoutn/p) + address + banks + odt/cs/ras/cas/we
         (        8 + 2 +           2        ) + 14      + 2     + 5
----------------------------------------------------------------------
                12 (1 bank with DQ & DQS pair) + 21 regular IOs at ram IO voltage


16 bit ram IO requires:
Requires 2DQbank(16bit data + 2xDQSn/p bank + 1xPLLoutn/p) + address + banks + odt/cs/ras/cas/we
         2DQbank(        16 + 4             + 2          ) + 14      + 2     + 5
----------------------------------------------------------------------
                 22 (2 banks with DQ & DQS pair) + 21 regular IOs at ram IO voltage

Add 3-4 more IOs for DDR3.
Check the data-sheets.  If you can run the DDR3 as slow as 200MHz, 400mtps, then go for DDR3 for sure.
If you can achieve 16 bit, then go for 16bit, though, you will need to make at least 3-4 IO banks at 1.5v.
You will need to change the 1.8v/1.5v linear regulator to a switcher just in case.  DDR2/3 do draw more power.

Other ram manufacturers will work.
I have never done a DDR3 design before, only DDR2.
(Been retired from electronics for 10 years now.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 06:01:30 pm
Check the data-sheets.  If you can run the DDR3 as slow as 200MHz, 400mtps, then go for DDR3 for sure.
Didn't you say that CV can run DDR3 at 325 MHz (or something like that)? I think the minimum for DDR3 with DLL on (which is a normal mode of operation for DDR3) is 300 MHz.
This External Memory Interface Spec Estimator (https://www.intel.com/content/www/us/en/programmable/support/support-resources/support-centers/external-memory-interfaces-support/emif.html) says that hard memory controller (which is present in all CV devices, some have more than one such block) can run DDR3 and DDR3L at 333 MHz in CV grade C8.

If you can achieve 16 bit, then go for 16bit, though, you will need to make at least 3-4 IO banks at 1.5v.
For sure go for x16 - that's double the bandwidth essentially for free as x16 memory chips are readily available.
You will need to change the 1.8v/1.5v linear regulator to a switcher just in case.  DDR2/3 do draw more power.
Agreed. Switchers also have better transient response, which is beneficial for memory.

Other ram manufacturers will work.
I only ever used Micron devices because as far as I can tell, it's the only manufacturer that has published full HDL simulation models for their memory devices. And the latter is a big thing if you're trying to implement a memory controller yourself.

I have never done a DDR3 design before, only DDR2.
(Been retired from electronics for 10 years now.)
I have done both DDR2 and DDR3L recently, and there is no substantial difference between them as far as layout does - at least when operating at lower frequencies (400 MHz and below). If you need to run faster, than you will need to do 40 Ohm traces instead of 50 Ohm ones, and it's significantly more tricky without using some expensive prepreg materials. The controller is different though due to the requirement of doing the write levelling for fly-by routing, but since I only ever used pre-made controllers, I didn't have to worry about these differences at all. And I don't think write levelling is really required for a single x16 memory device - it is more for cases when you have multiple memory devices (like using DIMM module).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 07:46:45 pm
Check the data-sheets.  If you can run the DDR3 as slow as 200MHz, 400mtps, then go for DDR3 for sure.
Didn't you say that CV can run DDR3 at 325 MHz (or something like that)? I think the minimum for DDR3 with DLL on (which is a normal mode of operation for DDR3) is 300 MHz.
This External Memory Interface Spec Estimator (https://www.intel.com/content/www/us/en/programmable/support/support-resources/support-centers/external-memory-interfaces-support/emif.html) says that hard memory controller (which is present in all CV devices, some have more than one such block) can run DDR3 and DDR3L at 333 MHz in CV grade C8.

303MHz/606mtps software mode, half rate 2:1 controller.  400MHz/800mtps with hard controller which even operates in full-rate mode.   We will be running the C8 as if it were a C7.  This is not a problem as all I wanted was to match the ram clock with a multiple of the core.  If we switch the core from 250MHz to 200MHz, running the ram at 400MHz would be great.  Our geometry processor will loose a little speed.  Overclock to 432MHz would be great since that's 27Mhz * 16.  (unless we pipeline the heck out of the geo unit, we can then jump it from 100Mhz to 200Mhz.  This could be something for a later date.)

The hard controller demands that the DQ IOs and DQS and CLK out are on specific pins (this I am sure) and the address/command lines are in an adjacent bank with direct connection to the same PLL (this may be more flexible).  But, Nockieboy should read the Intel's External Memory Interface Controller's user guide to make sure we get everything right.  1 mistake means the 400MHz gets cut down to 303MHz and I would not like to make a design which has multiple clock domains.  (I do not consider 2:1 & 1:2 different clock domains as our core is wired it like a DDR inside a second DDR just fattening the data bus, or offering 2 simultaneous access ports per 1 system clock as we are currently doing)

If the NXP chip does what it claims, it should also be able to be driven by a differential 1.5v LVDS IOs.  This just helps as each IO bank has 16 IOs and using half for HDMI and half for DDR addressees may help on available IO resources.
(We can simulate driving the NXP with 1.5v LVDS on the current HDMI test board thanks to my last addition of 4x 100ohm balanced terminator resistors.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 08:15:41 pm
The hard controller demands that the DQ IOs and DQS and CLK out are on specific pins (this I am sure) and the address/command lines are in an adjacent bank with direct connection to the same PLL (this may be more flexible).  But, Nockieboy should read the Intel's External Memory Interface Controller's user guide to make sure we get everything right.  1 mistake means the 400MHz gets cut down to 303MHz
Why don't you create a design first in Quartus, including pinout, and do a complete place & route and timing analysis before you commit to manufacturing the board? This way you can be sure that the pinout you've chosen will actually work. Xilinx memory generator always generates example design along with memory controller, such that it can be actually implemented in hardware and used to check memory operation. As far as I understand, Antel memory IP does the same thing, or is it?
Whenever I work on something with high-speed IO, I always do a design first - even if incomplete, but enough to see IO part working at full speed. This saved quite a bit of revisions from being duds due to bad IO choices.

and I would not like to make a design which has multiple clock domains.
Well if you implement a cache system like I suggested few posts back, the memory frequency will not matter (as long as there is enough bandwidth of course), because working with DDR will be decoupled from the rest of design, which will work with few BRAMs, while DDR side will use it's own BRAM port.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 08:34:38 pm

Other ram manufacturers will work.
I only ever used Micron devices because as far as I can tell, it's the only manufacturer that has published full HDL simulation models for their memory devices. And the latter is a big thing if you're trying to implement a memory controller yourself.

Agreed, this one is the cheapest (Automotive DDR3): MT41K64M16TW-107, but you are paying a premium of 2x at $1.98 each.  The 128mx8 version -> MT41K128M8DA-107 <- is cheaper.  This would leave a lot of free IOs and at 800mtps, even at 8 bit, the throughput still wouldn't be too bad.

Though you would need to run the device at 1.35v, or up to 1.45v.  Otherwise you would need 2 regulators to get the 1.5v and 1.35v for ram core.

For normal DDR3, 1.5v, use this one -> MT41J128M16JT-125K <-, 128mx16 @ 2$.
This is a 1.6GHz part, can it be run at 300MHz?
256mx8 -> MT41J256M8

I wonder if there are any reduced latency DDR3 rams.  Cut down the RAS-CAS-DATA cycle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 08:38:43 pm
The hard controller demands that the DQ IOs and DQS and CLK out are on specific pins (this I am sure) and the address/command lines are in an adjacent bank with direct connection to the same PLL (this may be more flexible).  But, Nockieboy should read the Intel's External Memory Interface Controller's user guide to make sure we get everything right.  1 mistake means the 400MHz gets cut down to 303MHz
Why don't you create a design first in Quartus, including pinout, and do a complete place & route and timing analysis before you commit to manufacturing the board? This way you can be sure that the pinout you've chosen will actually work. Xilinx memory generator always generates example design along with memory controller, such that it can be actually implemented in hardware and used to check memory operation. As far as I understand, Antel memory IP does the same thing, or is it?
Whenever I work on something with high-speed IO, I always do a design first - even if incomplete, but enough to see IO part working at full speed. This saved quite a bit of revisions from being duds due to bad IO choices.

I was getting to the point of asking Nockieboy to do at minimum add a DDR3 controller to the current design with a minimal bridge to the current code (IE as Z80 read/write ram access) just so he can confirm full timing closure in Quartus with his chosen IO pin connections.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 09:09:55 pm
and I would not like to make a design which has multiple clock domains.
Well if you implement a cache system like I suggested few posts back, the memory frequency will not matter (as long as there is enough bandwidth of course), because working with DDR will be decoupled from the rest of design, which will work with few BRAMs, while DDR side will use it's own BRAM port.
I want Nockieboy to code this, not me...
And it's has nothing to do with any cache system.
The new CV has plenty of spare ram blocks for multiple dual port, true dual clock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2020, 09:10:57 pm
RAM table:
Code: [Select]
Example possibilities :

DDR2 - W9751G8NB-25     =  64mx8  - 1.8v - 60 ball BGA  2.80$
       W9751G6NB-25     =  32mx16 - 1.8v - 84 ball BGA  2.08$
DDR3 - W631GG8MB-12     = 128mx8  - 1.5v - 78 ball BGA  1.76$
       W631GG6MB-11     =  64mx16 - 1.5v - 96 ball BGA  1.00$

8 bit ram IO requires:
Requires (8bit data + DQSn/p bank + PLLoutn/p) + address + banks + odt/cs/ras/cas/we
         (        8 + 2 +           2        ) + 14      + 2     + 5
----------------------------------------------------------------------
                12 (1 bank with DQ & DQS pair) + 21 regular IOs at ram IO voltage


16 bit ram IO requires:
Requires 2DQbank(16bit data + 2xDQSn/p bank + 1xPLLoutn/p) + address + banks + odt/cs/ras/cas/we
         2DQbank(        16 + 4             + 2          ) + 14      + 2     + 5
----------------------------------------------------------------------
                 22 (2 banks with DQ & DQS pair) + 21 regular IOs at ram IO voltage

Add 3-4 more IOs for DDR3.
Check the data-sheets.  If you can run the DDR3 as slow as 200MHz, 400mtps, then go for DDR3 for sure.
If you can achieve 16 bit, then go for 16bit, though, you will need to make at least 3-4 IO banks at 1.5v.
You will need to change the 1.8v/1.5v linear regulator to a switcher just in case.  DDR2/3 do draw more power.

Other ram manufacturers will work.
I have never done a DDR3 design before, only DDR2.
(Been retired from electronics for 10 years now.)

I'm having trouble sourcing those parts you've suggested from Mouser.  I'm going through a legitimate retailer this time around rather than AliExpress for my parts and Mouser is my preference.  Would this be any good for DDR3 - MT41K128M8DA (https://www.mouser.co.uk/ProductDetail/Micron/MT41K128M8DA-107J-TR?qs=j%252B1pi9TdxUaUI1YBTL%2FtEw%3D%3D)?

Agreed, this one is the cheapest (Automotive DDR3): MT41K64M16TW-107, but you are paying a premium of 2x at $1.98 each.  The 128mx8 version -> MT41K128M8DA-107 <- is cheaper.  This would leave a lot of free IOs and at 800mtps, even at 8 bit, the throughput still wouldn't be too bad.

Getting lost in choices, here.  So we're definitely going DDR3, yes?

I like the look of this one - less signals to route = less headache for me.  ;)  And it's in stock at Mouser.  :-+

Though you would need to run the device at 1.35v, or up to 1.45v.  Otherwise you would need 2 regulators to get the 1.5v and 1.35v for ram core.

It's not like I won't have room for another supply rail with the loss of the VGA connector, but it's added complication I suppose.

For normal DDR3, 1.5v, use this one -> MT41J128M16JT-125K <-, 128mx16 @ 2$.
This is a 1.6GHz part, can it be run at 300MHz?
256mx8 -> MT41J256M8

I wonder if there are any reduced latency DDR3 rams.  Cut down the RAS-CAS-DATA cycle.

Ah, that's in stock too.  Both good suggestions - I'd prefer the 8-bit one purely for easier routing and less IO headaches, but if the 16-bit one is going to provide better performance (i.e. allow me to use it for more MAGGIEs to access), then I'm sold.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 09:22:03 pm
Though you would need to run the device at 1.35v, or up to 1.45v.  Otherwise you would need 2 regulators to get the 1.5v and 1.35v for ram core.
No, you don't - all DDR3L devices are backwards compatible to "normal" DDR3 and will work just fine at 1.5 V.
This is a 1.6GHz part, can it be run at 300MHz?
<...>
I wonder if there are any reduced latency DDR3 rams.  Cut down the RAS-CAS-DATA cycle.
Yes you can, see attached table. It lists allowed CL depending on frequency. For 303 MHz (Tck = 3.3 ns), you can run it at 5-5-5 latency, CL=5, Trcd and Trp = 13.75ns / 3.3ns ~ 4.17 which rounds up to 5 (it needs to be in whole clock periods). Maximum frequency for CL5 is 333 MHz (Tck =  3 ns). For 400 MHz (Tck = 2.5 ns) you will need to go up to CL6.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 09:33:13 pm
Ah, that's in stock too.  Both good suggestions - I'd prefer the 8-bit one purely for easier routing and less IO headaches, but if the 16-bit one is going to provide better performance (i.e. allow me to use it for more MAGGIEs to access), then I'm sold.

The main maggies will always be 14 or 15.  The DDR ram will have 2-4 additional maggie layers (8bit vs 16bit) instead of the 1 which you would have gotten with the Hyperram.

At 720p, the main maggies would drop to 6 (maybe, -C6 could do it) and the DDR3 would drop to 1-2.

The DDR3 figures leaves ~half the bandwidth for the geo-blitter-audio-SD-Card HD DMA-Floating point ALU-Z80 access and I'm assuming full 800MHz controller.

(The truth is you can at least double/triple my DDR3 maggie figures, I've left room for massive overhead using a small burst size, but if you want more maggie layers for the DDR3 ram, for safety, you will have no choice but to introduce the ability for Z80 read wait states into your Z80 bridge code & use a larger burst size when filling the output display line buffer.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 10:03:52 pm
Ah, that's in stock too.  Both good suggestions - I'd prefer the 8-bit one purely for easier routing and less IO headaches, but if the 16-bit one is going to provide better performance (i.e. allow me to use it for more MAGGIEs to access), then I'm sold.
Well x16 interface will provide you double the bandwidth at a cost of additional 12 IO balls. Whether it's worth to you or not, only you can tell. I would go for x16 as more bandwidth is always good, but it's up to you of course.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 14, 2020, 10:45:46 pm
Okay, I'm going with the MT41J128M16JT (https://www.mouser.co.uk/ProductDetail/340-135528-REEL) DRAM.  Admittedly, for me it's almost a 'pin the tail on the parts list', as I don't really appreciate the nuances of the difference choices.  Just 'more RAM is good'.  :o  Plus, if I have the IOs and can route a 16-bit DRAM up then that should be the goal, really.

Can you pls post latest schematics?

Almost missed this, asmi.  Latest schematic attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 14, 2020, 11:03:50 pm
Okay, I'm going with the MT41J128M16JT (https://www.mouser.co.uk/ProductDetail/340-135528-REEL) DRAM.  Admittedly, for me it's almost a 'pin the tail on the parts list', as I don't really appreciate the nuances of the difference choices.  Just 'more RAM is good'.  :o  Plus, if I have the IOs and can route a 16-bit DRAM up then that should be the goal, really.
I would suggest you to buy this 2Gbit part, but do the routing for the 4Gbit MT41K256M16 part. Their footprints are backwards-compatible (4G part has ball T7 for A14 line, while for 2G this ball is "no-connect"), so that in case you will want to upgrade to 512 Mbytes later on, you would be able to just drop 512 Mbytes part onto existing board and update your FPGA design.

Almost missed this, asmi.  Latest schematic attached.
I don't see anything obviously wrong, but let's wait for BrianHG's final word on this. I don't see a Shottky diode for backpowering protection and static discharge circuit for the connector's shroud, but this is probably fine for a proof-of-concept.
Oh - one thing - I don't know if you really want to bother with this, but HDMI specification demands that no damage should occur if you short any pins in any combination on the connector. In your case I only see a problem if 5V line is shorted to ground.

BTW I really like how you laid out those DC isolation caps and resistors for HDMI lanes. It's beautiful! :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 14, 2020, 11:16:09 pm
Found a mistake.  See item in red.  Your using pins 31,30 instead of 32,31.


Look at FPGA pins -> Header P2 pins: (use 4 adjacent pairs for the HDMI digital data)
38p/39n -> 38/37
49p/50n -> 32/31
52p/53n -> 29/28
54p/55n -> 27/26
59p/60n -> 24/23
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2020, 10:06:15 am
I don't see a Shottky diode for backpowering protection and static discharge circuit for the connector's shroud, but this is probably fine for a proof-of-concept.

Soooo.... I'd need to connect a Schottky diode (would a BAT54S do?) to the 5V plane just back (left) from C12?

ESD protection for the shroud?  Will google this later.

Oh - one thing - I don't know if you really want to bother with this, but HDMI specification demands that no damage should occur if you short any pins in any combination on the connector. In your case I only see a problem if 5V line is shorted to ground.

Again, will have to google this later.

BTW I really like how you laid out those DC isolation caps and resistors for HDMI lanes. It's beautiful! :-+

 ;D

Found a mistake.  See item in red.  Your using pins 31,30 instead of 32,31.

D'oh!  Well spotted, BrianHG.  Fixed.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 02:49:19 pm
I haven't got what is a Maggie. Is there any doc?

Can't you implement a simpler SDRAM controller rather than DDR3?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 03:06:02 pm
Soooo.... I'd need to connect a Schottky diode (would a BAT54S do?) to the 5V plane just back (left) from C12?
Please excuse my paint.net skills, but it's something like that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 03:11:45 pm
I haven't got what is a Maggie. Is there any doc?

Can't you implement a simpler SDRAM controller rather than DDR3?
MAGGIE is our creation.  It stands for
Quote
This (multiple) address generator/graphics instruction engine (let's follow in the footsteps of the Amiga architects and call it MAGGIE).
It all began here 1 year ago: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2783972/#msg2783972 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2783972/#msg2783972)

It is a part of this VGA controller which generate a display window.
Each 'MAGGIE' layer/display window can be any color bit depth, 1bit, 2bit, 4bit, 8bit, 16 bit color.
Each one can have separate horizontal and vertical pixel zoom sizes, window sizes, horizontal raster sizes (even values larger than the visible screen area), and can point anywhere within system memory.
Each one has a priority, IE 1 window sits on top of another with optional transparent pixels.
When using the 16bit ARGB (alpha blend mix value, R,G,B), a gradient transparency from 1 MAGGIE window layer to the next renders each pixel drawn using the alpha color value to render a true 24bit color blend selection of those 2 pixels color values.
Windows with less than 8bit 256 color can be assigned to different parts of the 2x 256 color palettes.  16bit mode is true-color mode which again can be set to 4444-ARGB color, or 565-RGB color.
The windows have active pixel collision detection.
And a MAGGIE layer can be set to tile/font mode where it's read data points to any other font/tile point in memory with that font being 8x8,8x16,16x8,16x16 pixels & the font/tile memory can also be 1bit, 2bit, 4bit ,8bit, 16 bit color.

Think of it as a hardware accelerated window system where we can display 15 windows simultaneously, each with different video modes & palettes all at once with different transparency features for overlays.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 03:19:16 pm
Work on MAGGIE began in earnest a month later here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2825238/#msg2825238 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2825238/#msg2825238)

First MAGGIE window with bugs: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2827950/#msg2827950 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2827950/#msg2827950)

First good MAGGIE window addressed to the 'Font' memory : https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2830236/#msg2830236 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2830236/#msg2830236)

First multiple MAGGIES with different bitmaps, different color depths & different palettes: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2831296/#msg2831296 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2831296/#msg2831296)

First MAGGIEs with addressed fonts/tile memory & different colors here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2843840/#msg2843840 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2843840/#msg2843840)

MAGGIE complete : https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2849948/#msg2849948 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg2849948/#msg2849948)


Those were the days...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 03:24:49 pm
Can't you implement a simpler SDRAM controller rather than DDR3?
SDRAM will consume almost as many pins as DDR3 will, but will provide about 5 times less bandwidth (400 MHz DDR vs 166 MHz SDR), and several times less capacity for the price. Infact even a single 200 MHz HyperRAM module will outperform 16bit 166 MHz SDRAM. It makes no sense to use SDRAM anymore as HyperRAM controller is going to be simpler than SDRAM controller (because the former doesn't need to concern itself with timing refreshes, while the latter does).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 03:43:43 pm
Can't you implement a simpler SDRAM controller rather than DDR3?
SDRAM will consume almost as many pins as DDR3 will, but will provide about 5 times less bandwidth (400 MHz DDR vs 166 MHz SDR)
OMG, we really do need 4-5x that bandwidth.  Especially with 8-16 channel high fidelity audio combined with our current geometry unit which needs to be able to repaint a full screen of pixels 4-5x every 1/60th of a second if we want clean full screen geometry or blitter based animation.  (And not go any slower than the current internal FPGA ram...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 04:19:29 pm
My MSO is only able to follow signals << 200Mhz. And that's my limit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 04:23:50 pm
@BrianHG thank you for you fully detailed explanation

Thinking about the HDL code, from the simplest to the most difficult, I think I can order { SDRAM, HyperRAM, DDR3 }. That's the reason why I asked about SDRAM.

Here I really like to use old PC100 and PC133 ram-modules. I can dis-solder chips from there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 04:43:27 pm
@BrianHG thank you for you fully detailed explanation

Thinking about the HDL code, from the simplest to the most difficult, I think I can order { SDRAM, HyperRAM, DDR3 }. That's the reason why I asked about SDRAM.

Here I really like to use old PC100 and PC133 ram-modules. I can dis-solder chips from there.
PC133 ram would work well as the core currently operates at 125/250MHz.  The code we will be generating would allow for any ram controller.  Having 16bit SDR 125MHz, with allowances for RAS/CAS precharge and say a CAS burst size or 16 words to match the DDR3 controller burst size, you can still run at least 1-2 MAGGIE window layers from that ram without impacting the performance anywhere else, including geo/blitter/SD-card/sound with 480p video.  You would still have access to another 15 MAGGIE windows from the core FPGA ram for sprites/multi-playfield windows.

Though, at 720p, 1 layer from the ram at 16bit color with some sacrifice if geometry/blitter performance.  At 8bit 256 color, everything should work fairly fast, maybe enough for hi-res audio as well.  The FPGA ram would shrink down to around 5 MAGGIE window layers.

Now, the geometry/blitter can still copy to and from fpga ram and external SDRAM.

Your SDRAM controller would need to support read & write with write-mask since we may be writing only particular 8 bit words within a 16 word x 16bit burst.

I'd still think about normal DDR ram running at 125MHz to double your data transfer to 250mtps.
Using old laptop SODIM DDR or PC DDR ram modules as a module might even be easier to use if 16bit varieties exist.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 05:10:14 pm
My MSO is only able to follow signals << 200Mhz. And that's my limit.
You don't need any oscilloscope to debug memory. If you did your layout right, and your controller is verified in simulation, it will guarantee correct operation.
Besides, at some point you will have to resort to using other debugging techniques than oscilloscope. Even 1080p@60 HDMI is 1450 Mbps per data lane, and I just can't afford a scope that can display such fast signals, not to mention 6 Gpbs for SATA3 for example. Thankfully, Xilinx thought about that and so they offer in-circuit debugging tools that can use the very FPGA you actually run your design on.

Thinking about the HDL code, from the simplest to the most difficult, I think I can order { SDRAM, HyperRAM, DDR3 }. That's the reason why I asked about SDRAM.
I disagree. As someone who actually implemented both HyperRAM and SDRAM controllers myself, I will say that HyperRAM is significantly simpler.
But the simplest option for me is DDR3 controller, because I don't have to design anything - I simply use the one provided by Xilinx for free.

Here I really like to use old PC100 and PC133 ram-modules. I can dis-solder chips from there.
That is way too of a stone age tech to me. Memory capacity typically isn't that big of a deal for my designs, but bandwidth is almost always a limiting factor. And here DDR3 wins big time over SDRAM, this is why I choose it for pretty much all my designs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 05:12:37 pm
Using old laptop SODIM DDR or PC DDR ram modules as a module might even be easier to use if 16bit varieties exist.
SODIMM is always 64 bit (or 72 bit for ECC modules). There are few 32bit DDR3 SODIMM modules, but they are hard to find. Vast majority of modules you can actually buy are 64 bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 05:38:01 pm
Is it possible to have a dedicated small board for just the VideoRAM, and use it as a "synonymous blackbox attached via a high density a connector" in the final project?

This way, you can focus on the DRAM controller, use XILINX's IP or Altera's one, or even your own, and it  even offers the possibility to replace the module if it goes damaged or if you need one with more ram.

If it sounds reasonable, which datalink could be used?

A serial link similar to the hyper ram? Thus a kind of DDR3 controller that talks like an hyper ram module?

For me, such solution would be great and super nice, not only because you can recycle the VideoRam board for other projects without redesigning the whole board (I think the PCB for the VideoRam is critical), but also because it decouples the "implementation" from the project design, making the project more portable, more split-able in a team, and with more possibilities on the simulator side.

What do you think about?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 05:39:25 pm
My MSO is only able to follow signals << 200Mhz. And that's my limit.
You don't need any oscilloscope to debug memory. If you did your layout right, and your controller is verified in simulation, it will guarantee correct operation.
It took almost half a year to get Nockieboy to simulate-simulate-simulate.  Read back through this thread, there are things which could have never been debugged or optimized by him, or even by myself without simulation.

We even used the antiquated Quartus9.2 built in simulation tool for it's cheap easy and quick drawing waveform entry tool and it has always told the exact truth of the functioning state of our code in functional mode.  And in timing mode, it delivered what would be the actual output timings of the FPGA at the IO pins.

Making an SDR/DDR/DDR2/DDR3 controller means making a code which will generate the outputs just like in the datasheet in functional mode while using timing mode reveals the true IO pin timing which should either be verified visually, or done properly you should set the proper IO timing restrictions in the .sdc file and let the compiler tell you if your functional simulation will be sent to the ram chip without timing violations.

The DDR rams should be as simple to operate as SDRAM, it just the power-up sequence and setting the 4 MR# (mode register) registers which tells the ram how to operate and the burst size.  For the really high speed rams, there is an additional recommended tuning parameter for read timing during this power-up sequence which can complicate things. (Typically needed if you have a motherboard with an unknown number of attached memory modules in parallel creating an unpredictable load on the data lines)  At 400Mhz with a single ram chip, I've ignored this step with DDR2 rams in past without problem by just setting the default.

Once powered up & configured, the DDR rams operate just like SDRAM with 1 or 2 optional features for terminating a read burst.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 05:54:59 pm
1 last thing about the DRAM/DDR ram memory controller.  It needs a feature to be compatible with this GPU.  When you provide a list of RAM read request addresses, the ram controller will also need to accept a list of 'Destination Address' with the read requests.  Then as valid read data is being returned, the appropriate read request 'Destination Address' needs to be provided in parallel.

2. For write requests, the ram controller will need to accept a write-mask flag which masks out every 8 bits, IE a byte wide write mask enable.

3. It would be nice to have a separate port for read & write, or, when writing, the write data should be taken from the 'Destination Address' channel which usually has the read-request's destination pointer.

If Altera's or Xilinx's ram controller cannot do this, then you will need to engineer this feature around their ram controllers and embed the ram controller into an HDL module which makes the ram controller appear to have this feature.

With these 3 functions, tying any ram controller into the current GPU should be easy after a few ports are added to the current HDL.


Also, allowing access to when the refresh cycle is permitted also a big plus...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2020, 06:08:37 pm
Latest update for the DVI test card.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 06:15:31 pm
Just thicken the 3.3v trace and add a 100nf cap to GND at the first via-resistor on the left and another after the last via-resistor on the right.

Everything else is AOK.

I see you went to town on properly protecting the HDMI port's like asmi said.
Ok, fine even though for a test PCB, connecting it to GND should have been ok.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 06:35:01 pm
Is it possible to have a dedicated small board for just the VideoRAM, and use it as a "synonymous blackbox attached via a high density a connector" in the final project?

This way, you can focus on the DRAM controller, use XILINX's IP or Altera's one, or even your own, and it  even offers the possibility to replace the module if it goes damaged or if you need one with more ram.

If it sounds reasonable, which datalink could be used?

A serial link similar to the hyper ram? Thus a kind of DDR3 controller that talks like an hyper ram module?

For me, such solution would be great and super nice, not only because you can recycle the VideoRam board for other projects without redesigning the whole board (I think the PCB for the VideoRam is critical), but also because it decouples the "implementation" from the project design, making the project more portable, more split-able in a team, and with more possibilities on the simulator side.

What do you think about?
I see no reason for going into such complexity. I already suggested making a layout for 4 Gbit part, which will give you up to 512 MBytes of RAM, if you really need more, there are 8 Gbit parts out there (though they are a bit pricey, which is why I didn't suggest it), it will give you a full 1 GByte. If you design your layout for such part, you can install any lower capacity part on that footprint because they are designed for that exact scenario (top address lines are "no-connects" on lower capacity devices). Also, if you use a single x16 DDR3 part that is soldered directly onto a board, you can get away without any termination for address/control lines because traces are going to be short, if you want to go through any sort of connector, you will have to implement a proper termination, and that will require another VTT DC-DC converter which will track Vccdq/Vccdqs. Take a close look at the DDR3 memory module (be it UDIMM or SODIMM), and you will see a whole bunch of termination resistors. They are there for a reason. So such solution will be expensive - as you will need high speed connectors, which are expensive, you will also need that memory board to be 4 or even 6 layer board to maintain proper trace impedance as well as breaking out memory devices. And in the real life I doubt you will even actually swap memory as there is no case I can think of when you can have too much memory and will want to reduce it - there is zero downside to having more memory than you need once you actually have it on a board. So if he installs a 2 Gbit module and later decide that he needs 4 Gbit one - he can simply desolder 2G part and solder 4G one in it's place, and that will stay there even if later he realized that he can use less. In the hardware world there is no downside to having more capacity than your design needs. This whole connector approach is a typical case of overengineering.
As for reusability, I've already suggested designing a sort-of breakout board first with some high-speed connectors for stuff like LVDS, HDMI and whatnot, but nockieboy said that he wants to get this GPU board completed first. This GPU board is purpose-designed for a specific application, so there is no need nor there is a possibility for reusing it for something else.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 06:49:01 pm
1 last thing about the DRAM/DDR ram memory controller.  It needs a feature to be compatible with this GPU.  When you provide a list of RAM read request addresses, the ram controller will also need to accept a list of 'Destination Address' with the read requests.  Then as valid read data is being returned, the appropriate read request 'Destination Address' needs to be provided in parallel.

2. For write requests, the ram controller will need to accept a write-mask flag which masks out every 8 bits, IE a byte wide write mask enable.

3. It would be nice to have a separate port for read & write, or, when writing, the write data should be taken from the 'Destination Address' channel which usually has the read-request's destination pointer.

If Altera's or Xilinx's ram controller cannot do this, then you will need to engineer this feature around their ram controllers and embed the ram controller into an HDL module which makes the ram controller appear to have this feature.
I can't really speak for Altera's controller as I don't have any personal experience with it (other than quick titbits I've read here and there), but Xilinx controller for DDR2 and DDR3 implements a full AXI4 slave port (though it's possible to bypass that block and use "native" user interface too if you want, and for some other memory types you will have to as they lack AXI adapter, but this is irrelevant here).
1. AXI will not provide you address along with data, but the bus specification guarantees that you will receive your read data in the same order that you've submitted your read requests, so you can add a simple FIFO where you post your read addresses as you submit read requests, and take addresses from it as you receive the read data.
2. AXI fully supported per-byte write masks
3. AXI has separate channels for reading and writing (it actually has 5 channels in total - read address, read data, write address, write data and write response). Now - I haven't actually tried sending read and write request at the same clock cycle, so I don't know what's going to happen, but I assume there is some kind of arbitration logic inside controller for such cases. Gotta check the user guide for the memory controller.

Now, from what I read, Cyclone V hard memory controller internally uses AXI bus too, so it's external Avalon-MM bus probably behaves similar to AXI bus (as it's got AXI-to-AvalonMM adapter facing outside), but I don't know this for sure.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 06:50:58 pm
I see you went to town on properly protecting the HDMI port's like asmi said.
Ok, fine even though for a test PCB, connecting it to GND should have been ok.
Schematics from these types of test PCBs often end up simply copy-pasted into final products, which is why I generally try to implement them properly on prototypes - so that I could actually copy-paste them and not think about it too much.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2020, 06:58:03 pm
Just thicken the 3.3v trace and add a 100nf cap to GND at the first via-resistor on the left and another after the last via-resistor on the right.

Everything else is AOK.

All done - see latest attachments.

I see you went to town on properly protecting the HDMI port's like asmi said.
Ok, fine even though for a test PCB, connecting it to GND should have been ok.

In for a penny, in for a pound... ;)  I'll be needing/wanting to implement these protection measures on the GPU card, so may as well test them out on the test card, too.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 06:59:51 pm
1. AXI will not provide you address along with data, but the bus specification guarantees that you will receive your read data in the same order that you've submitted your read requests, so you can add a simple FIFO where you post your read addresses as you submit read requests, and take addresses from it as you receive the read data.

Like I said, place the ram controller in a box & withing that box, handle and pipe through the 'Destination address' with the read data & data-valid flag and we will be set to go.

I hope the ram controller doesn't pause after every single read request.  My old DDR2 ram controller scanned the next read or write req and if it was in the same current access column, it would fly the command through as just a new CAS would be asserted optimizing column access automatically.

A lot of our really fast filled geometry and blitter functions are already optimized sequential reads/writes (we been though hell coding the triangles & quadrilaterals to horizontally fill each line as well as having coded a pixel writer with sub-word caching for pixel writes with less than 16bits per pixel & video scale function on blitter which knows not to repeat read or repeat write pixels when zooming and shrinking an image...)  and I wouldn't want to waste such precious cycles going through a precharge and ras cycle for nothing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 07:00:25 pm
Just thicken the 3.3v trace and add a 100nf cap to GND at the first via-resistor on the left and another after the last via-resistor on the right.

Everything else is AOK.

All done - see latest attachments.

I see you went to town on properly protecting the HDMI port's like asmi said.
Ok, fine even though for a test PCB, connecting it to GND should have been ok.

In for a penny, in for a pound... ;)  I'll be needing/wanting to implement these protection measures on the GPU card, so may as well test them out on the test card, too.  :)
Almost perfect...  You forgot to thicken the 3.3v trace going to the 50ohm pull up resistors as well as the trace underneath.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 07:04:43 pm
In for a penny, in for a pound... ;)  I'll be needing/wanting to implement these protection measures on the GPU card, so may as well test them out on the test card, too.  :)
If you have some space left on a silkscreen, I'd suggest you to write there which FPGA pins connect to which HDMI lines - this way you won't have to reference schematics too often when you'll be working on HDL design. Mixing up HDMI channels is a pretty easy mistake to make during development, and can leave you scratching your head for hours because each HDMI channel has a specific function, and they are not interchangeable (unlike say DisplayPort lanes). Ask me how do I know this |O  :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 07:10:20 pm
My MSO is only able to follow signals << 200Mhz. And that's my limit.
I feel you.  When all else fails, visual proof says something...
You can always slow down your ram clock to 200MHz when debugging.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 07:16:01 pm
I hope the ram controller doesn't pause after every single read request.  My old DDR2 ram controller scanned the next read or write req and if it was in the same current access column, it would fly the command through as just a new CAS would be asserted optimizing column access automatically.
As I understand, Xilinx controller has internal FIFOs for commands, read and write data (as it supports backpressure), but from what I read on it, it can hold rows open if it sees additional commands that refer to the same row. So it does some internal optimizations, but they are not visible outside and you get your responses in exact same order you've submitted your requests.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 07:34:44 pm
I hope the ram controller doesn't pause after every single read request.  My old DDR2 ram controller scanned the next read or write req and if it was in the same current access column, it would fly the command through as just a new CAS would be asserted optimizing column access automatically.
As I understand, Xilinx controller has internal FIFOs for commands, read and write data (as it supports backpressure), but from what I read on it, it can hold rows open if it sees additional commands that refer to the same row. So it does some internal optimizations, but they are not visible outside and you get your responses in exact same order you've submitted your requests.
I foresee Nockieboy having to implement Z80 read cycle wait states in his Z80 bridge.
And I guess we will separate the ram instruction fetch from the ram data read into 2 separate channels with 1 burst cycle sized cache on each, or whatever size the ram controller can efficiently terminate a DDR3 burst.  This way we wont throw out 8-16 sequential op-code instructuions or data bytes after a read of a new address cutting down repetitious access to the ram controller.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 07:55:18 pm
I foresee Nockieboy having to implement Z80 read cycle wait states in his Z80 bridge.
And I guess we will separate the ram instruction fetch from the ram data read into 2 separate channels with 1 burst cycle sized cache on each, or whatever size the ram controller can efficiently terminate a DDR3 burst.  This way we wont throw out 8-16 sequential op-code instructuions or data bytes after a read of a new address cutting down repetitious access to the ram controller.
How long is Z80 memory access cycle? Doesn't it take several clock cycles at 8 MHz (125 ns)? I suspect you will be able read out a whole bunch of data from DDR3 in that time frame ;D
But like I said before, you guys will need to think about implementing a DMA controller. It's just not realistic to use such slow CPU to haul around megabytes of data. A single 32bit true-color image at 720p is about 3.5 MBytes, so just loading resources into memory will take forever unless you offload it to some sort of DMA engine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 08:09:49 pm
But like I said before, you guys will need to think about implementing a DMA controller. It's just not realistic to use such slow CPU to haul around megabytes of data. A single 32bit true-color image at 720p is about 3.5 MBytes, so just loading resources into memory will take forever unless you offload it to some sort of DMA engine.
You haven't been reading this thread, have you?
Search for SD-Card hard drive emulator.
What do you think the blitter also does.
Also, the math-co FPU & sound system.
The Z80 will be able to play realtime video from the SD-Card and even decode and encode .mp3 simultaneously in real-time.

Why do you think I need that 'Destination Address' with the read-requests.  With that and nothing more than the existing counters, I can redirect reads into any part of the GPU core, FPGA ram, GPU peripherals/control registers, or even back into the DDR ram controller to write the read data into a new address without any other added logic.

The entire GPU system is a gigantic DMA point A to DMA point B system with the Z80 only setting the equivilant to a start address and length, or you can DMA controls into the DMA controller as well.  Even the currently fully functioning blitter does this today which is 2 loop counters with a 'hop', with a combined scaler which allows you to grow and shrink the resulting copy, perfect for realtime audio resampling playback, IE variable period/pitch.

All reads in the current system have a destination pointer sent with them, whether it is used completely or partially.  I only side-stepped this with the Z80 read req access since it was so infrequent and 1 byte at a time to it's own single destination port.

The MAGGIE just defines 15 rectangular read windows into the FPGA cache, times it's alignment to the VGA sync generator and displays them all at the same time through the BART module and palette mixer.

This was why Nockieboy decided to step up to placing the Hyperram.  Then with a little more push, IE more maggie layers direct from ram and 720p capability, we were able to push him to DDR3 at 16 bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 08:19:23 pm
If you design your layout for such part

That's the point. I am not able to design such a PCB, neither to solder such a component, but I would buy a video-ram module if it existed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 08:48:11 pm
the math-co FPU & sound system.

are you going to implement a floating point unit? with basic operations {+,-,*,/,%} or also trigonometric functions {sin,cos,tan,sinch,cosch,tanch,...}?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 08:49:02 pm
If you design your layout for such part

That's the point. I am not able to design such a PCB, neither to solder such a component, but I would buy a video-ram module if it existed.
You can always use this guy...
https://www.digikey.com/en/products/detail/micron-technology-inc/MT46V32M16P-5B-J-TR/4315379 (https://www.digikey.com/en/products/detail/micron-technology-inc/MT46V32M16P-5B-J-TR/4315379)
It will be half speed of the DDR3.  That's still very good.  But which FPGA?  The only FPGA with a TQFP good pin-count is the CycloneIII at 240pin TQFP.  All other Cyclones dropped the 240pin in favor of BGA.  Only the 144 TQFP exists for all the new ones, though, the CycloneIII is basically identical if you aren't using any CPU hard core or high speed serdes, meaning compliant with this project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 08:50:47 pm
That's the point. I am not able to design such a PCB, neither to solder such a component
How do you know that? Have you actually tried?
I was in the same position just 3 or 4 years ago - scared of BGAs and DDRs and didn't even know how to begin tackling them. But here I am now designing DDR3 interfaces and soldering BGAs without any troubles whatsoever. If you want to move past your fear of BGAs and actually design a board, begin a new thread and outline what exactly you want to accomplish. I would be more than happy to help with both schematics and layout if parts you choose to work with will be something I have knowledge about/experience with, as would others I'm sure.
As for soldering - you only need a hot air gun (even cheap-ass one from ebay would do) and some tacky gel flux to successfully solder BGA. That's it! It's a lot simpler than you think. Once you get a little practice, you will be soldering BGAs faster than SOICs and TSSOPs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 15, 2020, 08:54:39 pm
the math-co FPU & sound system.

are you going to implement a floating point unit? with basic operations {+,-,*,/,%} or also trigonometric functions {sin,cos,tan,sinch,cosch,tanch,...}?
Haven't checked up on the trig functions, but yes on all other floating and 32bit integer math with 4x4 transformation matrix being processed from DMA address A to DMA address B.  Trig exists in Intel's megafunctions, but, I have never used them.  If the trig functions are free, I'll add them as well.  We are currently using 2 hardware multipliers only out of something like 70 units.  So we have room for math processing galore.

This means instead of the current 45 degree and 90 degree rotation & mirror tricks done in the blitter, we should be able to do full rotation and perspective transformation of geometric vertices before feeding the geometry processor.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 08:55:42 pm
It will be half speed of the DDR3.  That's still very good.  But which FPGA?  The only FPGA with a TQFP good pin-count is the CycloneIII at 240pin TQFP.  All other Cyclones dropped the 240pin in favor of BGA.  Only the 144 TQFP exists for all the new ones, though, the CycloneIII is basically identical if you aren't using any CPU hard core or high speed serdes, meaning compliant with this project.
The reason QFP is dropped in FPGA world is because you can't achieve good signal integrity with that package. Same reason for memory modules, starting from DDR2 they are BGA-only. Besides BGA versions are usually more compact, which is also important for end applications as space on PCB becomes more valuable as you increase amount of layers, so there is also a financial incentive to make your PCB as compact as you can. Just think for a second what your smart phone would look like if QFPs were the only option! :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 08:58:33 pm
You haven't been reading this thread, have you?
No, I didn't read entire thread, and I'm sorry that I missed that. I take my words back then - you're way ahead of me here :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 15, 2020, 09:04:13 pm
That's the point. I am not able to design such a PCB, neither to solder such a component

In all seriousness, three years ago I started out knowing next to nothing about electronics at all, let alone PCB design.  I started out building my Z80 computer on breadboard, then progressed to PCB when I found out you could design these things and have them made for you - that was a huge step for me, but I was still designing and building with through-hole (TH) components.  By the time I'd progressed to the point that I had a working computer, I was upgrading the designs to use SMD components - albeit the larger ones like SOICS, 0805s and the odd TSSOP here or there.

Then I started on this GPU journey, now I'm confidently designing and soldering a GPU card with an EQFP-144 FPGA at its heart and 0603 components and designing a new GPU card with an FBGA-256 FPGA and DDR3 SDRAM, with 0402 components in places.

You won't know until you try - and if you try, keep pushing the envelope - you'll surprise yourself with what you can learn and what you can do.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 15, 2020, 09:39:18 pm
How do you know that? Have you actually tried?

I have been doing electronics and micro-robotics for 15 years and designed a lot of simple 2 layers SBCs, mostly are 8bit, but there are also a couple of STM32 IMU boards (full smd design), and I have also designed a couple of FPGA boards like the Papilo/Pro (Xilinx XC6, two layers, again full smd design) plus expansions, which I am able to design and to solder myself,  but that's my current limit.

So, How do I know that? Have I actually tried? Yes, I have already tried with BGAs with bad results, and to be honest, now I am thinking about the purchase an IR oven to fix it.

Besides, I tend to avoid Xilinx's IPs, I prefer to have my own HDL code, that's an other limit because you need time to design and test stuff.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 15, 2020, 10:04:17 pm
So, How do I know that? Have I actually tried? Yes, I have already tried with BGAs with bad results, and to be honest, now I am thinking about the purchase an IR oven to fix it.
Since I started working with BGAs, by now I have soldered hundreds of boards using both reflow oven and hot air gun, and I've never had a single soldering failure with BGAs. Reflow oven makes things easier for sure, but it's definitely not required for successful BGA soldering.
Still, my offer stands, if you want to design your own FPGA board and need some assistance, feel free to start a thread and point us to it. I will be happy to help. Or if you want to have a bit of a head start, you can take my Spartan-7 project sources from the link in my signature, and hack it away to add/remove peripherals as you see fit.

Besides, I tend to avoid Xilinx's IPs, I prefer to have my own HDL code, that's an other limit because you need time to design and test stuff.
I see no reason to reinvent the wheel. Once I understand how IP works internally (and Xilinx user guides are generally very good at explaining that), I have no problem using them as black boxes. For memory controllers MIG (Xilinx Memory Interface Generator) uses some undocumented hard blocks to implement write and read levelling, so you can't really implement your own unless you reverse-engineer their controller. Which is possible, as it generates normal HDL code, but I didn't have a reason to bother with it because what MIG generates is guaranteed to work over full PVT range.
Another Xilinx IP that I use extensively is their Microblaze CPU core. Unlike Altera, Xilinx provides it completely free of charge for any configuration you can think of (even 64 bit core is available!), and it also provides a great software development toolchain so debugging firmware for it is super easy and convenient. It would've taken me years to create such infrastructure myself from scratch.
That said, I don't shy away from designing custom HDL modules when I want to or need to - the latter is the case for example for HDMI/DisplayPort out, as Xilinx IP for that cost money, or was the case for HyperRAM and LPDDR1 memory - I had to design controllers myself because none of them exist in free public access.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 09:39:14 am
Just a quick question before I send this PCB off for production - I had 3.3V pull-ups for the I2C lines from the FPGA (SCL_S and SDA_S) - I'm thinking these should be VCCIO pull-ups instead.  Is that right?

If the FPGA is running its IO at 2.5V, then feeding 3.3V into the SDA and SCL lines is going to cause issues?

EDIT: Aaaaaalso, I found a wiring error on the header.  I'd used the wrong pin for one half of one of the wired pairs.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 02:25:16 pm
Just a quick question before I send this PCB off for production - I had 3.3V pull-ups for the I2C lines from the FPGA (SCL_S and SDA_S) - I'm thinking these should be VCCIO pull-ups instead.  Is that right?

If the FPGA is running its IO at 2.5V, then feeding 3.3V into the SDA and SCL lines is going to cause issues?

EDIT: Aaaaaalso, I found a wiring error on the header.  I'd used the wrong pin for one half of one of the wired pairs.  ::)
I think you f-ed up your connector.  (It's head banging time again!)
Print your PCB
Rotate your PCB 180 degree and sit it ontop of the connector.
The IOs are now in the wrong place.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1110526)

The way you have your connector, pin 1 should be bottom left.  Right now, it is top left.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1108694)

See image, when rotating your PCB, the current pin 1 will move from top left to bottom right, but the dev board has pin 1 in the proper place, top right, not bottom right.

When counting dual-inline pins on these connector, pretend pin 1 is in the same place as a dip IC, except you then zipper count instead of down-up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 02:35:05 pm
Do not use IOs ' 38p/39n 38/37 INC-/INC+'.
Look at the PCB, those traces are long and go under and around the ram to the other side.
Move the LVDS IOs up/further right on the connector so that you only end up on the short trace IOs which feed the ram chip.

IO:
49p/50n -> 32/31
52p/53n -> 29/28
are short and ok.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 02:53:16 pm
Why not place R6, R7 where I placed the white arrow.  No need to make the VCCIO wiggle up to the NXP IC.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 03:17:48 pm
Also, move pin 17 & 18 down by 1.  We will need to make sure the SDRam controls are in a 'NOP' & disabled state to ensure the data IOs our LVDS wires are tied to have been disabled.

Worst case, you will need to use some kapton tape to protect the connector and hot-air remove the SDRam chip to attempt 720p.  Absolute worst case is if you need to do so just to get 480p working.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 03:24:43 pm
Worst case, you will need to use some kapton tape to protect the connector and hot-air remove the SDRam chip to attempt 720p.  Absolute worst case is if you need to do so just to get 480p working.
I doubt it's going to be a problem for 480p - that's like 270 Mbps per data lane? 720p is kind of "getting up there" with 745 Mbps. But I've seen with my own eyes HDMI running at 1080p@60 (1450 Mbps per data lane) with HDMI connector connected to FPGA via bodge-wires. It wasn't very reliable, mind you, but it did kind of work, which was surprising to see. I guess it makes sense that they've added a lot of resilience in the physical layer to allow it to work even with super-crappy HDMI cables, but still - it was weird to see it actually working at all.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 03:40:24 pm
Uhh that was a silly mistake with the header - I don't know if it was an issue with the type of header I'd used or what, but it was clearly wrong - well done for spotting that one. :clap:

Have updated the schematic and PCB with the other changes - should be up to date so far.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 03:51:46 pm
I think you f-ed up your connector.  (It's head banging time again!)
Oh crap, I've lost count on how many times did I make the same mistake! |O |O |O |O |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 03:59:11 pm
Uhh that was a silly mistake with the header - I don't know if it was an issue with the type of header I'd used or what, but it was clearly wrong - well done for spotting that one. :clap:

Have updated the schematic and PCB with the other changes - should be up to date so far.  :)
Little length and matching cleanup.  We are assuming that this matches the length from the IO pins on the eval board below.  The goal is at the end where the 100ohm termination resistors are located, the overall length of the +&- tracks are identical.

We cant do anything about the differences through the connector itself, only correct after the connector so it will undo the length difference introduced before the first connector on the bottom.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 03:59:34 pm
Oh crap, I've lost count on how many times did I make the same mistake! |O |O |O |O |O

It really shouldn't make me feel better, but knowing I'm not the only one who makes these mistakes does make me feel like I should be less harsh on myself.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 04:02:58 pm
Little length and matching cleanup.  We are assuming that this matches the length from the IO pins on the eval board below.  The goal is at the end where the 100ohm termination resistors are located, the overall length of the +&- tracks are identical.

We cant do anything about the differences through the connector itself, only correct after the connector so it will undo the length difference introduced before the first connector on the bottom.

So you mean correct for any differences in length created on the EasyFPGA board itself?  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 04:03:36 pm
Uhh that was a silly mistake with the header - I don't know if it was an issue with the type of header I'd used or what, but it was clearly wrong - well done for spotting that one. :clap:

Have updated the schematic and PCB with the other changes - should be up to date so far.  :)
Why cant my Adobe reader see your schematic.  It says I need a font package.
I don't like downloading unknown addons or upgrading to spy-ware...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 04:05:44 pm
Little length and matching cleanup.  We are assuming that this matches the length from the IO pins on the eval board below.  The goal is at the end where the 100ohm termination resistors are located, the overall length of the +&- tracks are identical.

We cant do anything about the differences through the connector itself, only correct after the connector so it will undo the length difference introduced before the first connector on the bottom.

So you mean correct for any differences in length created on the EasyFPGA board itself?  :o
Follow my picture.  The traces are going to the same pins, just that they run vertical before the +&- go into their 50ohm parallel routing.  The EasyFPGA looks like it takes a similar vertical route from IO pin to the connector.  We are just following the same parallel vertical trace flow and by the time the 2 traces go parallel on your HDMI PCB, the difference in length should be ~cancelled out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 04:08:01 pm
Why cant my Adobe reader see your schematic.  It says I need a font package.
I don't like downloading unknown addons or upgrading to spy-ware...

Oooh... no idea? I've not changed any fonts in it or anything.  It was using Times New Roman and Verdana... Hmmm.. try this one?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 04:14:15 pm
It really shouldn't make me feel better, but knowing I'm not the only one who makes these mistakes does make me feel like I should be less harsh on myself.  ;)
It just shows that we all are human beings, and so we all make mistakes. Which is why I always say (including to myself) - "Wait one more day and check everything one more time". Unfortunately I rarely listen to myself as whenever I complete a layout, I get so excited that I want to order PCBs ASAP ::), and that backfires on me every once in a while, especially often on "revision A"'s :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 04:23:47 pm
Why cant my Adobe reader see your schematic.  It says I need a font package.
I don't like downloading unknown addons or upgrading to spy-ware...

Oooh... no idea? I've not changed any fonts in it or anything.  It was using Times New Roman and Verdana... Hmmm.. try this one?
This is what I see:

Though Firefox shows it ok (crummily), though Firefox renders & prints .pdfs like crap.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 04:28:35 pm
I use Foxit Reader to view PDFs - both on the desktop and (I think) in browsers.  Here's what it should look like:

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 04:33:22 pm
Here I can open both with Adobe Acrobat Reader and both look OK.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 04:44:14 pm
Little length and matching cleanup.  We are assuming that this matches the length from the IO pins on the eval board below.  The goal is at the end where the 100ohm termination resistors are located, the overall length of the +&- tracks are identical.

We cant do anything about the differences through the connector itself, only correct after the connector so it will undo the length difference introduced before the first connector on the bottom.

So you mean correct for any differences in length created on the EasyFPGA board itself?  :o
Follow my picture.  The traces are going to the same pins, just that they run vertical before the +&- go into their 50ohm parallel routing.  The EasyFPGA looks like it takes a similar vertical route from IO pin to the connector.  We are just following the same parallel vertical trace flow and by the time the 2 traces go parallel on your HDMI PCB, the difference in length should be ~cancelled out.

Ah - the picture wasn't there when I looked.  How about this now?  I've removed the top silk mask to show the traces better.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 04:54:44 pm
beautiful  :clap:.
Time to start coding...

Let's start by dismantling everything but the sync generator & driving the existing VGA output on that PCB with 3bit color pattern.

Then, we will need 2 pieces for the HDMI.  (I still need to check something...)

Module #1: Clk, clk_ena, 24bit RGB +HS+VS+DE input, 4x10 bit parallel output.
This module takes in the VGA parallel interface and outputs 3x10bit parallel data which contains the 3x RGB channels with the embedded/encoded sync information.  Channel #4 is actually a fixed # "10'b1111100000" as it generates the pixel clock out.

Module #2: This will be an Intel megafunction which takes in the pixel Clk, Clk_10x which will be the serial output clock, and the 4x channels from module #1.  It will output 4 parallel serial streams which will feed the LVDS output butters.

That should make a DVI picture.

Then we will advance module #1 to add embedding audio packets during the horizontal blanking interval.
(Need to double check how this works.)

There are also concerns about HDMI being forced into YUV color mode instead of RGB, though RGB supposed to be supported.  I have numerous RGB to YUV color space converters, though I would like to avoid this step.  (You would get brightness, contrast, saturation and hue controls on your video card if you added the color-space-converter...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on November 16, 2020, 04:54:56 pm
The PDF includes a font called Simhei : https://www.wfonts.com/font/simhei (https://www.wfonts.com/font/simhei)

As for that schematic, is it acceptable to have those center trace pairs shorter in length compared to the ones on the side?

Also nitpicking, but personally it would bother me that single trace on top right of the connector going around the last trace.
It seems possible to route it along the other two to its left, pull those a bit closer to the chip at the corner and maybe place that capacitor or whatever it is diagonally? Horizontal would also work, just route that single trace on the right between the capacitor pads?

Maybe I'd thicken the trace going to the 2nd set of two pins on the 0.1" header a bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 05:18:13 pm
Also nitpicking, but personally it would bother me that single trace on top right of the connector going around the last trace.
It's the opposite orientation of what the length and trace spacing looks like on the PCB below with that yellow connector.  All we are trying to do is un-do that extended length of trace on the bottom PCB which would be on the opposite pin.

You would be absolutely correct in your judgement if the bottom PCB had matched the length of the traces to the differential paired IO pads on it's din connector.  This is not the way our real PCB will be wired straight to the BGA FPGA.  We are just best accommodating the cheap 25$ eval board to test out the NXP HDMI/DVI amplifier / cable driver IC.

(Note that the PCB is rotated around 180 degrees before being plugged in, so the lengths between the upper and lower pins to the FPGA equalize out  It's the parallel differential 100ohm terminator which need to be dead center at the end of the balanced trace pair and they are the way it's wired.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 05:21:16 pm
Owzat?

And what BrianHG said re: trace matching.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 05:30:48 pm
Owzat?

And what BrianHG said re: trace matching.  ;)

Nockieboy, you didn't have to do that change, mariush could have not possibly been talking about the DDC and HPD lines.  These signals operate at 100KHz.  You could run circles around the PCB going through each layer and it would still work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 05:34:17 pm
Nockieboy, you didn't have to do that change, mariush could have not possibly been talking about the DDC and HPD lines.  These signals operate at 100KHz.  You could run circles around the PCB going through each layer and it would still work.

Yeah, I know, but I have a bit of OCD when it comes to fine-tuning stuff like this.  I could happily spend the next week tweaking signal traces and component positioning to make it as efficient as possible (within my level of skill and knowledge, obviously).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 05:42:10 pm
Module #2: This will be an Intel megafunction which takes in the pixel Clk, Clk_10x which will be the serial output clock, and the 4x channels from module #1.  It will output 4 parallel serial streams which will feed the LVDS output butters.
Are you sure you will need a 10x clock? On Xilinx devices output SERDES operates in DDR mode, so it only requires 5x clock (because DDR). So for 720p you only need 371.25 MHz for the pixel clock as opposed to 742.5 MHz. This is why it's possible to achieve 720p while being completely in spec (global clock buffers can only go up to 630 MHz or so).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 05:47:22 pm
Yeah, I know, but I have a bit of OCD when it comes to fine-tuning stuff like this.  I could happily spend the next week tweaking signal traces and component positioning to make it as efficient as possible (within my level of skill and knowledge, obviously).
If I were you, I'd rather look at the 3D model of the board with all parts on there and see if I can actually hand-assemble it. For example, the passive connected to the right bottom pin of that QFN looks to me a bit too close to the QFN to actually solder it with an iron without touching the QFN. Try to think about the order in which you will be soldering parts and see if something might be in the way of a soldering iron at some point in assembly.
I assume you are going to hand-solder it, if not, pls ignore everything I just said.

Also, just in case you guys didn't see it first time around, I would like to once again suggest going for 0.8 mm thick board as opposed to regular 1.6 mm. This should lower trace impedance and bring it a bit closer to 50 Ohm as they are supposed to be.

Oh, and one more thing - if you will be OK with 24/25 Hz refresh rate as opposed to 60 Hz, you can do full 1080p with the same bandwidth (or slightly lower for 24 Hz) as 720p@60.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 05:52:34 pm
Module #2: This will be an Intel megafunction which takes in the pixel Clk, Clk_10x which will be the serial output clock, and the 4x channels from module #1.  It will output 4 parallel serial streams which will feed the LVDS output butters.
Are you sure you will need a 10x clock? On Xilinx devices output SERDES operates in DDR mode, so it only requires 5x clock (because DDR). So for 720p you only need 371.25 MHz for the pixel clock as opposed to 742.5 MHz. This is why it's possible to achieve 720p while being completely in spec (global clock buffers can only go up to 630 MHz or so).
Yes, 2:1 and 1:1 modes exist.  In 2:1 DDR mode, 840mb, IE:420Mhz is the peak for a -C6 grade device.  Oddly, in 1:1 mode, you can clock an IO up to 500MHz, IE, maximum toggle rate of 250Mhz on a single clocked DFF driving an IO pin.  I wonder if this means a low quality out of spec 1gb/sec might be possible in DDR mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 05:59:41 pm
Oh, and one more thing - if you will be OK with 24/25 Hz refresh rate as opposed to 60 Hz, you can do full 1080p with the same bandwidth (or slightly lower for 24 Hz) as 720p@60.
Well, 30Hz... Forgot about that one, but yes, 30Hz 1080p can be done if 720p works. (Including 24Hz & 25Hz)

That would be nice to see a Z80 playing 1080p games even it the frame-rate is 30Hz....

You got the ram for it.
But, with a fill rate of around 75million pixels a second, except for tile-constructed playfields and use of sprites, or just huge stored bitmaps, maintaining 30fps gaming can get difficult.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 06:12:05 pm
Yeah, I know, but I have a bit of OCD when it comes to fine-tuning stuff like this.  I could happily spend the next week tweaking signal traces and component positioning to make it as efficient as possible (within my level of skill and knowledge, obviously).
If I were you, I'd rather look at the 3D model of the board with all parts on there and see if I can actually hand-assemble it. For example, the passive connected to the right bottom pin of that QFN looks to me a bit too close to the QFN to actually solder it with an iron without touching the QFN. Try to think about the order in which you will be soldering parts and see if something might be in the way of a soldering iron at some point in assembly.
I assume you are going to hand-solder it, if not, pls ignore everything I just said.

Also, just in case you guys didn't see it first time around, I would like to once again suggest going for 0.8 mm thick board as opposed to regular 1.6 mm. This should lower trace impedance and bring it a bit closer to 50 Ohm as they are supposed to be.

Oh, and one more thing - if you will be OK with 24/25 Hz refresh rate as opposed to 60 Hz, you can do full 1080p with the same bandwidth (or slightly lower for 24 Hz) as 720p@60.

It all looks okay to my untrained eye?  The HDMI connector is an approximation - there's no 3D model for one I'm using.

And yes, I saw the 0.8mm board recommendation and will be using that when I place the order. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 06:22:12 pm
It all looks okay to my untrained eye?
Yea, those are seriously large pads for QFN - I did not expect that. I don't see orientation mark for the QFN on a silkscreen - but maybe it's just a bad angle.
I would work a bit on a silkscreen, but layout-wise it looks OK to me, at least on the first sight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 07:38:32 pm
I don't see orientation mark for the QFN on a silkscreen - but maybe it's just a bad angle.
I would work a bit on a silkscreen, but layout-wise it looks OK to me, at least on the first sight.
Yes, the pin 1 ID is missing...
Add a fat dot or arrow on the silkscreen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 07:51:06 pm
Well Nockieboy, if you got your blitter emulated text mode fully functional, then, at 1920x1080, you can render a nice high resolution 24x36 pixel font roasting the old 8x16 and still get 80 column x 30 rows, or use a 20x36 font so the text still looks square on a 16:9 display with 96x30 characters.  In fact, you have enough ram for a 2 bit 4 color font where you can dither the edges to 2 additional shades of grey plus the white or 16 color fonts with 14 shades of grey plus the white text.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 08:56:22 pm
Yes, the pin 1 ID is missing...
I don't see polarity mark for the diode either.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 09:28:25 pm
Yeah, I know, but I have a bit of OCD when it comes to fine-tuning stuff like this.  I could happily spend the next week tweaking signal traces and component positioning to make it as efficient as possible (within my level of skill and knowledge, obviously).
Now I definitely can't wait to see your OCD going nuts as you route and length-match DDR3 interface :-DD :-DD :-DD As someone with a relatively mild case of the same illness things get... painful at times when I work on DDRx interfaces :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 09:38:49 pm
Arrg, stop the board.  I tried using those pins in Quartus and it says that the maximum for the selected IO is 640mbs.  Fine for 480p, but not 720p.  I think I've just selected the wrong IO standard in Quartus, but I need to make sure if you want to attempt 720p.

Ok, 'STTL-2 Class II' on those chosen IOs supports 740mb/sec, so we are ok...
In fact, we can even do it non-differential.  If the NXP will take in a non-differential and output proper HDMI, then you only need 4 outputs to drive the HDMI saving another 4 IOs.  However, you loose the common mode noise rejection between the FPGA and NXP IC.  But, I guess it is the same for DDR3 data lines...

Otherwise, the board is fine.

Ok, it's annoying how Quartus hounds you when you use their LVDS megafunction when compiling, checking the clocks exactly and aborting if you exceed a single MHz.  I'm having trouble getting 740MHz and true differential working with the exact chosen IO, however, the code is simple enough to compile in a CV chip and Quartus tells you if you will achieve the official frequency or not.

This is also good if we use Quartus' DDR3 memory compiler and choose the IO pins.  It will tell us straight in the face if we will achieve the 400MHz/800mtps mark or not.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 10:15:07 pm
In fact, we can even do it non-differential.
No, you can not.

If the NXP will take in a non-differential and output proper HDMI
No, it can not.

Don't get too excited just yet. We still don't see any image on nockieboy's monitor.

And the IC you've chosen is purely analog one. It doesn't do anything aside from voltage shifting. Here is direct quote from the datasheet:
Quote
The PTN3366 does not retime any data. It contains no state machines. No inputs or outputs of the device are latched or clocked. Because the PTN3366 acts as a transparent level shifter, no reset is required.
So it just takes what's on input and places it on the output - no logic, no latches, no nothing.
I would've chosen something more smart, with retiming.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 16, 2020, 10:19:58 pm
This is also good if we use Quartus' DDR3 memory compiler and choose the IO pins.  It will tell us straight in the face if we will achieve the 400MHz/800mtps mark or not.
Xilinx MIG (Memory Interface Generator) doesn't even let you select options or enter parameters which won't work with device/speed grade/package combination you've chosen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 16, 2020, 10:51:39 pm
Yes, the pin 1 ID is missing...
Add a fat dot or arrow on the silkscreen.

Added a white dot - bottom right corner, next to C2, corresponding with pin 1. :-+

Yes, the pin 1 ID is missing...
I don't see polarity mark for the diode either.

It's underneath the diode. Check any of my previous posts with the 2D PCB image.  ;)

Don't get too excited just yet. We still don't see any image on nockieboy's monitor.

And the IC you've chosen is purely analog one. It doesn't do anything aside from voltage shifting. Here is direct quote from the datasheet:
Quote
The PTN3366 does not retime any data. It contains no state machines. No inputs or outputs of the device are latched or clocked. Because the PTN3366 acts as a transparent level shifter, no reset is required.
So it just takes what's on input and places it on the output - no logic, no latches, no nothing.
I would've chosen something more smart, with retiming.

I won't lose sleep over not being able to test or output 720p.  I don't know enough about the signal speeds or other factors at play here to know how much leeway we have with these signals.  Would a 'smart' device be overkill?  Or would it be the difference between being able to display 480p or 720p?

I can't help but look at this video...

https://youtu.be/bTamCo2C6kg?t=105 (https://youtu.be/bTamCo2C6kg?t=105)

... and wonder if we're over-engineering or over-worrying about the problem, though.  Admittedly, we can't see what else is on the little PCB that holds the HDMI connector, but it doesn't seem to me that the maker is that concerned about differential pairing, trace lengths, or even the power of the FPGA he's using (it's a Cyclone II EP2C5T144 (https://www.ebay.co.uk/itm/Hobby-Components-UK-Altera-Cyclone-II-EP2C5T144-FPGA-Dev-Board/163837381272?hash=item2625780a98:g:9loAAOSwCkldZp57) connected with ribbon cable, for Pete's sake) - it seems to spit out a stable 480p image just fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 10:57:12 pm
If the NXP will take in a non-differential and output proper HDMI
No, it can not.

Don't get too excited just yet. We still don't see any image on nockieboy's monitor.

And the IC you've chosen is purely analog one. It doesn't do anything aside from voltage shifting. Here is direct quote from the datasheet:
Heheheh, did you not know?  A linear differential amplifier only evaluates the 2 input signals, if 1 input is higher than the other, the output will go high, IE the + goes to + and the - goes to -.  If the + input is lower than the - input, then the + output goes low while the - output goes high.  It's basically a 3GHz differential opamp with a differential output line driver.

If the internal terminator hold both the +&- inputs to 1.8v via in's internal 50ohm terminator resistor and we only cycle the +input through that 0.1uf cap, as we push the + above and below the 50 1.8v threshold while the - stays at 1.8v, the amp will make a balanced output...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 11:04:07 pm
... and wonder if we're over-engineering or over-worrying about the problem, though.  Admittedly, we can't see what else is on the little PCB that holds the HDMI connector, but it doesn't seem to me that the maker is that concerned about differential pairing, trace lengths, or even the power of the FPGA he's using (it's a Cyclone II EP2C5T144 (https://www.ebay.co.uk/itm/Hobby-Components-UK-Altera-Cyclone-II-EP2C5T144-FPGA-Dev-Board/163837381272?hash=item2625780a98:g:9loAAOSwCkldZp57) connected with ribbon cable, for Pete's sake) - it seems to spit out a stable 480p image just fine.

It's not that.  You are making a public domain PCB and code available on github.  We just want to make sure whoever builds the thing will:
A) Get it operational no matter what monitor or cable they have.
B) Wont accidentally kill their FPGA when plugging the thing into a monitor.
C) Won damage a really expensive TV they may be connecting this VGA board to.

This 92cent NXP chip allows us to check those boxes while a flat ribbon cable might work for you and a few others, I cannot in good conscience let you try and save that 1$ and send out questionable hardware, especially after removing all the other parts on your PCB.  IE, no analog VGA to fall back on...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 11:20:26 pm
I just tried compiling a 740mb 4 channel serializer for CycloneV.  All the differential IO voltage standards work fine.  It's just the CycloneIII which couldn't handle 740mbs, only 640mbs.

Also, the new Quartus, you just provide parallel data & clock, it will automatically configure the PLL on it's own.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 16, 2020, 11:43:56 pm
So many damn features.
It's gonna take time to setup the best possibly way for our GPU.

Though, 400MHz seems to turn up (not red) as well as the CV's 'hard external memory controller'.

I also like the that you can define multiple in, out, IO read/write ports and set a priority to each one.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2020, 10:49:03 am
It's not that.  You are making a public domain PCB and code available on github.  We just want to make sure whoever builds the thing will:
A) Get it operational no matter what monitor or cable they have.
B) Wont accidentally kill their FPGA when plugging the thing into a monitor.
C) Won damage a really expensive TV they may be connecting this VGA board to.

This 92cent NXP chip allows us to check those boxes while a flat ribbon cable might work for you and a few others, I cannot in good conscience let you try and save that 1$ and send out questionable hardware, especially after removing all the other parts on your PCB.  IE, no analog VGA to fall back on...

In fairness, I'm all for safety and making sure it works - see my changes to the ESD protection for the HDMI connector as an example - I was just throwing a grenade into the conversation between you and asmi around the whole 'will it, won't it' at 480p/720p.  I'm sure that if someone can bodge a 480p output using a Cyclone II and some ribbon cable, this should work quite nicely given the thought that's gone into it - especially if the Cyclone V's IO can manage the frequencies needed for 720p.  :)

I'm going to pull the trigger on this PCB order later today and put the parts order in with Mouser.  That'll include (most of) the parts I'll need for the GPU card, too - including:
...and a whole host of passives in 0402 and 0603.

On a slight tangent, can anyone shed any light on the MAX3421 USB Interface IC?  I've got it (and supporting components) in my trolley with the intention of adding it to the GPU card (or, more likely, building a test/dev card to try it out on my EasyFPGA dev board), but it's not a cheap IC and I'm wondering about the viability of using it to replace the PS2 port, so I can use a USB keyboard instead of a PS2 one.  Anyone have any thoughts on the idea?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2020, 11:41:11 am
JLCPCB is quoting CAN$13.21 for 10x 0.8mm PCBs.  More than half of that is shipping to the UK. ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 12:33:56 pm
On a slight tangent, can anyone shed any light on the MAX3421 USB Interface IC?  I've got it (and supporting components) in my trolley with the intention of adding it to the GPU card (or, more likely, building a test/dev card to try it out on my EasyFPGA dev board), but it's not a cheap IC and I'm wondering about the viability of using it to replace the PS2 port, so I can use a USB keyboard instead of a PS2 one.  Anyone have any thoughts on the idea?
There is also FT313H chip, which is about two times cheaper and supports USB 2.0 high-speed (480 Mbit/s). But I have no experience with either of them, so can't really say anything for or against. Purely on paper FTDI chip seems like a better idea (cheaper, higher speed - you can even connect thumb drive to it), and if you combine it with something like USB2514 (4 port USB 2.0 hub), you can implement 4 USB 2.0 ports and so connect not only keyboard and mouse, but other stuff as well. That would probably be another good candidate for a prototype PCB.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2020, 05:02:19 pm
@BrianHG
which protections would you recommend between a FPGA and a CGA-CRT tube (C-G-A, not VGA)?

You're going to want to start your own thread for anything off-topic like this.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 06:32:07 pm
  • MT41J128M16JT-125:K TR (https://www.mouser.co.uk/ProductDetail/340-135528-REEL) DDR3 DRAMS.

LCSC has stock of the DDR3, why not let JLPCB mount that ram with the FPGA?

https://lcsc.com/product-detail/FLASH_Micron-Tech-MT41J128M16JT-093-K_C395383.html (https://lcsc.com/product-detail/FLASH_Micron-Tech-MT41J128M16JT-093-K_C395383.html)

Though it's the 1066MHz version.  Ask asmi if it will work down at 400MHz, or 303MHz.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 06:48:15 pm
I'm sure that if someone can bodge a 480p output using a Cyclone II and some ribbon cable, this should work quite nicely given the thought that's gone into it - especially if the Cyclone V's IO can manage the frequencies needed for 720p.  :)

He might only be doing 240p/480i which is 135 megabit, or, a maximum signal of 67.5MHz going down that ribbon cable.
If he is doing 480p, then that's double, 270megabit, or a maximum signal of 135MHz going down that ribbon cable.

(Both of these well withing CycloneI/II/III/IV capabilities.)

720p is 742.5megabit, or a top frequency of 372.75MHz going down an HDMI cable.

Only Cyclone V -7/-6 reach this mark or CycloneIV -6-7 on specific IO banks running with Altera's megafunctions & expected code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 07:06:48 pm
One more thing I would like to add regarding USB. I read up a bit on FT313H and it seems like a good device - it implements SRAM-like access via 8 or 16 bit wide parallel bus (this is good for speed) which can run up to 1000 / 80 ns = 12.5 MHz, so up to 25 MBytes/s of bandwidth. It's got 24 KB of internal memory, and supports both PIO and DMA operations. It also implements EHCI (Enhanced Host Controller Interface), which is Intel's standard (https://www.intel.ca/content/www/ca/en/products/docs/io/universal-serial-bus/ehci-specification.html) for USB 2.0 controllers, that is good in a sense that there is quite a bit of information out there on how to use it, but not so good in a sense that you will have to write quite a bit of code, as well as you will need to have a good knowledge of how USB bus actually works at the packet level. Another good news is that unlike most other specifications, USB specs are all in public access, so there won't be any shortage of information.
My concern here is that all that software stuff may prove to be too much for a little Z80 to handle. USB stacks has always been relatively light on hardware, but heavy on software. This design decision was a key to it's success as software can be updated in the field while hardware can not, but in our case it might become a problem. Things like keyboard and mouse will probably be OK as they don't generate much USB traffic, but something more bus-intensive might be a challenge. I still think it's worth a try to implement and experiment with, but I also think it's important to set your expectation appropriately.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 07:19:01 pm
https://lcsc.com/product-detail/FLASH_Micron-Tech-MT41J128M16JT-093-K_C395383.html (https://lcsc.com/product-detail/FLASH_Micron-Tech-MT41J128M16JT-093-K_C395383.html)

Though it's the 1066MHz version.  Ask asmi if it will work down at 400MHz, or 303MHz.
Absolutely - see attached speed bin. BTW these tables are all taken from the datasheet for these chips ;)
DDRx memory devices is a rare shining example of HW design done right when it comes to compatibility - higher-speed devices will work in lower-speed modes, DDR3L devices (1.35V) will work in "regular" DDR3 mode (1.5V), all footprints for specific bus width are designed to ensure that lower capacity devices will work instead of higher-capacity ones, and the other way around, and devices from different vendors work together no problem (if other parameters are compatible). You won't find many examples like that in hardware world.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2020, 07:50:11 pm
One more thing I would like to add regarding USB. I read up a bit on FT313H and it seems like a good device - it implements SRAM-like access via 8 or 16 bit wide parallel bus (this is good for speed) which can run up to 1000 / 80 ns = 12.5 MHz, so up to 25 MBytes/s of bandwidth. It's got 24 KB of internal memory, and supports both PIO and DMA operations. It also implements EHCI (Enhanced Host Controller Interface), which is Intel's standard (https://www.intel.ca/content/www/ca/en/products/docs/io/universal-serial-bus/ehci-specification.html) for USB 2.0 controllers, that is good in a sense that there is quite a bit of information out there on how to use it, but not so good in a sense that you will have to write quite a bit of code, as well as you will need to have a good knowledge of how USB bus actually works at the packet level. Another good news is that unlike most other specifications, USB specs are all in public access, so there won't be any shortage of information.
My concern here is that all that software stuff may prove to be too much for a little Z80 to handle. USB stacks has always been relatively light on hardware, but heavy on software. This design decision was a key to it's success as software can be updated in the field while hardware can not, but in our case it might become a problem. Things like keyboard and mouse will probably be OK as they don't generate much USB traffic, but something more bus-intensive might be a challenge. I still think it's worth a try to implement and experiment with, but I also think it's important to set your expectation appropriately.

I just want to be able to plug a USB keyboard into my computer, maybe a mouse at a stretch.  That's really it.  It would be nice to replace the PS2 keyboard interface as it's getting harder and harder to find PS2 keyboards these days (and I don't have a PS2 mouse), whereas USB ones are ubiquitous.  My intention was for the FPGA to pass characters (or mouse coordinates) to the Z80 in much the same way as the current PS2 interface does.  I'm not really concerned with accessing USB storage - that would definitely be a big ask of the Z80, I think.

I think that 8/16-bit bus between the FT313 and the FPGA will be an issue for me, though - that's potentially a lot of IOs that I may not have, depending on how the DDR3 goes.  The MAX3421 can do it over an SPI connection, so that keeps IO usage to an absolute minimum.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 08:09:48 pm
 :palm: Intel, with their new online datasheet BS.
Here are all the CV  in old fashioned .pdf.

Cyclone V Handbook Volume I -> General IC features
https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v2.pdf (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v2.pdf)

Cyclone V Handbook Volume II -> GX tranceivers (not us...)
https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v3.pdf (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v3.pdf)

Cyclone V Handbook Volume III -> Hard Processor System (Contains information on A9 & hard memory controler)
https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v4.pdf (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v4.pdf)

Cyclone V Handbook Datasheet I -> Contains IO voltages, standards & maximum switching clock MHz of normal IOs and core ALU/ram FMAX.
https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v1.pdf (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyclone-v/cv_5v1.pdf)

Page 52 of the 'datasheet' has the True-Differential-LVDS transmitter specs.
The jitter rating is worst case 160ps.  This is good enough for HDMI 720p without any re-clocking.
However, the 'Intel-dicks' didn't define the 'SERDES factor J = 1 to 2, Uses DDR Registers ' in the data sheet, though you do see it is part of the 'True Differential I/O Standards - fHSDR'rated at 840mbps & we know from the DDR controller that the DDR buffers can do at least 800mbps on the -6 & -7 variants.

Page 18 says the Cyclone V can support up to 2 DDR3 hard-memory controllers @400MHz, 800mtps.  The soft-controller at 300MHz is for when you place the DDR on any IOs you like.  The hard controller means you must properly wire the each dedicated 8/9 DQ's in a bank with the 2 DQS/DQSn for that bank to get the 400MHz/800mtps speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 08:17:10 pm
I just want to be able to plug a USB keyboard into my computer, maybe a mouse at a stretch.  That's really it.  It would be nice to replace the PS2 keyboard interface as it's getting harder and harder to find PS2 keyboards these days (and I don't have a PS2 mouse), whereas USB ones are ubiquitous.  My intention was for the FPGA to pass characters (or mouse coordinates) to the Z80 in much the same way as the current PS2 interface does.  I'm not really concerned with accessing USB storage - that would definitely be a big ask of the Z80, I think.
I agree, but "a man can dream" (C) :)

I think that 8/16-bit bus between the FT313 and the FPGA will be an issue for me, though - that's potentially a lot of IOs that I may not have, depending on how the DDR3 goes.  The MAX3421 can do it over an SPI connection, so that keeps IO usage to an absolute minimum.
Have you actually started putting together schematics for all these updates?

Most USB-capable SoCs these days connect to USB 2.0 PHY via ULPI bus, which is a parallel 8 bit bus, and implement EHCI inside the SoC itself. This is why I was surprised to learn that such chips even exist as a stand-alone devices. The more I read about it, the more I like it. Of course, if you want performance, that device won't quite cut it, but in many-many cases performance is not very critical, and 10-20 MBytes/s might be more than enough, especially if you also get simplicity of implementation. Come to think of it, even USB audio streaming would require much less bandwidth than that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 08:22:41 pm
Page 18 says the Cyclone V can support up to 2 DDR3 hard-memory controllers @400MHz, 800mtps.  The soft-controller at 300MHz is for when you place the DDR on any IOs you like.  The hard controller means you must properly wire the each dedicated 8/9 DQ's in a bank with the 2 DQS's for that bank to get the 400MHz/800mtps speed.
But does it actually list the pins you are supposed to use? I was not able to find such information anywhere...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 08:28:19 pm
Page 18 says the Cyclone V can support up to 2 DDR3 hard-memory controllers @400MHz, 800mtps.  The soft-controller at 300MHz is for when you place the DDR on any IOs you like.  The hard controller means you must properly wire the each dedicated 8/9 DQ's in a bank with the 2 DQS's for that bank to get the 400MHz/800mtps speed.
But does it actually list the pins you are supposed to use? I was not able to find such information anywhere...
Ahhh, you are looking for the 'Pin Planner' / IO pin list.

They are labeled already in the current schematic blocks, + in Quartus, when you open the chosen IC's pin-planner, they are also all fully labeled.
Give me a sec, I do believe Excel spreadsheets exist from Intel with the same info.

However, I will not let Nockieboy get away with finishing the schematic until he builds a project with at least a wired DDR3 ram controller into the FPGA he is using with a simple separate read and write port to unused IO pins at a minimum.  I want to see a timing closure compile of such a project guaranteeing the chosen DDR3 wiring will work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 08:40:56 pm
However, I will not let Nockieboy get away with finishing the schematic until he builds a project with at least a wired DDR3 ram controller into the FPGA he is using with a simple separate read and write port to unused IO pins at a minimum.  I want to see a timing closure compile of such a project guaranteeing the chosen DDR3 wiring will work.
When I design a board with 7 series FPGA, in Vivado there is a way to quickly and graphically put together a "simple" (it's not very simple really, but since we use only pre-made IPs, it seems that way) design with memory controller, softcore CPU with debug module, and GPIO module (to flash some LEDs) so that I can test that my DDR pinout will work, and I also use this design in initial hardware bring-up since it's known-to-work. In Vivado such design literally take a couple of minutes to put together (pin mapping is by far the longest stage as it's more-or-less manual), and after 5-10 minutes to place&route design I have my bitstream ready to be programmed into the FPGA.

Is something like this possible in Intel world? I seem to recall that qsys thingy, but it's been few years since I touched it, so don't really remember much of what it can do.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 09:07:30 pm
Question for Nockieboy, will you stick with Quartus Prime 18.1 for this project, or upgrade to Quartus Prime 20.3?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 09:08:32 pm
However, I will not let Nockieboy get away with finishing the schematic until he builds a project with at least a wired DDR3 ram controller into the FPGA he is using with a simple separate read and write port to unused IO pins at a minimum.  I want to see a timing closure compile of such a project guaranteeing the chosen DDR3 wiring will work.
When I design a board with 7 series FPGA, in Vivado there is a way to quickly and graphically put together a "simple" (it's not very simple really, but since we use only pre-made IPs, it seems that way) design with memory controller, softcore CPU with debug module, and GPIO module (to flash some LEDs) so that I can test that my DDR pinout will work, and I also use this design in initial hardware bring-up since it's known-to-work. In Vivado such design literally take a couple of minutes to put together (pin mapping is by far the longest stage as it's more-or-less manual), and after 5-10 minutes to place&route design I have my bitstream ready to be programmed into the FPGA.

Is something like this possible in Intel world? I seem to recall that qsys thingy, but it's been few years since I touched it, so don't really remember much of what it can do.
Yes.  But when Nockieboy will be doing this for the first time, it will take longer than 5-10 minutes...
Those screenshots from Intel's DDR3 ram controller setup page generates 2 things you can use, either a 'Block Symbol' which you place in a block diagram which will have a bunch of input and output busses (IE Address-data in/out, or avilon bus), and IOs port for the DDR3 ram chips/module which you wire to where you like.  Or, it will output a VHDL/Verilog module with those busses and IOs as ports & parameter settings which you may adjust.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 10:05:00 pm
For the external DDR memory interface, the CV Handbook Vol I section 6 spells it out.

Table 6-5 tells you the where the DQs blocks exist.
All x8, 3 of them on the bottom.
We need 3, plus we will also use an x8 block as the HDMI transmitter lanes.
Maybe the bottom and 1 lower left or right side set to 1.5v will be enough for the ram & HDMI.

Figure 6-2 shows the DQS pins and DLL connections on our chosen CV IC.
Figure 6-8 shows the PHYCLK networks.

 :palm:  |O
Table 6-16 shows the 'Hard Memory Controller Width for CV ', in the F256 pin device, it is not bonded to the IOs.
You need the U484 or F484 device, or, M383 device to get the 400MHz.

So, we are stuck with 303MHz, 606mtps without any sort of overclocking the fabric.
Or the compiler allows a higher speed without timing violations because our design is so simple.
Or we write our own and cheat a little to get the IO port's theoretical ~800Mhz DDR data IO rate, though, 400MHz logic to control the ram would need to be a simple sequencer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 10:11:02 pm
Pinout files:

https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/dp/cyclone-v/5ceba2.pdf (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/dp/cyclone-v/5ceba2.pdf)
https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/dp/cyclone-v/5ceba2.txt (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/dp/cyclone-v/5ceba2.txt)
https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/dp/cyclone-v/5ceba2.xls (https://www.intel.com/content/dam/altera-www/global/en_US/pdfs/literature/dp/cyclone-v/5ceba2.xls)

Need to be careful about the LVDS output.  If we want the 'TRUE' 740/840mbps, we need to choose dedicated LVDS TX pair channels and not the emulated ones which only achieve 640mbps.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 10:25:07 pm
:palm:  |O
Table 6-16 shows the 'Hard Memory Controller Width for CV ', in the F256 pin device, it is not bonded to the IOs.
You need the U484 or F484 device, or, M383 device to get the 400MHz.

So, we are stuck with 303MHz, 606mtps without any sort of overclocking the fabric.
Or the compiler allows a higher speed without timing violations.
Or we write our own and cheat a little to get the IO port's theoretical ~800Mhz DDR data IO rate, though, 400MHz logic to control the ram would need to be a simple sequencer.
See - Antel itself pushes you towards Xilinx! ;) There you will have your 400 MHz DDR3, and 720p HDMI, and more :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2020, 10:45:49 pm
:palm:  |O
Table 6-16 shows the 'Hard Memory Controller Width for CV ', in the F256 pin device, it is not bonded to the IOs.
You need the U484 or F484 device, or, M383 device to get the 400MHz.

So, we are stuck with 303MHz, 606mtps without any sort of overclocking the fabric.
Or the compiler allows a higher speed without timing violations.
Or we write our own and cheat a little to get the IO port's theoretical ~800Mhz DDR data IO rate, though, 400MHz logic to control the ram would need to be a simple sequencer.

See - Antel itself pushes you towards Xilinx! ;) There you will have your 400 MHz DDR3, and 720p HDMI, and more :-DD
Yup, you need to pay 4$ more for the F484 version, and more PCB area...
I say they should have retired their entire 28nm garbage and only begin their lineup with the Arria FPGAs.
Or, drop the prices of their 28nm lineup by at least 50% and drop their Arria line's price by a good 50-70%.  Then they will be a good competitive deal.  But this is 'Intel' with their 'Complex' and overpriced self-induced superiority.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 17, 2020, 10:58:25 pm
Yup, you need to pay 4$ more for the F484 version, and more PCB area...
I meant Artix-7, it's 256 ball package has 170 user IO balls, which will be more than enough for DDR3 and for everything else. And no need for level shifting for HDMI, and even 1080p@60Hz if you overclock it a little.

But this is 'Intel' with their 'Complex' and overpriced self-induced superiority.
I hope they will learn the lesson once again brought to them by AMD. Last time they did so, but evidently it didn't last for long. Hopefully this time it will last longer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2020, 11:31:45 pm
I think that 8/16-bit bus between the FT313 and the FPGA will be an issue for me, though - that's potentially a lot of IOs that I may not have, depending on how the DDR3 goes.  The MAX3421 can do it over an SPI connection, so that keeps IO usage to an absolute minimum.
Have you actually started putting together schematics for all these updates?

Hmm.. well, I did do a schematic for the MAX3421 based on the datasheet - it's on the 'Peripherals' page of all the recent GPU schematics I've posted (NOT the DVI Tester ones).

Most USB-capable SoCs these days connect to USB 2.0 PHY via ULPI bus, which is a parallel 8 bit bus, and implement EHCI inside the SoC itself. This is why I was surprised to learn that such chips even exist as a stand-alone devices. The more I read about it, the more I like it. Of course, if you want performance, that device won't quite cut it, but in many-many cases performance is not very critical, and 10-20 MBytes/s might be more than enough, especially if you also get simplicity of implementation. Come to think of it, even USB audio streaming would require much less bandwidth than that.

I agree - if I want performance (anything more than the USB 1 12MBytes/s) then I'll need an 8- or 16-bit interface to the USB Host chip, but for keyboard and mouse usage, I think an SPI interface will work just fine.

Question for Nockieboy, will you stick with Quartus Prime 18.1 for this project, or upgrade to Quartus Prime 20.3?

Don't mind upgrading to 20.3 (well, more accurately, installing 20.3 alongside the other two versions) if it provides more useful tools/is better.

:palm:  |O
Table 6-16 shows the 'Hard Memory Controller Width for CV ', in the F256 pin device, it is not bonded to the IOs.
You need the U484 or F484 device, or, M383 device to get the 400MHz.

So, we are stuck with 303MHz, 606mtps without any sort of overclocking the fabric.
Or the compiler allows a higher speed without timing violations.
Or we write our own and cheat a little to get the IO port's theoretical ~800Mhz DDR data IO rate, though, 400MHz logic to control the ram would need to be a simple sequencer.

See - Antel itself pushes you towards Xilinx! ;) There you will have your 400 MHz DDR3, and 720p HDMI, and more :-DD
Yup, you need to pay 4$ more for the F484 version, and more PCB area...
I say they should have retired their entire 28nm garbage and only begin their lineup with the Arria FPGAs.
Or, drop the prices of their 28nm lineup by at least 50% and drop their Arria line's price by a good 50-70%.  Then they will be a good competitive deal.  But this is 'Intel' with their 'Complex' and overpriced self-induced superiority.

:o Ooookaaaay.  So where does this leave us with the Cyclone V FBGA256 as the FPGA of choice?  Should I start looking at shoehorning an F484 into the PCB, or just stop :horse: and bite the bullet and switch over to Xilinx?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 12:10:22 am
Just so we are clear, at 300MHz, you are still getting 1.2 giga-bytes a second with even a CV-8...
With overhead, ~1 giga-byte a second.
Do you need more?

Just for comparison, the Hyperram would have achieved ~150 megabytes a second.

1 VGA/480p 16bit color display MAGGIE layer eats around 54 megabytes a second.
1 16bit 720p@60hz, or 1080p@30hz MAGGIE layer eats around 150 megabytes a second.
(That's 4 16 bit 1080p layers easy with DDR3 at 300MHz, or 12 VGA 640x480 layers.  These figures leaves excessive access time left for the accelerated geometry, audio, FPU, SD-hard-disk at a rate the Z80 cant even begin to cope with even if it were 100MHz.  Not to mention if you use 1 layer less, or 1 or 2 of the counted layers is only 8 bit 256 colors.  And all this still has 0 effect on the FPGA internal memory's layers which operate in parallel.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 18, 2020, 12:33:02 am
I agree - if I want performance (anything more than the USB 1 12MBytes/s) then I'll need an 8- or 16-bit interface to the USB Host chip, but for keyboard and mouse usage, I think an SPI interface will work just fine.
Well if you move to a larger package or to Artix, you will have enough IO pins for everything. I still think that FTDI chip is a better long-term option as it provides better path for new functionality down the road. And SRAM is much easier protocol than SPI.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 18, 2020, 12:37:28 am
Just for comparison, the Hyperram would have achieved ~150 megabytes a second.
Why 150? It's running at 200 MHz DDR, so theoretical maximum will be 400 Mbytes/s, and in practice my design achieved bandwidth quite close to the limit (though I used 166 MHz DDR devices because 200 MHz ones didn't exist yet at that time). The trick here to utilize LONG bursts - not 4-8 clocks long, but more like 64 clocks long or even longer. This way you will better amortize initial access latency, even if you work in double latency mode (which is how I did it because I had two modules running in parallel lockstep).
DDR3 x16 running at 300 MHz will give you about triple that bandwidth (300 * 2 * 2 = 1200 vs 400), 400 MHz will give 4 times bandwidth.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 12:49:24 am
Just for comparison, the Hyperram would have achieved ~150 megabytes a second.
Why 150? It's running at 200 MHz DDR, so theoretical maximum will be 400 Mbytes/s, and in practice my design achieved bandwidth quite close to the limit (though I used 166 MHz DDR devices because 200 MHz ones didn't exist yet at that time). The trick here to utilize LONG bursts...
We cannot do long bursts every time and you cannot terminate midway a long burst with Hyperram when you need to.
We would also throw out a lot of clock cycles here when drawing thin vertical lines.
Intel's DDR3 controller specifies smart alternating banking with multiport priority & weight allocation with burst termination capabilities built in.  Are you saying Nockieboy would have achieved all that with his home-made Hyperram controller?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 18, 2020, 01:00:21 am
We cannot do long bursts every time and you cannot terminate midway a long burst with Hyperram when you need to...
What do you mean? Of course you can terminate burst whenever you need to. As long as you provide data, it will accept it. Same for reading - as long as you hold CS low and provide clocks, it will continue pumping out data. There are a couple of gotchas with page wraparounds, but other than that - it's that simple. If you want to to cut off your write burst mid-clock, you can use RWDS to suppress write of the falling edge.
The only real downside of HyperRAM compared to DDRx is that it's not pipelined, meaning you can't send a new command as another one is being executed, and this way effectively hide access latency. With DDRx you can, and that's how you achieve the best data bus utilization.
Intel's DDR3 controller specifies smart alternating banking with multiport priority & weight allocation with burst termination capabilities built in.  Are you saying Nockieboy would have achieved all that with his home-made Hyperram controller?
Absolutely. HyperBus protocol is super-simple - you send address, you wait for latency, and you send data/receive data. That's all there is to it. Use cache BRAM for random access within page and only commit/read long cache lines - and you will achieve very high bus utilization with minimal effort. And use double-buffering to avoid race conditions.
Like I said, the only serious downside of HyperRAM (aside from too few options as far as capacity goes) is the fact that it's not pipelined. This seriously harms random access speed. Everything else are just advantages - it's simple, it's low pin count, it's fairly efficient if utilized properly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 03:25:00 am
We cannot do long bursts every time and you cannot terminate midway a long burst with Hyperram when you need to...
What do you mean? Of course you can terminate burst whenever you need to. As long as you provide data, it will accept it. Same for reading - as long as you hold CS low and provide clocks, it will continue pumping out data.
I knew about setting the burst size and well aware of all the wrap-around ramifications.  I have engineered my own DDR2 controller ~12 years ago.  I missed the part about terminating mid burst just by removing the CS.  Damn, a number of additional penalties & cycles galore just to get the thing started again, especially if you just want to hop somewhere else in the same page...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 18, 2020, 03:41:00 am
Damn, a number of additional penalties & cycles galore just to get the thing started again, especially if you just want to hop somewhere else in the same page...
This is why I'm so insistent on doing long bursts. With DDRx you can do random access within the page, or within different pages as long as they are in different banks, with virtually no penalty (thanks to pipelining), but with HyperRAM bursts are the only way to achieve reasonable bus utilization. This is especially so if you need to use fixed double latency (this is default setting BTW even in 64 MBit devices) - for example if you want to use double-die devices, or have multiple devices in parallel lockstep. Random access is *incredibly* expensive with HyperRAM. HyperBus protocol was clearly designed to work with caches (long cache lines will help amortize initial latency), or video/audio streaming (where again you work with rather large chunks at a time), and no attempt was made to improve performance of random access.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2020, 11:51:34 am
Just so we are clear, at 300MHz, you are still getting 1.2 giga-bytes a second with even a CV-8...
With overhead, ~1 giga-byte a second.
Do you need more?

Just for comparison, the Hyperram would have achieved ~150 megabytes a second.

1 VGA/480p 16bit color display MAGGIE layer eats around 54 megabytes a second.
1 16bit 720p@60hz, or 1080p@30hz MAGGIE layer eats around 150 megabytes a second.
(That's 4 16 bit 1080p layers easy with DDR3 at 300MHz, or 12 VGA 640x480 layers.  These figures leaves excessive access time left for the accelerated geometry, audio, FPU, SD-hard-disk at a rate the Z80 cant even begin to cope with even if it were 100MHz.  Not to mention if you use 1 layer less, or 1 or 2 of the counted layers is only 8 bit 256 colors.  And all this still has 0 effect on the FPGA internal memory's layers which operate in parallel.)

Ah, maybe I got the wrong end of the stick when I read your previous posts - I read it as though the C5 was going to have difficulty doing what we want.  More than happy with those figures. ;D

I agree - if I want performance (anything more than the USB 1 12MBytes/s) then I'll need an 8- or 16-bit interface to the USB Host chip, but for keyboard and mouse usage, I think an SPI interface will work just fine.
Well if you move to a larger package or to Artix, you will have enough IO pins for everything. I still think that FTDI chip is a better long-term option as it provides better path for new functionality down the road. And SRAM is much easier protocol than SPI.

Just to be clear, the only reason I'm not using the FT313H chip is because I'm not sure how many IOs I'll have available, and I'm still slightly averse to routing all those signals.  I'm sure that'll go when I get started on this DDR3, though... :o

Maybe I'm more likely to have success with the SRAM interface if it's simpler and it's also a lot cheaper and requires no support chip to handle the VBUS, but I see no harm in throwing together a board based on the MAX3421 to try out on my FPGA dev board; with an SPI interface, I could link the USB dev board to my existing GPU card by temporarily re-purposing the existing serial debug port (and a couple of spare IOs) into an SPI port and try out whatever solution I come up with on an actual GPU card connected to my Z80.

My confidence in getting a working USB interface is pretty low though - there's not a lot of help online about it and what there is seems to be talking about using software stacks, embedded Linux OSes or PIC chips (throwing a whole other tool chain into the mix) and general tomfoolery like that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 18, 2020, 02:19:34 pm
Need to be careful about the LVDS output.  If we want the 'TRUE' 740/840mbps, we need to choose dedicated LVDS TX pair channels and not the emulated ones which only achieve 640mbps.
Missed this part - what the hell is "emulated" LVDS and how it differs from "True"? No such thing on 7 series, all diff pairs there are the same :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 03:34:16 pm
Need to be careful about the LVDS output.  If we want the 'TRUE' 740/840mbps, we need to choose dedicated LVDS TX pair channels and not the emulated ones which only achieve 640mbps.
Missed this part - what the hell is "emulated" LVDS and how it differs from "True"? No such thing on 7 series, all diff pairs there are the same :)
The difference is in each IO bank, there are 16 IOs total, 4 pairs true TX differential pairs and 4 true RX pairs.  Use these pairs as as pairs and you get 840mbps with 160ps output jitter on the TX.  Use any other IO combinations as your transmitter or receiver and you get 640mbps with 160ps jitter.  Use any IOs you like as an emulated differential receiver or transmitter pair, the jitter jumps to 360ps.

Which pairs are which is located in the pinout files I listed above, but, not in the schematics where we have just an ##p & ##n shown on the FPGA symbol.

We made a booboo on the chosen LVDS drivers for the HDMI board as 1 of the 4 pairs chosen was a RX pair instead of TX.  So, Quartus is telling me that our limit is 640mbps for 1 pair and I thought it was a limit of the C4, not that the pair I chose was faster at RX instead of TX if we used the next adjacent pair.
 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2020, 03:43:48 pm
We made a booboo on the chosen LVDS drivers for the HDMI board as 1 of the 4 pairs chosen was a RX pair instead of TX.  So, Quartus is telling me that our limit is 640mbps for 1 pair and I thought it was a limit of the C4, not that the pair I chose was faster at RX instead of TX if we used the next adjacent pair.

Is this a booboo I need to (or it would benefit from being) correct before I submit the PCB design?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 18, 2020, 03:44:52 pm
The difference is in each IO bank, there are 16 IOs total, 4 pairs true TX differential pairs and 4 true RX pairs.  Use these pairs as as pairs and you get 840mbps with 160ps output jitter on the TX.  Use any other IO combinations as your transmitter or receiver and you get 640mbps with 160ps jitter.  Use any IOs you like as an emulated differential receiver or transmitter pair, the jitter jumps to 360ps.

Which pairs are which is located in the pinout files I listed above, but, not in the schematics where we have just an ##p & ##n shown on the FPGA symbol.

We made a booboo on the chosen LVDS drivers for the HDMI board as 1 of the 4 pairs chosen was a RX pair instead of TX.  So, Quartus is telling me that our limit is 640mbps for 1 pair and I thought it was a limit of the C4, not that the pair I chose was faster at RX instead of TX if we used the next adjacent pair.
Oh wow - didn't even know that is a thing. No such nonsense in 7 series. All 24 diff pairs in the IO bank (50 pins total per bank, 2 pins per bank are non-differential) are the same and can reach max datasheet speed (and even higher as experience shows).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 05:22:43 pm
We made a booboo on the chosen LVDS drivers for the HDMI board as 1 of the 4 pairs chosen was a RX pair instead of TX.  So, Quartus is telling me that our limit is 640mbps for 1 pair and I thought it was a limit of the C4, not that the pair I chose was faster at RX instead of TX if we used the next adjacent pair.

Is this a booboo I need to (or it would benefit from being) correct before I submit the PCB design?

     The pins we chose have a 640mbps limit.  However, they should still work, just that we cannot guarantee 720p/1080p with those pins, just 1024x768 max.

If you want true 840mbps, the only IO pins available on the 144pin package are:
85p,84n
87p,86n
99p,98n
103p,101n
(All available on P3)

However, using P3 means removing U8 and R30 thru R33 from the dev-board.
These traces are long, unbalanced and traverse throughout the eval PCB unlike our current IO port which just goes to that ram chip just below.

I say stick with what we have and just test up to 1024x768.
The IOs we will choose on the real CV board will support 840mbsp, IE 720p/1080p@30hz.
This doesn't mean we wont try overclocking the current test board to 720p anyways...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 06:41:22 pm
The difference is in each IO bank, there are 16 IOs total, 4 pairs true TX differential pairs and 4 true RX pairs.  Use these pairs as as pairs and you get 840mbps with 160ps output jitter on the TX.  Use any other IO combinations as your transmitter or receiver and you get 640mbps with 160ps jitter.  Use any IOs you like as an emulated differential receiver or transmitter pair, the jitter jumps to 360ps.

Which pairs are which is located in the pinout files I listed above, but, not in the schematics where we have just an ##p & ##n shown on the FPGA symbol.

We made a booboo on the chosen LVDS drivers for the HDMI board as 1 of the 4 pairs chosen was a RX pair instead of TX.  So, Quartus is telling me that our limit is 640mbps for 1 pair and I thought it was a limit of the C4, not that the pair I chose was faster at RX instead of TX if we used the next adjacent pair.
Oh wow - didn't even know that is a thing. No such nonsense in 7 series. All 24 diff pairs in the IO bank (50 pins total per bank, 2 pins per bank are non-differential) are the same and can reach max datasheet speed (and even higher as experience shows).
Nope. I was wrong.  It doesn't seem to care.  I placed 840mbps on tx & rx alike on different banks & the CV says it will run fine from 872mbps to 1092.9mbps depending on IOs chosen.  I wonder why they call them differential RX&TX in the pinout sheet.  Maybe there is something to do with they may be grouped into PLL channels/assignments.  I guess it makes no difference if you are not clocking in from an external source.  (FMAX gets worse if I place 1 transmitter pair on each corner of the FPGA, it's at it's best if all 4 are inside 1 IO bank, or 2 adjacent banks with all the IO at the edge of the FPGA.)

Note that this is different than when compiling with C4, it does hit a hard wall limit of 640 for the top and bottom IO banks, and for the left and right side, it's the 840 limit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2020, 08:36:30 pm
Addition to the above.  With the IOs set to DIFF-SSTL-Class I&II, any n&p IO pair can achieve 840 megabit, but you need the 2 resistor terminator.  When set to LVDS mode, IE 1 single terminator resistor across the n&p output, with AC coupled capacitor support, then the n&p IOs with the 'TX' need to be used for transmitters and the n&p IOs with the 'RX' need to be used for receive.  Note this means the FPGA uses an on-die termination resistor which you can software set to a few values.

So, if you want to use an TX n&p pair as an LVDS RX channel, you can set it to DIFF-SSTL-Class I&II and place a termination 50/100 ohm resistor on your PCB.

The TX io pairs have programmable series resistors for each output pin.
The RX io pairs have programmable parallel resistors between the n&p input lines.
The advantage of using the LVDS & similar buffer settings is traces from point A to point B, no PCB level termination resistors between FPGAs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 19, 2020, 05:35:04 pm
Parts and PCBs are now on order. :)

While I'm waiting for the PCBs to be delivered, I guess I should head back and finish that HDL ellipse function. :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 19, 2020, 11:03:24 pm
Parts and PCBs are now on order. :)

While I'm waiting for the PCBs to be delivered, I guess I should head back and finish that HDL ellipse function. :scared:
Ok, you need to change 1 thing in the current basic code.  Right now it makes an ellipse inside a box coordinates.
You need to change it so it makes an ellipse from a 'center x,y' coordinate and an 'x,y radius'.
Then it will be ready to convert to HDL.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 20, 2020, 12:41:34 am
While I'm waiting for the PCBs to be delivered, I guess I should head back and finish that HDL ellipse function. :scared:
Since you guys seems to be dead set on Cyclone V, you can also start working on DDR3 interface schematics and layout :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 20, 2020, 12:55:26 am
While I'm waiting for the PCBs to be delivered, I guess I should head back and finish that HDL ellipse function. :scared:
Since you guys seems to be dead set on Cyclone V, you can also start working on DDR3 interface schematics and layout :popcorn:
Nockieboy needs to create a project with his chosen FPGA and place in a configured DDR3 controller with dummy controls and a DVI serializer with 2 configured PLLs.  Set/wire the IOs pins and compile.  The compiler will then tell him if everything is AOK...  He cannot complete this PCB without doing so.

But before that, before entering the DDR3 controller, he need to read it's documentation and see what features and configuration he will want to use.  He also needs to decide whether to tie everything together to the existing GPU via block diagram, or go 100% HDL and drop the block diagram entry he has been using to date and write modules merging his existing HDL cores.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 20, 2020, 09:24:40 pm
But before that, before entering the DDR3 controller, he need to read it's documentation and see what features and configuration he will want to use.  He also needs to decide whether to tie everything together to the existing GPU via block diagram, or go 100% HDL and drop the block diagram entry he has been using to date and write modules merging his existing HDL cores.

Tackling the easiest task first, I'd like to stick with the block diagram.  It provides me with an easily understandable overview of how all the modules interlink that I just wouldn't have with some large, unwieldy block of HDL instantiating everything.

As for the DDR features/configuration, I've made a start on the datasheet. ???  So you want me to specify things like the burst length, burst type, CAS latency, operating mode, DLL RESET, write recovery and precharge power down mode?

Without having much of a clue about all these configuration options, I guess I'd need BL8 as we won't be interested in BC4 nibbles.  Sequential burst type?

Write Recovery is set as the result of a calculation - WR (cycles) = roundup (tWR [ns]/tCK [ns]).  Were we looking at 200MHz for the DDR clock?  That's tCK of 5ns, but how do I find tWR?

That's probably it for me for the next few days - got a busy weekend and next week.  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 20, 2020, 10:05:40 pm
But before that, before entering the DDR3 controller, he need to read it's documentation and see what features and configuration he will want to use.  He also needs to decide whether to tie everything together to the existing GPU via block diagram, or go 100% HDL and drop the block diagram entry he has been using to date and write modules merging his existing HDL cores.

Tackling the easiest task first, I'd like to stick with the block diagram.  It provides me with an easily understandable overview of how all the modules interlink that I just wouldn't have with some large, unwieldy block of HDL instantiating everything.

As for the DDR features/configuration, I've made a start on the datasheet. ???  So you want me to specify things like the burst length, burst type, CAS latency, operating mode, DLL RESET, write recovery and precharge power down mode?

Without having much of a clue about all these configuration options, I guess I'd need BL8 as we won't be interested in BC4 nibbles.  Sequential burst type?

Write Recovery is set as the result of a calculation - WR (cycles) = roundup (tWR [ns]/tCK [ns]).  Were we looking at 200MHz for the DDR clock?  That's tCK of 5ns, but how do I find tWR?

That's probably it for me for the next few days - got a busy weekend and next week.  :-\
For now, select a 300MHz ram clock and select a matching ram chip.  The megafunction will automatically enter all those fields for you.   I know they only have the -125/-15E versions of the ram chip.  This is ok as we are not clocking up to the 1GHz of the ram chip available at LCSC.

The additional features like on-die-termination should also be enabled as by default, they are not.

Also, 'enable hard memory interface' should be disabled.

Begin with this.
You will want to make a new project with your chosen FPGA, 256 ball, -C7.
You will need to add a PLL which takes in your reference 50MHz and outputs 300MHz.
Set IO pins on selected banks.  (Avoid using bank 5A for ram.)
Also, under controller settings, we will use the 'byte enable' and create 2 ports, 1 read and 1 write.
Begin here.
We will then occupy the ram controller with temporary dummy controls an compile to see if we can extend the FMAX beyond 300/600MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 20, 2020, 10:30:47 pm
For now, select a 300MHz ram clock and select a matching ram chip.
Set it to 303 MHz to stay within datasheet specs for DDR3 - it specifies 3.3 ns as max clock period, which corresponds to 1000 / 3.3 = 303.(03) MHz, so 303 is "close enough".

Also, before you settle on pinout, build a diagram of your package like the one in attachment (Xilinx did that for us, but other vendors couldn't be bothered for some reason, even though it's super-useful) which overlays DQ groups and IO bank numbers over physical package. This will allow you to see that you can actually route the pinout to a single DDR3 x16 module. You can think of it this way - you will need 2 adjacent DQ groups for data bus, and two more for address/control. If you will look at memory device's pinout, you will see that there are three separate "sections" - one for address/control, and two for two separate DQ groups (DQ0-7,DQS0+/-,DM0 for byte 0, DQ8-15,DQS1+/-,DM1 for byte 1). You will need to use a bit of imagination to think of how it's going to look like on a board, but one of advantages of "soft" controllers is that you have a lot more freedom to select pinout to facilitate routing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 20, 2020, 11:02:05 pm
Actual compiler tested FMAX IO bank speeds.  CycloneV 256 BGA

Bank #  - Inner IOs - outer IOs
Bank 8A - 766/702   - 1088/706
Bank 7A - 844/710   - 1086/710
Bank 5B - 709/709   - 1086/717
Bank 5A - 1082/717  - 653/653   (The outer IOs are dual-purpose configuration pins)
Bank 4A - 877-717   - 991/717
Bank 3B - 938/717   - 912/717
Bank 3A - 832/717   - 946/717
Bank 2A - 703/703   - 719/702

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 20, 2020, 11:06:30 pm
Actual compiler tested FMAX IO bank speeds.  CycloneV 256 BGA
Are these real numbers you can actually physically measure on outputs, or just BS numbers that can theoretically happen but never do in a real world?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 20, 2020, 11:17:44 pm
Actual compiler tested FMAX IO bank speeds.  CycloneV 256 BGA
Are these real numbers you can actually physically measure on outputs, or just BS numbers that can theoretically happen but never do in a real world?
I tied a DDR port to all the IOs with 2 counters for the clk & clk_n feeding the DDR bus.
I set the system PLL clock to 350MHz.
The figures are what Quartus reported as the maximum attainable clock frequency.
I'm sure Quartus knows how fast it's chip can run.

Only half of port 5A failed to achieve the 700mbps data rate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2020, 11:36:20 pm
@nockieboy: nothing?

At least get started on the entry level 24bit RGB + HS/VS/DE -> DVI converter.

Begin with the basic sync generator tied to the current dev-board's 7 color output RGB plug with a basic white screen.

Then simulate that tied to your 24bit RGB + HS/VS/DE  to 3x 10 bit parallel symbol output. (IE embeded HS/VS/DE & 24bit color input).

(Simulate here.)

Then add a serializer which takes the 4x10 bit in (last one is the pixel clock) and outputs the 4 serial bits.

(Simulate here, & test new PCB)

Next switch over/add to 48KHz stereo HDMI embedded audio with a source rom sine wave.

(Test on TV with audio support)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2020, 10:36:37 am
Work has been really busy and tomorrow will be my first day off for two weeks, so no real progress on the project yet.  All I've managed to do in the small amount of spare time I've had is to work on the text blitting to get a hardware scroll working.

The video I've just done isn't great - 320x200 mode, multicolour text is deleted with the wrong colour background (blue instead of black), but it works fine in single-colour text, but the video demonstrates scrolling text up the screen using the blitter.

It also works in 640x400 mode too.  The smaller-than-VGA resolutions are due to RAM limitations in the EP4CE10.

I've tried to get 320x240x2 working, but whatever I try I can't seem to get it to display anything.  640x400x1 and 320x200x4 work fine.

https://www.youtube.com/watch?v=5rEpDNTOUBs (https://www.youtube.com/watch?v=5rEpDNTOUBs)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2020, 11:56:06 am
Parts and PCBs are now on order. :)

While I'm waiting for the PCBs to be delivered, I guess I should head back and finish that HDL ellipse function. :scared:
Ok, you need to change 1 thing in the current basic code.  Right now it makes an ellipse inside a box coordinates.
You need to change it so it makes an ellipse from a 'center x,y' coordinate and an 'x,y radius'.
Then it will be ready to convert to HDL.

Okay, is this really as easy as adding a couple more variables and working out the box coordinates from the supplied centre x,y and radius?

Code: [Select]
Dim As Integer x0 = xc - radius, y0 = yc - radius
Dim As Integer x1 = xc + radius, y1 = yc + radius

I added the above two lines to the existing FreeBasic function to draw an ellipse, corrected the expected parameters for the subroutine and it's working fine?  I guess this solution will probably add a clock cycle to the HDL function and you'll probably point out there's a better way to do it.  ;)

Parts arrived a few days ago, by the way.  I'm just waiting on the PCBs, which are on their way.

EDIT:  There's probably some optimisation of the subroutine I can do as we don't need to worry about ordering x0/y0 and x1/y1 anymore.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 27, 2020, 02:33:37 pm
hardware scroll working.

how does it work?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2020, 03:08:03 pm
hardware scroll working.

how does it work?

So the screen is just a bitmap - when a newline is needed, the software checks if the last line is reached.  If it is, then it uses the blitter in the FPGA to copy the screen (minus the top row of pixels) and pastes it to the top of the screen (0,0).  The end result is the whole screen is shifted up by one row of pixels.  Repeat that 16 times (as that's the height of each text row) and you've got a hardware scroll, neatly scrolling the screen up one row at a time as required.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2020, 04:00:37 pm
Wow, nice smooth accelerated vertical text scrolling on a 320x200x16 color graphics screen with accelerated font rendering.  Funny how even without trying, we don't see vertical sync animation tearing.  I guess if you did it horizontally with enough graphics, it would become visible unless you timed the blitt to the VS.

You can also try 'Bold' test by painting each letter twice 1 pixel apart with translucency enabled for at least the second character.

As for 320x240x2, did you change the output screen & output blitt depth setting correctly?  Remember when selecting a color for the output characters you limit the output color to 2 bits.  I guess it would still work with more bits, jut maybe the output color would be messed up.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2020, 04:39:48 pm
Wow, nice smooth accelerated vertical text scrolling on a 320x200x16 color graphics screen with accelerated font rendering.  Funny how even without trying, we don't see vertical sync animation tearing.  I guess if you did it horizontally with enough graphics, it would become visible unless you timed the blitt to the VS.

There's no tearing at all.   ;D

You can also try 'Bold' test by painting each letter twice 1 pixel apart with translucency enabled for at least the second character.

Ah yes, hadn't thought of that!  Will give that a go next.  :-+

As for 320x240x2, did you change the output screen & output blitt depth setting correctly?  Remember when selecting a color for the output characters you limit the output color to 2 bits.  I guess it would still work with more bits, jut maybe the output color would be messed up.

Okay, well I don't want to lose you all in Z80 assembly (I would normally 'simplify' this code, but I don't have the time at the moment), but here's my setup code for 320x200x4 - this works (as you've seen in the video):
Code: [Select]
    ; Set screen mode flags
    LD      A,4
    LD      (SCR_MODE),A
    LD      A,3                 ; Valid values: 0, 1, 3, 7, 15
    LD      (SCR_BPP),A
    LD      HL,0140H            ; 320 pixels wide
    LD      (SCR_WDTH),HL
    LD      HL,00C8H            ; 200 pixels high
    LD      (SCR_HITE),HL
    LD      HL,0340H            ; Lower 3 bytes of 2nd pixel row address
    LD      (ROW2_ADR),HL
    LD      HL,0400H
    LD      (DELAY),HL          ; set scroll delay

    ; Set graphics | 4-bit colour
    LD      A,10
    LD      (GPU_RAM+60H),A

    ; Leave foreground and background colours (default to 0)

    ; Set screen memory base address to 1200h
    LD      A,12H
    LD      (GPU_RAM+64H),A

    ; Set YINC_ADDR (bytes per line - this changes with bpp!)
    ; This is half the pixel width as there are 2 pixels per byte
    ; in the current 4 bpp mode
    LD      HL,0A000H               ; set to 160 bytes per line for 4 bpp
    LD      (GPU_RAM+66H),HL

    ; X_SIZE to 320 pixels width
    LD      HL,013FH
    LD      (GPU_RAM+68H),HL

    ; Y_SIZE to 200 rows height (remember - 1 less than target)
    LD      A,0C7H ; 200 rows height
    ;LD      A,0EFH ; 240 rows height
    LD      (GPU_RAM+6BH),A

    ; X & Y scale (set to 1 to double size of image - 320x240 into 640x480 screen)
    LD      HL,0101H
    LD      (GPU_RAM+6CH),HL

    ; X & Y sub-pixel position (set to 0,0)
    LD      HL,0000H
    LD      (GPU_RAM+6EH),HL

    ; set GPU base_addr for graphics
    GPU_CMD 0F001H       ; set Y[3] to 01
    GPU_CMD 0B200H       ; set X[3] to 200
    GPU_CMD 7F00H        ; send cmd 124 to set destination base address
    ; set raster width (H) and bit depth (L)
    GPU_CMD 0F000H       ; reset Y[3] to 0
    GPU_CMD 0B140H       ; set X[3] to 320
    GPU_CMD 7103H        ; set dest width to Y[3]X[3] and bpp to 3 for 16 colours
    ; set X & Y limits
    GPU_CMD 8140H        ; set X[0] to 320
    GPU_CMD 0C0C8H       ; set Y[0] to 200
    ;GPU_CMD 0C0F0H       ; set Y[0] to 240
    GPU_CMD 5F00H        ; set max X & Y to X[0],Y[0]
   
    ; Turn off the blitter
    GPU_CMD 0000H        ; Blitter, PM & CP disabled

This is a straight lift from my assembly code for the graphics test program, so apologies if your Z80 assembly isn't fluent.

Here's the 320x240x2 setup code:
Code: [Select]
    ; Set screen mode flags
    LD      A,2
    LD      (SCR_MODE),A
    LD      A,1                 ; Valid values: 0, 1, 3, 7, 15
    LD      (SCR_BPP),A
    LD      HL,0140H            ; 320 pixels wide
    LD      (SCR_WDTH),HL
    LD      HL,00F0H            ; 240 pixels high
    LD      (SCR_HITE),HL
    LD      HL,0250H            ; Lower 3 bytes of 2nd pixel row address
    LD      (ROW2_ADR),HL
    LD      HL,0800H
    LD      (DELAY),HL          ; set scroll delay

    ; Set graphics mode | BP2RAST_cmd | 2-bit colour
    LD      A,9
    LD      (GPU_RAM+60H),A

    ; Set foreground to white, leave background black
    LD      A,0FH
    LD      (GPU_RAM+62H),a

    ; Set screen memory base address to 1200h
    LD      A,12H
    LD      (GPU_RAM+64H),A

    ; Set YINC_ADDR (bytes per line - this changes with bpp!)
    ; This is 1/4 the pixel width as there are 4 pixels per byte
    ; with 2 bit per pixel mode
    LD      HL,5000H               ; set to 80 bytes per line for 2 bpp @ 320
    LD      (GPU_RAM+66H),HL

    ; X_SIZE to 319 pixels width
    LD      HL,013FH
    LD      (GPU_RAM+68H),HL

    ; Y_SIZE to 239 rows height
    LD      A,0EFH ; 239 rows height
    LD      (GPU_RAM+6BH),A

    ; X & Y scale (set to 1 to double size of image - 320x240 into 640x480 screen)
    LD      HL,0101H
    LD      (GPU_RAM+6CH),HL

    ; X & Y sub-pixel position (set to 0,0)
    LD      HL,0000H
    LD      (GPU_RAM+6EH),HL

    ; set GPU base_addr for graphics
    GPU_CMD 0F001H       ; set Y[3] to 01
    GPU_CMD 0B200H       ; set X[3] to 200
    GPU_CMD 7F00H        ; send cmd 124 to set destination base address
    ; set raster width (H) and bit depth (L)
    GPU_CMD 0F000H       ; reset Y[3] to 0
    GPU_CMD 0B140H       ; set X[3] to 320
    GPU_CMD 7101H        ; set dest width to Y[3]X[3] and bpp to 2 for 4 colours
    ; set X & Y limits
    GPU_CMD 8140H        ; set X[0] to 320
    GPU_CMD 0C0F0H       ; set Y[0] to 240
    GPU_CMD 5F00H        ; set max X & Y to X[0],Y[0]
    ; Turn off the blitter
    GPU_CMD 0000H        ; Blitter, PM & CP disabled

Then finally, doesn't matter which of the two previous setup functions are executed, the blitter is set up for text as below:
Code: [Select]
SET_BLIT:
    ; Set base memory address to start of font table ($0200)
    GPU_CMD 0C000H          ; set Y[0] to 0
    GPU_CMD 8200H           ; set X[0] to 200
    GPU_CMD 7800H           ; set base memory address
    ; Set the source raster width to 8 pixels and 1 bit color depth
    GPU_CMD 0A008H          ; set X[2] to 8
    GPU_CMD 0E000H          ; set Y[2] to 0
    GPU_CMD 7200H           ; set raster width to Y[2] pixels, 1 bpp
    ; Set the destination raster width to SCR_WDTH pixels and SCR_BPP color depth
    LD      HL,(SCR_WDTH)   ; Get pixel width of screen
    LD      BC,0A000H       ; Command to load width into X[2]
    ADD     HL,BC           ; Add pixel width to the command
    CALL    send_gpu        ; set X[2] to SCR_WDTH
    GPU_CMD 0E000H          ; set Y[2] to 0
    LD      HL,7303H
    LD      A,(SCR_BPP)
    LD      L,A             ; Overwrite '03' with SCR_BPP
    CALL    send_gpu        ; set destination raster width to X[2] pixels, 4 bpp
    ; Set the blitter width and height to 8x16
    GPU_CMD 0A007H       ; set X[2] to 7
    GPU_CMD 0E00FH       ; set Y[2] to 15
    GPU_CMD 7400H        ; set copy width/height to 8x16 pixels
    ; Turn on the blitter
    LD      HL,0001H        ; Blitter enabled, PM & CP disabled
    LD      A,(BLIT_SET)
    LD      L,A             ; Override settings with defined features
    CALL    send_gpu
    RET
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2020, 06:35:38 pm
You can also try 'Bold' test by painting each letter twice 1 pixel apart with translucency enabled for at least the second character.

It works, but the font is low-res so the difference isn't as obvious as it would be on a finer, higher-res tileset.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2020, 04:13:51 am
When running the blitter, remember, you have a 'source bits/color' setting for the font which is 0 (ie 1bpp/2colors) and a 'destination bits/color' which now should be 1 or 3, (ie 2bpp/4 colors, or, 4bpp/16 colors).  Are these set properly?

Are you able to draw regular pixels the old fashioned way on the 2bpp 4 color screen?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2020, 12:02:32 pm
When running the blitter, remember, you have a 'source bits/color' setting for the font which is 0 (ie 1bpp/2colors) and a 'destination bits/color' which now should be 1 or 3, (ie 2bpp/4 colors, or, 4bpp/16 colors).  Are these set properly?

Are you able to draw regular pixels the old fashioned way on the 2bpp 4 color screen?

It's something to do with my code - have fixed one issue, can now see text in 2bpp mode - but there's other issues that I'll need to bugfix in my code.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2020, 03:16:33 pm
All fixed - working fine in 2 bpp mode now.  One issue was with the colour being 'out of bounds' for the bpp mode - it was causing some very odd behaviour, but it's all sorted now.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2020, 03:18:08 pm
At least get started on the entry level 24bit RGB + HS/VS/DE -> DVI converter.

Begin with the basic sync generator tied to the current dev-board's 7 color output RGB plug with a basic white screen.

Then simulate that tied to your 24bit RGB + HS/VS/DE  to 3x 10 bit parallel symbol output. (IE embeded HS/VS/DE & 24bit color input).

Will get started on this next.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2020, 03:23:00 pm
Parts and PCBs are now on order. :)

While I'm waiting for the PCBs to be delivered, I guess I should head back and finish that HDL ellipse function. :scared:
Ok, you need to change 1 thing in the current basic code.  Right now it makes an ellipse inside a box coordinates.
You need to change it so it makes an ellipse from a 'center x,y' coordinate and an 'x,y radius'.
Then it will be ready to convert to HDL.

Okay, is this really as easy as adding a couple more variables and working out the box coordinates from the supplied centre x,y and radius?

Code: [Select]
Dim As Integer x0 = xc - radius, y0 = yc - radius
Dim As Integer x1 = xc + radius, y1 = yc + radius

I added the above two lines to the existing FreeBasic function to draw an ellipse, corrected the expected parameters for the subroutine and it's working fine?  I guess this solution will probably add a clock cycle to the HDL function and you'll probably point out there's a better way to do it.  ;)

Parts arrived a few days ago, by the way.  I'm just waiting on the PCBs, which are on their way.

EDIT:  There's probably some optimisation of the subroutine I can do as we don't need to worry about ordering x0/y0 and x1/y1 anymore.

@BrianHG - don't know if you missed this post - any feedback at all?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2020, 07:53:16 pm

Okay, is this really as easy as adding a couple more variables and working out the box coordinates from the supplied centre x,y and radius?

Code: [Select]
Dim As Integer x0 = xc - radius, y0 = yc - radius
Dim As Integer x1 = xc + radius, y1 = yc + radius

I added the above two lines to the existing FreeBasic function to draw an ellipse, corrected the expected parameters for the subroutine and it's working fine?  I guess this solution will probably add a clock cycle to the HDL function and you'll probably point out there's a better way to do it.  ;)


You are adding complexity to the routine which was once was a center ellipse converted to a box ellipse by the original source from the website you got that code from, and now you are sitting that code inside 2 more box un/re-center variables to convert it back into a center ellipse routine...

We want to simplify, not complicate things here.

Take a look at the last 'integer general ellipse' algorithm .pdf I posted.  In the middle of that .pdf, there is a simple code which generates a 'center ellipse' using 2 small loops to generate each half of the curve (actually 1/2 of each quadrant which is what we want).  That one removes all the clutter and should convert to both basic and verilog in a snap written as is.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 29, 2020, 09:10:28 pm
why do you need eclipses?
aren't lines and triangles enough as "basic" primitives?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2020, 10:23:04 pm
why do you need eclipses?
aren't lines and triangles enough as "basic" primitives?
A Z80 is very basic and slow.  Yes, you can construct circles from triangles or a bunch of line segments.  There are a ton of apps at low res where a 'pixel/raster' rendering of circles/ellipses is a very useful geometry portion of such an engine.  Eventually Nockieboy may add the ability for the GPU to process such chunks of memory as compiled geometric vertices, however, if you need a circle/ellipse, having an available command which takes 6 variables to construct any you like which renders at core clock speed is very useful.  Complaining about adding this to the GPU:

Code: [Select]
// First 45 degrees 1 quadrant of arc
int a2 = a*a , b2 = b*b , fa2 = 4*a2 ;
int x , y , sigma ;
for ( x = 0 , y = b , sigma = 2*b2+a2*(1-2*b ) ; b2*x <= a2*y ; x++)
{
  DrawPixel ( xc+x , yc+y ) ; // draw 4 quadrants around center coordinates
  DrawPixel ( xc-x , yc+y ) ;
  DrawPixel ( xc+x , yc-y ) ;
  DrawPixel ( xc-x , yc-y ) ;

  if ( sigma >= 0 )
  {
    sigma += fa2*(1-y) ;
    y--;
  }
  sigma += b2*(4*x+6);
}

// Second 45 degrees of 1 quadrant of arc
int a2 = a*a , b2 = b*b , fb2 = 4*b2 ;
int x , y , sigma ;
for ( x = a , y = 0 , sigma = 2*a2+b2*(1-2*a) ; a2*y <= b2*x ; y++)
{
  DrawPixel ( xc+x , yc+y ) ; // draw 4 quadrants around center coordinates
  DrawPixel ( xc-x , yc+y ) ;
  DrawPixel ( xc+x , yc-y ) ;
  DrawPixel ( xc-x , yc-y ) ;
 
 if ( sigma >= 0 )
  {
    sigma += fb2*(1-x) ;
    x--;
  }
  sigma += a2*(4*y+6);
}

// Ideally, in verilog, the first and second 45 degrees should be the same code run twice once further simplification has been done.

After all the effort in a processor which was developed to render triangles, smartly filled horizontally line by line to optimize memory access cache with a new pixel ready every single core clock in a 6k logic gate FPGA with everything else we squished in there is now, not adding the above function is just being lazy.  Especially since we are upgrading to a 25kle FPGA.  (I would add that a 'general ellipse' which means an ellipse with a rotation is also much more complicated, but would cover more capability.)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 29, 2020, 10:37:34 pm
You are adding complexity to the routine which was once was a center ellipse converted to a box ellipse by the original source from the website you got that code from, and now you are sitting that code inside 2 more box un/re-center variables to convert it back into a center ellipse routine...

We want to simplify, not complicate things here.

Take a look at the last 'integer general ellipse' algorithm .pdf I posted.  In the middle of that .pdf, there is a simple code which generates a 'center ellipse' using 2 small loops to generate each half of the curve (actually 1/2 of each quadrant which is what we want).  That one removes all the clutter and should convert to both basic and verilog in a snap written as is.

Okay, aside from the filling loop, here's the FreeBasic code for the ellipse algorithm you're talking about:

Code: [Select]
Sub drawCircle(ByVal xc As integer, ByVal yc As Integer, ByVal radius As integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)

   Dim As Integer a = radius, b = radius : Rem values of diameter
Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2

x=0
y=radius
sigma = 2*b2+a2*(1-2*b)
   While (b2*x <= a2*y)
      draw_pixel(xc+x, yc+y, colour) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, colour) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, colour) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, colour) : Rem   IV. Quadrant
     
If (filled) Then
      For xd=xc-x to xc+x
draw_pixel (xd, yc+y, colour)
draw_pixel (xd, yc-y, colour)
      Next xd
EndIf

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend
   
   x=radius
   y=0
   sigma = 2*a2+b2*(1-2*a)
   While (a2*y <= b2*x)
      draw_pixel(xc+x, yc+y, colour) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, colour) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, colour) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, colour) : Rem   IV. Quadrant

If (filled) Then
      For xd=xc-x to xc+x
draw_pixel (xd, yc+y, colour)
draw_pixel (xd, yc-y, colour)
      Next xd
EndIf

If (sigma>= 0) Then
sigma += fb2*(1-x)
x=x-1
EndIf
sigma = sigma + a2*(4*y+6)
y=y+1
   Wend
 
End Sub

I seem to have had a breakthrough in understanding the algorithm and FreeBasic and it's working fine, producing the same results as the previous function I was using.

Tomorrow I'll finish this off - at the moment it'll only draw circles, with a minor tweak to the input parameters it'll draw any ellipse, but I'll do that tomorrow when I have more time.

Is this what you're saying will convert to HDL easily?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2020, 10:50:51 pm
Yes.  What you have is a modified linegen which makes 2 arcs generating the variables X&Y.  And if we look at the two 45 degree segments/halves, with a little effort, we will make that two loop code into a single loop code, called twice with a selection switch to draw each 45 degree half.  Then, for the output, we will make the 4x 'drawpixels' into 1 'drawpixel' and call the routine 4 times, each time with a switch selecting to output 1 of those 4 quadrants.

For the fill flag, we already have that programmed programmed into our verilog code where we currently fill the triangles and boxes.  All we need the ellipse to do is generate the outer edge of the arc line by line, or in a manner where we can see the y coordinate has moved.  Again, already coded as you know.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 29, 2020, 11:30:08 pm
I have recently implemented a VT100-fully functioning-but-features-reduced engine in VHDL. It's small, and I like it because for the host-CPU it's basically an "advanced serial port" with a large FIFO. I want more features, so I am thinking about implementing a VT220, and about that I am also thinking about implementing a small Softcore (RISC-V multi-cycle) so I could program it in C. This way the next VT220-on-chip will be simpler and it will take less time and effort than thinking about how to design/develop/test/and verify algorithms in HDL.

So, regarding this project, I wonder: why not implementing a Softcore, say a RISC-V CPU, that does all the graphics stuff? This way, the Z80 would only need to move code and data into the GPU's ram (DMA is possible here), and the "graphic CPU" can be programmed in C more comfortably and more productively.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2020, 11:39:36 pm
So, regarding this project, I wonder: why not implementing a Softcore, say a RISC-V CPU, that does all the graphics stuff? This way, the Z80 would only need to move code and data into the GPU's ram (DMA is possible here), and the "graphic CPU" can be programmed in C more comfortably and more productively.
Will the softcore render 125 million new pixels a second (any line angle/shape) and only eat around 1k logic elements & 1k ram for software and hardware & registers and fifo, including the blitter function with rotation & up/down size/scale sampling & translucency features with adaption for different source bitplane depths to different destination bitplane depths with pixel overwrite/collision detection?

Because this is what we have now, including the addition of the ellipse.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on November 30, 2020, 09:40:59 am
translucency

How does this work?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Nominal Animal on November 30, 2020, 10:45:52 am
translucency
How does this work?
There are two mechanisms: copy with constant fractional opacity, blending the target and the copied together at target; and copying with an alpha channel (fourth component per pixel), which does the same except using the alpha channel opacity for each pixel.

The math is usually implemented by scaling (aligning to highest bit) each color component, then multiplying with the opacity for the new pixmap, 1-opacity for the target pixels, summing the two together, and using the most significant bits for the target.  Sometimes the pixmap pixel color values will have their components premultiplied with its opacity channel value ("pre-multiplied color components"), although that tends to affect the dynamic range and thus produce slightly worse visual results.

For example, to blend two 8-bit color components c0 and c1, opacity a being between 0 (keep c0) and 256 (use c1) you use
    c = ((256 - ac0 + a·c1) >> 8
This poses a slight issue when a is also only 8-bit. In that case, either the actual value a used is (a' + (a' >> 7)), or there is no true full transparency for one of the pixmaps (original or copied).

As you can see, there are six multiplications and six additions that can be done in parallel, and makes up most of the computation involved.  (There is some bit shifting depending on the bit depths involved, too, but that's minor.)  It is perfect for an FPGA or dedicated logic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 30, 2020, 12:17:16 pm
Yes.  What you have is a modified linegen which makes 2 arcs generating the variables X&Y.  And if we look at the two 45 degree segments/halves, with a little effort, we will make that two loop code into a single loop code, called twice with a selection switch to draw each 45 degree half.  Then, for the output, we will make the 4x 'drawpixels' into 1 'drawpixel' and call the routine 4 times, each time with a switch selecting to output 1 of those 4 quadrants.

For the fill flag, we already have that programmed programmed into our verilog code where we currently fill the triangles and boxes.  All we need the ellipse to do is generate the outer edge of the arc line by line, or in a manner where we can see the y coordinate has moved.  Again, already coded as you know.

Okay, I have the full ellipse function working now.  It takes X,Y coordinates for the centre of the ellipse and a & b values for X- and Y-axis dimensions, as well as the usual colour and filled attributes.

Am I needing to optimise this code before translation to HDL, or are your comments about reducing to one loop part of the Verilogification process?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 30, 2020, 02:58:38 pm
So, regarding this project, I wonder: why not implementing a Softcore, say a RISC-V CPU, that does all the graphics stuff? This way, the Z80 would only need to move code and data into the GPU's ram (DMA is possible here), and the "graphic CPU" can be programmed in C more comfortably and more productively.
Video card is a parallel system, while CPU is serial one. You can't replace one with another without losing a lot of performance.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2020, 06:01:20 pm
translucency

How does this work?
Sorry, little correction.  In the geometry unit, we only have transparency.
To render each pixel, the geometry unit's pixel writer does a 'read-modify-write' of each written pixel.  This is how it can determine pixel collisions, decide whether 1 pixel or the other should be written on top and convert between different bitplane formats, all handled by the 'pixel-writer' module.

In the current 'MAGGIE' layers system, we currently have translucency between layers since we use a 16 bit ARGB color system, 4 bit alpha translucency + 12 bit RGB.  The resulting function for each pixel is the exact formula as 'Nominal Animal' described.  When adding the DDR ram with the larger new CycloneV FPGA, we will have the option to introduce the 'Alpha blend' in our 'pixel-writer' module when in true-color mode as with <16 bit color screens, there is no way to calculate or pre-determin the output color palette to be chosen.

The MAGGIE system allows this since it's output overlay is calculated after going through the palette where the decoded color output of each layer is always 16/32bits & we are able to mix the resulting colors providing a true-color output.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2020, 10:10:25 am
Yes.  What you have is a modified linegen which makes 2 arcs generating the variables X&Y.  And if we look at the two 45 degree segments/halves, with a little effort, we will make that two loop code into a single loop code, called twice with a selection switch to draw each 45 degree half.  Then, for the output, we will make the 4x 'drawpixels' into 1 'drawpixel' and call the routine 4 times, each time with a switch selecting to output 1 of those 4 quadrants.

For the fill flag, we already have that programmed programmed into our verilog code where we currently fill the triangles and boxes.  All we need the ellipse to do is generate the outer edge of the arc line by line, or in a manner where we can see the y coordinate has moved.  Again, already coded as you know.

Okay, I have the full ellipse function working now.  It takes X,Y coordinates for the centre of the ellipse and a & b values for X- and Y-axis dimensions, as well as the usual colour and filled attributes.

Am I needing to optimise this code before translation to HDL, or are your comments about reducing to one loop part of the Verilogification process?  ???

So, optimisation of existing code or crack on with Verilogification?

Code: [Select]
Sub drawCircle(ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)

Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2

x=0
y=b
sigma = 2*b2+a2*(1-2*b)
   While (b2*x <= a2*y)
      draw_pixel(xc+x, yc+y, colour) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, colour) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, colour) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, colour) : Rem   IV. Quadrant
     
If (filled) Then
      For xd=xc-x to xc+x
draw_pixel (xd, yc+y, colour)
draw_pixel (xd, yc-y, colour)
      Next xd
EndIf

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend
   
   x=a
   y=0
   sigma = 2*a2+b2*(1-2*a)
   While (a2*y <= b2*x)
      draw_pixel(xc+x, yc+y, colour) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, colour) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, colour) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, colour) : Rem   IV. Quadrant

If (filled) Then
      For xd=xc-x to xc+x
draw_pixel (xd, yc+y, colour)
draw_pixel (xd, yc-y, colour)
      Next xd
EndIf

If (sigma>= 0) Then
sigma += fb2*(1-x)
x=x-1
EndIf
sigma = sigma + a2*(4*y+6)
y=y+1
   Wend
 
End Sub
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 01, 2020, 04:18:22 pm
That company was founded in 1993, and their V1000 is based on a single Mips-like CPU, accessing all the video memory. The v1000 is a RISC CPU @ 25 MHz having a one-cycle multiplication of 32 * 32 occupying a solid part of the chip! All operations were performed in 32-bit integers with a fixed comma, and there was also a one-cycle instruction for calculating the approximate inverse value, that is, a two-stroke approximated integer division, and the usual set of RISC instructions.
Modern GPUs are massive SIMD machines, which means a single sequence of instructions is scheduled into 1000's of identical cores, which are fed by (and feed into) very high-latency, but massive bandwidth GDDR6/6X memory. This is what allows them to output 8.3 million of pixels of 4K many times per second, and process 100's of millions of triangles while rendering each frame.
There is no realistic way to replicate that inside FPGA, unless you use a really big and fast one (==super expensive and very power-hungry) with HBM2 DRAM, or you can settle for way less impressive results. Like maybe 1M triangles and 1080p resolution are possible if you use 64bit DDR3 memory bus running at 933 MHz and a something like 160T Kintex-7 device, as you will be lucky to fit 100 cores into it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2020, 09:25:19 pm
So, optimisation of existing code or crack on with Verilogification?

Code: [Select]
Sub drawCircle(ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer, ByVal colour as Integer, ByVal filled As Boolean = FALSE)

Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2

x=0
y=b
sigma = 2*b2+a2*(1-2*b)
   While (b2*x <= a2*y)
      draw_pixel(xc+x, yc+y, colour) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, colour) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, colour) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, colour) : Rem   IV. Quadrant
     
If (filled) Then
      For xd=xc-x to xc+x
draw_pixel (xd, yc+y, colour)
draw_pixel (xd, yc-y, colour)
      Next xd
EndIf

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend
   
   x=a
   y=0
   sigma = 2*a2+b2*(1-2*a)
   While (a2*y <= b2*x)
      draw_pixel(xc+x, yc+y, colour) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, colour) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, colour) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, colour) : Rem   IV. Quadrant

If (filled) Then
      For xd=xc-x to xc+x
draw_pixel (xd, yc+y, colour)
draw_pixel (xd, yc-y, colour)
      Next xd
EndIf

If (sigma>= 0) Then
sigma += fb2*(1-x)
x=x-1
EndIf
sigma = sigma + a2*(4*y+6)
y=y+1
   Wend
 
End Sub

Ok, to begin with, get rid of the fill nonsense for now and remembering that we will only be outputting a single quadrant at a time, step 1 is to test the code...

Code: [Select]
Sub draw_ellipse (ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer)

Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2
        Dim As Integer cr,cg,cb


cr=255:cg=0:cb=0

x=0
y=b
sigma = 2*b2+a2*(1-2*b)
   While (b2*x <= a2*y)
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
     

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend




cr=0:cg=255:cb=0
   
   x=a
   y=0
   sigma = 2*a2+b2*(1-2*a)
   While (a2*y <= b2*x)
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant


If (sigma>= 0) Then
sigma += fb2*(1-x)
x=x-1
EndIf
sigma = sigma + a2*(4*y+6)
y=y+1
   Wend

End Sub

I've attached the basic code and .exe in the .zip.
Just move the mouse to manipulate the ellipse.
I used 2 colors, red when drawing the first 45 degrees, green when drawing the second.
  (Press ESC key to quit...)
  (Sorry, the code craps out if the X&Y radius are both 0)

Take a look at what happens when the ellipse is very narrow.
Yes, the code needs 1 more thing before we begin to HDL it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 04, 2020, 12:05:08 am
Ok, here are the fixes.
What was needed was 2 things.
1.  If the radius of the ellipse on the current 45 degree plane is 0, just render a straight line.
2.  If after rendering the curve of the ellipse on the current 45 degree plane still has a remainder, IE it hasn't reached the '0' axis, finish rendering a line.

See code and attached examples:
Code: [Select]
Sub draw_ellipse (ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer)

Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2
        Dim As Integer cr,cg,cb


cr=255:cg=0:cb=0

x=0
y=b
sigma = 2*b2+a2*(1-2*b)
   While ((b2*x <= a2*y) and b>0)
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
     

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend

REM Finish line if Y hasn't landed on 0
if y<=1 then
  y=0
    for x=x to a
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
    next x
endif


cr=0:cg=255:cb=0
   
   x=a
   y=0
   sigma = 2*a2+b2*(1-2*a)
   While ((a2*y <= b2*x) and a>0)
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant


If (sigma>= 0) Then
sigma += fb2*(1-x)
x=x-1
EndIf
sigma = sigma + a2*(4*y+6)
y=y+1
   Wend

REM Finish line if X hasn't landed on 0
if x<=1 then
  x=0
    for y=y to b
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
    next y
endif

End Sub

Next step; if you look at the above code, it is doing the same thing twice, except that X&Y, A&B are swapped.
Basically, before we make the HDL, we want to make that '45 degree' arc as an internal function once, (since we are hard-coding the logic gates, only code the math once) while feeding that function the 2 different startup conditions and swapping the result.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 04, 2020, 10:27:34 am
Hmm... I can't figure out the best way to cater for the second run-through of the arc-drawing function.  I need to swap x and y for the arc calculations, but I need to keep them the same for the draw_pixel calls.  I can't figure out a simple way to do this without ugly hacks. Code below uses drawArc to draw the first arc, but the second is still drawn the old way.  Is there a better way to make drawArc work for both arcs than adding a boolean parameter to the function and having two sets of draw_pixel calls, one with x and y swapped?

Code: [Select]
Sub draw_ellipse (ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer)

   Dim As Integer x, y, sigma, xd
   Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2
   Dim As Integer cr,cg,cb

   cr=255:cg=0:cb=0
   x=0
   y=b
   drawArc (x, y, a, b, xc, yc, cr, cg, cb) *****  First call to drawArc, second call needs to be 'drawArc (y, x, b, a, xc, yc, cr, cg, cb)
                                            *****  but part of drawArc needs x & y not to be flipped (draw_pixel calls)
   cr=0:cg=255:cb=0   
   x=a
   y=0
   sigma = 2*a2+b2*(1-2*a)
   While ((a2*y <= b2*x) and a>0)
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant

      If (sigma>= 0) Then
         sigma += fb2*(1-x)
         x=x-1
      EndIf
      sigma = sigma + a2*(4*y+6)
      y=y+1
   Wend

   Rem Finish line if X hasn't landed on 0
   If x<=1 Then
      x=0
      For y=y to b
         draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
         draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
         draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
         draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
      Next y
   EndIf

End Sub

Sub drawArc (ByVal x As Integer, ByVal y As Integer, ByVal a As Integer, ByVal b As Integer, ByVal xc As Integer, ByVal yc As Integer, ByVal cr As Integer, ByVal cg As Integer, ByVal cb As Integer)

   Dim As Integer sigma
   Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2

   sigma = 2*b2+a2*(1-2*b)
   While ((b2*x <= a2*y) and b>0)
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant

      If (sigma>= 0) Then
         sigma += fa2*(1-y)
         y=y-1
      EndIf
      sigma = sigma + b2*(4*x+6)
      x=x+1
   Wend

   REM Finish line if y hasn't landed on 0
   If y<=1 Then
      y=0
      For x=x to a
         draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
         draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
         draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
         draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
      Next x
   EndIf

End Sub
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 04, 2020, 04:11:34 pm
Just for completeness, here's my hacky (but working) ellipse function:

Code: [Select]
Sub draw_ellipse (ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer)

Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2
   Dim As Integer cr,cg,cb

cr=255:cg=0:cb=0
x=0
y=b
drawArc (FALSE, x, y, a, b, xc, yc, cr, cg, cb)

cr=0:cg=255:cb=0   
   x=a
   y=0
   drawArc (TRUE, y, x, b, a, xc, yc, cr, cg, cb)


End Sub

Sub drawArc (ByVal inv As Boolean, ByVal x As Integer, ByVal y As Integer, ByVal a As Integer, ByVal b As Integer, ByVal xc As Integer, ByVal yc As Integer, ByVal cr As Integer, ByVal cg As Integer, ByVal cb As Integer)

Dim As Integer sigma
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2

sigma = 2*b2+a2*(1-2*b)
   While ((b2*x <= a2*y) and b>0)
   
    If (inv) Then
      draw_pixel(xc+y, yc+x, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-y, yc+x, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+y, yc-x, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-y, yc-x, cr, cg, cb) : Rem   IV. Quadrant
    Else
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
    EndIf

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend

REM Finish Line if y hasn't landed on 0
If y<=1 Then
  y=0
    For x=x to a
      If (inv) Then
      draw_pixel(xc+y, yc+x, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-y, yc+x, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+y, yc-x, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-y, yc-x, cr, cg, cb) : Rem   IV. Quadrant
      Else
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
      EndIf
    Next x
EndIf

End Sub
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2020, 01:15:30 am
Just for completeness, here's my hacky (but working) ellipse function:

Code: [Select]
Sub draw_ellipse (ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer)

Dim As Integer x, y, sigma, xd
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2
   Dim As Integer cr,cg,cb

cr=255:cg=0:cb=0
x=0
y=b
drawArc (FALSE, x, y, a, b, xc, yc, cr, cg, cb)

cr=0:cg=255:cb=0   
   x=a
   y=0
   drawArc (TRUE, y, x, b, a, xc, yc, cr, cg, cb)


End Sub

Sub drawArc (ByVal inv As Boolean, ByVal x As Integer, ByVal y As Integer, ByVal a As Integer, ByVal b As Integer, ByVal xc As Integer, ByVal yc As Integer, ByVal cr As Integer, ByVal cg As Integer, ByVal cb As Integer)

Dim As Integer sigma
Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2

sigma = 2*b2+a2*(1-2*b)
   While ((b2*x <= a2*y) and b>0)
   
    If (inv) Then
      draw_pixel(xc+y, yc+x, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-y, yc+x, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+y, yc-x, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-y, yc-x, cr, cg, cb) : Rem   IV. Quadrant
    Else
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
    EndIf

If (sigma>= 0) Then
sigma += fa2*(1-y)
y=y-1
EndIf
sigma = sigma + b2*(4*x+6)
x=x+1
   Wend

REM Finish Line if y hasn't landed on 0
If y<=1 Then
  y=0
    For x=x to a
      If (inv) Then
      draw_pixel(xc+y, yc+x, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-y, yc+x, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+y, yc-x, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-y, yc-x, cr, cg, cb) : Rem   IV. Quadrant
      Else
      draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
      draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
      draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
      draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
      EndIf
    Next x
EndIf

End Sub
Ok, study your correct 'flip' and move the (red parts):

   x=0
   y=b
   drawArc (FALSE, x, y, a, b, xc, yc, cr, cg, cb)

and

   x=a
   y=0
   drawArc (TRUE, y, x, b, a, xc, yc, cr, cg, cb)

inside the draw arc.

This should eliminate the (stuff in red):
   Dim As Integer x, y, sigma, xd
   Dim As Integer a2 = a*a, b2 = b*b, fa2 = 4*a2, fb2 = 4*b2
   Dim As Integer cr,cg,cb

Right at the top of your code.
Next, make 1 output at a time and add to the 'Sub drawArc (ByVal inv As Boolean,...' another flag called 'Quadrant' which goes from 0 to 3.  Then call the 'drawArc (FALSE, [quadrant] ' and 'drawArc (TRUE, [quadrant]' 4 times to generate the ellipse.

In Verilog, the module will only output 1 quadrant/set of coordinates at a time.  When calling the ellipse from the Z80, you will call the Draw-Ellipse 4 times to draw the 4 corners.  This will allow you to either render ellipses when calling the 4 with the same center coordinates, or move the XY center coordinates to make rectangle boxes with rounded corners.

Do not worry about the fill, the line filler runs outside the draw-ellipse generator.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2020, 10:32:44 am
In Verilog, the module will only output 1 quadrant/set of coordinates at a time.  When calling the ellipse from the Z80, you will call the Draw-Ellipse 4 times to draw the 4 corners.  This will allow you to either render ellipses when calling the 4 with the same center coordinates, or move the XY center coordinates to make rectangle boxes with rounded corners.

To have rounded edges on a rectangle, I'm going to need to rotate the ellipse or arc by 45 degrees, though?

Here's what I've done - all working fine:

Code: [Select]
Sub draw_ellipse (ByVal xc As integer, ByVal yc As Integer, ByVal a As integer, ByVal b As Integer)
   
   Dim As Integer cr, cg, cb=0, quad
   
    For quad=0 To 3
        cr=0:cg=255
        drawArc (TRUE, quad, a, b, xc, yc, cr, cg, cb)
        cr=255:cg=0
        drawArc (FALSE, quad, a, b, xc, yc, cr, cg, cb)
    Next quad
   
End Sub

Sub drawArc (ByVal inv As Boolean, ByVal quadrant As Integer, ByVal af As Integer, ByVal bf As Integer, ByVal xc As Integer, ByVal yc As Integer, ByVal cr As Integer, ByVal cg As Integer, ByVal cb As Integer)
   
    Dim As Integer sigma, x=0, y, a, b, a2, b2, fa2, fb2
   
    If (inv) Then
        a=bf
        b=af
    Else
        a=af
        b=bf
    EndIf
   
    a2 = a*a
    b2 = b*b
    fa2 = 4*a2
    fb2 = 4*b2
    y=b
   
    sigma = 2*b2+a2*(1-2*b)
    While ((b2*x <= a2*y) and b>0)
   
        Select Case quadrant
            Case 0
                If (inv) Then
                    draw_pixel(xc+y, yc+x, cr, cg, cb) : Rem   I. Quadrant
                Else
                    draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
                EndIf
            Case 1
                If (inv) Then
                    draw_pixel(xc-y, yc+x, cr, cg, cb) : Rem  II. Quadrant
                Else
                    draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem  II. Quadrant
                EndIf
            Case 2
                If (inv) Then
                    draw_pixel(xc+y, yc-x, cr, cg, cb) : Rem III. Quadrant
                Else
                    draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem III. Quadrant
                EndIf
            Case 3
                If (inv) Then
                    draw_pixel(xc-y, yc-x, cr, cg, cb) : Rem  IV. Quadrant
                Else
                    draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem  IV. Quadrant
                EndIf
            Case Else
                Return
        End Select
   
        If (sigma>= 0) Then
            sigma += fa2*(1-y)
            y=y-1
        EndIf
        sigma = sigma + b2*(4*x+6)
        x=x+1
       
    Wend

    REM Finish Line if y hasn't landed on 0
    If y<=1 Then
        y=0
        For x=x to a
        If (inv) Then
              draw_pixel(xc+y, yc+x, cr, cg, cb) : Rem   I. Quadrant
              draw_pixel(xc-y, yc+x, cr, cg, cb) : Rem   II. Quadrant
              draw_pixel(xc+y, yc-x, cr, cg, cb) : Rem   III. Quadrant
              draw_pixel(xc-y, yc-x, cr, cg, cb) : Rem   IV. Quadrant
        Else
              draw_pixel(xc+x, yc+y, cr, cg, cb) : Rem   I. Quadrant
              draw_pixel(xc-x, yc+y, cr, cg, cb) : Rem   II. Quadrant
              draw_pixel(xc+x, yc-y, cr, cg, cb) : Rem   III. Quadrant
              draw_pixel(xc-x, yc-y, cr, cg, cb) : Rem   IV. Quadrant
        EndIf
        Next x
    EndIf
   
End Sub

Have attached geoarc.bas and the compiled .exe in the zip below.  There was a little head-scratching caused by trying to remove x and y from the function parameters and normalising the inputs to the drawArc function, but I worked it out in the end. ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2020, 11:03:29 am
So this arrived the other day - unwrapped today to take a look.  Those 0403s around the QFN don't look as bad as I thought they'd be.  Guess I'll just lightly tin one set of pads, fix the resistors/caps to those pads and then solder the other sides to their pads, same way as I do all the others, just with a little more care.

Have looked up a couple of videos on YouTube to see how best to solder the QFN.  That's going to be a first for me, but I've got 10 QFNs and 10 boards, so I'm hoping I'll get the hang of it before the 10th one.  :o  In fairness, doesn't look too hard - flux, lightly tin the pads, clean and flux, pop the QFN down and attempt to follow some sort of soldering profile as best I can with my heatgun.  I guess the thinner PCB will warm up more quickly, but I'll need to be careful not to overheat it.

For anyone following along to get a sense of scale, C11 and R18 are 0805 components, the network of resistors and capacitors near the thru-holes at the top of the card are 0603, and the components around the QFN footprint are 0402s.  The cutting mat underneath has 1cm boxes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2020, 07:52:04 pm
Nice PCB.  Only place the 100ohm parallel terminators and 0.1uf caps.  Do not place the double 50ohm terminators.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 08, 2020, 07:55:12 pm
In Verilog, the module will only output 1 quadrant/set of coordinates at a time.  When calling the ellipse from the Z80, you will call the Draw-Ellipse 4 times to draw the 4 corners.  This will allow you to either render ellipses when calling the 4 with the same center coordinates, or move the XY center coordinates to make rectangle boxes with rounded corners.

To have rounded edges on a rectangle, I'm going to need to rotate the ellipse or arc by 45 degrees, though?

Here's what I've done - all working fine:

Think for a second.   There are 4 quadrants being plotted.  Hence 4 sides of the ellipse.
Q1: What happens (IE what it the resulting shape) if you call only 1 of the 4?
Q2: What happens if you change the Xc/Yc and call a single different 1 of 4 each time?

I'll ignore the ' REM Finish Line if y hasn't landed on 0' having drawn 4 quadrants.  We will fix this in verilog...

Ok, now, to convert the function into verilog.  We will make the function look/have the same IOs and controls as the current 'line_generator.sv'.  Except, we will add a 2 bit input called 'Quadrant' which latches which quadrant to output/render when the 'RUN' is asserted.

Basically copy & rename the 'line_generator.sv' into a 'ellipse_generator.sv' and add a new 2 bit input called 'Quadrant'.

As for the 'geometry_xy_plotter.sv', we will generate a 'line_select_mux' module which will address the  'line_generator.sv' or 'ellipse_generator.sv' into the place of the first current 'line_generator.sv' which will select between the 2 depending of the called graphics op-code.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2020, 03:27:56 pm
Think for a second.   There are 4 quadrants being plotted.  Hence 4 sides of the ellipse.
Q1: What happens (IE what it the resulting shape) if you call only 1 of the 4?
Q2: What happens if you change the Xc/Yc and call a single different 1 of 4 each time?

Ah, wasn't thinking straight when I asked that question.  ;)

Ok, now, to convert the function into verilog.  We will make the function look/have the same IOs and controls as the current 'line_generator.sv'.  Except, we will add a 2 bit input called 'Quadrant' which latches which quadrant to output/render when the 'RUN' is asserted.

Basically copy & rename the 'line_generator.sv' into a 'ellipse_generator.sv' and add a new 2 bit input called 'Quadrant'.

All done - see attached.  I was going to push on and attempt to convert the FreeBasic into HDL, but don't we need an input for 'invert' as well?

We're going to be doing multiplication.  Can't recall without looking (and can't at the moment) if we've done that before - that'll infer some extra logic I'm guessing, so I didn't want to rush ahead and get it all wrong without waiting to see what you've got in mind next. :)

As for the 'geometry_xy_plotter.sv', we will generate a 'line_select_mux' module which will address the  'line_generator.sv' or 'ellipse_generator.sv' into the place of the first current 'line_generator.sv' which will select between the 2 depending of the called graphics op-code.

Does it need to be a separate module?  Would have thought that would be a convenient thing just to drop into geometry_xy_plotter.sv, unless you've got plans to re-use it elsewhere?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2020, 05:47:06 pm
Had a go at building the DVI tester today.  Took me three attempts to get the QFN to solder to the PCB in a way that I'm vaguely happy with - it probably still isn't soldered properly, but looks good on all contacts as best I can tell, so I've assembled the rest of the board.  That's when I found that 0402s aren't that bad, just damn fiddly and it's really hard trying not to deposit too much solder when attaching them, even though I'm using 0.5mm solder.

Have had to stop, though, as I've realised I've made a mistake - I didn't order any 0402 12.4K resistors. |O  This means I've got no R3 and I guess the board won't work.  That's going to be a delay to get those resistors, guess I'll just have to bite the bullet and do another big order with Mouser to negate their P&P charges, otherwise it'll cost me about $20 for 100 of those resistors...  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 10, 2020, 08:52:58 pm
Have had to stop, though, as I've realised I've made a mistake - I didn't order any 0402 12.4K resistors. |O  This means I've got no R3 and I guess the board won't work.  That's going to be a delay to get those resistors, guess I'll just have to bite the bullet and do another big order with Mouser to negate their P&P charges, otherwise it'll cost me about $20 for 100 of those resistors...  :-\
Don't worry - that happens to all of us every once in a while :-[ Especially for REV 1 of a project.
Don't you have any local online retailers which don't charge ridiculous fees for shipping small orders? There is no rush for these parts to arrive, as you still have no code for it, and just plugging it in won't do anything (well, aside from ensuring it won't let the magic smoke out when you connect it and power up for the first time :D ). I would just go onto LCSC and order reels of all passive parts (most of them are super cheap there, even those from name-brands), and let them slowboat via e-packet or something like that, while you work on HDL code to get this stuff up and running. You will find a use for these parts in your later projects.
In the mean time I suggest you to download HDMI spec - version 1.3a can be downloaded for free after filling out a short form here: https://www.hdmi.org/requestform/clickrequestasync?docId=16 (https://www.hdmi.org/requestform/clickrequestasync?docId=16) This version will be more than enough for your needs, so skim through it to get familiar with how things work at the high level. Don't get bogged down in details for now, just basic familiarization will be enough. You will see a lot of similarities with VGA, the differences will be mostly in what happens during blanking intervals - that's when all auxiliary information like stream info packets, audio, and/or other things, are transmitted (in case of VGA or DVI it's just a whole bunch of nothingness).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: mariush on December 10, 2020, 09:07:01 pm

Have had to stop, though, as I've realised I've made a mistake - I didn't order any 0402 12.4K resistors. |

You could just stack 2-3 resistors ... parallel resistors ... ex 68k + 15k gives you 12.3k  , 39+39+33 gives you 12.26 etc , 47+47+27 = 12.56 ....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2020, 10:11:54 pm

Have had to stop, though, as I've realised I've made a mistake - I didn't order any 0402 12.4K resistors. |

You could just stack 2-3 resistors ... parallel resistors ... ex 68k + 15k gives you 12.3k  , 39+39+33 gives you 12.26 etc , 47+47+27 = 12.56 ....

I just don't have the selection of resistors in any size (except maybe through-hole) to make up that value, let alone 0402 which I've just started using.

Don't you have any local online retailers which don't charge ridiculous fees for shipping small orders? There is no rush for these parts to arrive, as you still have a code for it, and just plugging it in won't do anything (well, aside from ensuring it won't let the magic smoke out when you connect it and power up for the first time :D ). I would just go onto LCSC and order reels of all passive parts (most of them are super cheap there, even those from name-brands), and let them slowboat via e-packet or something like that, while you work on HDL code to get this stuff up and running. You will find a use for these parts in your later projects.

Not really, no.  They all seem to price their shipping and 'free' thresholds to dissuade people from making small orders.  The only real supplier/s of cheap and small-quantity parts are the Chinese distributors, and I was trying to ween myself off them. Might have to make an exception, especially as time isn't an issue as you rightly point out.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 10, 2020, 10:41:06 pm
Not really, no.  They all seem to price their shipping and 'free' thresholds to dissuade people from making small orders.  The only real supplier/s of cheap and small-quantity parts are the Chinese distributors, and I was trying to ween myself off them. Might have to make an exception, especially as time isn't an issue as you rightly point out.  ;)
Looked at the Farnell: https://uk.farnell.com/help-delivery-information They show free shipping for 40+ quid, which sounds great. Over here we have 100$ free shipping threshold at both Digikey and Mouser.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 11, 2020, 11:50:48 am
Not really, no.  They all seem to price their shipping and 'free' thresholds to dissuade people from making small orders.  The only real supplier/s of cheap and small-quantity parts are the Chinese distributors, and I was trying to ween myself off them. Might have to make an exception, especially as time isn't an issue as you rightly point out.  ;)
Looked at the Farnell: https://uk.farnell.com/help-delivery-information They show free shipping for 40+ quid, which sounds great. Over here we have 100$ free shipping threshold at both Digikey and Mouser.

Yeah, Mouser do the same - the £40 threshold for free shipping is the same.  Just annoying that I have to make up a £40+ order for what is effectively 0.011p worth of resistor that I need. ;)

Having read the datasheet, it appears I might not need it anyway - the following is lifted straight from the datasheet:

7.2 Analog current reference
The REXT pin (pin 6) is an analog current sense port used to provide an accurate current reference for the differential outputs OUT_Dx. For best output voltage swing accuracy, use of a 12.4 kohm resistor (1% tolerance) connected between this terminal and GND is recommended.

If an external 12.4 kohm 1% resistor is not used, this pin can be connected to GND or VDD directly (0 ohm). In any of these cases, the output functions normally but at reduced accuracy over voltage and temperature of the following parameters: output levels (VOL), differential output voltage swing, and rise and fall time accuracy.


It doesn't specify just how much the accuracy is reduced, but it should function well enough for me to work out if the board and HDL are working as expected, whilst I wait for the 12.4K resistors from wherever I end up ordering them from.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2020, 11:54:48 pm
Not really, no.  They all seem to price their shipping and 'free' thresholds to dissuade people from making small orders.  The only real supplier/s of cheap and small-quantity parts are the Chinese distributors, and I was trying to ween myself off them. Might have to make an exception, especially as time isn't an issue as you rightly point out.  ;)
Looked at the Farnell: https://uk.farnell.com/help-delivery-information They show free shipping for 40+ quid, which sounds great. Over here we have 100$ free shipping threshold at both Digikey and Mouser.

Yeah, Mouser do the same - the £40 threshold for free shipping is the same.  Just annoying that I have to make up a £40+ order for what is effectively 0.011p worth of resistor that I need. ;)

Having read the datasheet, it appears I might not need it anyway - the following is lifted straight from the datasheet:

7.2 Analog current reference
The REXT pin (pin 6) is an analog current sense port used to provide an accurate current reference for the differential outputs OUT_Dx. For best output voltage swing accuracy, use of a 12.4 kohm resistor (1% tolerance) connected between this terminal and GND is recommended.

If an external 12.4 kohm 1% resistor is not used, this pin can be connected to GND or VDD directly (0 ohm). In any of these cases, the output functions normally but at reduced accuracy over voltage and temperature of the following parameters: output levels (VOL), differential output voltage swing, and rise and fall time accuracy.


It doesn't specify just how much the accuracy is reduced, but it should function well enough for me to work out if the board and HDL are working as expected, whilst I wait for the 12.4K resistors from wherever I end up ordering them from.
I would say, don't bother ordering the 12.4k for now.  Just insert a 10k resistor.  Let's see what happens.  Save the 12.4k for when you need to make another larger order.

I will have time this weekend to help you with the Ellipse.  It shouldn't be too hard as we have done this type of coding before everywhere else.  And, multiply in verilog is just a ' * '.  I will go more into the coding tomorrow.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2020, 05:18:03 am
Ok, let's take a look at what needs to be done with your code.

The line generator outline is ok. maybe we should rename a few things for ease of understanding.

Code: [Select]
/*
 * ELLIPSE GENERATOR MODULE
 *
 * v 0.1.001
 *
 */

module ellipse_generator (
// inputs
  input logic                clk,              // 125 MHz pixel clock
  input logic                reset,            // asynchronous reset
  input logic                enable,           // logic enable
  input logic                run,              // HIGH to draw / run the unit
  input logic          [1:0] quadrant,         // specifies which quadrant of the ellipse to draw
  input logic signed  [11:0] Xc,               // 12-bit X-coordinate for center of ellipse
  input logic signed  [11:0] Yc,               // 12-bit Y-coordinate for center of ellipse
  input logic signed  [11:0] A,               // 12-bit X-radius, the width
  input logic signed  [11:0] B,               // 12-bit Y-radius, the height
  input logic                ena_pause,         // set HIGH to pause line generator while it is drawing
// outputs
  output logic               busy,             // HIGH when ellipse_generator is running
  output logic signed [11:0] X_coord,          // 12-bit X-coordinate for current pixel
  output logic signed [11:0] Y_coord,          // 12-bit Y-coordinate for current pixel
  output logic               pixel_data_rdy,   // HIGH when coordinate outputs are valid
  output logic               ellipse_complete     // HIGH when ellipse is completed
 
);

Next, some of the internal logic:

Code: [Select]
logic               draw_line     = 1'b0 ;
logic        [1:0]  quadrant_latch = 2'b0 ;  // This logic latches which quadrant to draw when run is issued
logic        [2:0]  geo_sub_func1 = 3'b0 ;  // This logic defines which step is running, IE first setup for first 45 degrees,
                              // draw the first 45 degrees if the radius is not 0, finish the ellipse if the remaining radius is <=1,
                              // setup for the second 45 degrees (inv), draw the second 45 degrees if the radius is not 0,
                              // finish the ellipse if the remaining radius is <=1, end the busy and await the next command.
logic signed [11:0] x                   ;  internal drawing x coordinate
logic signed [11:0] y                   ;  internal drawing x coordinate
logic signed [11:0] af                  ;
logic signed [11:0] ab                 ;
logic signed [23:0] a2                 ; // Note that the 4* fa2 & fb2 arent needed as they will just be a logic shift inside the code
logic signed [23:0] b2                 ;
logic signed [23:0] sigma            ;

logic               pixel_data_rdy_int   ;     // HIGH when coordinate outputs are valid
logic               busy_int             ;     // HIGH when coordinate outputs are valid

Now for the combinational logic:

Code: [Select]
always_comb begin

   pixel_data_rdy = pixel_data_rdy_int && !ena_pause ; // immediately clear the pixel_data_ready output when the pause is high.
   busy           = busy_int || run ;                  // immediately make busy flag high when run is asserted
   
end

This stays the same as these outputs are crucial to match & be compliant with the line-generator's output.

Now, for the next part:
Code: [Select]
always_ff @( posedge clk  or posedge reset) begin

   if ( reset ) begin
   
      // reset geometry counters and flags
// *********  Fill this in ********* //
       
   end
   else if ( enable ) begin // draw_busy_int must be LOW or the line generator won't run

      if ( run ) begin  // load values and begin drawing the line

         // Initialise starting coordinates and direction for immediate plotting
         quadrant_latch <= quadrant   ; // latch which of the 4 quadrants will be drawn

         if ((A==0) && (B==0)) begin // 0 X&Y radius, drawing only a single center point

         X_coord            <= Xc   ; // initialize starting X pixel location
         Y_coord            <= Yc   ; // initialize starting Y pixel location

            pixel_data_rdy_int <= 1'b1 ; // set pixel_data_rdy_int flag
            line_complete      <= 1'b1 ; // make sure line_complete is set.
            geo_sub_func1      <= 1'b0 ; // reset the phase counter
            draw_line          <= 1'b0 ; // no line to draw
            busy_int           <= 1'b0 ; // the line generator is busy_int  from the next cycle

         end
         else begin //  Drawing a full ellipse

// *********  Work on this  ********* //

Use the other code to begin.  First start initialize the variables and begin only the first 45 degrees.
Just output the X&Y, do not bother with any quadrants yet.
Setup a simulation test bench in Quartus driving the input and a clock.  No other modules.
Drive some test inputs and I'll prepare the Freebasic code to print out the rendered coordinates of the arc.


(Arrrrgggg, the page count is over 9000 ......)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2020, 06:16:59 am
Ok, here is the freebasic geoarc.bas & exe.
The green and red text show the two 45 degree phases of the computed X&Y arc coordinates.
The cyan and magenta text which occasionally appears shows the flat line remaining at the end of an arc or a flat arc.

Your verilog simulation test bench should spit out the same numbers given the same a&b radius.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2020, 01:21:03 pm
Bit confused - we've got no 'inv' input and what are 'af' and 'ab' for?  I guess they're 'a' and 'b' in the FreeBasic ellipse function - but instead of setting them via 'inv', am I supposed to set them via the current geo_sub_func1 value?  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2020, 01:29:20 pm
Bit confused - we've got no 'inv' input and what are 'af' and 'ab' for?  I guess they're 'a' and 'b' in the FreeBasic ellipse function - but instead of setting them via 'inv', am I supposed to set them via the current geo_sub_func1 value?  ???

geo_sub_func1 is just a logic register to store which state your sequencer is running.

IE, when run is asserted, do your setup and make it 1.
When it's 1, do something else like run the main first arc.
When that arc completes, make it 2 if you need to finish drawing a flat line, otherwise make it 3.
When it's 2, finish the flat line and make it 3.
When it's 3, for now, stop/complete line and make the module into it's idle non-running state.

(Though, states 3 through 6 would generate the 'inv' portion of the arc, but for now, just worry about steps 1-3).

Think of it like a program counter.
A program counter where you need to tell it to increment only when you are ready to stop what you are currently doing and get onto the next step, or jump somewhere else.

You have already done this before in the old line_generator and a number of other times using the 'case' command, or, if() / else if() sequences.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2020, 01:40:25 pm
I'll be back lateron tonight, so, setup any sequencer & a sim test bench for now, even if you don't get the formula exactly right.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2020, 03:06:50 pm
See attached for test bench setup.  I've just used the ellipse_generator.sv file, no frills or extra modules, to test its output.

As far as the ellipse_generator module goes, it's nowhere near finished yet.  I've added some logic to more closely match the FreeBasic function - things I feel were needed - but you may have been one or two steps ahead of me in optimising the HDL routine when you specified the inputs originally, so I may have added some things that aren't right / needed.

I have the very basic framework of the ellipse generation, but am not finishing the ellipse off yet.  It looks like I need at least one more geo_sub_func1 step to complete the final 'for...next' loop to finish the line.  Not sure I'm going down the right route, so feedback appreciated.  Will have more time tomorrow to work on this, today is busy unfortunately.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2020, 10:19:36 pm
Please reserve the test bench/project names.

I believe we had the Geo-Writer as a complete build of the geometry system, actual commands in, written pixels to a memory module out.

Right now, all I wanted was the ellipse module, naked all on it's own for debugging.

Just it's inputs fed and outputs viewed.  No Z80 geometry command system.
Just like the first line_generator's test bench we had oh-so-many months ago.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2020, 10:32:57 pm
Please reserve the test bench/project names.

I believe we had the Geo-Writer as a complete build of the geometry system, actual commands in, written pixels to a memory module out.

Right now, all I wanted was the ellipse module, naked all on it's own for debugging.

Just it's inputs fed and outputs viewed.  No Z80 geometry command system.
Just like the first line_generator's test bench we had oh-so-many months ago.

Yeah, that's what you've got.  Because I copied the folder from the geo_writer_v7 for the new project, it has the same name.  But all it is in the test bench is the ellipse_generator.sv, no other fluff.

The ellipse_generator.sv file is in the test bench project, but I've added it here as requested.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2020, 02:19:42 am
     Ok, here we go.  You made a few mistakes like when you had to multiply by 2, you right left shifted by 2.   That's wrong.  A right left shift by 1 is a multiply by 2.  Though you did get the multiply by 4 correct???

     OK, that being said, I redone the 'case' statement layout and removed some glutt.

     In the TB, I changed all the coordinates from hex to signed decimal for ease of viewing.

     The current FMAX is 84 MHz, a far cry from the required 125MHz or preferred 150MHz.
We are also eating 24 9bit embedded multipliers.  It turns out this way because of all the parallel non-matched multiplies used all over the place.  Some we can get rid of by using 2 clock cycles 2 perform 2 different multiplies, such as the multiple '^2' for the X & Y used in the setup before the arc begins to draw.

     In the new Cyclone V, you using 7 DSP blocks out of 28.  Though the rest of the GPU only uses 2 more.  Also, it's sad that the CV FMAX has dropped to 80MHz.  (This might be due to other factors which may disappear when the logic becomes embedded deep within the core of the FPGA, like the way the IO pins are timed.)

     I've attached all the updates.

     The next step is to increase the FMAX before we continue as all the rest of the logic just reloads the current arc loop with flipped X&Y or, completes a straight line.  The final step is to add or subtract the ellipse center coordinates from the rendered X&Y depending on the requested 'quadrant'

     Step 1, looking at the code, how do you think we will attack the low FMAX and get it above 125MHz?

(For those reading, the current code only generates the first green part of the ellipse shown in the freebasic screenshot image)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on December 15, 2020, 02:21:20 am
     Ok, here we go.  You made a few mistakes like when you had to multiply by 2, you right shifted by 2.   That's wrong.  A right shift by 1 is a multiply by 2...

You probably meant left shift?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2020, 02:24:06 am
     Ok, here we go.  You made a few mistakes like when you had to multiply by 2, you right shifted by 2.   That's wrong.  A right shift by 1 is a multiply by 2...

You probably meant left shift?
My mild form of dyslexia kicking in.  I always flip things around, not just letters, but signs and directions when coding.  Thank god the only thing I don't flip around is +&- when powering electronics or diode orientation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2020, 06:39:30 am
Ok, Nockieboy, I've attached an update.  It seems to function identical to the first code, but, it now compiles with an FMAX of 100MHz.  Double check my math.

I foresee problems.  Part of the trick I employed ate up a few more multipliers.  Plus, because of the damn While/If () loop which compares B^2*x with A^2*y, which was originally done/cropped to 24 bits, we may need to do it at 32 bits.  If the width of the ellipse is 2047, that 11 bits, square that + multiply that with the y, then you get a 33 bit result.  If I make the While/If condition compare 2x 33 bit numbers instead of the current 24 bits, our FMAX drops back down to 84MHz.

I will need to look at other integer Bresenham Ellipse functions to see if I can imagine a shortcut without having to resort to a multistaged pipelined version.

I attached the 100MHz version.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2020, 11:38:05 am
     Ok, here we go.  You made a few mistakes like when you had to multiply by 2, you right left shifted by 2.   That's wrong.  A right left shift by 1 is a multiply by 2.  Though you did get the multiply by 4 correct???

Ah, typos.  I do understand that a bit-shift to the left each position is equivalent of multiplying by 2, and to the right is division by 2.  Just shows I shouldn't program when I'm in a rush. ::)

     Step 1, looking at the code, how do you think we will attack the low FMAX and get it above 125MHz?

My lack of knowledge and skill with HDL means I'm a bit of a blunt instrument when it comes to this sort of thing, so my first (and only) tactic to increase the FMax would be to break the calculations down into more, smaller steps.

Ok, Nockieboy, I've attached an update.  It seems to function identical to the first code, but, it now compiles with an FMAX of 100MHz.  Double check my math.

It seems to be running-on for an extra pixel at the end with a 25x25 ellipse, or I'm misreading the results? ???  Take a look at the simulation I've done with a 25x25 ellipse - simulation output doesn't quite match the FreeBasic one - it looks like the ellipse generator needs to stop a pixel earlier?  But otherwise, it's producing the right output.

However, if I run a simulation with a 27x27 ellipse, it seems to work fine?  I must be getting confused with X/Y output in the 25x25 case...?

I foresee problems.  Part of the trick I employed ate up a few more multipliers.  Plus, because of the damn While/If () loop which compares B^2*x with A^2*y, which was originally done/cropped to 24 bits, we may need to do it at 32 bits.  If the width of the ellipse is 2047, that 11 bits, square that + multiply that with the y, then you get a 33 bit result.  If I make the While/If condition compare 2x 33 bit numbers instead of the current 24 bits, our FMAX drops back down to 84MHz.

This is probably me being very short-sighted, but under what conditions would we ever need to worry about an ellipse 2047 pixels wide on a display that can only handle 640x480, or 720p?  If I was writing a flight simulator, I might need to draw the arc of an ellipse much larger than the screen to represent the horizon from high altitude, but there'd be more important things I'd have to worry about with the available memory and number-crunching power than whether the horizon is flat or curved.

I will need to look at other integer Bresenham Ellipse functions to see if I can imagine a shortcut without having to resort to a multistaged pipelined version.

Extra stages in the setup part of the function aren't the greatest of concerns - there'll be a limit to how quickly the Z80 can setup/request ellipses to be drawn and I don't think a few additional 8ns clock cycles in the setup of each request will be a performance-breaker (or even noticeable up to a point), but once the function starts hammering out pixels, I guess that's where we need to be careful.

Have added ellipse_generator.sv as well - same as the version you've posted previously, but have updated the version number to prevent mistakes and formatted the code a little.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2020, 07:37:30 am

It seems to be running-on for an extra pixel at the end with a 25x25 ellipse, or I'm misreading the results? ???  Take a look at the simulation I've done with a 25x25 ellipse - simulation output doesn't quite match the FreeBasic one - it looks like the ellipse generator needs to stop a pixel earlier?  But otherwise, it's producing the right output.

However, if I run a simulation with a 27x27 ellipse, it seems to work fine?  I must be getting confused with X/Y output in the 25x25 case...?


Yes, you have found a bug.  There is a problem.  In the original 'Program' code, there is an order of operations.  The 'While (b2*x <= a2*y)' is being computed & checked after Y may have been decremented by 1 (depending on sigma's sign) and after X has been incremented by 1.  However, in Verilog, the problem is that the X&Y inside that while has the previous results even though the next output pixel is being computed.  I thought changing the ' <= ' to a ' < ' fixed the problem, however, apparently not in all cases.

So that's 1 thing to fix.  Looking at the code, the massive condition where:

sigma          <= sigma + (b2 * (( x << 2 ) + 3'd6 )) + ((a2 << 2) * ( 24'd1 - y )) ;
or
sigma          <= sigma + (b2 * (( x << 2 ) + 3'd6 )) ;

It has 2 large parallel multiplies with 3 adds  ''  24bit + (24bit * 14bit) + (26bit * (1-12bit))  '', or the second addition half depending on the sign of the 'sigma'.

Pipelining this is possible, yet complex since that While() also needs to take into account changes in the X&Y and it also has another two 24bit by 12 bit multiplies to also be done in parallel.

Before continuing, I will look at some other ellipse functions to see it they remove some of the cluster of math.   I suspect there is a shortcut for simplifying the 2 multiplies in the While() & perhaps 1 of the multiplies in the 'sigma' adjustment.

The high bitcount multiplies just on their own might need a 2 clock cycle pipe as well as the 3 way parallel add meaning pipelining has become truly troublesome since we need the sign of 'sigma' computed before we decide to subtract from Y or not.  The other method is to always wait to 2 + 2 clock cycles for each sum to come in meaning instead of 125 million pixels a second, this generator will only render 31 million pixels a second.  (Not counting the fill, the fill will still be 125mpps)  Running a fixed 2 clock cycle ALU here may also allow us to consolidate the math into 1 DSP element instead of using 7.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2020, 04:56:25 pm
After a little playing around, the best I could do with the current architecture is 110MHz, with the added bonus of cutting down the 9bit alu elements by 33% & logic elements by 25%.  However, even if it is possible to refine this design to 125MHz, it will create code which may become a bottleneck in the future if you ever need to change 1 little thing.

Time to look at other ellipse generators before committing to a multi-stage pipeline design.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2020, 05:17:48 pm
Ok, here is 1 older box ellipse code which can be done with only 1 single 12bitx12bit multiply for the multiple squares during the setup, but, when drawing, it only uses add and subtract &the 'While' loop has no math at all, it just compares the magnitude of 2 final 12 bit coordinates (x0 <= x1).  >150MHz shouldn't be a problem:

Already coded here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3287072/#msg3287072 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3287072/#msg3287072)

This code behaves much more like the Bresenham's line-generator, except it has 2 error calculations on the x&y step instead of only 1.  Before we commit to this code, I will look through the other ellipse source .pdf I posted awhile back to see it a center-ellipse already exists without any multiplication during the rendering.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2020, 10:38:05 pm
Ok, here is 1 older box ellipse code which can be done with only 1 single 12bitx12bit multiply for the multiple squares during the setup, but, when drawing, it only uses add and subtract &the 'While' loop has no math at all, it just compares the magnitude of 2 final 12 bit coordinates (x0 <= x1).  >150MHz shouldn't be a problem:

Already coded here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3287072/#msg3287072 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3287072/#msg3287072)

This code behaves much more like the Bresenham's line-generator, except it has 2 error calculations on the x&y step instead of only 1.  Before we commit to this code, I will look through the other ellipse source .pdf I posted awhile back to see it a center-ellipse already exists without any multiplication during the rendering.

That sounds promising.  I didn't realise adding the ellipse generator would cause such problems, but it's interesting to see the issues caused by the additional of some simple (on the face of it) arithmetic.

In other news, I've finished one of the HDMI DAC cards - well, apart from the DIL header - I'm just hoping the QFN soldering is good.  I guess I can always remove it and try again if not.

Seems my biggest issue with soldering 0402s is trying not to get too much solder down!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2020, 11:53:47 pm
That sounds promising.  I didn't realise adding the ellipse generator would cause such problems, but it's interesting to see the issues caused by the additional of some simple (on the face of it) arithmetic.
Arithmetic is not a problem.  Waiting for a result before deciding to add or subtract 2 figures before each iteration means the math needs to achieve the FMAX in a single clock, or if the math takes 2 clocks, you pipe in the numbers and wait for the result to change and decide whether to run the next iteration.

We already have a 2 clock multiply-add-shift 32 bits in our 'pixel coordinates' to 'memory address' generator.  Here it is not a problem since the input doesn't rely on the output results 2 clocks later, so, everything is just fed in a pipe manner.  Thanks to this, that part of the code can operate at ~200MHz instead or 100MHz.  Extending that pipe by another clock or two will get the FMAX up to the core's theoretical maximum frequency listed in the data sheet.

This next ellipse generator sort of computes 2 or the 'sigma' progressively by addition or subtraction waiting for them to approach each other instead of re-multiplying A&B by each sigma each iteration while adding an offset & when testing for the end of the arc.  However, I must test the angle of 1 of the ellipse quadrants in FreeBasic first to make sure it's the edge I want.  Plus, it needs to be simplified to a center axis ellipse.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2020, 11:55:23 pm
In other news, I've finished one of the HDMI DAC cards - well, apart from the DIL header - I'm just hoping the QFN soldering is good.  I guess I can always remove it and try again if not.

Seems my biggest issue with soldering 0402s is trying not to get too much solder down!
Looks like you need a little flux-off and a firm bristle brush to clean off the residue and then you are ready to go.
Have you searched for the DVI specification so you may design your first serializer?
I believe it shouldn't be tough, when a sync change comes in, you insert the right code on the 30 bit data bus.  1 pixel before your vid_ena you send the video enable code, then place video data on the 30 bits with an offset.  1 pixel after the vid_ena ends, send the video disable.  (I think as this is how it was done on my SDI encoder, however, in DVI, the vid_ena may be encoded on the upper/lower bits.)  As for the last 10 bits, the pixel clock, it should have a fixed #, something like 10'b1111100000.

Altera's serdes function should do the job with the right configuration.  Make a default 4 channel unit, 40 bits in, 4 channel out in Quartus Prime for the CV and get the example generated SystemVerilog code function call so you may enter it into your DVI serializer module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 17, 2020, 02:14:43 am
DVI output works basically like VGA, except your color channel information and sync signals go into HDMI encoders and then into serializers (one of each per channel, all identical for all channels). A page or two back I posted a link to HDMI 1.3a spec pdf download page.

You will need to implement an HDMI encoder, which takes in 8 bits of color information and control signals (hsync/vsync, video enable), and turns them into 10 bit codes generated using specific algorithm described in the specification, and those 10 bit characters will need to be sent over the wire via serializers. During blanking blue channel (channel 0) will send codes for sync signals, other channels will send a pre-defined code for "nothing to see here".

For "native" HDMI mode, all the "magic" happens during blanking, as that's when all other data (audio, video metadata, etc.) is transmitted, but for DVI mode this is not required.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2020, 03:27:50 am
DVI output works basically like VGA, except your color channel information and sync signals go into HDMI encoders and then into serializers (one of each per channel, all identical for all channels). A page or two back I posted a link to HDMI 1.3a spec pdf download page.

You will need to implement an HDMI encoder, which takes in 8 bits of color information and control signals (hsync/vsync, video enable), and turns them into 10 bit codes generated using specific algorithm described in the specification, and those 10 bit characters will need to be sent over the wire via serializers. During blanking blue channel (channel 0) will send codes for sync signals, other channels will send a pre-defined code for "nothing to see here".

For "native" HDMI mode, all the "magic" happens during blanking, as that's when all other data (audio, video metadata, etc.) is transmitted, but for DVI mode this is not required.
First let him start with DVI as it should activate any monitor and it is dirt simple.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2020, 09:37:21 am
Ok, take a look at these freebasic code.

Geoarc is the new code modified to generate a center ellipse.
Notice the 3 rendering errors.
A) offset errors as the ellipse becomes flat.
B) vertical ellipse has a top pixel error.
C) 32 bit error when the radius of the are becomes too big.

Carefully notice the rendering of the original geoarc_complex.bas.  Look at the precision coordinate positions of the beginning and ending as the ellipse as the ellipse becomes flat.

The simpler 'box-ellipse' seems to only be good at drawing an ellipse in a box as rendering connecting corner errors don't show as all 4 quadrants touch even if they are off by +/- 1 pixel.  You have no dot-precise measurement to see single pixel alignment errors on the 4 corners of the vertical and horizontal axis if they cleanly merge to produce what looks like a perfect ellipse.

I'll try another designed 'center-ellipse' code which has the add and subtract simplicity of the box-ellipse, yet calculates the ellipse from 2x 45 degree points generating a precise beginning and end.  Remember, we want to use the edges of 1 of the 4 quadrants of the ellipse to connect to boxes and lines drawn with your other geometry commands when you want to draw a rounded corners.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2020, 09:44:49 am
Ok Nockieboy, here is another ellipse generator:

https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267096/#msg3267096 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267096/#msg3267096)

Now, I extrapolated the .pdf code here (removed some stuff and simplified other stuff):
Code: [Select]
void ellipseMidpoint (int xCenter, int yCenter, int Rx, int Ry)

{

int Rx2 = Rx * Rx;
int Ry2 = Ry * Ry;

int twoRx2 = 2 * Rx2;
int twoRy2 = 2 * Ry2;

int p;
int x = 0;
int y = Ry;
int px = 0;
int py = twoRx2 * y;

/* Region 1 */

p = ( (Ry2 - (Rx2 * Ry) + (0.25 * Rx2)) ) + 0.5;

while (px < py) {

  x++;
  px += twoRy2;

    if (p < 0) {
               p += Ry2 + px;
               }
    else {
               y--;
               py -= twoRx2;
               p += Ry2 + px - py;
         }

  PlotPoints (xCenter+x, yCenter+y, 0,255,0);
  }

/* Region 2 */

p = ( (Ry2 * (x+0.5) * (x+0.5) + Rx2 * (y-1) * (y-1) - Rx2 * Ry2) ) + 0.5 ;

while (y > 0) {

  y--;
  py -= twoRx2;

    if (p > 0) {
               p += Rx2 - py;
               }
    else {
               x++;
               px += twoRy2;
               p += Rx2 - py + px;
         }

  PlotPoints (xCenter+x, yCenter+y, 255,0,0);
  }
}

This should render 1 quadrant of the ellipse, however, I do not like how the author has manipulated the structure of 'Region 2' which isn't a mirror match of 'Region 1'  Please convert to freebasic code & I have a feeling like with our current 'Geoarc_complex.bas', we will end up using just 'Region 1' twice flipping the X&Y coordinates and X&Y radius.  As you can see, this code has no complex iterations during the render or test to see if the 'Region' of the arc has completed.  (The 2 region differences may be used to complete the lines in a flat ellipse, but I prefer to do it externally.)

Send me a working Freebasic version for testing...
(Region 1&2 are your old 'Inv' function - green / red lines of the complex geoarc function...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 17, 2020, 04:53:47 pm
Ok Nockieboy, here is another ellipse generator:

https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267096/#msg3267096 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3267096/#msg3267096)

Now, I extrapolated the .pdf code here (removed some stuff and simplified other stuff):
Code: [Select]
void ellipseMidpoint (int xCenter, int yCenter, int Rx, int Ry)

{

int Rx2 = Rx * Rx;
int Ry2 = Ry * Ry;

int twoRx2 = 2 * Rx2;
int twoRy2 = 2 * Ry2;

int p;
int x = 0;
int y = Ry;
int px = 0;
int py = twoRx2 * y;

/* Region 1 */

p = ( (Ry2 - (Rx2 * Ry) + (0.25 * Rx2)) ) + 0.5;

while (px < py) {

  x++;
  px += twoRy2;

    if (p < 0) {
               p += Ry2 + px;
               }
    else {
               y--;
               py -= twoRx2;
               p += Ry2 + px - py;
         }

  PlotPoints (xCenter+x, yCenter+y, 0,255,0);
  }

/* Region 2 */

p = ( (Ry2 * (x+0.5) * (x+0.5) + Rx2 * (y-1) * (y-1) - Rx2 * Ry2) ) + 0.5 ;

while (y > 0) {

  y--;
  py -= twoRx2;

    if (p > 0) {
               p += Rx2 - py;
               }
    else {
               x++;
               px += twoRy2;
               p += Rx2 - py + px;
         }

  PlotPoints (xCenter+x, yCenter+y, 255,0,0);
  }
}

This should render 1 quadrant of the ellipse, however, I do not like how the author has manipulated the structure of 'Region 2' which isn't a mirror match of 'Region 1'  Please convert to freebasic code & I have a feeling like with our current 'Geoarc_complex.bas', we will end up using just 'Region 1' twice flipping the X&Y coordinates and X&Y radius.  As you can see, this code has no complex iterations during the render or test to see if the 'Region' of the arc has completed.  (The 2 region differences may be used to complete the lines in a flat ellipse, but I prefer to do it externally.)

Send me a working Freebasic version for testing...
(Region 1&2 are your old 'Inv' function - green / red lines of the complex geoarc function...)

Working FreeBasic version of code attached.  I can't split the Region 1 and Region 2 sections as Region 2 is depending on some value set by processing Region 1 - could be x,y, px, py or something else - but I have a working example of the above code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2020, 08:56:54 pm
Did you not take a look at my above attached code (2 posts up) with the 2 versions and 3 errors and work from there???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 17, 2020, 10:33:51 pm
Did you not take a look at my above attached code (2 posts up) with the 2 versions and 3 errors and work from there???

:palm: No I missed that post somehow - I just did what you asked (below).  Will have a look at those tomorrow.

Send me a working Freebasic version for testing...
(Region 1&2 are your old 'Inv' function - green / red lines of the complex geoarc function...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 18, 2020, 12:34:10 am
I guess you could rename my previous post's geoarc.bas to geoarc_boxstyle.bas & copy & rename the geoarc_complex.bas to geoarc.bas & add in this new code only drawing that 1 quadrant like the other 2.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 18, 2020, 03:26:18 pm
I think this is what you want?

Looks like another issue with the 2nd region - the red line jumps off on a tangent when the ellipse becomes very wide.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 18, 2020, 10:28:29 pm
Ok, much better.  The code generating the vertical region 1 is perfect like you said.  Region 2 is missing the final few pixels when the ellipse is almost flat and it's missing all the pixels when it is flat.  (You can say that this is region 1 not finishing the last flat part of the line.  This isn't a problem as we add code to finish the flat portion of the ellipse like what we have in the _complex version.)

Let me play with this code tonight.  I think getting rid of region 2 and draw region 1 twice with flipped X&Y & A&B like we did in the _complex version would make that identical 'mirror' version of the vertical arc.

The good news is that this region 1 of this generator looks almost perfect and if that 45degree mirror & flip trick works, we should have the Verilog in a day.

Also, look at what happens to the region 2 with really large ellipses, the math breaks and the line goes flat.  We are exceeding 32 bits.  Let's see what happens when doubling region 1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2020, 06:10:50 am
Ok, please scrutinize the crap out of this freebasic version.  If it is good, I will make code it to verilog for you.

When I say scrutinize, I mean that the graphics is rendered perfectly.

Also, make sure the code looks good.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 19, 2020, 10:32:04 am
Ok, please scrutinize the crap out of this freebasic version.  If it is good, I will make code it to verilog for you.

When I say scrutinize, I mean that the graphics is rendered perfectly.

Also, make sure the code looks good.

The code is looking sweet - MUCH simpler than the complex iteration we had before.  I've just formatted the code a little and added-in the quadrant drawing, so the function will now draw all four quadrants as specified by the 'quadrant' parameter.  Probably completely unnecessary, but I feel like I've done something!  ;)

As far as my testing can go, it would appear the arcs are spot on.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 19, 2020, 02:20:54 pm
Whilst looking at the DVI specification and spending half an hour on the fpga4fun HDMI page (https://www.fpga4fun.com/HDMI.html) before I realised the example is for a Xilinx FPGA (:palm:), I came across this repo on github which purports to implement an HDMI interface with embedded audio... https://github.com/hdl-util/hdmi.git (https://github.com/hdl-util/hdmi.git).

I've only spent five minutes with it - have cloned the repo and attempted to build it in Quartus II, but it's throwing errors in the audio_clock_regeneration_packet.sv file (it doesn't seem to like this next line):
Code: [Select]
line 41: localparam int CYCLE_TIME_STAMP_COUNTER_WIDTH = $clog2(20'(int'(real'(CYCLE_TIME_STAMP_COUNTER_IDEAL) * 1.1))); // Account for 10% deviation in audio clock

... but then I never expect to clone a github repo and it just 'work' straight away.  They normally take more time to get working than it would take to build the thing from scratch, but I was hoping that I might be able to save some time and also use a more powerful interface (the inclusion of audio in the output is very desirable).

Anyway, I've gone back to the fpga4fun example and am trying to convert it for my test-case.  It seems nice and simple, but it looks like the OBUFDS and DCM_SP and BUFG components are created by the Xilinx IDE, like Altera's megafunctions.  OBUFDS looks simple enough - it just drives the two differential-pair output pins with the data and an inverted copy of the data, from what I can gather from the equivalent file in the github repo above (although it does some funny stuff with IO pins which complicates module somewhat).

But can I replace DCM_SP and BUFG with a PLL clock multiplier to get the required 250MHz clock?

Here's my DVI_test code below - I've commented it for the most part, but just past half-way down the code you'll see the instantiation of OBUFDS, DCM_SP and BUFG components.  These are what I'm having issues with understanding, currently.

Code: [Select]
module video_source(
    // inputs
    input        clk,       // 25MHz pixel clock
   
    // outputs
    output [2:0] TMDSp,     // TMDS data out
    output [2:0] TMDSn,
    output       TMDS_CLKp, // pixel clock out
    output       TMDS_CLKn
   
);

reg [9:0] x, y ; // horizontal & vertical pixel counters
reg hSync      ;
reg vSync      ;
reg D_EN       ; // Display ENable

/* Create timing signals for a valid 640x480 display.
 *
 * This requires D_EN to be enabled when the raster is
 * within the visible display area and for the raster
 * counters (X and Y) to be updated and reset according
 * to their position on the screen.
 *
 * hSync and vSync should also go high according to the
 * specifications outlined for the 640x480 video mode.
 */
always @(posedge clk) begin

    D_EN <= ( x < 640 ) && ( y < 480 ) ; // enable display if pixel counters are in visible display area
    x    <= ( x == 799 ) ? 0 : x + 1   ; // increment horizontal pixel counter, or reset if at end of line
   
    if( x == 799 ) begin // horizontal pixel counter has reached end of row
        if ( y == 524 ) begin
            y <= 0     ; // reset vertical pixel counter
        end else begin
            y <= y + 1 ; // increment vertical pixel counter
        end
    end
   
    hSync <= ( x >= 656 ) && ( x < 752 ) ; // hSync goes HIGH when horizontal pixel counter is between 655 and 752
    vSync <= ( y >= 490 ) && ( y < 492 ) ; // vSync goes HIGH when vertical pixel counter is between 489 and 492
   
end

wire [7:0] W = {8{x[7:0]==y[7:0]}} ;
wire [7:0] A = {8{x[7:5]==3'h2 && y[7:5]==3'h2}} ;
reg  [7:0] red   ;
reg  [7:0] green ;
reg  [7:0] blue  ;

// Create a display pattern
always @(posedge clk) begin

    red   <= ( { x[5:0] & { 6 { y[4:3] == ~x[4:3] } }, 2'b00 } | W ) & ~A ;
    green <= ( x[7:0] & { 8{ y[6] } } | W ) & ~A ;
    blue  <= y[7:0] | W | A ;
   
end

//
// Create three TMDS_encoder instances to handle the Red, Green, Blue and Control signals
//
wire [9:0] TMDS_red   ;
wire [9:0] TMDS_green ;
wire [9:0] TMDS_blue  ;

TMDS_encoder encode_R(
    .clk ( clk      ),
    .VD  ( red      ),
    .CD  ( 2'b00    ),
    .VDE ( D_EN     ),
    .TMDS( TMDS_red )
);
TMDS_encoder encode_G(
    .clk ( clk        ),
    .VD  ( green      ),
    .CD  ( 2'b00      ),
    .VDE ( D_EN       ),
    .TMDS( TMDS_green )
);
TMDS_encoder encode_B(
    .clk ( clk              ),
    .VD  ( blue             ),
    .CD  ( { vSync, hSync } ),
    .VDE ( D_EN             ),
    .TMDS( TMDS_blue        )
);

//
// Multiply 25MHz clock by 10 to generate a 250MHz clock
wire clk_TMDS       ;
wire DCM_TMDS_CLKFX ; // 25MHz x 10 = 250MHz
DCM_SP #(.CLKFX_MULTIPLY(10)) DCM_TMDS_inst(.CLKIN(clk), .CLKFX(DCM_TMDS_CLKFX), .RST(1'b0) ) ;
BUFG BUFG_TMDSp(.I(DCM_TMDS_CLKFX), .O(clk_TMDS)) ;

//
// Create three 10-bit shift registers running at 250MHz
reg [3:0] TMDS_mod10       = 0 ; // modulus 10 counter
reg [9:0] TMDS_shift_red   = 0 ;
reg [9:0] TMDS_shift_green = 0 ;
reg [9:0] TMDS_shift_blue  = 0 ;
reg       TMDS_shift_load  = 0 ;

always @(posedge clk_TMDS) begin

    TMDS_shift_load  <= ( TMDS_mod10 == 4'd9 )                                    ;
    TMDS_shift_red   <= TMDS_shift_load ? TMDS_red    : TMDS_shift_red  [9:1]     ;
    TMDS_shift_green <= TMDS_shift_load ? TMDS_green  : TMDS_shift_green[9:1]     ;
    TMDS_shift_blue  <= TMDS_shift_load ? TMDS_blue   : TMDS_shift_blue [9:1]     ;
    TMDS_mod10       <= ( TMDS_mod10 == 4'd9 ) ? 4'd0 : TMDS_mod10 + 4'd1         ;
   
end

OBUFDS OBUFDS_red  ( .I( TMDS_shift_red  [0] ),  .O( TMDSp[2] ), .OB( TMDSn[2] ) ) ;
OBUFDS OBUFDS_green( .I( TMDS_shift_green[0] ),  .O( TMDSp[1] ), .OB( TMDSn[1] ) ) ;
OBUFDS OBUFDS_blue ( .I( TMDS_shift_blue [0] ),  .O( TMDSp[0] ), .OB( TMDSn[0] ) ) ;
OBUFDS OBUFDS_clock( .I( clk ), .O( TMDS_CLKp ), .OB( TMDS_CLKn ) )                ;

endmodule

//*********************************************************************************************************
//
// TMDS Encoder Module
//
//*********************************************************************************************************
module TMDS_encoder(
    input            clk,
    input      [7:0] VD,      // video data (red, green or blue)
    input      [1:0] CD,      // control data
    input            VDE,     // video data enable, to choose between CD (when VDE=0) and VD (when VDE=1)
    output reg [9:0] TMDS = 0
);

wire [3:0] Nb1s            = VD[0] + VD[1] + VD[2] + VD[3] + VD[4] + VD[5] + VD[6] + VD[7]                                   ;
wire       XNOR            = ( Nb1s > 4'd4 ) || ( Nb1s == 4'd4 && VD[0] == 1'b0 )                                            ;
wire [8:0] q_m             = { ~XNOR, q_m[6:0] ^ VD[7:1] ^ { 7{ XNOR } }, VD[0] }                                            ;
reg  [3:0] balance_acc     = 0                                                                                               ;
wire [3:0] balance         = q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7] - 4'd4                    ;
wire       balance_sign_eq = ( balance[3] == balance_acc[3] )                                                                ;
wire       invert_q_m      = ( balance == 0 || balance_acc == 0 ) ? ~q_m[8] : balance_sign_eq                                ;
wire [3:0] balance_acc_inc = balance - ( { q_m[8] ^ ~balance_sign_eq } & ~( balance == 0 || balance_acc == 0 ) )             ;
wire [3:0] balance_acc_new = invert_q_m ? balance_acc-balance_acc_inc : balance_acc + balance_acc_inc                        ;
wire [9:0] TMDS_data       = { invert_q_m, q_m[8], q_m[7:0] ^ { 8{ invert_q_m } } }                                          ;
wire [9:0] TMDS_code       = CD[1] ? (CD[0] ? 10'b1010101011 : 10'b0101010100) : ( CD[0] ? 10'b0010101011 : 10'b1101010100 ) ;

always @(posedge clk) begin

    TMDS        <= VDE ? TMDS_data : TMDS_code  ;
    balance_acc <= VDE ? balance_acc_new : 4'h0 ;
   
end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 19, 2020, 03:07:09 pm
The reason there are so many code examples for Xilinx FPGA is because it's very trivial to implement HDMI on that platform.

OBUFDS - Output BUFfer with Differential Signalling
DCM - Digital Clock Manager (think of it as advanced PLL with additional functionality)
BUFG - global clock buffer (entry into low-skew lines designed to distribute clock signals across the die)

The code you've posted does not use SERDES, which is fine for lower frequencies, but won't work for things like 720p, which run at 742.5 MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2020, 09:42:22 pm
... but then I never expect to clone a github repo and it just 'work' straight away.  They normally take more time to get working than it would take to build the thing from scratch, but I was hoping that I might be able to save some time and also use a more powerful interface (the inclusion of audio in the output is very desirable).
;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2020, 09:49:29 pm
I think this is what you want?

Looks like another issue with the 2nd region - the red line jumps off on a tangent when the ellipse becomes very wide.
There was no need to add the 4 quadrants.  They are implies, but, thanks.
You only did a half job, you forgot to add them during the 'finish-flat ellipse' portion.

Anyways, I'll code it tonight & I decided to do it with on single 24bit or 32bit A*B=Y multiplier using the existing setup.
At least if you read the code, you will see how I went about doing that.  24 bit should have no problems passing the 125MHz, maybe even the 150 point, but 32bit X 32 bit with 32 bit out, I never tried.  However, the design will allow for a 2 clock piped multiplier witch will negate the problem.  The new code should render 125mpps no problem as there are no such heavy duty multiple multiplies during the iteration loop.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on December 19, 2020, 10:13:32 pm
The reason there are so many code examples for Xilinx FPGA is because it's very trivial to implement HDMI on that platform.

OBUFDS - Output BUFfer with Differential Signalling
DCM - Digital Clock Manager (think of it as advanced PLL with additional functionality)
BUFG - global clock buffer (entry into low-skew lines designed to distribute clock signals across the die)

The code you've posted does not use SERDES, which is fine for lower frequencies, but won't work for things like 720p, which run at 742.5 MHz.

Yep. Out of curiosity, do you think there is any possibility that SERDES could be inferred from pure HDL (maybe with a particular coding style), or if it's never going to be inferred and you need to explicitely instantiate that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2020, 10:46:38 pm
The reason there are so many code examples for Xilinx FPGA is because it's very trivial to implement HDMI on that platform.

OBUFDS - Output BUFfer with Differential Signalling
DCM - Digital Clock Manager (think of it as advanced PLL with additional functionality)
BUFG - global clock buffer (entry into low-skew lines designed to distribute clock signals across the die)

The code you've posted does not use SERDES, which is fine for lower frequencies, but won't work for things like 720p, which run at 742.5 MHz.

Yep. Out of curiosity, do you think there is any possibility that SERDES could be inferred from pure HDL (maybe with a particular coding style), or if it's never going to be inferred and you need to explicitely instantiate that?
     Well, initiating 2 different SERDES, like Intel/Xilinx with a compiler directive to select between the 2 shouldn't be a problem as both SERDES would eventually have the same configuration selected unless you are targeting a vendor specific feature.  Software SERDES also shouldn't be a problem though you wont hit those super high speed specific HW.  Selecting the IO buffer type and configuring it's drive and terminations characteristics/features does become much more vendor specific and even with a compiler directive to select between the two, their configuration would probably be totally different.

     For example, in Quartus, you can define the outputs coming from your SERDES logic in the pin-mapping floor-plan separate of any HDL code.  For example, if you assign you output 'DVI_OUT[3..0]' as LVDS or Differential STTL in the compiler's assignment editor, it will automatically force those onto 4 output pairs, 8 output pins and you will need to specify the +output pin and the compiler will force it's -output on the corresponding differential IO pair.
     You can also obviously initiate in your HDL the LVDS/Differential IOBUF with whatever configuration you like bypassing the need to configure the IO pin specifics in the pin-mapping floor-plan editor.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 20, 2020, 12:42:46 am
Yep. Out of curiosity, do you think there is any possibility that SERDES could be inferred from pure HDL (maybe with a particular coding style), or if it's never going to be inferred and you need to explicitely instantiate that?
No chance. If you remember, you can't actually achieve 10:1 DDR serialization ratio with a single SERDES, you will need to use a cascaded pair. Which is of course how it was designed to be - since you have SERDES per pin, differential pair gives you two SERDES'es. And they will have to run at DDR, so bit clock will be 5x from parallel one. That means, if you were to write this code manually, there is got to be a CDC circuit for parallel to bit clock, which in reality is implemented in SERDES in silicon. Obviously all of that is highly device-specific, nice thing about 7 series is that entire series have identical HW blocks, so migrating from Spartan-7 to Artix-7 to Kintex-7 to Virtex-7 is absolutely painless, but if you were to go to Ultrascale for example, you will have to make changes in a code.
The same deal is with MGTs. These are device family specific such that even GTPs in Artix-7 are quite a bit different from GTXes in Kintex-7.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 20, 2020, 11:44:14 am
Here it is, the new ellipse generator.
Currently, the FMAX is 129MHz.
Only, it only uses 4 9bit multiplier elements instead of 24.
However, the logic element count has more than doubled.

The only problem is to get 129MHz, I had to limit the core to 24 bits.  At the preferred 32 bits, we only get 116MHz.  This is due to having a 2 alternate 4 way 32bit signed parallel adds for every iteration of the arc.  I will think of something as we need 32bit for ellipses with a radius of 2047x2047.  However, this will make a circle 4095x4095, outside our signed 12 bit coordinate system.  I will try shaving a few bits and removing the sign where it is not needed as in the timing report, it is only the last 2-3 MSB bits of the 'p' accumulator which cannot meet the 125MHz timing with that 4 way parallel add.

For now, the core is set to 24bits.  Perform your tests.  It should match the Freebasic output other than the 'quadrant' is setup in a different order.  Let me know how it works.  Test all you like.

Get attached simulation setup.  If it works, next I try to enlarge the 24 bit core without sacrificing FMAX and then we integrate into the GPU.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 20, 2020, 04:13:17 pm
I've done some simulations using various dimensions for the ellipse - have attached some typical variations, and have tested permutations of X and Y from 0-40 pixels (and other sizes without checking ALL the pixels) - all are pixel-perfect in the simulation output compared with the expected output provided by the FreeBasic code.

I can't get it to break. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 20, 2020, 05:53:42 pm
I've done some simulations using various dimensions for the ellipse - have attached some typical variations, and have tested permutations of X and Y from 0-40 pixels (and other sizes without checking ALL the pixels) - all are pixel-perfect in the simulation output compared with the expected output provided by the FreeBasic code.

I can't get it to break. :-+
That final 1x20 simulation results are wrong.  Are you sure you didn't change the inputs and forgot to run/update the results?
Try at least 1 shape other than perfect circles or near vertical lines...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 20, 2020, 06:02:46 pm
Uh, looks like I messed up the images or something - the output is fine, it matches geo.bas with everything I've thrown at it so far.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 21, 2020, 04:13:49 am
Tutorial for Nockieboy in improving FMAX.  Part 1.

  Ok, for the new 'ellipse_generator.sv', we have a problem passing our required 125MHz when running the core at 32bits.  Right now, our limit is 117 MHz.  Looking at the timing report, we see that a lot of signals (From Node) p[ # ],px[ # ],ry2[ # ],px[ # ] do not make it to the register p[ # ] (To Node) in time.  The worst signal arrives 0.54ns late (Slack in -xxx ns).  See:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1135710)
(Unfortunately, in QuartusPrime when compiling for CV, I think they only provide 1 single worst case timing signal.  I'm sure there is a ways to increase the size of the timing report so you get a better overview.)

  Ok, so we need to look at the code to see what P is equal to and why these signals feeding it come in too late and how we may be able to improve the situation.
  Here is how I begin to approach the problem and the technique I used here is middle of the road and there are other ways, but this was my first approach trying to maintain the current structure.  First look to see everywhere I make register 'p' = to something.  Here:

Code: [Select]
When sub_function == 3
p <= (alu_mult_y + 2) >> 2 ;
When sub_function == 6
p <= p + ry2 - alu_mult_y ;
When sub_function == 7 && (px <= py) && (p <= 0)
p <= p + ry2 + (px + (ry2<<1)) ;
When sub_function == 7 && (px <= py) && !(p <= 0)
p <= p + ry2 + (px + (ry2<<1)) - (py - (rx2<<1)) ;

  Below, I'm showing you how the compiler constructs the logic for calculating 'p' (approximately). Remember, the FPGA is not a CPU passing memory variable to and from a single ALU, all the above instructions need to be combined into a single set of gates to make the 32 bit register 'p' equal the following function at the core clock of 125MHz.
(Yes, I tried to get this right, so analyze it...)

Code: [Select]
p <= ( p * (sub_function !=3)) +
     (( (((alu_mult_y + 2) >> 2) * sub_function == 3) )) -
     (( ((alu_mult_y) * sub_function == 6) )) +
     (( ry2 * ( sub_function == 6 || (sub_function == 7 && (px <= py)) ) )) +
     (( (px + (ry2<<1)) * ((sub_function == 7) && (px <= py)) )) -
     (( (py - (rx2<<1)) * ((sub_function == 7) && (px <= py) && !(p <= 0)) )) ;

YES, all that shit...  Though, the compiler will simplify the algebra as much as possible, this is the mess that 32 bit register 'p' must equal with all those other variables being 32 bits which feed a mass of gates to compute for the D-flipflop 32 bit data input.  Apparently, the necessary entire mass of gates will fail to guarantee the correct solution when register 'p' is clocked (with everything else of course) above 117MHz.

  'p' is dependent on the sub_function[3:0] number, (px <= py), !(p <= 0), plus the 32 bit registers 'p' itself since it is being added to itself, then alu_mult_y both added by 2 and shifted and again natively, rx2, ry2, px and py.

Code: [Select]
sub_function     = 4 bits
(px<=px)        = 32+32 bits
(p<=0)          = 32 bits
'p'             = 32 bits
alu_mult_y      = 32bits *2=64 (shifted and non shifted)
rx2,ry2,px2,py3 = 32*4bits =128

TOTAL: 324 bits / 324 wires/signals to generate the result 'p'.

Here is a test I performed.  What I did was make p<=0 at sub_function==3 and getting rid of sub_function 6 which changes the equation to:

Code: [Select]
p <= ( p * (sub_function !=3)) +
     (( ry2 + (px + (ry2<<1))) * ((sub_function == 7) && (px <= py)) ) -
     (( (py - (rx2<<1)) * ((sub_function == 7) && (px <= py) && !(p <= 0)) )) ;

We got rid of the 2 * alu_mult_y cutting 64 wires from the 324 needed from the first equation.
Now the compiler give us an FMAX of 132MHz and looking at the worst case timing paths, 'p' (To Node) is actually third down on the list which means there is something else above which is limiting the system to 132MHz.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1135714)

So, we have a goal, how to incorporate these 2 setup actions:
Code: [Select]
p <= (alu_mult_y + 2) >> 2 ;
p <= p + ry2 - alu_mult_y ;
And not add any complexity/dependancies to the above test 132MHz FMAX equation.

The trick I decided to use was to temporarily store '(alu_mult_y + 2) >> 2' in ry2 and then just use the beginning of what already exists in the equation:
(remove the red part and just keep the beginning...)
p <= p + ry2 + (px + (ry2<<1)) - (py - (rx2<<1)) ;

Ok, trick 1, with the repeat of reusing ry2.
In the above sub_function==3, I made 'ry2 <= (alu_mult_y + 2) >> 2'.  Since ry2 only has 1 = alu_mult_y, adding this here doesn't really slow down that register.
Now during sub_function==4, I made 'p <= ry2'.  Since 'ry2' is added to 'p' everywhere else, this doesn't add additional signal dependencies to the master 'p <= 'blahhh blahhh blahhh' ' equation.

Sub_function==5, since ry2 will now have been updated to the next value, I just added:
p <= p + ry2;
Again, no new dependencies to calculate the master equation 'P'.

Sub_function==6, ok, there was no choice, I had to make it:
p <= p - alu_mult_y;
This added a 32 new bits of dependence.  Let's try a compile and see the results.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1135718)

As you can see, the new FMAX is 121MHz and there are only 4 signals too slow to make the cut.
Now, we know getting rid of that '- alu_mult_y' will allow us to clear the hurdle with spades, but without doing back-flips let's try 1 thing first.

The rx2 & ry2 are the square of the Xr & Yr 12 bit numbers which I have forced to 32 bits.
Since they are only positive integers from 0 to 2047, the result will always be an unsigned 22 bit number.  Let's see if I force these to 'UNSIGED 22 bits' since rx2 & ry2 are used so often everywhere in that gigantic ' p <= blahhh blahhh blahhh '.

Ok, talk about just clearing the hurdle, 126MHz...
We also went from 926 Logic elements to 888.

Question, can we do better.
Another solution may be making a temporary register hold:
p <= (alu_mult_y + 2) >> 2 ;
p <= p + ry2 - alu_mult_y ;
Then at the last step. make p<= that 1 register.
Optimization attempt #2 as well as testing only making the Rx2 & Ry2 = 22bits with the original code for tomorrow.

Test V9 attached spaghetti code.
Snapshots not necessary unless there are errors...
(I also found out I'm doing 2 sub_functions uselessly identically twice, the correction will be done next.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 21, 2020, 11:58:51 am
Tutorial for Nockieboy in improving FMAX.  Part 1.

...

  Below, I'm showing you how the compiler constructs the logic for calculating 'p' (approximately). Remember, the FPGA is not a CPU passing memory variable to and from a single ALU, all the above instructions need to be combined into a single set of gates to make the 32 bit register 'p' equal the following function at the core clock of 125MHz.
(Yes, I tried to get this right, so analyze it...)

Code: [Select]
p <= ( p * (sub_function !=3)) +
     (( (((alu_mult_y + 2) >> 2) * sub_function == 3) )) -
     (( ((alu_mult_y) * sub_function == 6) )) +
     (( ry2 * ( sub_function == 6 || (sub_function == 7 && (px <= py)) ) )) +
     (( (px + (ry2<<1)) * ((sub_function == 7) && (px <= py)) )) -
     (( (py - (rx2<<1)) * ((sub_function == 7) && (px <= py) && !(p <= 0)) )) ;

YES, all that shit...  Though, the compiler will simplify the algebra as much as possible, this is the mess that 32 bit register 'p' must equal with all those other variables being 32 bits which feed a mass of gates to compute for the D-flipflop 32 bit data input.  Apparently, the necessary entire mass of gates will fail to guarantee the correct solution when register 'p' is clocked (with everything else of course) above 117MHz.

 :o :o :o

Whoah.  Well, firstly thank you for that post - it was immensely useful in understanding what's going on 'under the hood' of the compiler and in identifying Fmax bottlenecks in the HDL.  I mean... damn!!  And I think I understood most of it, too!  ;D

Okay, here's what I've got from the latest code for the p register since you've amended the code - pulling out any lines where the p-register is having a value assigned to it:

Code: [Select]
if (sub_function == 4)
p <= p + ry2 ;

if (sub_function == 5)
p <= p + ry2 ;

if (sub_function == 6)
p <= p - alu_mult_y ;

if (sub_function == 7) && (px <= py) && (p <= 0)
p <= p + ry2 + (px + (ry2<<1)) ;

if (sub_function == 7) && (px <= py) && !(p <= 0)
p  <= p + ry2 + (px + (ry2<<1)) - (py - (rx2<<1)) ;

And from that, my attempt at what the compiler is doing to get the HDL-equivalent of those rules:

Code: [Select]
p <= p + ( ( ( sub_function  > 3 ) && ( sub_function != 6 ) ) * ry2 )
       -   ( ( sub_function == 6 ) * alu_mult_y )
       + ( ( ( sub_function == 7 ) && ( px <=  py ) ) * ( px + ( ry2<<1) ) )
       - ( ( ( sub_function == 7 ) && ( px <=  py ) && ( p > 0) ) * ( py - ( rx2<<1) ) )

If I've understood and worked it out correctly, that looks a LOT simpler than the mess that was there before you'd worked on the Fmax performance last night.  :-+

  'p' is dependent on the sub_function[3:0] number, (px <= py), !(p <= 0), plus the 32 bit registers 'p' itself since it is being added to itself, then alu_mult_y both added by 2 and shifted and again natively, rx2, ry2, px and py.

Code: [Select]
sub_function     = 4 bits
(px<=px)        = 32+32 bits
(p<=0)          = 32 bits
'p'             = 32 bits
alu_mult_y      = 32bits *2=64 (shifted and non shifted)
rx2,ry2,px2,py3 = 32*4bits =128

TOTAL: 324 bits / 324 wires/signals to generate the result 'p'.

I know it's nothing compared to far more complex projects that people do on FPGAs, but it blows my mind to think that the fitter is trying to route 324 lanes of data around the die just for this one single function. :o

Test V9 attached spaghetti code.
Snapshots not necessary unless there are errors...
(I also found out I'm doing 2 sub_functions uselessly identically twice, the correction will be done next.)

Yes, sub_function 4 and 5 can be merged into one with the line below, right?

Code: [Select]
p <= p + ( ry2 << 1 ) ;
OR, would it be better to do this instead and remove step 6 entirely by merging it into step 5?  EDIT: Have just realised - the alu takes 2 clocks for its result to be valid, so this may not be a valid solution.  :-\

Code: [Select]
if (sub_function == 4)
p <= p + ry2 ;

if (sub_function == 5)
p <= p + ry2 - alu_mult_y ;

That would remove one step from sub_function but also simplify the logic for the entire system, as this:

p <= p + ( ( ( sub_function  > 3 ) && ( sub_function != 6 ) ) * ry2 )
       -   ( ( sub_function == 6 ) * alu_mult_y )
      + ( ( ( sub_function == 7 ) && ( px <=  py ) ) * ( px + ( ry2<<1) ) )
      - ( ( ( sub_function == 7 ) && ( px <=  py ) && ( p > 0) ) * ( py - ( rx2<<1) ) )

...could become this:

p <= p + ( ( sub_function  > 3 ) * ry2 )  <<-- simplifies this line by one dependency
       -   ( ( sub_function == 5 ) * alu_mult_y )
      + ( ( ( sub_function == 6 ) && ( px <=  py ) ) * ( px + ( ry2<<1) ) )
      - ( ( ( sub_function == 6 ) && ( px <=  py ) && ( p > 0) ) * ( py - ( rx2<<1) ) )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 21, 2020, 03:48:58 pm
Just as an aside, I've got the attached project building now, but it appears to be using some sort of megafunction to set up the TMDS outputs and I cannot assign pins in the Pin Planner to get the project to work on my EasyFPGA board with the DVI Tester.  The pins are already assigned and read only when I go to the Pin Planner.

I'm thinking I should just remove the OBUFDS elements entirely from hdmi.sv (lines 319-334) and just connect tmds_current[] to the output pins whilst inverting the _n pin signal, allowing me to assign pins in Pin Manager as usual. Hopefully.  Seems OBUFDS uses the altera_gpio_lite megafunction, but I can't find it in the IP Catalog so I can't seem to find where it's assigning the IO pins to the TMDS signals.

I'm probably going to get a lot of flak for not just doing it from scratch, but I like the promise of being able to output an HDMI signal and include audio in the bit stream - that's a major benefit over straight DVI and is why I'm plugging away at this example project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 22, 2020, 10:28:11 am
OR, would it be better to do this instead and remove step 6 entirely by merging it into step 5?  EDIT: Have just realised - the alu takes 2 clocks for its result to be valid, so this may not be a valid solution.  :-\

Code: [Select]
if (sub_function == 4)
p <= p + ry2 ;

if (sub_function == 5)
p <= p + ry2 - alu_mult_y ;

That would remove one step from sub_function but also simplify the logic for the entire system, as this:

p <= p + ( ( ( sub_function  > 3 ) && ( sub_function != 6 ) ) * ry2 )
       -   ( ( sub_function == 6 ) * alu_mult_y )
      + ( ( ( sub_function == 7 ) && ( px <=  py ) ) * ( px + ( ry2<<1) ) )
      - ( ( ( sub_function == 7 ) && ( px <=  py ) && ( p > 0) ) * ( py - ( rx2<<1) ) )

...could become this:

p <= p + ( ( sub_function  > 3 ) * ry2 )  <<-- simplifies this line by one dependency
       -   ( ( sub_function == 5 ) * alu_mult_y )
      + ( ( ( sub_function == 6 ) && ( px <=  py ) ) * ( px + ( ry2<<1) ) )
      - ( ( ( sub_function == 6 ) && ( px <=  py ) && ( p > 0) ) * ( py - ( rx2<<1) ) )

     This wouldn't do any optimization since '( sub_function  > 3 ) * ry2' cannot be allowed when sub_function is >6.  Also, what happens when the sub_function is 6 and  ( px <=  py ) is not valid, the ry2 should not be added in that case.  Also, remember that the compiler simplifies and the boolean gate level, IE and, nand, on, nor, xor as it constructs addition and subtraction functions using the digital gates.

     I've attached a new version where I added 1 clock to the setup.  I also discovered if you want a radius of 2047, because of this required setup function:

p = ( (Ry2 - (Rx2 * Ry) + (0.25 * Rx2)) ) + 0.5

if Ry = 2047 & Rx=2047, and Ry2=Ry^2, same for Rx2, then

p= (( 2047 * 2047 - (2047*2047*2047) + (0.25*2047*2047)) ) +0.5

The result is ' -8572120061 '.  8572120061 is a 33bit number, plus, we want negative, so this means 'P' needs to be 34 bits to support a radius of 2047.  (Note I do realize that this is a circle which is 4095 pixels wide, but, you might be doing 1080p @30Hz when moving to the new CV board with DDR3 ram and display screens can be much larger than the display resolution where you may be scrolling oversized backgrounds.

Anyways, test the new attached code and only report errors.  I will document the enhancements and reasoning tomorrow, but it now calls Altera's LPM_MULT megafunction instead of using the simple Verilog ' Y <= A * B '.  The other enhancement better ensures reaching the FMAX at 34 bit even though the old one just managed to do it at 125MHz on the dot.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 22, 2020, 03:21:07 pm
All looks good - haven't found any errors.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 22, 2020, 05:14:10 pm
Arrrrgggg, found a bug...

Looking at the ellipse generator code, in the setup, we have  the following:

py = rx2 * ry * 2.

That's 2047*2047*2047*2 = 17154715646, a 34bit number.  But, py is also a singed integer.  This means we need 35 bits for the core (3 registers p,py,px), not 34.

Ok, here is the final code.  I really trimmed the fat and implicitly set the depths of all the registers and multiplier to exactly whats needed.  I used register px to build the timing problematic register p since px only needs to begin with 0 when begging to draw the ellipse.  Since during the arc iterations px is added to itself and ry2*2, I made ry2 compute the rounded rx2/4 and added it to px.  The again with the authentic ry2, then subtracted that nasty huge (rx2*ry) from the multiplier's Y output, then made p<=px finishing the setup of p.  Then if you look at the possible formula for p during the arc iterations, you will see we cut out 64 signals from the original 1st formula.  This is why even with an increase of another bit, we still can achieve such a good FMAX.

Our embeded 9 bit element multiplier count went from 6 down to 4 units and our FMAX is now 133MHz.  Next step, integrate into the full geo_writer, then update your GPU for testing.  I'll do that tonight.  This means if we are lucky, I can take a look at your HDMI core in another day.

The comments in the source code have been corrected and now the setup for generating the arc has dropped back down to 7 steps.  Please test.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 22, 2020, 06:23:36 pm
Hmm.. first test was a 20x20 ellipse - these are the results.  They don't look right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 22, 2020, 06:25:33 pm
Ok, hang on...  Probably a 1 second fix...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 22, 2020, 06:50:31 pm
Ok, I accidentally flipped around a few things.  Unfortunately, the FMAX is now 125.98MHz.
But it is still functional...
Test...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 22, 2020, 07:46:37 pm
That's looking good with testing so far.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 23, 2020, 07:34:26 am
Ok, you apparently never checked the 'quadrants'.  When mirrored or flipped, not both, the coordinate I was subtracting from the center coords was the wrong one as the X&Y coordinates supposed to be swapped when switching the 'INV' mode.

I already integrated the ellipse_generator into the main geometry unit, however, because of the way the geometry unit skips and begins on a new Y position after the half-way point, I could not use our existing in-built raster filler.  It requires that the Y axis continuously adds or subtracts to function.

I've attached the new ellipse_generator with an embedded semi-smart X axis raster fill.  And to make Nockieboy happy, I sort of used his old trick way back to automatically 'pause' the line_generator every time it changed a Y coordinate while drawing when I requested the feature for the filled triangles.

See and test the attached simulation.
( Sadly, the ellipse generator takes ~1k logic elements. )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 23, 2020, 08:16:04 am
Ok, here is the full ellipse generator fully integrated into the full geometry processor unit.  Yes, everything is there in the test-bench.  The pixel-writer currently disabled for ease of viewing when testing.

The ellipse uses X0 & Y0 to define it's center.
And it uses X1 & Y1 to define it's X & Y radius.

cmd_h 0x06 draws an ellipse with color cmd_l.
(Unless the blitter is turned on where it will paint the source raster image along plotted coordinates.)
cmd_h 0x0E draws a filled ellipse with color cmd_l.

cmd_h 0x07 will set the quadrant with cmd_l.

How to draw a complete ellipse:
Issue cmd_h=0x07 with cmd_l=00.     (set quadrant 0)
Issue cmd_h=0x06 with cmd_l=color.
Issue cmd_h=0x07 with cmd_l=01.     (set quadrant 1)
Issue cmd_h=0x06 with cmd_l=color.
Issue cmd_h=0x07 with cmd_l=02.     (set quadrant 2)
Issue cmd_h=0x06 with cmd_l=color.
Issue cmd_h=0x07 with cmd_l=03.     (set quadrant 3)
Issue cmd_h=0x06 with cmd_l=color.

For a filled ellipse, change the cmd_h=0x06 to 0x0E.

Let me know if everything looks ok.
Remember, this test bench has everything in hexadecimal.
And, if you are looking at the address generator pixel write commands, is drawn pixels are outside bounds, they will not generate a 'draw_cmd_rdy'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 23, 2020, 01:09:30 pm
Ok, you apparently never checked the 'quadrants'.  When mirrored or flipped, not both, the coordinate I was subtracting from the center coords was the wrong one as the X&Y coordinates supposed to be swapped when switching the 'INV' mode.

Ah, no - I can't see the quadrants in geoarc, so I hadn't tested them.  This is why I'm not a beta- or product- tester.  :-[

I've attached the new ellipse_generator with an embedded semi-smart X axis raster fill.  And to make Nockieboy happy, I sort of used his old trick way back to automatically 'pause' the line_generator every time it changed a Y coordinate while drawing when I requested the feature for the filled triangles.

 ^-^ ^-^ ^-^ ^-^ ^-^

See and test the attached simulation.
( Sadly, the ellipse generator takes ~1k logic elements. )

Hmm.. well, I thought I'd just see how it looks in terms of resource usage after compiling for the EP4CE10 in Quartus Prime and, surprise surprise, it doesn't fit - it's over by around 1500 LEs and 130 LABs (very approximate ballpark figures as I wasn't taking notes).

Ok, here is the full ellipse generator fully integrated into the full geometry processor unit.  Yes, everything is there in the test-bench.  The pixel-writer currently disabled for ease of viewing when testing.

The ellipse uses X0 & Y0 to define it's center.
And it uses X1 & Y1 to define it's X & Y radius.

cmd_h 0x06 draws an ellipse with color cmd_l.
(Unless the blitter is turned on where it will paint the source raster image along plotted coordinates.)
cmd_h 0x0E draws a filled ellipse with color cmd_l.

cmd_h 0x07 will set the quadrant with cmd_l.

How to draw a complete ellipse:
Issue cmd_h=0x07 with cmd_l=00.     (set quadrant 0)
Issue cmd_h=0x06 with cmd_l=color.
Issue cmd_h=0x07 with cmd_l=01.     (set quadrant 1)
Issue cmd_h=0x06 with cmd_l=color.
Issue cmd_h=0x07 with cmd_l=02.     (set quadrant 2)
Issue cmd_h=0x06 with cmd_l=color.
Issue cmd_h=0x07 with cmd_l=03.     (set quadrant 3)
Issue cmd_h=0x06 with cmd_l=color.

For a filled ellipse, change the cmd_h=0x06 to 0x0E.

Let me know if everything looks ok.
Remember, this test bench has everything in hexadecimal.
And, if you are looking at the address generator pixel write commands, is drawn pixels are outside bounds, they will not generate a 'draw_cmd_rdy'.

Wow, thanks.  This is going to take some testing as it'll be purely test bench-based.  I've got some real reasons to get the design done for the CV board as quickly as possible now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 23, 2020, 05:15:36 pm
Ok, I put everything into the full GPU_EP4CE10 project.
It has the full geometry unit with the ellipse generator.
I had to lower the MAGGIE layers from 6 to 5 to get the ellipse to fit.

The FMAX only reaches 122MHz, but it should probably still work.

To achieve the 122MHz, I had to make an enhancement to the 'pixel_address_generator', so there may be a
new bug with the geometry processor.  Please test everything.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 23, 2020, 09:06:04 pm
Oh yeah, I forgot I could reduce the number of Maggies... |O  Not thinking straight - have a lot going on.  Building the project as I write this, but won't be able to test until tomorrow now.

I'm guessing the reduced Fmax is because the FPGA is basically full, restricting the fitter to using whatever pathways are available rather than the quickest or most efficient.

EDIT: Yeah, the fitter is really working hard.  It's at 94% of LEs and took 4m44 to compile.  :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 23, 2020, 11:26:42 pm
Just had 5 minutes before I hit the sack to add ellipses to my Z80 test program.  It just draws ellipses based on random xc, yc and x/y radii so the vast majority of ellipses extend outside the visible screen area (I'll have more time tomorrow to set up a better test - concentric circles/ellipses in steadily-reducing radii) but from I can see so far, the ellipse engine is working beautifully.  ;D :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 24, 2020, 06:25:28 am
Remember, if your ellipses are centered, on a 320x200 screen, a radius of 160x100 would fill the screen.  The ellipses should look a lot better at 640x400.

Ok, I've attached all the updated consolidated test-benches and the complete GPU_EP4CE10 project.

The GPU_EP4CE10 now has an FMAX of 127MHz.  >:D
Let's see some videos of the speed of the ellipse routine.
(LOL, many are probably completely drawn before the 8 MHz Z80 even gets to execute the next opcode as it runs even ~4x slower than that.)

Next, maybe I can look at your HDMI stuff.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 24, 2020, 09:08:00 am
(This is a joke...)
@Nockieboy, can you do a comparison speed test of having the Z80 manually software render the ellipses VS using the geometry unit.  I wonder how the Z80 would handle all the 32bit integers needed for each iteration, then actually writing pixels through ram.  Yes, don't even think about using the built in geometry pixel write command.

What do you think the speed difference would be?
100000:1 is my bet for outline ellipses.
20000:1 for large filled ones.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 24, 2020, 12:06:12 pm
(This is a joke...)
@Nockieboy, can you do a comparison speed test of having the Z80 manually software render the ellipses VS using the geometry unit.  I wonder how the Z80 would handle all the 32bit integers needed for each iteration, then actually writing pixels through ram.  Yes, don't even think about using the built in geometry pixel write command.

What do you think the speed difference would be?
100000:1 is my bet for outline ellipses.
20000:1 for large filled ones.

Yeah I'd thought of this myself a little while ago, but I need to edit my copies of MBASIC or BBCBASIC to insert the necessary graphics routines to get graphical output.  I don't have the time to do that at the moment (but it's on my to-do list).  I know the Z80 doesn't exactly have a high IPC :-DD, but this one isn't hamstrung like the 80's ones by only being able to access memory when the raster is in the non-display areas of the screen, plus it's running at twice the speed of a typical 80's Z80.  I think you're right though - it'd be four or five orders of magnitude slower than the GPU. 

I've attached three images showing the ellipse output at the three screen resolutions the EP4CE10 can muster.  If I get some time later, I'll see about drawing the quadrants in different colours, but it all looks good. ;D :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 24, 2020, 03:07:04 pm
No video of randomly painted sized filled ellipses with different colored outline running all over the screen?

At least the ellipses are perfectly formed creating that nice moiré pattern.  It was worth going through the hassle of finding the right routine.

Once you have the CV working with DDR3, this GPU/Sound/Ram/SDcard board would be well suited to a CPU of caliber like 68020/68030 up to 50MHz.  If you ever get the time to make your geometry unit to execute self-compiled/interpreted geometric 2D/3D structures, it should be good for 68040/68060 @ 100-200MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 24, 2020, 04:22:35 pm
Here's a couple of videos for you - the random circle fill isn't running at full speed as I have a keypress check each loop, but we know it's going to be pretty quick and tearing the screen up if I ran it at full speed.  ;)

https://youtu.be/kX6uaDxLaB8 (https://youtu.be/kX6uaDxLaB8)
https://youtu.be/jYf3ThImGpQ (https://youtu.be/jYf3ThImGpQ)

If I don't appear on here again today, have a healthy and happy Christmas everyone. May Santa's sack be full of whatever is on your wishlist.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2020, 10:01:41 am
Here's a couple of videos for you - the random circle fill isn't running at full speed as I have a keypress check each loop, but we know it's going to be pretty quick and tearing the screen up if I ran it at full speed.  ;)

https://youtu.be/kX6uaDxLaB8 (https://youtu.be/kX6uaDxLaB8)
https://youtu.be/jYf3ThImGpQ (https://youtu.be/jYf3ThImGpQ)

If I don't appear on here again today, have a healthy and happy Christmas everyone. May Santa's sack be full of whatever is on your wishlist.  :)
Merry X-Mas everyone.

I'm assuming the first video is obviously not a palette trick which we would have done in the old days.
As with a 16 color screen, you have more than 16 circles to animate the shade through.
Though, you could have done that trick with a 256 color screen, but I know you don't have the ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 25, 2020, 07:08:28 pm
I'm assuming the first video is obviously not a palette trick which we would have done in the old days.
As with a 16 color screen, you have more than 16 circles to animate the shade through.
Though, you could have done that trick with a 256 color screen, but I know you don't have the ram.

No palette tricks here. :) Each frame the grey circles are redrawn, then the one white circle is drawn.  The grey circles start at a radius of 200 and reduce by 4 every circle - so 49 circles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 26, 2020, 06:15:08 am
Just as an aside, I've got the attached project building now, but it appears to be using some sort of megafunction to set up the TMDS outputs and I cannot assign pins in the Pin Planner to get the project to work on my EasyFPGA board with the DVI Tester.  The pins are already assigned and read only when I go to the Pin Planner.

I'm thinking I should just remove the OBUFDS elements entirely from hdmi.sv (lines 319-334) and just connect tmds_current[] to the output pins whilst inverting the _n pin signal, allowing me to assign pins in Pin Manager as usual. Hopefully.  Seems OBUFDS uses the altera_gpio_lite megafunction, but I can't find it in the IP Catalog so I can't seem to find where it's assigning the IO pins to the TMDS signals.

I'm probably going to get a lot of flak for not just doing it from scratch, but I like the promise of being able to output an HDMI signal and include audio in the bit stream - that's a major benefit over straight DVI and is why I'm plugging away at this example project.


Ok,I attached the simulation test bench.

Warning, in file: audio_clock_regeneration_packet.sv
  I had to comment out line 41 and replace it with line 42 since Quartus 9.1 could not handle the " real' " in the formula.  Later versions of Quartus can handle the term properly, so, you should comment back in line 41 and comment out line 42.  The difference is a potential rounding error with huge numbers and dividers.

  I also bypassed the IOBUFF module to make it transparently pass the data through.

  When loading the project into Quartus Prime, you will need to first change the Cyclone to the one on your developer PCB.  You will only output the 'P' pins unless we inverted the N&P polarity in the circuit.  If we did so, only output the 'N' port pin.  Do not output the N&P together.  Right now, I wired only the 'P' channel to all 4 outputs.

  Next, you will need to first do a 'Start - Analysis & Synthesis'.  Then go into the 'Pin Planner' and set the ' I/O Standard ' to LVDS.  You will notice that the TMDS pins have automatically doubled to versions with and extra {n} at the end.  Now, drag the 'non {n}' versions of the pins onto the correct differential 'P' output on the FPGA.  Also set the CLK to the right Input as well.  (You will notice that the pin-planner will automatically position the {n} versions of the output port to the 'n' pair on the LVDS output.)

   Next, go into the assignment editor and copy & paste the assigned TMDS output pins and in the duplicate group, change their assignment name from IO standard to 'Fast Output Registers' and set the value to 'On'.  Save the changes then compile.  (Only the original 'output pin' names need the 'Fast output registers.)

  Note that my last 2 instructions (defining the output as an LVDS differential and Fast Output register) can be properly set and defined in the IOBUF, but that will take reading some documentation on your part and learning everything about specifying the output buffer.

  With your 20MHz scope, you should see a 25.2MHz signal on the TMDS_Clk pin on both FPGA IOs, N&P, of your test circuit, though if will look like a sine wave since your scope is even slower than 25MHz.  If it looks OK, then try plugging in an HDMI monitor.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 27, 2020, 11:02:12 am
Warning, in file: audio_clock_regeneration_packet.sv
  I had to comment out line 41 and replace it with line 42 since Quartus 9.1 could not handle the " real' " in the formula.  Later versions of Quartus can handle the term properly, so, you should comment back in line 41 and comment out line 42.  The difference is a potential rounding error with huge numbers and dividers.

  I also bypassed the IOBUFF module to make it transparently pass the data through.

  When loading the project into Quartus Prime, you will need to first change the Cyclone to the one on your developer PCB.  You will only output the 'P' pins unless we inverted the N&P polarity in the circuit.  If we did so, only output the 'N' port pin.  Do not output the N&P together.  Right now, I wired only the 'P' channel to all 4 outputs.

  Next, you will need to first do a 'Start - Analysis & Synthesis'.  Then go into the 'Pin Planner' and set the ' I/O Standard ' to LVDS.  You will notice that the TMDS pins have automatically doubled to versions with and extra {n} at the end.  Now, drag the 'non {n}' versions of the pins onto the correct differential 'P' output on the FPGA.  Also set the CLK to the right Input as well.  (You will notice that the pin-planner will automatically position the {n} versions of the output port to the 'n' pair on the LVDS output.)

   Next, go into the assignment editor and copy & paste the assigned TMDS output pins and in the duplicate group, change their assignment name from IO standard to 'Fast Output Registers' and set the value to 'On'.  Save the changes then compile.  (Only the original 'output pin' names need the 'Fast output registers.)

Okay, I got this far and compiled - but Quartus is throwing errors at me:

Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_CLK_p is not supported by the device at location 49 (PAD_68) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 49; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_p[2] is not supported by the device at location 59 (PAD_83) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 59; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_p[1] is not supported by the device at location 54 (PAD_74) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 54; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_p[0] is not supported by the device at location 52 (PAD_72) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 52; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_CLK_p(n) is not supported by the device at location 50 (PAD_69) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 50; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_p[2](n) is not supported by the device at location 60 (PAD_84) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 60; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_p[1](n) is not supported by the device at location 55 (PAD_75) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 55; board resistor(s) will be needed
Error (169218): I/O standard LVDS on output or bidirectional pin TMDS_p[0](n) is not supported by the device at location 53 (PAD_73) -- only input pins of this I/O standard are allowed at this location
   Info (169217): Consider using I/O standard LVDS_E_3R or mini-LVDS_E_3R instead of LVDS for pin at location 53; board resistor(s) will be needed
Info (171121): Fitter preparation operations ending: elapsed time is 00:00:01
Warning (171167): Found invalid Fitter assignments. See the Ignored Assignments panel in the Fitter Compilation Report for more information.
Error (171000): Can't fit design in device
Error: Quartus Prime Fitter was unsuccessful. 9 errors, 9 warnings
   Error: Peak virtual memory: 4914 megabytes
   Error: Processing ended: Sun Dec 27 10:53:42 2020
   Error: Elapsed time: 00:00:06
   Error: Total CPU time (on all processors): 00:00:04
Error (293001): Quartus Prime Full Compilation was unsuccessful. 11 errors, 15 warnings

Either I've done something wrong with the assignments editor or we over-estimated the usefulness of the EP4CE6 for what we're trying to do... ???

Assignment Editor and Pin Planner images attached for info.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 27, 2020, 11:37:27 am
Change the 'IO Standard' to LVDS_E_3R for now.

I need to check the code, but it appears the author is probably not be using Altera's LVDS SERDES function.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 27, 2020, 12:25:02 pm
That compiles just fine now. :-+  Uses 20% of the CE6's LEs (1,232).   Will see about testing the eval board later when I have time and post the results.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 28, 2020, 04:38:43 pm
Ok, since I was getting bored waiting...
I added a new command to the geometry unit.  Hurray...  More things for you to test and demo.

Ok, you will be using cmd_h 0x07 (Shared with the 'Quadrant selection) and cmd_h 0x0F.

When setting cmd_h 0x0F, the register hw_position will be set with the contents of cmd_l.
The default is 0.

When setting cmd_h 0x07, cmd_l can be:
0x00 .. 0x03 => Set ellipse quadrant.
0x8# .. 0x8# => Wait for hw_position*1 to pass by # times/frames.  # = 1 through F/15 allowed.
0x9# .. 0x9# => Wait for hw_position*2 to pass by # times.  # = 1 through F allowed.
0xA# .. 0xA# => Wait for hw_position*4 to pass by # times.  # = 1 through F allowed.
0xB# .. 0xB# => Wait for hw_position*8 to pass by # times.  # = 1 through F allowed.

The hw_position, default being 0 means the vertical wait position is 1 line after the display frame has ended.  This gives you maximum time before the next frame begins to draw.  To request a delay before executing the next command, the # of cmd_l set with cmd_h 0x07 needs to be at least 1 or higher to wait multiple frames.  Having a hw_position of 100 and using the cmd_h 0x07 with cmd_l 0xA# means the pause position will be located 400 line/h-syncs after the end of the display frame.  If you choose a hw_position larger than the number of available lines in a frame, it will just abort trying to wait after 2 frames.  The larger numbers are there for future higher resolution support.

Go back to your smooth vertical text scroll example and before each vertical blitter jump, insert a wait command for 1 frame instead of using the Z80 delay and see if you get a clean vertical scroll without any visible tear.  Also try using wait for 2 or 3 frames to further slow down the vertical scroll.  Let me know if it works.  Since there are 16 steps, you can manipulate each frame count to have the carriage return begin slow, speed up, then decelerate during the 16 steps by a few frames.  The commands should allow additional Z80 processing even though the animation scroll sequence may not be complete by the next key-press/drawn graphics.

(Careful, you can now generate such slow animations that if you are not testing the geometry command FIFO full status, geo_stat_rd[0], before sending commands, you can overfill it...)

I've attached the new GPU_EP4CE10_vwait_inst.zip and test bench Geo_Writer_V10_complete_vwait_inst.zip which contain the wait commands.  The FMAX has 1 route a little too slow, but should still work.  FMAX is becoming difficult to achieve without some added work optimizing the core.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 29, 2020, 08:15:33 am
For a cool smooth accelerating/decelerating looking carriage return below the screen, try these delays.

Code: [Select]
Wait 1 vs.  (Step 1), Blit screen up 1 line and clear bottom line.
Wait 4 vs.  (Step 2), Blit screen up 1 line and clear bottom line.
Wait 3 vs.  (Step 3), Blit screen up 1 line and clear bottom line.
Wait 3 vs.  (Step 4), Blit screen up 1 line and clear bottom line.
Wait 2 vs.  (Step 5), Blit screen up 1 line and clear bottom line.
Wait 2 vs.  (Step 6), Blit screen up 1 line and clear bottom line.
Wait 1 vs.  (Step 7), Blit screen up 1 line and clear bottom line.
Wait 1 vs.  (Step 8), Blit screen up 1 line and clear bottom line.
Wait 1 vs.  (Step 9), Blit screen up 1 line and clear bottom line.
Wait 1 vs.  (Step 10), Blit screen up 1 line and clear bottom line.
Wait 1 vs.  (Step 11), Blit screen up 1 line and clear bottom line.
Wait 2 vs.  (Step 12), Blit screen up 1 line and clear bottom line.
Wait 2 vs.  (Step 13), Blit screen up 1 line and clear bottom line.
Wait 3 vs.  (Step 14), Blit screen up 1 line and clear bottom line.
Wait 3 vs.  (Step 15), Blit screen up 1 line and clear bottom line.
Wait 4 vs.  (Step 16), Blit screen up 1 line and clear bottom line.
Done...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 29, 2020, 12:03:54 pm
As soon as I get time, I'll take a look at the smooth scrolling - thanks for that!  :-+

Okay, I had five minutes to dig the silly-scope out to take a look at the dev board's output and have got these traces to show for it - the first is the INC+ output on pin 31 of the header, the second is INX2+ on pin 24.  The scope is obviously working flat-out at its minimum time/div setting.  Looks like some form of coherent output.

Plugged the HDMI in to my monitor - nothing.  Have tried hot-plugging, switching the dev board on/off whilst connected, switching inputs on the monitor, getting no indication of a signal from the DVI tester. 

My first thought is to confirm there's actually a signal getting to the HDMI connector on the DVI tester board - I figure the biggest chance of error is with my soldering of the QFN, but I've used up my spare time today, so debugging will have to wait a little while longer.  :(

EDIT:  Of course, I've just realised I haven't changed VCCIO down to 2.5V yet! :o  :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 29, 2020, 01:51:56 pm
Don't worry about the 2.5v.  The QFN amp IC can operate with a  huge range of inputs.  It operates like an analog differential comparitor.  The lower voltage test is for when we use the 'True LVDS' mode on the lower voltage output CV board.

Also check your scope, it might have an X10 magnification for the horizontal scan rate.

Also, if you are using a computer desktop screen like the LG Flatron, make sure you use the HDMI input.  My old LG Flatron doesn't like HDMI feeding it's DVI input.  It doesn't care if you feed DVI into it's HDMI input.  IE, the HDMI input is backwards compatible, but the DVI input isn't forwards compatible.

Also, make sure we didn't swap any of the +&- on the TMDS signals.  Any swapped signals need to be inverted in the Quartus Block Diagram Schematic since we cannot do so in the pin-planner.

Also, the QFN amp might not output a signal without a load.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 29, 2020, 02:23:36 pm
Also, the 'LVDS_E_3R' mode requires the pullup resistors...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 29, 2020, 02:47:20 pm
I looked at your schematic.
Are you sure you arent supposed to invert a signal?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 29, 2020, 05:36:01 pm
I looked at your schematic.
Are you sure you arent supposed to invert a signal?

I've just gone over it again and yes, it looks like the clock signal (INC) needs to be inverted.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 29, 2020, 06:00:52 pm
Also, make sure we didn't swap any of the +&- on the TMDS signals.  Any swapped signals need to be inverted in the Quartus Block Diagram Schematic since we cannot do so in the pin-planner.

Literally inverted? As in, insert an inverter between the 'top' module and the output pins for both _p and _n outputs on the clock signal pair?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: FenTiger on December 29, 2020, 06:14:02 pm
Just swap the pins, i.e. connect tmds_clock_p to TMDS_CLK_n and vice versa.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 29, 2020, 06:23:23 pm
Just swap the pins, i.e. connect tmds_clock_p to TMDS_CLK_n and vice versa.

Yeah, should have thought of that myself.  The _n pin wasn't explicitly defined in the schematic before, though - but now I've got it there, I can just swap the wires.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2020, 12:33:33 am

1 single inverter would have also worked...
How did the second pin appear?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2020, 05:40:01 am
Make sure on your scope that both the N&P output are oscillating with a 180degree phase difference.
You'll need 2 probes and need to turn on the horizontal time-base x10 magnification on your scope.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 30, 2020, 07:30:02 am
Also double check that you assign right color channels to HDMI data lanes, as they are not interchangeable. Data lane 0 is for blue color data and sync signals, lane 1 - green, lane 2 - red.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2020, 09:59:20 am
Also double check that you assign right color channels to HDMI data lanes, as they are not interchangeable. Data lane 0 is for blue color data and sync signals, lane 1 - green, lane 2 - red.
He's still missing something so much more simple stupid.  I want to see if he can figure it out....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2020, 12:30:15 pm
Also double check that you assign right color channels to HDMI data lanes, as they are not interchangeable. Data lane 0 is for blue color data and sync signals, lane 1 - green, lane 2 - red.
He's still missing something so much more simple stupid.  I want to see if he can figure it out....

I haven't got DE or DDC_EN outputs set up. DE needs to be LOW, DDC_EN needs to be HIGH.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 30, 2020, 12:33:50 pm
Also double check that you assign right color channels to HDMI data lanes, as they are not interchangeable. Data lane 0 is for blue color data and sync signals, lane 1 - green, lane 2 - red.
He's still missing something so much more simple stupid.  I want to see if he can figure it out....

I haven't got DE or DDC_EN outputs set up. DE needs to be LOW, DDC_EN needs to be HIGH.
;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 30, 2020, 01:54:48 pm
Silly-scope traces for clock p & n and data lane 0 p & n attached, showing 180-degree phase difference.

Despite adding the DE signal (permanently LOW), still no image on the monitor.  I'm going to need to do some further testing with the monitor (root out my old RPi with full-size HDMI connector on it) to make sure it's not the monitor messing me about (there's only one HDMI connector on the back, so no confusion over DVI/HDMI).

I guess I'm going to need to start thinking about somehow testing for signals coming out at the HDMI connector on the DVI tester?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 12:43:24 am
Strange, usually the pixel clock is the lowest frequency component.
The other data lines should have components averaging to the middle of your low bandwidth scope since they are operating in the 125MHz domain...

Also, channels 0,1 & 2 may be backwards.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 31, 2020, 01:26:19 am
Silly-scope traces for clock p & n and data lane 0 p & n attached, showing 180-degree phase difference.
Is horizontal scale the same on both traces? If so, your clock is wrong - HDMI clock lane is a symbol clock, not pixel one. As such, one period of symbol clock should cover 10 bit times for the data lanes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 04:01:25 am
Silly-scope traces for clock p & n and data lane 0 p & n attached, showing 180-degree phase difference.
Is horizontal scale the same on both traces? If so, your clock is wrong - HDMI clock lane is a symbol clock, not pixel one. As such, one period of symbol clock should cover 10 bit times for the data lanes.
This is a bit of a problem as his scope is 20MHz only and we cannot predict what the output and trace lock & would look like on the lanes.  Especially with a fixed test pattern.  I would have foreseen more middle level junk.  Perhaps in the horizontal frame, there just seems to be a repetitious pattern which appears to be lower frequency than the pixel clock.  In the simulation output, the data lanes do have 10 distinct bits per 'symbol clock'.  And the symbol clock does end up being equal to what would be the equivilant VGA dac pixel clock in the end.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 04:05:14 am
@Nockieboy, with the 'IO Standard' set to LVDS_E_3R, you probably need to add those 8x 51ohm resistors to your DVI tester board.  However, I only see this as an issue above 300mbps.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 04:49:58 am
You have been Nockied!!!

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1142288)

I wonder how long this would have gone on if I hadn't checked...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 01:36:26 pm
 :palm:  I'll get my coat...

All the outputs need to be reversed on the Quartus schematic - so that means the clock is the one pair that now doesn't need to be reversed...? :o

EDIT:  In my defence, the TX outputs where connected up to the PTN3366 to create the simplest routing to the HDMI connector.  If I'd connected positive to positive, negative to negative, each of the pairs would have had to cross over to get to the HDMI connector...  Which seems a bit odd, you'd think the chip or the connector would be made so that wouldn't happen, but I recall someone telling me a while ago that it didn't matter which way round the connections were made, but I guess it helps to know that they're swapped around though, so that the outputs can be swapped accordingly in Quartus...  I'd forgotten I'd done that. ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 01:45:12 pm
I just want to confirm that reversing the outputs is simply a case of swapping the output as per the attached schematic?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1142434)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 01:46:07 pm
Yes, in Quartus, move the clk pin back to the positive output from the module and move the 3 data lines to the module's negative output...
You got it right.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 02:04:34 pm
Apologies for the potato-camera picture, but IT WORKS!!  ;D ;D ;D :-+

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1142446)

Bit blurry, but the screen boundaries are clearly visible and the monitor is picking up a 480p/60Hz HDMI signal.

EDIT: Not shown in the picture above, but I stepped through the monitor's menu and it was also picking up the audio component in the HDMI signal - although there's no sound to hear just yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 02:19:22 pm
Ready to try 720 @ 60Hz?
Also, 1080p @ 30Hz?  (No blur on this one...)

Also, a 2.5v IO test...  Though, that NXP amplifier IC was explicit, it should work from 2.5v drive all the way to 0.325v drive.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 02:22:09 pm
Ready to try 720 @ 60Hz?
Also, 1080p @ 30Hz?  (No blur on this one...)

Definitely.  I'm just looking through the code currently to see how to set it up for 720p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 02:25:24 pm
Bit blurry, but the screen boundaries are clearly visible and the monitor is picking up a 480p/60Hz HDMI signal.
Yes, unlike analog VGA where the monitor may add artificial sharpness for the quality of the ADC sampling and poor analog cables, the full digital DVI/HDMI upsampling usually looks smoother/softer...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 02:33:59 pm
Oooops, the module you are using uses x10 on the PLL instead of x5.  I don't think they are using Altera's SERDES.  If not, it may not be possible to achieve the 742.5mbps as the code cant run that fast if they are using a software SERDES instead of a hardware one.

The code internally seems to support DDRIO mode, IE shift 2 bits per clock.  You will need to read up on how to get it to work, or it might be automatic...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 02:34:19 pm
Bit blurry, but the screen boundaries are clearly visible and the monitor is picking up a 480p/60Hz HDMI signal.
Yes, unlike analog VGA where the monitor may add artificial sharpness for the quality of the ADC sampling and poor analog cables, the full digital DVI/HDMI upsampling usually looks smoother/softer...

Oh it was sharp enough irl, it's just my mobile camera was having trouble with the lighting in the room and my hands weren't steady enough to take a sharp picture.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 02:44:45 pm
The code internally seems to support DDRIO mode, IE shift 2 bits per clock.  You will need to read up on how to get it to work, or it might be automatic...

The DDRIO is a parameter in the HDMI module.  Just turn it on and make the x10 clock only x5.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 02:47:28 pm
Oooops, the module you are using uses x10 on the PLL instead of x5.  I don't think they are using Altera's SERDES.  If not, it may not be possible to achieve the 742.5mbps as the code cant run that fast if they are using a software SERDES instead of a hardware one.

Hmm... the ALTPLL config megawizard can't achieve the required 740MHz on the PLL.  It'll manage 739MHz, but complains that the requested mult/div factors are not achievable if I ask for one more megahertz. :-\

It manages 720x480p just fine, though - you may not see any difference in the next screenshot, but the vertical lines are definitely slightly thinner than the 640x480 version.

[attachimg=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 02:54:44 pm
Oooops, the module you are using uses x10 on the PLL instead of x5.  I don't think they are using Altera's SERDES.  If not, it may not be possible to achieve the 742.5mbps as the code cant run that fast if they are using a software SERDES instead of a hardware one.

Hmm... the ALTPLL config megawizard can't achieve the required 740MHz on the PLL.  It'll manage 739MHz, but complains that the requested mult/div factors are not achievable if I ask for one more megahertz. :-\

It manages 720x480p just fine, though - you may not see any difference in the next screenshot, but the vertical lines are definitely slightly thinner than the 640x480 version.

(Attachment Link)
Set the X10 clock to 371.25Mhz (IE x5) and learn about using the DDR output mode.
It's one of the parameters...
First test with the current 480p by making the current x10 252 Mhz on the PLL 1/2 the current speed and setting the DDRIO parameter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 31, 2020, 02:58:31 pm
Hmm... the ALTPLL config megawizard can't achieve the required 740MHz on the PLL.  It'll manage 739MHz, but complains that the requested mult/div factors are not achievable if I ask for one more megahertz. :-\

It manages 720x480p just fine, though - you may not see any difference in the next screenshot, but the vertical lines are definitely slightly thinner than the 640x480 version.
I'd suggest you implement a simple I2C master and dump out DDC information for this monitor, it will tell you exactly which modes are supported. There are MANY different options possible: https://www.mythtv.org/wiki/Modeline_Database (https://www.mythtv.org/wiki/Modeline_Database)
Also touch you FPGA to check if it gets warm (or hot) - I found that when you push really high clocks through FPGA (as in - "out of spec high"), they get rather hot. At least in my case Spartan-7 50T device would've cooked itself if I didn't add a heatsink on top of it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 03:02:24 pm
The code internally seems to support DDRIO mode, IE shift 2 bits per clock.  You will need to read up on how to get it to work, or it might be automatic...

Quartus isn't going to play ball with me.  :-\  I've enabled DDRIO mode, halved the multiplier on the x10_pixel_clk so that it's a x5_pixel_clk, which made the ALTPLL megawizard happy to synthesise the PLL, but when compiling the project Quartus threw this at me:

Error (176060): The transmitter driving I/O pin TMDS_CLK_p at data rate 743 Mbps exceeds the maximum allowed data rate of 550 Mbps for LVDS_E_3R output

I'll wait to see if you have any suggestions, but it appears that 720p testing will have to continue on the CV - but I still consider this exercise a success as it means I can replace the VGA output on the CV board AND it takes up less space and IOs than the TFP410 would have done, whilst still giving me 640x480 (or even 720x480) video output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 03:08:50 pm
Tell Quartus that your source clock is 37MHz instead of 50, but, keep the PLL divider ratios the same.

IE, if you have a frequency set, then record the set divider ratios, then, when editing the PLL, set the source clock to 37MHz.  Then for the output frequency, set those divider ratios instead of a set frequency and give it a try.

You are basically tricking Quartus to overclock the outputs.

The outputs on the CV using the true- LVDS is 740MHz, not 743MHz, so, we will do the same trick, but, with 49.7MHz in place of the 50MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 03:16:32 pm
Try changing the IO standard to HSIODR if available.  It has a higher FMAX.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 03:29:22 pm
Tell Quartus that your source clock is 37MHz instead of 50, but, keep the PLL divider ratios the same.

IE, if you have a frequency set, then record the set divider ratios, then, when editing the PLL, set the source clock to 37MHz.  Then for the output frequency, set those divider ratios instead of a set frequency and give it a try.

You are basically tricking Quartus to overclock the outputs.

The outputs on the CV using the true- LVDS is 740MHz, not 743MHz, so, we will do the same trick, but, with 49.7MHz in place of the 50MHz.

Okay, I've given this a try but the monitor is displaying the same image as before and telling me I've got a 480p HDMI signal.  :-//

Have attached the Quartus schematic so you can see the PLL settings, and a screenshot of top.sv to show the hdmi.sv instantiation values.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 03:34:14 pm
That reference 50MHz is making a mess of things.  I hope you changed that to 27MHz for the CV board.
Can you send me the QP project.
I'll add a primary PLL to first generate 27MHz from the 50, then use the second PLL to make the video clocks.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 03:38:33 pm
That reference 50MHz is making a mess of things.  I hope you changed that to 27MHz for the CV board.
Can you send me the QP project.
I'll add a primary PLL to first generate 27MHz from the 50, then use the second PLL to make the video clocks.

I hadn't, but it'll be easy enough to change the BOM.  Project attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 04:18:39 pm
Give this a try.
I changed the FPGA to a -7, so it believes the DDRIO FMAX is 640mbps instead of 550.
And in the second PLL, I have the correct dividers setup, but, I told Quartus it was receiving a 23MHz clock instead of 27.
The first PLL creates the 27MHz and 48KHz audio clocks from the source 50MHz.

Other than setting the vertical scan rate to the standard 59.94hz, I didn't do anything else.
Give it a test.
Also, you can go back to 480p for testing with the 2 PLLs as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 04:30:52 pm
Just tried it - no signal that the monitor can recognise, unfortunately. :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 04:35:42 pm
Try 480p, 720x480 using DDR mode.

IE edit the second PLL to 27mhz in, 135mhz & 27Mhz out.

Just want to make sure the DDR mode is functional.
If so, then you probably need to add the 8x 50ohm pullup resistors and maybe play with the 2 dipswitches.


At least if the DDR functions, we can try a CV build and see if the compiler will pass the 743MHz barrier when using a 'true-differential' set of IO pins.  A -6 has a 840MHz max, a -7 has a 740MHz max.  That 2.5 MHz difference should be over-clockable with clean data as we are even amplifying the output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2020, 05:15:34 pm
I also just realized the possibility of the compiler merging the 2 PLLs together into 1 and literally reformulating the divider ratios to match the 23MHz source and multiply the clocks from there.  Right now, we will say this is not the case.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 07:32:44 pm
Try 480p, 720x480 using DDR mode.

IE edit the second PLL to 27mhz in, 135mhz & 27Mhz out.

Just want to make sure the DDR mode is functional.
If so, then you probably need to add the 8x 50ohm pullup resistors and maybe play with the 2 dipswitches.


At least if the DDR functions, we can try a CV build and see if the compiler will pass the 743MHz barrier when using a 'true-differential' set of IO pins.  A -6 has a 840MHz max, a -7 has a 740MHz max.  That 2.5 MHz difference should be over-clockable with clean data as we are even amplifying the output.

Hmm, okay..  I've had to roll back my project to before your change to add the 27MHz PLL.  No matter what I've tried, I've not been able to output a signal the monitor could read.  Won't be able to test any more tonight, but I'll take another look at trying DDR mode tomorrow morning.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 31, 2020, 07:49:59 pm
It would appear that the DDRIO mode doesn't work - or doesn't work just by halving the x10 pixel clock and setting DDRIO to 1'b1, in any case.  Have tried to get it working with the basic 640x480 output that I know works - seems the same problem is evident.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 31, 2020, 08:08:20 pm
You might want to go through P&R warnings - at least in Vivado they often contain hints as to why something doesn't work.
But fundamentally I think you guys should just leave it alone for now. The fact that 480p works fine should give you confidence to drop VGA port and TFP410 for good, so that you can finish your PCB design and continue with your experiments on a new board. Also note all issues found with breakout board and write them down somewhere, so that you won't forget to correct them when you transfer design to a final board. I often place such notes as text right in the schematic, because it not uncommon for me to begin incorporating these things into a final board few moths after I've done my testing, so obviously I forget a lot of stuff.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 31, 2020, 08:37:40 pm
EDIT:  In my defence, the TX outputs where connected up to the PTN3366 to create the simplest routing to the HDMI connector.  If I'd connected positive to positive, negative to negative, each of the pairs would have had to cross over to get to the HDMI connector...  Which seems a bit odd, you'd think the chip or the connector would be made so that wouldn't happen, but I recall someone telling me a while ago that it didn't matter which way round the connections were made, but I guess it helps to know that they're swapped around though, so that the outputs can be swapped accordingly in Quartus...  I'd forgotten I'd done that. ::)
It could be that the chip pinout was designed for placement on the other side of the board from HDMI connector. I can see how this would allow for more tight layout. It's not uncommon for interface chips to have several versions with different pinouts optimized for different placement scenarios.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 01, 2021, 03:49:13 am
Ok, here is the HDMI_multi_tests.zip...

5 Projects inside:

HDMI_test_SDR_480p  > only proceed onto the next project if this one works.
HDMI_test_DDR_480p  > only proceed onto the 720p projects if this one works.

If the first 2 pass, then try all these 3:
HDMI_test_720p_A    >  Attempts 742.5 mbps exact using odd dividers in the PLLs.
HDMI_test_720p_B    >  Attempts ~740 mbps proper short dividers.  (This could have been the official 742.5 if you had a 27MHz crystal on the PCB.)
HDMI_test_720p_C    >  Attempts 640 mbps proper short dividers.  This is an oddball low frequency non-standard 720p @ 52.5hz.  It may have a chance on your desktop PC monitor's HDMI input.  If the monitor reports frequency out of range instead of dead/no video, then we know the HDMI data was understood, just that the video mode was a lemon scan rate.  Audio packets will most likely be corrupt.

Happy New Years...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 01, 2021, 03:01:00 pm
Ok, here is the HDMI_multi_tests.zip...

5 Projects inside:

HDMI_test_SDR_480p  > only proceed onto the next project if this one works.
HDMI_test_DDR_480p  > only proceed onto the 720p projects if this one works. <<< FAILS HERE

If the first 2 pass, then try all these 3:
HDMI_test_720p_A    >  Attempts 742.5 mbps exact using odd dividers in the PLLs.
HDMI_test_720p_B    >  Attempts ~740 mbps proper short dividers.  (This could have been the official 742.5 if you had a 27MHz crystal on the PCB.)
HDMI_test_720p_C    >  Attempts 640 mbps proper short dividers.  This is an oddball low frequency non-standard 720p @ 52.5hz.  It may have a chance on your desktop PC monitor's HDMI input.  If the monitor reports frequency out of range instead of dead/no video, then we know the HDMI data was understood, just that the video mode was a lemon scan rate.  Audio packets will most likely be corrupt.

As above - the DDR_480p test doesn't work - no HDMI signal picked up by the monitor.

Happy New Years...

And to you!  :D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 01, 2021, 03:23:46 pm
Can you do me a favor and try changing the IO Standard to Differential 2.5v SSTL Class II.

I tried simulating the 480p SDR and DDR.  The output from the 2 look identical other than the PLL startup time.  If this doesn't work, can you point me to where you downloaded the source code.  I do know that in the code, they are using their own parallel to serial shift register instead of an official SERDES and that the DDR is their own home made 2-step shift-er.

Without using the DDR, or, Altera's SERDES which also uses a 5x clock to transmit the 10bit high megabaud output, you could never use this particular code for 720p or 1080p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 01, 2021, 03:28:43 pm
If the change in IO standard doesn't work, return it back and try placing 1 inverter on the 5x/10x clock, or one inverter on the pixel clock. (Inbetween PLL and HDMI transmitter...)
The simulation final HDMI output did match (on old Quartus with Cyclone III), yet, what I gave you did match and the video out didn't work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 01, 2021, 05:36:07 pm
Can you do me a favor and try changing the IO Standard to Differential 2.5v SSTL Class II.

I tried simulating the 480p SDR and DDR.  The output from the 2 look identical other than the PLL startup time.  If this doesn't work, can you point me to where you downloaded the source code.  I do know that in the code, they are using their own parallel to serial shift register instead of an official SERDES and that the DDR is their own home made 2-step shift-er.

Without using the DDR, or, Altera's SERDES which also uses a 5x clock to transmit the 10bit high megabaud output, you could never use this particular code for 720p or 1080p.

Here's the source for the HDMI code I'm using: https://github.com/hdl-util/hdmi/ (https://github.com/hdl-util/hdmi/)

Changing the IO standard to Differential 2.5v SSTL Class II just threw errors when I tried to compile the code - unsupported standard or something.

If the change in IO standard doesn't work, return it back and try placing 1 inverter on the 5x/10x clock, or one inverter on the pixel clock. (Inbetween PLL and HDMI transmitter...)
The simulation final HDMI output did match (on old Quartus with Cyclone III), yet, what I gave you did match and the video out didn't work.

Adding an inverter doesn't work either - no HDMI signal picked up by the monitor.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2021, 03:16:22 am
Ok, I think that step 1 should be reverting to the original code where we get the errors:
Code: [Select]
Error (15856): Output port O of I/O output buffer "top:inst1|hdmi:hdmi|OBUFDS:obufds|altera_gpio_lite:obufds_inst|altgpio_one_bit:gpio_one_bit.i_loop[3].altgpio_bit_i|true_diff_output_buf.obuf" must drive a top-level pin
Error (15856): Output port O of I/O output buffer "top:inst1|hdmi:hdmi|OBUFDS:obufds|altera_gpio_lite:obufds_inst|altgpio_one_bit:gpio_one_bit.i_loop[2].altgpio_bit_i|true_diff_output_buf.obuf" must drive a top-level pin
Error (15856): Output port O of I/O output buffer "top:inst1|hdmi:hdmi|OBUFDS:obufds|altera_gpio_lite:obufds_inst|altgpio_one_bit:gpio_one_bit.i_loop[1].altgpio_bit_i|true_diff_output_buf.obuf" must drive a top-level pin
Error: Quartus Prime Analysis & Synthesis was unsuccessful. 3 errors, 10 warnings
Error: Peak virtual memory: 644 megabytes
Error: Processing ended: Fri Jan 01 22:08:27 2021
Error: Elapsed time: 00:00:27
Error: Total CPU time (on all processors): 00:00:34
Error (293001): Quartus Prime Full Compilation was unsuccessful. 5 errors, 10 warnings

Ok, what Quartus is saying isn't that there is a coding error.  It is saying that the defined output buffer must drive a top level pin.
Let's see if we can resolve that properly instead of skipping the IOBUF module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2021, 03:29:19 am
Ok, issue properly resolved.  All I had to do was assign the 'top.sv' as top hierarchy in quartus to allow compilation.  I do not like this solution as it demands that this module needs to become the top priority in quartus.

Doing the above has just wired the top.sv directly to IO pins ignoring the rest of the design.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2021, 04:35:42 am
I think you need to join Hithub and ask the author how to do everything since he wrote the code.

With his code, you cannot seem to use the LVDS_E_3R.
You cannot seem to be able to invert the output data.
The DDR doesn't seem to work.

And you cannot use any earlier versions Quartus other than 18.0 and above thanks to the:
Error: Node instance "true_diff_output_buf.obuf" instantiates undefined entity "fiftyfivenm_io_obuf

It would be useful to be able to properly bypass these issues before you go onto the 'DDR' problem.
That is unless you want to claim our current bypass as 'perfect' and claim the 'DDR' is flawed which we cannot truly officially do.  All you can say is that we got the 480p SDR mode working with a separate top hierarchy in Quartus and turning on the DDR with a 5x clock fails at the same 480p.

Remember that we are using Cyclones.
Also mention that a selection for inverting individual bits is useful as N&P wiring can be easily made straight.
Also mention that using emulated LVDS, IE LVDS_E_3R is still capable of 650mb/sec.
Also offer the 94cent NXP IC we found to buffer and protect the source LVDS and your example schematic.

Try to get the guy to do some minimal work for you.
Maybe upload the example 480p to him.
(Make clear that you bypassed the OBUFDS.v to get the code to fit.)

Without DDR support, or use Quartus serializer, you will never go above 480p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2021, 09:36:36 am
Ok, I modified the GitHub's HDMI transmitter code to use Altera's 'altlvds_tx' serializer megafunction.
It's set to 480p, and I also now added the ability to configure each TMDS output channel's polarity.
I also added a parameter PIXEL_MHZ which overrides and tells the serializer the source pixel clock frequency.  It has no effect anywhere else.  This means if we try 720p where the bit rate is 742.5mbps while the -7's limit is only 740.0mbps, we can just lie here and set it to 74MHz instead and Quartus wont have a melt-down aborting the compile.

Let me know if it works.

The 'altlvds_tx' serializer also tells the IOs up the chain of any number of modules to be configured as differential of any type and works out the maximum bitrate based on which pins you use.  It also now works with earlier versions of Quartus all the way back to 9.1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 02, 2021, 10:15:47 am
 :scared: Do me a favor and test this old DDR one as well.
It seems the - tmds clk_n pin in all the previous package were not assigned, IE they were set to weak pull-up VCC only.

Though, the - tmds clk_n was also not assigned in the SDR build as well...

Anyways, the altlvds_tx version is the true way to do it unless you want to debug the damn IOBUF and manually set every nuance hoping you haven't left anything to chance including setting up the PLL manually.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 11:27:09 am
Don't know what happened yesterday, but I missed any notification of your posts so apologies for the delay replying.

Ok, I modified the GitHub's HDMI transmitter code to use Altera's 'altlvds_tx' serializer megafunction.
It's set to 480p, and I also now added the ability to configure each TMDS output channel's polarity.
I also added a parameter PIXEL_MHZ which overrides and tells the serializer the source pixel clock frequency.  It has no effect anywhere else.  This means if we try 720p where the bit rate is 742.5mbps while the -7's limit is only 740.0mbps, we can just lie here and set it to 74MHz instead and Quartus wont have a melt-down aborting the compile.

Let me know if it works.

The 'altlvds_tx' serializer also tells the IOs up the chain of any number of modules to be configured as differential of any type and works out the maximum bitrate based on which pins you use.  It also now works with earlier versions of Quartus all the way back to 9.1.

This one works - getting good 480p HDMI output. :-+

:scared: Do me a favor and test this old DDR one as well.
It seems the - tmds clk_n pin in all the previous package were not assigned, IE they were set to weak pull-up VCC only.

Though, the - tmds clk_n was also not assigned in the SDR build as well...

Anyways, the altlvds_tx version is the true way to do it unless you want to debug the damn IOBUF and manually set every nuance hoping you haven't left anything to chance including setting up the PLL manually.

No joy with this one - still no HDMI output detected by the monitor. :-//

I think you need to join Hithub and ask the author how to do everything since he wrote the code.

Will do.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 12:04:16 pm
Don't know what happened yesterday, but I missed any notification of your posts so apologies for the delay replying.

Ok, I modified the GitHub's HDMI transmitter code to use Altera's 'altlvds_tx' serializer megafunction.
It's set to 480p, and I also now added the ability to configure each TMDS output channel's polarity.
I also added a parameter PIXEL_MHZ which overrides and tells the serializer the source pixel clock frequency.  It has no effect anywhere else.  This means if we try 720p where the bit rate is 742.5mbps while the -7's limit is only 740.0mbps, we can just lie here and set it to 74MHz instead and Quartus wont have a melt-down aborting the compile.

Let me know if it works.

The 'altlvds_tx' serializer also tells the IOs up the chain of any number of modules to be configured as differential of any type and works out the maximum bitrate based on which pins you use.  It also now works with earlier versions of Quartus all the way back to 9.1.

This one works - getting good 480p HDMI output. :-+

Holy crap....
Great.
Make sure the audio is available too.
Give me a minute to compile a few 720p tests.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 12:29:58 pm
Ok, here are 3 720p tests.

Because of the source 50MHz clock and only 2 PLLs, version A has the pixel clock at 74.23MHz instead of the true 74.25MHz.

Version B has it at 74MHz.

Version C has it at 64MHz being that the IO Pin standard of LVDS_E_3R's limit is officially 640mbps.   Version C might only work on a PC monitor as the output is a weird 51.6Hz.

If version C works, then we pretty much know something is weird with the original author's 'DDR' function as if the current clues already don't point to a problem somewhere.

If none work, you will probably need to add those 8 resistors you did not place on your PCB as the termination is required for the higher bit rates.  Worst, the DRAM chip would probably need to be removed.  However, since Altera's official 'altlvds_tx' megafunction has properly transmitted 480p, and with the megafunction's specs match the datasheet's numbers, using the right 4 LVDS IOs on the CV is pretty much a go if you use my patched version of the HDMI transmitter.  (Note that the right 740mbps true-LVDS outputs are on the sides of the CycloneIV, not the bottom row which we used because of convenience.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 02:17:46 pm
All three work fine. :o

Here's an image from the 'A' test - B & C are identical.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1144176)

EDIT:  Test 'C' reports HDMI 720p @ 52Hz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 02:30:15 pm
LOL.... So much for the 650mbps limit.  But wait, you are actually using a -8 chip, the limit supposed to be 550mbps and you are doing 742mbps.  With this kind of stretch, I wonder if 1080p @60hz would work with a -6 cyclone and the NXP amp IC.  It's official true-LVDS is 840mbps and we need 1485mbps.  The NXP IC also has an enhancement gain beginning at 1.5GHz all the way up to 3GHz as it was designed to amplify weak signals.

Did you install the resistors?
The NXP chip being mounted right next to the Cyclone must be sharpening the edge of the sluggish IOs.

Please test the next one.  Let me know if the lines are razor sharp.

Something ain't right with the original author's 'DDR' function.  Yet, I did a simulation of both 480p with and without the DDR and they appeared to match.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 02:33:37 pm
LOL.... So much for the 650mbps limit.  But wait, you are actually using a -8 chip, the limit supposed to be 550mbps and you are doing 742mbps.

Did you install the resistors?
The NXP chip being mounted right next to the Cyclone must be sharpening the edge of the sluggish IOs.

Please test the next one.  Let me know if the lines are razor sharp.

I guess there's a big safety margin in those performance quotes....  :o

No, haven't installed the termination resistors.  Here's a picture of my setup - if you look closely, you'll see no termination resistors, just blank pads where they should go.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1144186)

The NXP chip will be even closer to the CV on the final board - with dedicated signal lines not being shared with a DRAM chip like the existing dev board setup!  (The DRAM chip is hidden underneath the DVI Tester board, for those following along).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 02:40:08 pm
Please test the next one.  Let me know if the lines are razor sharp.

No HDMI signal detected.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 02:58:07 pm
Ok, all I did was use video ID mode 16, 1080p@60Hz and half the clock rate for 30Hz.  I looked at the CEA861D spec and this video mode's format ID is actually #34.  I added this mode to the HDMI transmitter code and re-zipped the new project.

Note that not all computer screens will support this 30Hz mode, but HDMI TVs will as it is part of the spec.

Give this one a test...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 03:08:22 pm
Note that not all computer screens will support this 30Hz mode, but HDMI TVs will as it is part of the spec.

Give this one a test...

I'm getting a message on the monitor - "HDMI Out of Range - 67.4kHz / 81 Hz"
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 03:13:27 pm
Note that not all computer screens will support this 30Hz mode, but HDMI TVs will as it is part of the spec.

Give this one a test...

I'm getting a message on the monitor - "HDMI Out of Range - 67.4kHz / 81 Hz"
Found another bug.  The author of the original code has stripped the number of bits for the horizontal and vertical counters unless a particular video mode was selected.  He should have let the compiler deal with that...
Try this build.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 03:24:06 pm
Note that not all computer screens will support this 30Hz mode, but HDMI TVs will as it is part of the spec.

Give this one a test...

I'm getting a message on the monitor - "HDMI Out of Range - 67.4kHz / 81 Hz"
Found another bug.  The author of the original code has stripped the number of bits for the horizontal and vertical counters unless a particular video mode was selected.  He should have let the compiler deal with that...
Try this build.

No HDMI signal at all with this one.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 03:29:10 pm
Quote
No HDMI signal at all with this one. 

You will probably need to try a different screen which supports 30Hz.  Or, something else in the HDMI code isn't done right.  We do not know if the author has ever successfully tested 1080p @ 60Hz in the first place.
You can also try looking at the '' 'real '' command in the parameter in the audio packet portion of the code.  I have it removed for compatibility, but, I doubt that would make a difference.

Ok, we know you can do video above 480p.

It is time to build a CV project with only Altera's DDR3 ram controller configured and plan the IO banks & pins.  We would like to get an FMAX of 371.25MHz or 324MHz instead of the bottom end guaranteed 303MHz.  The first 2 are nice multiples of 27MHz & 720p video clock.  I doubt we can achieve 27Mhz*16=432MHz unless you are using a CV-6 and a little trickery.

Then insert the HDMI and plan the IO pins.

Then build your PCB, then add the other slow Z80 & other IO ports.

Also, if there is IO room, you might be able to place 2 HDMI ports even if you only wire up one of them.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 03:37:10 pm
Ok, we know you can do video above 480p.

The 720p mode is looking sharp and stable.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1144226)

It is time to build a CV project with only Altera's DDR3 ram controller configured and plan the IO banks & pins.  We would like to get an FMAX of 371.25MHz or 324MHz instead of the bottom end guaranteed 303MHz.  The first 2 are nice multiples of 27MHz & 720p video clock.  I doubt we can achieve 27Mhz*16=432MHz unless you are using a CV-6 and a little trickery.

Then insert the HDMI and plan the IO pins.

Then build your PCB, then add the other slow Z80 & other IO ports.

So just a standalone CV project for the DDR3 controller?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 03:40:12 pm
Found another bug.  I had to add another reference to mode #34.  But it seems it was only for the packet counter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 03:45:02 pm
Found another bug.  I had to add another reference to mode #34.  But it seems it was only for the packet counter.

No valid HDMI signal.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 03:45:11 pm
So just a standalone CV project for the DDR3 controller?
Yes.  Make a DDR3 controller set to the ram chip we are using and have 2 read/write ports for now.
Set and wire the memory IOs and PLL.
Create dummy controls for the DDR3 controller's read and write port commands.

BTW, Hun, what with that photo?
Where did the text and color bars come from?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 03:48:28 pm
Try using your monitor with your PC in HDMI 1080p @ 30Hz/29.97Hz.  If the monitor shows a picture, then there is a flaw in the HDMI code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 04:00:15 pm
BTW, Hun, what with that photo?
Where did the text and color bars come from?

The HDMI project on github has a basic test screen (the coloured edges of the screen created with a single line in the top.sv file).  There is a more advanced output from another repo by the same author, compatible with the top.sv in our test project.  I just added the symbol file and couple of other files from the other repo and modded our top.sv to use them to generate the output you see in the pic.  I figured it was a little more helpful than just the coloured edges.

EDIT: Note that I've only done that with the HDMI_test_720p_altlvds_tx_A project (oh, and the original SDR_480p one too).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 04:25:25 pm
Ok, no prob.
It may be useful to add an audio tone on the audio input for testing.
The 720pA is the closest to the real thing.  Off by 20khz, but having a 27MHz source crystal would fix the issue.

See if you can get your PC to output 1080p @ 29.97Hz onto your monitor.
It is not worth my time debugging someone else's code if the limitation is in your monitor.
The 1080p @29.97Hz has the same clock as the 720P version A.
I suspect the code based on the weird high frequency error message when the counters did not have enough bits, so they looped around quickly.
You can try changing the counters in the top.sv from 10bits to 13bits.  IE [9:0] to [12:0].  Maybe that will fix the bug.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 04:59:55 pm
Ok, no prob.
It may be useful to add an audio tone on the audio input for testing.
The 720pA is the closest to the real thing.  Off by 20khz, but having a 27MHz source crystal would fix the issue.

See if you can get your PC to output 1080p @ 29.97Hz onto your monitor.
It is not worth my time debugging someone else's code if the limitation is in your monitor.
The 1080p @29.97Hz has the same clock as the 720P version A.
I suspect the code based on the weird high frequency error message when the counters did not have enough bits, so they looped around quickly.
You can try changing the counters in the top.sv from 10bits to 13bits.  IE [9:0] to [12:0].  Maybe that will fix the bug.

The counters are already 14-bit in top.sv?  But anyway, I've been unable to set up a 1080p 30Hz display on my PC, but as luck would have it Santa brought my daughter a new TV for Christmas, so the old one was sitting around gathering dust.  I've just set it up and plugged the test board into it with the latest HDMI_test_1080p_altlvds_tx project running, and it works!  A pixel-sharp 1080p image at 30Hz!  :-+

As soon as I plug in some noise generation, I'll test the audio output as well (my PC monitor doesn't have built-in speakers so I couldn't test it before).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on January 03, 2021, 05:06:25 pm
You might want to try 1080p@24Hz, which is standard HDMI mode:
Code: [Select]
pixel_clk hres  hs_s hs_e hs_t vres vs_s vs_e vs_t
74.16 1920 2558 2602 2750 1080 1084 1089 1125
pixel_clk - pixel clock frequency
hres - horizontal active area width
hs_s - horiz. sync start
hs_e - horiz. sync end
hs_t - total horiz. line length
vres - vertical active area height
vs_s - vertical sync start
vs_e - vertical sync end
vs_t - total vertical sync length
hound here: https://www.mythtv.org/wiki/Modeline_Database (https://www.mythtv.org/wiki/Modeline_Database)
This mode worked with my monitor, and it requires slightly less bitrate than 720p@60, so it should be easier to reach.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 05:22:48 pm
You might want to try 1080p@24Hz, which is standard HDMI mode:
Code: [Select]
pixel_clk hres  hs_s hs_e hs_t vres vs_s vs_e vs_t
74.16 1920 2558 2602 2750 1080 1084 1089 1125
pixel_clk - pixel clock frequency
hres - horizontal active area width
hs_s - horiz. sync start
hs_e - horiz. sync end
hs_t - total horiz. line length
vres - vertical active area height
vs_s - vertical sync start
vs_e - vertical sync end
vs_t - total vertical sync length
hound here: https://www.mythtv.org/wiki/Modeline_Database (https://www.mythtv.org/wiki/Modeline_Database)
This mode worked with my monitor, and it requires slightly less bitrate than 720p@60, so it should be easier to reach.
What's the format number?
These are the official DTV HDTV modes circa CEA-861-D:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1144296)

BTW, your 24hz mode is format id #32, however, if a monitor wont do the basic #34, it probably wont do #32.  Also, the pixel clock frequency is wrong.  In the  CEA-861-D specs, it should be either 74.25Mhz for 24hz, or, 74.188MHz for telecin 23.98Hz.  There is no 74.16Mhz standard.  Do not get your tech information from Wiki please...
We are achieving the 74.25Mhz fine, otherwise, Nockieboy would have seen some digital garbage with the 720p version A example.

The problems we had trying to get higher clock rates were issues with the author's home made serializing code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 05:41:50 pm
Okay, I'm trying to add audio but I'm clearly not understanding how to do it.  I'm trying to get a sawtooth waveform sent out to the HDMI audio.  This is the source I'm working from:

Code: [Select]
module sawtooth
#(
    parameter int BIT_WIDTH = 16,
    parameter int SAMPLE_RATE = 48000,
    parameter int WAVE_RATE = 480
)
(
    input logic clk_audio,
    output logic signed [BIT_WIDTH-1:0] level = BIT_WIDTH'(0)
);

localparam int NUM_PCM_STEPS = (BIT_WIDTH + 1)'(2)**(BIT_WIDTH + 1)'(BIT_WIDTH) - 1;
localparam real FREQUENCY_RATIO = real'(WAVE_RATE) / real'(SAMPLE_RATE);
localparam bit [BIT_WIDTH-1:0] INCREMENT = BIT_WIDTH'(NUM_PCM_STEPS * FREQUENCY_RATIO);

always @(posedge clk_audio)
    level <= level + INCREMENT;
endmodule

And this is how I've integrated it into top.sv:
Code: [Select]
module top (

input  logic       clk_pixel,
input  logic       clk_audio,

output logic [3:0] tmds
);

parameter int AUDIO_BIT_WIDTH = 16 ;
parameter int SAMPLE_RATE = 48000  ;
parameter int WAVE_RATE = 480      ;

parameter BIT_WIDTH   = 12 ;
parameter BIT_HEIGHT  = 11 ;
parameter FONT_WIDTH  = 8  ;
parameter FONT_HEIGHT = 16 ;

localparam int  NUM_PCM_STEPS = (AUDIO_BIT_WIDTH + 1)'(2)**(AUDIO_BIT_WIDTH + 1)'(AUDIO_BIT_WIDTH) - 1;
localparam real FREQUENCY_RATIO = real'(WAVE_RATE) / real'(SAMPLE_RATE);
localparam bit  [AUDIO_BIT_WIDTH-1:0] INCREMENT = AUDIO_BIT_WIDTH'(NUM_PCM_STEPS * FREQUENCY_RATIO);

logic [15:0] audio_sample_word [1:0] = '{ 16'sd0, 16'sd0 } ;
logic signed [AUDIO_BIT_WIDTH-1:0] level ;

always @(posedge clk_audio) begin

  audio_sample_word <= '{ level + 16'sd1, level - 16'sd1 } ;
  level <= level + INCREMENT;
 
end

I think the issue is with setting audio_sample_word - don't think I'm doing it right.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on January 03, 2021, 05:46:26 pm
BTW, your 24hz mode is format id #32, however, if a monitor wont do the basic #34, it probably wont do #32.  Also, the pixel clock frequency is wrong.  In the  CEA-861-D specs, it should be either 74.25Mhz for 24hz, or, 74.188MHz for telecin 23.98Hz.  There is no 74.16Mhz standard.  Do not get your tech information from Wiki please...
Did you miss the part where I said "it works with my monitor"?
And that is not a standard wiki either.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on January 03, 2021, 05:51:14 pm
I think the issue is with setting audio_sample_word - don't think I'm doing it right.
I noticed you generate audio signal using different clock from the one used for serialization - are you sure there are provisions inside your HDMI component for proper CDC?
There are great many audio formats, but standard PCM uses unsigned format with middle values being zero, so for 16 bit samples 0x7fff/0x8000 is zero, 0xffff - maximal positive value, 0 - minimal negative value.
Quote
16'sd1
What is this?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 05:59:27 pm
I think the issue is with setting audio_sample_word - don't think I'm doing it right.
I noticed you generate audio signal using different clock from the one used for serialization - are you sure there are provisions inside your HDMI component for proper CDC?
There are great many audio formats, but standard PCM uses unsigned format with middle values being zero, so for 16 bit samples 0x7fff/0x8000 is zero, 0xffff - maximal positive value, 0 - minimal negative value.
Quote
16'sd1
What is this?
The author of the original code used 16'sd1 which means assigning a 16bit signed decimal value of 1.  I guess he did it this way since when he defined the 'logic'  he did not know he could have stated 'logic signed'...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 03, 2021, 06:06:32 pm
Original author code for mute audio:
Code: [Select]
logic [15:0] audio_sample_word [1:0] = '{ 16'sd0, 16'sd0 } ;

always @(posedge clk_audio) begin

  audio_sample_word <= '{ audio_sample_word[0] + 16'sd1, audio_sample_word[1] - 16'sd1 } ;
 
end
Get rid of:
audio_sample_word <= '{ audio_sample_word[0] + 16'sd1, audio_sample_word[1] - 16'sd1 } ;

just add these 2 lines:
audio_sample_word[0] <= audio_sample_word[0] + INCREMENT;
audio_sample_word[1] <= audio_sample_word[1] + INCREMENT;

And change:
logic [15:0] audio_sample_word [1:0] = '{ 16'sd0, 16'sd0 } ;
to:
logic signed [15:0] audio_sample_word [1:0] = '{ 16'sd0, 16'sd0 } ;

This should make a buzz.


Code: [Select]
logic signed [15:0] audio_sample_word [1:0] = '{ 16'sd0, 16'sd0 } ;

always @(posedge clk_audio) begin

audio_sample_word[0] <= audio_sample_word[0] + INCREMENT;
audio_sample_word[1] <= audio_sample_word[1] + INCREMENT;
 
end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2021, 06:59:23 pm
Nope - still not getting any sound.  I've attached my test project as I'm not convinced it isn't something I've done.  I've got to tap out for tonight now, but will continue to plug at this during the week.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2021, 04:48:22 am
Nope - still not getting any sound.  I've attached my test project as I'm not convinced it isn't something I've done.  I've got to tap out for tonight now, but will continue to plug at this during the week.
Test 1, go to the 'audio_clock_regeneration_packet.sv', line 41/42 and replace 41 disabling 42.
Then undo the above localparam change.  Though Quartus 9.1 doesn't like the 'real', the newer ones do.
Let me know if this works.  If it does, I think I will re-write the line properly getting rid of that annoying 'real' as some versions of Quartus don't like multiplying by tiny fractions in the middle of everything.

I do not like how Quartus's parameter handles the 'real' term as it cannot be used in the same way as Q9.1.

I do not like the newer Quartus relying on Modelsim to simulate your design.  Modelsim is a great tool for simulating code, however, it does not reflect any mistakes/differences Quartus' compiler may make when it compiles the same code and it does not do proper timing simulations down to the FPGA fabric like the old Q9.1 with the older FPGAs.  :(  The old simulator simulated the actual final compiled fabric giving a dead on output, not a gate level simulation with timing approximation by a third party simulation tool.

(Also, the code you sent me no longer has the patches for 1080p @ 30Hz)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2021, 07:45:54 am
Here you go.
Try to erase all the other old projects as they differ in revisions.
And I cleaned up some of the stuff.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2021, 10:42:39 am
Here you go.
Try to erase all the other old projects as they differ in revisions.
And I cleaned up some of the stuff.

All good - 480p output with audio tone.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2021, 10:48:50 am
Ok, it's that " real' " in the localparam in the audio section.  I'm going to fix it so that the " real' " isn't needed.

Do a test for 720p.
Remember that we lie to the 'altlvds_tx', but you will find that out quick.
Make the PLL as close to 74.25MHz otuput as possible.
Recompute the needed video frame rate.
Remember, 720p is not 60fps exactly, I have listed the proper output frame rates and you need to calculate the error/change so the audio scheduler can send the right number of packets.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2021, 11:15:31 am
Give this V2 a test.
Still 480p.  No 'real' used anywhere in the localparams.
If it works, try it at 720p.
Then, get onto a new master CV video card with the first most important DDR3 interface.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2021, 12:19:00 pm
Give this V2 a test.
Still 480p.  No 'real' used anywhere in the localparams.
If it works, try it at 720p.
Then, get onto a new master CV video card with the first most important DDR3 interface.

Works nicely - also in 720p.  Have attached the project running in 720p mode as I've added a couple of parameters to top.sv, so that the screen mode can be changed from the schematic page and PLL without having to go into top.sv to change code/values within.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2021, 12:44:19 pm
Ok, let's see a DDR3 controller.
Remember to use the CV in the project, except use a -7 as we will slightly overclock the -8.
Remember, we will want to enable ODT (On Die Termination) in the DDR3 chip.
Also, 2 or 3 ram ports would be nice.

We also know the minimum allowed clock frequency for the DDR3 is 303MHz & you will have a source oscillator clock of 27MHz.  Though many large fractional divisions are possible, smaller whole numbers are preferred.  2 targets for the ram controller would be 27*12=324MHz.  This should just make it as 303MHz was guaranteed by Intel with any CV chip.  Funny how all speed grade versions of the CV, -8, -7, -6 all have the same limit, yest with the IO speed and LVDS, all 3 increase in speed according to the data sheet.  Intel's speed grades are BS.  Somehow their DDR3 controller bypasses the IO's limitations on the -8 chip.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2021, 01:15:57 pm
Get cracking on the DDR3...
You got maybe 2-3 months left to get your new PCB built and functioning enough to begin working on your own...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 06, 2021, 10:00:46 am
Though this hasn't altered our current project's functionality, this patch for the 'audio_clock_regeneration_packet.sv' > 'real < workaround fixes a rounding error with the multiply of 1.1 so that it works exactly how the original author intended.

New lines 42 & 43.
Code: [Select]
// This parameter works around the >'real < bug in Quartus versions prior to Quartus v12.
localparam int CYCLE_TIME_STAMP_COUNTER_WIDTH = $clog2(20'(int'((VIDEO_RATE * int'(N) / 128 / (AUDIO_RATE/1.1)) ))); // Account for 10% deviation in audio clock

Please update all your source files.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 08, 2021, 02:54:41 pm
Ok, here is the latest HDMI encoder with audio support.
This version has uses the Altera's altlvds_tx serializer & has the following parameters:
Code: [Select]
    // Set to 1 to activate the external clk_pixel_x5 input.
    // Set to 0 to automatically internally generate a PLL for the TMDS TXD clock.
    // Using 0 will usually use an additional PLL if Quartus cannot merge the required clock with an existing external PLL.
    parameter bit  USE_EXT_PLLx5 = 1'b1 ;

    // Tells the ALTLVDS_TX serializer what the approximate source pixel clock is.  Only needs to be within 1 MHz.
    // Only used when USE_EXT_PLLx5 is disabled.
    // You may lie here and state your pixel clock is only 74MHz or 64MHz allowing compile for -7/-8 Cyclone FPGAs
    // while still truly running a 74.25MHz pixel clock, 742.5mbps when using either LVDS or emulated LVDS_E_3R IO standard.
    parameter int PIXEL_MHZ = 27,

    // Invert the TMDS channels, 0 thru 2, and 3 for the clock channel.
    // IE - Swaps the +&- pins of the LVDS output pins for ease of PCB routing.
    parameter bit INV_TMDS0 = 1'b0,
    parameter bit INV_TMDS1 = 1'b0,
    parameter bit INV_TMDS2 = 1'b0,
    parameter bit INV_TMDS3 = 1'b0,


The changes were done in the original GitHub's 'hdmi.sv' and saved as a new source file 'hdmi_altlvds.sv'.
Video mode #34, 1080p@29.97Hz, 74.25MHz pixel clock  was added to the supported video mode list.
Also, a pure sine wave 1KHz test audio tone was added with the generator source code 'Sine_1KHz_16b_48ksps.sv'.

Nockieboy, Please let me know if this works.

If good, there are 2 other changes I want to add after looking into getting a DDR3 controller going.
1.  An improved audio sample input section which doesn't rely on a 48KHz PLL output which causes clock domain problems between the pixel clock and audio clock.
2.  Make this generator able to in-system software switch between all the video modes & have the PLLs automatically re-configure.

Download the attached project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 08, 2021, 03:56:52 pm
Works perfectly.  :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 12, 2021, 11:39:34 pm
Don't suppose I could ask for a quick bit of help with this Verilog, please?

What I'm trying to do is create an array of bytes which the module sends via an SPI module.  Worked fine with a parameter array set in the block schematic.  But now I'm trying to make the array more flexible, so I can set the values of the bytes and the number of bytes to transmit whilst the HDL is running.  Now I'm hitting a block - it's probably because I don't understand the arrays well enough.

I'm trying to copy the parameter array init_cmds into the cmd_queue during reset, so the module can pass those bytes out to the SPI tx module when it comes out of reset.  Problem is, it's not working and I'm likely just getting garbage transmitted.  I've tried simulating (using Quartus II, not Modelsim), but can't seem to get the cmd_queue register to appear in the simulation as it's probably getting compiled out or something.  Not getting any errors on compile, though.

The key lines (I think) are these (taken out of context):

parameter int max_cmds                 = 32                ; // maximum command_queue length
parameter int num_init_cmds            = 2                 ; // no. of initial commands in queue  **** this is actually 12, set in the Block Schematic
parameter int init_cmds[num_init_cmds] = '{ 8'h00, 8'h00 } ;    **** again, this has 12 bytes set in the Block Schematic

logic [7:0] cmd_queue[max_cmds] ;
logic       num_queue  = 0      ;

cmd_queue[0:(num_init_cmds - 1)] <= init_cmds[0:(num_init_cmds - 1)] ;
num_queue   <= num_init_cmds ;

tx_data  <= cmd_queue[cur_cmd] ;

Full code below:
Code: [Select]
/*
 * Simple USB interface control module to test the MAX3421E USB chip
 *
 * J.Nock 2021
 */

module control (

   input logic        clk,
   input logic        reset,     // active LOW
   input logic        gpx,
   input logic        m_int,
   input logic  [7:0] rx_data,
   input logic        done,
   input logic        KEY1,      // user buttons, active LOW
   input logic        KEY2,
   input logic        KEY3,
   input logic        KEY4,
   
   output logic       start,
   output logic [7:0] tx_data,
   
   output logic [7:0] LED_1,     // EasyFPGA-specific 7-segment display to
   output logic [7:0] LED_2,     // show read values from SPI
   output logic       LED_3      // USB connection detection LED

);

parameter int max_cmds                 = 32                ; // maximum command_queue length
parameter int num_init_cmds            = 2                 ; // no. of initial commands in queue
parameter int init_cmds[num_init_cmds] = '{ 8'h00, 8'h00 } ;

logic [7:0] rx_buff1   = 8'b0   ;
logic [7:0] rx_buff2   = 8'b0   ;
logic [3:0] cur_cmd    = 0      ; // current command in pipeline (max 16)
logic       old_done   = 1'b0   ; // edge-detect for done signal
logic       tx_done    = 1'b0   ; // tx_done flag so commands is only sent once
logic       buff_swtch = 1'b0   ; // when buff_swtch is HIGH, record Rx'd data (this ignores data Rx'd during CMD transmission)

logic       old_int    = 1'b0   ;
logic [7:0] cmd_queue[max_cmds] ;
logic       num_queue  = 0      ;
logic       int_req    = 1'b0   ;
logic       conn_LED   = 1'b1   ; // LOW to light LED for connection events

wire        int_edge   = ( !old_int && m_int ) ; // int_req goes HIGH on posedge of m_int

always @( posedge clk ) begin

   LED_1   <= rx_buff1 ;
   LED_2   <= rx_buff2 ;
   LED_3   <= conn_LED ;
   old_int <= m_int    ; // update m_int edge detector
   
   if ( int_edge ) begin // interrupt posedge detected
   
      //int_req <= 1'b1 ; // set int_req flag
     
   end
   
   if ( !KEY1 || !reset || !gpx ) begin
     
      cmd_queue[0:(num_init_cmds - 1)] <= init_cmds[0:(num_init_cmds - 1)] ;
      num_queue   <= num_init_cmds ;
      old_done    <= 1'b0  ;
      rx_buff1    <= 8'b0  ;
      rx_buff2    <= 8'b0  ;
      cur_cmd     <= 3'b0  ;
      tx_done     <= 1'b0  ;
      tx_data     <= 8'b0  ;
      start       <= 1'b0  ;
     
   end
   else if ( int_req && tx_done ) begin // MAX3421E is requested our attention and we're not transmitting on SPI
   
      int_req <= 1'b0 ; // reset int_req flag
     
      /* TODO:
       * 1) Read R25
       * 2) Check bits we want to action (b5 initially for CONDETIRQ)
       * 3) Update an LED on the dev board
       */
     
      conn_LED <= !conn_LED ; // Switch on/off the LED to show an event was detected
     
      // 4) Write a 1 to b5 in R25 to ack the int
      /*cmd_queue[0] <= 202   ; // Write to R25
      cmd_queue[1] <= 32    ; // Set b5 (CONDETIRQ) to 1 to reset it
      num_queue    <= 2     ; // 2 commands in the queue
      cur_cmd      <= 3'b0  ;
      tx_done     <= 1'b0  ;*/
   
   end
   else begin // reset & gpx HIGH
      // Buffer RX'd data if done goes HIGH,
      // otherwise keep old_done LOW
      if ( old_done && !done ) begin // negedge detected for done signal
         
         if ( buff_swtch ) begin
         
            rx_buff1 <= rx_data  ; // buffer the received data
            rx_buff2 <= rx_buff1 ;
           
         end
         old_done   <= 1'b0        ;
         buff_swtch <= !buff_swtch ;
         
         if ( cur_cmd < num_queue ) begin
           
            tx_done <= 1'b0 ; // reset tx_done to send next byte
           
         end
         else begin // EOL
           
            tx_data  <= 8'b0 ; // end of transmission - last byte sent
            tx_done  <= 1'b1 ; // one-shot stays high to prevent more bytes being
            cur_cmd  <= 3'b0 ; // transmitted but everything else is reset
            start    <= 1'b0 ;
           
         end
         
      end
      else begin
         
         old_done  <= done    ;
         
      end
     
      if ( !tx_done && ( cur_cmd < num_queue ) ) begin // if cmd hasn't been sent already and cmd isn't 0
         
         tx_data  <= cmd_queue[cur_cmd] ;
         start    <= 1'b1               ;
         tx_done  <= 1'b1               ;
         cur_cmd  <= cur_cmd + 1'b1     ;
         
      end
      else if ( !tx_done && ( cur_cmd == num_queue ) ) begin // reached end of commands array
         
         tx_data  <= 8'b0 ;
         start    <= 1'b0 ;
         cur_cmd  <= 3'b0 ;
         
      end
      else begin
         
         start    <= 1'b0   ; // make start a one-clk pulse
         
      end
   
   end // reset & gpx high
   
end

endmodule


EDIT: No matter, fixed it by referring back to our HW_REGS code in the GPU project. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2021, 08:58:14 am
Here is the latest version of Geo_ellipse.
Finally, everything is 100% Systemverilog with an authentic fully featured Modelsim testbench.

Good with Quartus 13 & up.  Just open the project and do a 'Start Analisys and Synthesis', then run simulation tool 'RTL simulation'.  Everything should startup automatically.  Or, you can manually add the files to your own Modelsim project.

This testbench has been setup for RTL simulation only.

From within Modelsim, to reset the simulation, quick re-compile and rerun the simulation type/run script:
do ../../ellipse_rerun_rtl.do

The text file 'ellipse_commands_in.txt' contains the simulation drawing coordinates.
The format is as follows:
Filled <0,1>, Quadrant<0,1,2,3>, Xcenter<signed#>, Ycenter<signed#>, Xradius<unsigned#>, Yradius<unsigned#>

The testbench will run as many commands you list in in the .txt file.
After simulation, all the generated ellipse's coordinates will be stored in:
ellipse_generated_results.txt
as well as full logic waveform in the wave display.

Be gentle, this is my first semi-extravagant use of a testbench file & modelsim.

@Nockieboy, I found a few harmless coding issued in the original source 'ellipse_generator.sv' which I patched.  You might as well update the main GPU with this new file.

(Update coming in next post.  Stand-alone Model-sim project, Don't need to run Quartus, just Modelsim.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2021, 01:29:30 am
Ok, here is the stand-alone Modelsim Ellipse Generator project.

Code: [Select]
* To setup simulation,Start Modelsim, The goto 'File - Change Directory' and select this files directory.
 * Then, for altera users, in the transcript, type:
 * do setup_altera.do
 *
 * For non-altera users, just type:  (This one is fine for altera users as well.)
 * do setup.do
 *
 * To run the simulation, (also does a quick recompile) type:
 * do run.do

No Quartus needed.

File 'ellipse_commands_in.txt' contains the draw commands.  Instructions inside the file.
Yes, the test bench reads and extracts commands from an ascii test file and renders the results by injecting the commands while simulating the HDL.  The 'do run.do' recompiles any changes in any of the source files and runs again.  After the sim has stopped, manually injecting commands will work, but those commands will no longer be added to the output files.  Breaking/stopping a simulation early during the run & changing core registers, then continuing will effect the output files during that run.

Generated file 1 'ellipse_generated_results.txt' has a table of the rendered coordinates from the rendered commands inputs.

Generated file 2 'ellipse_generated_bitmap.bmp' has a picture of the rendered ellipse command inputs.
(Yes, you are reading right, I got Modelsim rendering a raster .bmp picture file directly from a simulation.)

For Xilinx or generic modelsim users who might want to try, this should work with any vendor's modelsim.  Instead of executing the 'do setup_altera.do', just execute 'do setup.do' as this project doesn't use any altera dedicated functions.  Once setup, the 'do run.do' will still setup and run the simulation properly.

Let me know if the bitmap show properly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2021, 01:53:20 am
Next, simulation of the full Geometry unit with a text script file describing the commands by name.

-Wave output on the simulator.
-Text out log file of the command being executed with ns position on the wave, pixel xy coord out, color, pixel address out, ect as a spreadsheet.
-Second text file with the pixel memory writer's access read and write operations.
-Import of ram and font file from existing GPU so that we can simulate blitter texting and transparency functions.
-Incremental additional commands in the middle of the simulation without restarting.
-and finally a bitmap picture rendered after each new added command to see what's going on.

With this, who needs a Z80 or GPU PCB...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2021, 02:38:13 am
Ok, I cleaned up and finalized the HDMI encoder with a new automatic PLL generator module.
Everything is documented here: https://www.eevblog.com/forum/fpga/hdmi-dvi-encoder-with-audio-smart-quartus-pll-integration-in-systemverilog/msg3430622/#msg3430622 (https://www.eevblog.com/forum/fpga/hdmi-dvi-encoder-with-audio-smart-quartus-pll-integration-in-systemverilog/msg3430622/#msg3430622)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 27, 2021, 11:08:23 am
Latest Cyclone V GPU schematics attached.  Have had a little time to go through them and update the video output to the current DVI/HDMI output and removed the VGA out to make some space on the PCB for the USB interface, which I'm still working on (slowly!)

I haven't connected up the DVI/HDMI to the FPGA yet, as I haven't really got much of an idea where I'll be connecting the DDR3 to, so I suspect there may be some alterations required to the existing connections without adding more until that's finalised.

Particular attention is needed on the last page and power supplies - I'm starting to think about connections between the SDRAM and the FPGA and I suspect I need to connect up some termination resistors somewhere, somehow?  Also, the DDR3 needs a reference voltage - how would be best to supply this?  Will it mean another power supply on the board?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on January 27, 2021, 09:14:05 pm
Particular attention is needed on the last page and power supplies - I'm starting to think about connections between the SDRAM and the FPGA and I suspect I need to connect up some termination resistors somewhere, somehow? 
As a rule of thumb, you only need dedicated termination if your traces are "electrically long", which means the length is a significant fraction of wavelength ("the magic number" is 10-15%). For 400 MHz, wavelength is 60 cm, so you will need to worry about termination if your traces are longer than 60-90 mm. Practically this means that if you only use a single DDR3 memory device and it's physically close to FPGA, your traces will most likely be shorter than that.
That said, you've got to treat these rules of thumb for what they are, and as such if in doubt I normally run board level simulations to figure out if I need termination, and if so, what is the best value for it. Even if you won't have any termination for address/control lines, you still should have differential termination for the clock line (typically it's a 100 Ohm resistor between + and - traces) as close to the receiver pins (memory device) as possible. I always use a 0402 resistor which is placed under memory chip right next to breakout vias which go to the top layer to the clock balls. This way I minimize the stub length.
What makes or breaks DDR3 interface is a layout. Here are few rules that need to be observed:
1. adjacent traces are at least 2H away from each other (where H - distance between a trace and a reference plane), and at least 1H in breakout regions (under BGAs as typically there is not enough space for 2H spacing).
2. reference plane(s) MUST be contiguous and should not have any cutouts under all DDR3-related traces. Again, this is not always possible under BGA, but do your best to satisfy this. Breaks in reference plane leads to BIG impedance discontinuity of traces (~50 Ohm to 80-90 Ohm) and causes signal reflections.
3. Clock lines have to be the longest traces among all DDR3 traces. See attached picture ("borrowed" from IMX6 datasheet) for all length matching rules. If the datasheet/user guide/application note for your FPGA calls for different tolerances, you them instead of what I posted.
4. Each additional transition between signal layers causes impedance breaks too, so minimize layer changes for data traces. Try your best to limit them to a single via on each end (in breakout regions of memory device and FPGA).

Also, the DDR3 needs a reference voltage - how would be best to supply this?  Will it mean another power supply on the board?
There are devices designed specifically for this task - for example TPS51200. But in your case you can likely get away using a simple resistive divider - two 1K resistors with parallel 10nF filter caps, as well as a single 1uF decoupling cap between a midrail and the ground. At least that's how I've been doing it, and so far all my DDR2/3/3L interfaces always worked from the first revision. Just make sure this midrail is away from noisy traces.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 29, 2021, 12:41:45 am
Hi Nockieboy,

     I engineered a nice complete SystemVerilog test-bench scripting & now a BMP saver which can support any resolution.  It's now wired up to the ellipse generator and operates on decoding any commands in the source script ascii file.  This is 3/4 the work necessary to running/driving a simulation of your entire geometry unit's processing as all the leg work of decoding commands and calling tasks to drive the inputs can now be added.

    I placed the ellipse standalone version here to take a look at:

https://www.eevblog.com/forum/fpga/systemverilog-example-testbench-which-saves-a-bmp-picture-and-executes-a-script/msg3436876/#msg3436876 (https://www.eevblog.com/forum/fpga/systemverilog-example-testbench-which-saves-a-bmp-picture-and-executes-a-script/msg3436876/#msg3436876)

    Please let me know if the script setup is adequate before I paste in the full geometry unit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 02, 2021, 11:25:20 am
I'm trying to make a determined start on the DDR3.  :o

Please bare in mind that my electronics experience with RAM so far has been limited to 128KB & 512KB SRAM DIP and SOIC chips (these ones (https://www.mouser.co.uk/datasheet/2/12/AS6C4008-1265427.pdf)).  My knowledge and comfort zone extends to parallel 8-bit data, 16-bit address buses and no more additional complexity than RDn, WRn and CSn signals.  So when I say the DDR3 controller in Quartus looks complicated, and the DDR3 datasheet is gobbledegook, I really mean: :scared:  |O :'(  :wtf: :horse:

The way I would approach this task is to do what I'm trying to do currently - do the schematic and board layout, worry about the HDL after.  I think the DDR3 itself is wired okay and has sufficient decoupling - it certainly follows other published designs - I just need to sort termination and some reference voltage pull-ups to some of the data lines, or something? :-//

I'm trying to connect it up to the FPGA - you know, make progress in an area I think I can actually do something, but I've stopped here because it's likely I'm supposed to get the DDR3 controller up and running first, then let Quartus decide which pins the signals are going to be routed to.  Anyway, I've attached a PDF showing the current state of the DDR3 and the FPGA's current free pins.

So I'm looking at Banks 4A and 5B as potential candidates to connect the DDR3 to... is that right?  That would leave 4A for the DVI/HDMI output.  Or I could swap Bank 5A to 5B and use 5A for the DDR3?  I'm looking to place the DDR3 chip in the bottom-right corner of the FPGA on the board. Hopefully.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 02, 2021, 10:07:18 pm
Setting up a controller first is a right way to go because you can't just connect DDR3 chip to random FPGA pins and hope it will work. This applies to most high-speed interfaces, not just DDR3.

That said, I wish I could help you with setting it up, but I know nothing about Altera's IP, how it works and what kind of pinout restrictions does it have.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 04, 2021, 03:27:51 pm
Ok, here is the complete GEOMETRY unit test-bench.  After all this work, I found some hidden errors in the blitter unit, so this post also includes a full update to the 'GPU_EP4CE10' project.  Please test and let me know if it works as a numerous minor 'invisible' glitches/bugs were uncovered and patched.

For the geometry test-bench, it is a stand-alone SystemVerolog project which you only need ModelSim running to run.  Just un-zip the 'GPU_GEOMETRY_Testbench_v1.0.zip', open ModelSim, select 'File - Change Directory...', then type in the transcript:
do setup.do    > sets up ModelSim
do run.do       > Re-compiles & runs the test-bench executing the default 'GEO_tb_command_list.txt'.

The results should be:
1.  A waveform with the Script_CMD and LINE# showing you all the generated waveforms.
2.  Three  .bmp pictures.
3.  A log file 'GEO_tb_command_results.txt' showing you the sent commands.

Geometry command list in the ascii .txt file:
Code: [Select]
******************************************************************************************************************
Commands: (*** No spaces allowed in any <FILE_NAME>)

[at]LOG_FILE  <FILE_NAME>            > Generates a results log file.         (No spaces allowed in file name).
[at]END_LOG_FILE                     > Forcefully closes/ends the log file.
[at]STOP                             > Stops the script processing/simulation.  Click on 'run -all' to continue script after the stop command.
[at]END                              > Ends the script processing/simulation. (You may now paint/set youw own manual controls in the waveform view and run -all)

[at]LOAD_GPU_RAM <file_name.bin>     > Reads a binary file, up to 1 megabyte, into the GEO pixel-writer memory. 
[at]SAVE_GPU_RAM <file_name.bin>     > Saves GEO pixel-writer 1 megabyte memory into a binary file.
[at]CLR_GPU_RAM                      > Clears the GPU memory

[at]CLR_BMP      <color_byte>        > Clears the test geometry_plotter bitmap memory to a set byte.  (This is not the pixel writer)

[at]SAVE_GEO_BMP   <FILE_NAME> <width> <height> <1=B&W>            > Saves a 256 color BMP picture of the geometry_plotter's output, NOT GPU Ram. Max 2048x2048.  <1=B&W> or 0 for dummy 256 color palette
[at]SAVE_PIXIE_BMP <FILE_NAME> <src/dest> <width> <height> <1=B&W> > Saves a 256 color BMP picture of the pixie-writer system GPU memory. SET_PAGET settings must be set & PIXIE must be enabled prior to draw commands.  <1=B&W> or 0 for dummy 256 color palette

[at]RESET                            > Sends a reset to the geometry unit.
[at]ENA_PIXIE <0/1>                  > Enables/disables pixel writer.  (Pixel writer is disabled by default)
[at]WAIT_IDLE <0/1>                  > Waits for the all processes to finish whatever they are currently doing before running next command. IE 1 command at a time.

[at]SEND_CMD <h0000-hFFFF>           > send a raw command, 16 bit hex value

[at]SET_XY  <x/y> <0..3> <decimal>                             > Sets 12 bit register X or Y with 12 bit decimal value 0-4095, basically calls SEND_CMD with the right value.
[at]SET_PAGET <src/dest> <base_address_hex> <width> <depth>    > Sets PAGET's (pixel address generator) source/dest   memory address, image width, color depth in bits/pixel = (1/2/4/8/16).
[at]SET_MAX_XY <x>   <y>                                       > Sets the maximum destination XY resolution.

[at]DRAW PIXEL <X>   <Y>   <c>                                          > Draws a dot at coordinates [XY], c=color(0..255)
[at]DRAW LINE  <aX>  <aY>  <bX>  <bY>  <c>                              > Draws a line from coordinates a[XY] to b[XY].
[at]DRAW BOX   <aX>  <aY>  <bX>  <bY>  <c>   <f>                        > Draws a box from top left a[XY] to bottom right b[XY] coordinates. f=fill(0/1)
[at]DRAW TRI   <aX>  <aY>  <bX>  <bY>  <cX>  <cY>  <c>   <f>            > Draws a triangle with coordinates [abc][XY].
[at]DRAW QUAD  <tlX> <tlY> <trX> <trY> <brX> <brY> <blX> <blY> <c> <f>  > Draws a quadrilateral, tl=Top Left, tr=Top Right, br=Bottom Right, bl=Bottom Left.
[at]DRAW ELLI  <Xc>  <Yc>  <Xr>  <Yr>  <c>   <q>   <f>                  > Draws an ellipse. Q=Quadrant.
                fill     = 0/1
                Quadrant = 0-3 to draw 1 of 4 quadrants.
                Quadrant = 4   to draw all 4 quadrants.

**** BLITTER must have PAGET (SRCE/DEST) set to function.

[at]BLIT TCOL  <transparent_color>         > [0.255]  Selects which color in the source image will be transparent when doing a paste when paste mask is enabled.
[at]BLIT SIZE  <px> <py> <width> <height>  > Sets the source image top left pixel position (px,py) and the copy (width,height) in pixels.
[at]BLIT ZOOM  <usX> <usY> <dsX> <dsY>     > Sets blitter zoom, us=upsample   float X/Y zooms up the SRCE image copy input   1.000000 to 4095.00000. (12 bit granularity)
                                                                ds=downsample float X/Y shrinks  the DEST image paste output 1.000000 to 0.000245.   (12 bit granularity)

[at]BLIT CONFIG  <ena>  <mask> <h-centp> <mirror> <v-centp> <flip> <r90>  <r45>

         ena       = blitter off/on             1 = blitter on when writing pixels.
                                                0 = blitter off when writing pixels.
         mask      = Transparancy mask enable.  1 = source transparent color pixels will not paste pixels onto destination, IE those colors are transparent.
                                                0 = Every pixel from the source will paste onto the destination.
         h-centp   = horizontal center paste.   1 = Offset the paste to the left by half of blit_width.
                                                0 = Use the paste coordinates as the beginning left.
         mirror    = Horizontal mirror paste.   1 = Mirror the output on the X axis.
                                                0 = Off.
         v-centp   = Vertical center paste.     1 = Offset the paste up by half of blit_height
                                                0 = Use the paste coordinates as the beginning top of the paste
         flip      = Vertical flip paste.       1 = Vertically flip the output on the Y axis.
                                                0 = Off
         r90       = Enable Rotate 90 degree.   1 = Swaps the X&Y coordinates on the paste.
         r45       = Enable Rotate 45 degree.   1 = Increments/decrements the X&Y coordinates on the paste in unison.


[at]VWAIT  <#of frames> <video line#>        > Pause geometry processor until the #frames and video line# has been reached.
           Frames = 1 thru 15, 0 = no wait
           line   = 0 thru 255               > (There is a hidden multiplier for line (1,2,4,8) to support video modes up to 2040 lines.  Not supported in this demo.)

*****************************************************************************************************************


After the 'do run.do', you may execute the other example command scripts by typing:
Code: [Select]
do test_8bitfont.do
do test_45deg.do              > Takes ~1 minute to simulate...
do test_art.do
do test_blitter.do
do test_blitter_hires.do      > Takes ~1 minute to simulate...
do test_vwait.do


The above 'do test_****.do' only change the 'TB_COMMAND_SCRIPT_FILE' parameter to a new source script filename, then a 'restart -f', then a 'run -all' to run the simulation.

If everything works OK, this will end any additions to the current Geometry unit.  The next version will be separated into 4 blocks, operate with 16bit X&Y coordinates with a 32/64 bit opcode while the pixel address generator and pixel writer will need upgrading to 32bit addressing, 32 bit color support and 256bit data bus for the ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 04, 2021, 07:23:30 pm
Ok, here is the complete GEOMETRY unit test-bench.  After all this work, I found some hidden errors in the blitter unit, so this post also includes a full update to the 'GPU_EP4CE10' project.  Please test and let me know if it works as a numerous minor 'invisible' glitches/bugs were uncovered and patched.

Hidden errors? Anything interesting, or the kind that don't make any material difference to the output?  I've tested the new project on the hardware - works fine, can't detect any problems with my test software.  :-+

Will test the geometry test bench as soon as I'm able.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 04, 2021, 09:16:34 pm
Hidden errors like when you scale/zoom/enlarge the output, an extra line/pixel of graphics appear on the right and bottom of the output paste which is only 1 pixel wide while when you shrink the output, the first line and pixel along the top left is sometimes missing.  (What was going on is that the last line an pixel in the set width and height of the source bitmap wasn't being enlarged/zoomed, so it became only a single pixel thick even if you has the zoom set to 25x.)

There are also some issues with rotate 45 degrees and 90 de degrees simultaneously.  The 90 degrees moved the object onto a different quadrant, but, didn't actually turn it around, same issue with the mirror and flip.  Though, rotate 90 combined with a mirror & flip did work properly.

Also, the 45 had a jitter checkerboard in the output, always.  Right now, the checkerboard pattern is fixed so long as the paste scale is 1:1.  I cannot do much when simultaneously scaling and rotating at 45 degrees, so, your current solution is scale the source image, then do a 1:1 45 degree rotate.  This is something which needs a re-work of the blitter engine to fix properly, so I will not touch and doing it with 2 passes will need to be how it's done for now, or live with a speckle pattern along lines in the 45 degree pasted results.  Working without 'true color' is also a factor as I cannot smooth pixels unless the scale factor zoom enlarge settings always covers more than 4 pixels.

As for hidden errors, sometimes when writing pixels, depending on the next command, the GEO unit was sending a pile of write pixels of the last pixel in the drawing command.  Nothing you would see in the output as all the writes were correct, but, a waste of memory access.  Though, after drawing a line, writting 4 of the same pixels at 125MHz, I doubt your Z80 could ever be programmed to detect that...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 05, 2021, 03:58:16 am
I'm trying to make a determined start on the DDR3.  :o

Please bare in mind that my electronics experience with RAM so far has been limited to 128KB & 512KB SRAM DIP and SOIC chips (these ones (https://www.mouser.co.uk/datasheet/2/12/AS6C4008-1265427.pdf)).  My knowledge and comfort zone extends to parallel 8-bit data, 16-bit address buses and no more additional complexity than RDn, WRn and CSn signals.  So when I say the DDR3 controller in Quartus looks complicated, and the DDR3 datasheet is gobbledegook, I really mean: :scared:  |O :'(  :wtf: :horse:

The way I would approach this task is to do what I'm trying to do currently - do the schematic and board layout, worry about the HDL after.  I think the DDR3 itself is wired okay and has sufficient decoupling - it certainly follows other published designs - I just need to sort termination and some reference voltage pull-ups to some of the data lines, or something? :-//

I'm trying to connect it up to the FPGA - you know, make progress in an area I think I can actually do something, but I've stopped here because it's likely I'm supposed to get the DDR3 controller up and running first, then let Quartus decide which pins the signals are going to be routed to.  Anyway, I've attached a PDF showing the current state of the DDR3 and the FPGA's current free pins.

So I'm looking at Banks 4A and 5B as potential candidates to connect the DDR3 to... is that right?  That would leave 4A for the DVI/HDMI output.  Or I could swap Bank 5A to 5B and use 5A for the DDR3?  I'm looking to place the DDR3 chip in the bottom-right corner of the FPGA on the board. Hopefully.  ;)
We have gone over this topic in this thread.
Wiring up Altera controller forces you to wire all the DDR3 IOs properly.
Remember, you need 2 IO banks for enough IO.

Preferably 2 IO banks sharing connection to 1 PLL.

1 of the IO banks needs a dedicated differential PLL output pins.

The DQS lines are also differential and need to be connected to Altera's  DQSp and DQSn IOs.  There a 2 of these differential DQS lines, LDQSn/p and UDQSn/p.

The IO bank which uses the LDQS needs to have it's DQ io pins tied to DQ7:0.

The IO bank which uses the UDQS needs to have it's DQ io pins tied to DQ15:8.

Begin with this.  All the other DDR3 controls are unidirectional (FPGA -> DDR3) running at half or quarter speed latched on the rising CLK signal, so you have more flexibility with these.

You may want to configure 3 IO banks at DDR3 IO voltage levels as the other DDR3 controls maybe easier to wire with extra IO on hand.  It is still a plus to make sure the third IO bank directly connects to the same PLL driving the DDR3 clk input.

The HDMI may be driven from the same IO bank running at the same IO voltage as the DDR3 ram.  It's only 8 output right at the edge of the FPGA.  Make sure those 8 are true differential LVDS outputs.  However, with our tests on the emulated differential output on the Cyclone IV board rated at 640mbps, we know we achieved that 1080mbps speed.  This translates into the potential of running the ram error free at 540MHz instead of down at the minimum guaranteed 303MHz, but, I wouldn't hold your breath.  There would be a trade-off of ram controller complexity VS raw throughput burst.  With video, raw throughput bursts it great, but with geometry drawing commands, complexity may gain an upper edge.  (This assumes we end up using a third party or our own opensource DDR3 controller.  Going to the 484 pin CV, you get access to the dedicated HardPHY pins to control the DDR3 which has the complexity & speed, but a much more expensive FPGA and a design which cannot be compiled on a third party vendor's FPGA.)  But with a Z80 feeding the geo unit, the raw throughput means many more MAGGIE layers on the DDR3, or 32 bit true color with a few layers while the geo will still run circles around the Z80.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 06, 2021, 12:32:54 am
Do not use port 5A.  Read my post here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3335836/#msg3335836 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3335836/#msg3335836)

Go into the CV datasheet, look at the picture of the FPGA fabric layout and choose the IO banks where the DQs land on the highest FMAX in my linked post where 2 adjacent banks share a corner connection to a PLL with dedicated PLL output pins if you want the fastest possible DDR 3 controller.  Bank 5A will shove you right down to the minimum advertised limit listing from Intel of 303MHz.

Show me a snapshot of the datasheet's FPGA fabric.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 09, 2021, 01:53:19 pm
Bank 5B is looking good as it's currently completely unused, and 7A can be freed up with a little clever routing or re-placement of the audio output.  Failing that, 4A and 3B.  Going to struggle to find a third adjacent bank.   I think the top-right corner is my preferred placement for the DDR, if the FPGA's IO will allow it.

Go into the CV datasheet, look at the picture of the FPGA fabric layout and choose the IO banks where the DQs land on the highest FMAX in my linked post where 2 adjacent banks share a corner connection to a PLL with dedicated PLL output pins if you want the fastest possible DDR 3 controller.  Bank 5A will shove you right down to the minimum advertised limit listing from Intel of 303MHz.

Show me a snapshot of the datasheet's FPGA fabric.

I can't find any reference to the FPGA fabric in the datasheet?  Or anywhere else for that matter - I remember seeing something like that in the Pin Planner in Quartus, but can't seem to find how to view it again.  :-[ :-\ :(

This is a real problem for me at the moment - I've got very little spare time to work on the project and I spend most of it trying to catch up with where I was at.  :palm:

I've attached latest PCB layout, schematic showing the FPGA's free pins and the Cyclone V bank diagram from the Quartus Pin Planner, in the vain hope that some of it will be useful.  I'm running low on useable free space on the PCB now.  I can move the signals coming in the right side of the FPGA (Z80 data and control signals) up or down as necessary to try to accommodate a SDRAM on the right side.  The bottom side still needs to accommodate U3 (enough for DVI output) and U11 (enough for a SPI).  There is potential for the PS/2 to be dropped completely if my USB interface works out (still in development currently).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 09, 2021, 08:22:47 pm
Bank 5B is looking good as it's currently completely unused, and 7A can be freed up with a little clever routing or re-placement of the audio output.  Failing that, 4A and 3B.  Going to struggle to find a third adjacent bank.   I think the top-right corner is my preferred placement for the DDR, if the FPGA's IO will allow it.

Go into the CV datasheet, look at the picture of the FPGA fabric layout and choose the IO banks where the DQs land on the highest FMAX in my linked post where 2 adjacent banks share a corner connection to a PLL with dedicated PLL output pins if you want the fastest possible DDR 3 controller.  Bank 5A will shove you right down to the minimum advertised limit listing from Intel of 303MHz.

Show me a snapshot of the datasheet's FPGA fabric.

I can't find any reference to the FPGA fabric in the datasheet?  Or anywhere else for that matter - I remember seeing something like that in the Pin Planner in Quartus, but can't seem to find how to view it again.  :-[ :-\ :(

This is a real problem for me at the moment - I've got very little spare time to work on the project and I spend most of it trying to catch up with where I was at.  :palm:

I've attached latest PCB layout, schematic showing the FPGA's free pins and the Cyclone V bank diagram from the Quartus Pin Planner, in the vain hope that some of it will be useful.  I'm running low on useable free space on the PCB now.  I can move the signals coming in the right side of the FPGA (Z80 data and control signals) up or down as necessary to try to accommodate a SDRAM on the right side.  The bottom side still needs to accommodate U3 (enough for DVI output) and U11 (enough for a SPI).  There is potential for the PS/2 to be dropped completely if my USB interface works out (still in development currently).
Everything else shouldn't be wired.  The DDR3 gets absolute priority, then you can think about everything else.

Please check Cyclone V Device Handbook: Volume 1: Device Interfaces and Integration, page 216, Figure 6-8: PHYCLK Networks in Cyclone V E A2 and A4 Devices to show you the PLL connection to the banks.  You want to select IO banks which share a PLL and whose PLL has a dedicated outputs directly to one of the bank.  Make sure that your reference clock oscillator input is on a positive clock pin which goes to that PLL.  Page 206/207 shows the connections to the DQS groups and which shared DLL have direct connections.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 09, 2021, 09:21:41 pm
I know it's a bit of off-topic, but have you considering buying DECA board mentioned in the thread nearby? https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/ (https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/)
For the price, it's an absolute bargain, Among other things, it's got HDMI TX, microSD card socket, healthy 512 MBytes of DDR3 RAM, 100MBit Ethernet, USB 2.0 ULPI, audio codec, and it's got 69 digital GPIO pins on connectors, which should be more than enough to connect the rest of your system - I seem to recall you mentioned you need 63 FPGA IO pins. And, most importantly, it's got a rather large FPGA device with 50K LUTs.
I've ordered two even though I'm not really sure what I'm gonna do with them yet :-// The reason I ordered two is to get the order over $50 for free shipping, as a single board with shipping charge was actually more expensive than two boards with free shipping :-DD
I suspect the stock won't last for long, so you might want to grab one (or two :P ) while you can.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 09, 2021, 10:50:34 pm
I know it's a bit of off-topic, but have you considering buying DECA board mentioned in the thread nearby? https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for- (https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-)$37/
For the price, it's an absolute bargain, Among other things, it's got HDMI TX, microSD card socket, healthy 512 MBytes of DDR3 RAM, 100MBit Ethernet, USB 2.0 ULPI, audio codec, and it's got 69 digital GPIO pins on connectors, which should be more than enough to connect the rest of your system - I seem to recall you mentioned you need 63 FPGA IO pins. And, most importantly, it's got a rather large FPGA device with 50K LUTs.
I've ordered two even though I'm not really sure what I'm gonna do with them yet :-// The reason I ordered two is to get the order over $50 for free shipping, as a single board with shipping charge was actually more expensive than two boards with free shipping :-DD
I suspect the stock won't last for long, so you might want to grab one (or two :P ) while you can.
Other than converting 3.3v to 5v for his Z80, I would say just place a Z80 inside the FPGA and be done with it.
He can test everything on those dev boards before considering making a dedicated GPU card for 5v Z80 and 68K series.

I would like to see the code avoid HW vendor specific calls so that any of the top vendor FPGA may be used.
It's too bad about the Lattice tools, the LFE5U45 is under 16$ at digikey and it is also a 45k gate beast with over 2 megabit ram inside for 16$us, (LFE5U85 - 85kgate 4megabit for 37$, LFE5U25, 9$)  a bit more IO than the CV and a certified minimum 312MHz for DDR3, slowest -6 version, 400MHz for -8.  Cyclone is reverse, -8=slow, -6=fastest.

I've found Modelsim to be quite useful and fast when developing HDL as it recompiles and can run my test scripts within a few seconds as seen with the entire GPU's geometry test above.  I wonder which sim tool Lattice provides with their 'Diamond' environment.

Funny, with Altera, you can install their ModelSim Lite all by itself without Quartus which is what I've been using the past few weeks to make my Geometry test bench and HDMI PLL configuration code.  It would be funny to work in Altera's Modelsim just to write code for Lattice Diamond.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 12:06:41 am
Other than converting 3.3v to 5v for his Z80, I would say just place a Z80 inside the FPGA and be done with it.
He can test everything on those dev boards before considering making a dedicated GPU card for 5v Z80 and 68K series.
The most important part is that he can verify in hardware DDR3 interface on a known-good board. The user guide for the boards says it's wired for 300 MHz soft controller, which is what you guys are aiming for on CV board. Screwing up the wiring for DDR3 is the biggest risk I see for a full custom board. And as I understand, the fabric inside MAX10 is very similar to the one used in CIV-CV, so porting should not be a problem.

It's too bad about the Lattice tools, the LFE5U45 is under 16$ at digikey and it is also a 45k gate beast with over 2 megabit ram inside for 16$us, (LFE5U85 - 85kgate 4megabit for 37$, LFE5U25, 9$)  a bit more IO than the CV and a certified minimum 312MHz for DDR3, slowest -6 version, 400MHz for -8.  Cyclone is reverse, -8=slow, -6=fastest.
For Xilinx -1 is the slowest, -3 is the fastest. Some families (like Spartan-7) do not have -3 speed grade, they only have -1 and -2.

Funny, with Altera, you can install their ModelSim Lite all by itself without Quartus which is what I've been using the past few weeks to make my Geometry test bench and HDMI PLL configuration code.  It would be funny to work in Altera's Modelsim just to write code for Lattice Diamond.
I absolutely hated ModelSim that shipped with Quartus back in a day because it's artificially slowed down to entice you to upgrade into paid versions. It was a huge relief when I moved to Vivado with it's built-in simulator because it's fully-featured, not gimped down version of anything, and because how well it integrates into the IDE.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 10, 2021, 12:24:17 am
I absolutely hated ModelSim that shipped with Quartus back in a day because it's artificially slowed down to entice you to upgrade into paid versions. It was a huge relief when I moved to Vivado with it's built-in simulator because it's fully-featured, not gimped down version of anything, and because how well it integrates into the IDE.
Slowed down?  How so?  Re-compiles are almost instant.

In Xilinx, how long does it take to simulate my Geometry test-bench above running the:
GEO_tb_art.txt  script,  (Altera MS = 1 sec for 718,400 ns runtime)  (System Clk toggle rate = 100MHz)
And the
GEO_tb_45deg_zilog.txt script. (Altera MS no waveform = 25 sec for 13,851,400 ns runtime, all waveforms logged = 45sec.)

Includes the generation of the .bmp.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 12:53:18 am
Slowed down?  How so?  Re-compiles are almost instant.

Here is official info: https://www.intel.ca/content/www/ca/en/software/programmable/quartus-prime/model-sim.html (https://www.intel.ca/content/www/ca/en/software/programmable/quartus-prime/model-sim.html)
Free version has 10K executable lines limit, paid version is 33% faster.

In Xilinx, how long does it take to simulate my Geometry test-bench above running the:
GEO_tb_art.txt  script,  (Altera MS = 1 sec for 718,400 ns runtime)  (System Clk toggle rate = 100MHz)
And the
GEO_tb_45deg_zilog.txt script. (Altera MS no waveform = 25 sec for 13,851,400 ns runtime, all waveforms logged = 45sec.)

Includes the generation of the .bmp.
No idea. I don't have time to port it to 7 series platform.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 10, 2021, 01:05:23 am
Slowed down?  How so?  Re-compiles are almost instant.

Here is official info: https://www.intel.ca/content/www/ca/en/software/programmable/quartus-prime/model-sim.html (https://www.intel.ca/content/www/ca/en/software/programmable/quartus-prime/model-sim.html)
Free version has 10K executable lines limit, paid version is 33% faster.

In Xilinx, how long does it take to simulate my Geometry test-bench above running the:
GEO_tb_art.txt  script,  (Altera MS = 1 sec for 718,400 ns runtime)  (System Clk toggle rate = 100MHz)
And the
GEO_tb_45deg_zilog.txt script. (Altera MS no waveform = 25 sec for 13,851,400 ns runtime, all waveforms logged = 45sec.)

Includes the generation of the .bmp.
No idea. I don't have time to port it to 7 series platform.
Port, how so.  It's pure SystemVerilog.
1 folder with 7 .sv files, the top one being the 'GPU_GEO_tb.sv'.  The setup do files are just the vsim include all .sv and compile command while the optional run.do selects which waveforms you wish to see in the waveform window.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 10, 2021, 08:53:07 am
I know it's a bit of off-topic, but have you considering buying DECA board mentioned in the thread nearby? https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/ (https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/)
For the price, it's an absolute bargain, Among other things, it's got HDMI TX, microSD card socket, healthy 512 MBytes of DDR3 RAM, 100MBit Ethernet, USB 2.0 ULPI, audio codec, and it's got 69 digital GPIO pins on connectors, which should be more than enough to connect the rest of your system - I seem to recall you mentioned you need 63 FPGA IO pins. And, most importantly, it's got a rather large FPGA device with 50K LUTs.
I've ordered two even though I'm not really sure what I'm gonna do with them yet :-// The reason I ordered two is to get the order over $50 for free shipping, as a single board with shipping charge was actually more expensive than two boards with free shipping :-DD
I suspect the stock won't last for long, so you might want to grab one (or two :P ) while you can.

I think 44 pins absolute bare minimum just to interface with the host computer.  I took a look at the DECA - does look like a good deal, though shipping is more than the cost of the board itself so I see what you're saying about ordering two!  I'm not too far off getting this CV board finished (though the inclusion of DDR3 is a bit of an iceberg).  Not sure what I'd do with the DECA to be honest, let alone two of them, but it's very tempting! ;)

EDIT: Wrote that before I saw the rest of your conversation above.  So maybe getting one (or two!) would be a good idea for DDR3 controller testing etc?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 10, 2021, 10:01:37 am
Everything else shouldn't be wired.  The DDR3 gets absolute priority, then you can think about everything else.

I do have some physical constraints with the board layout that I have to consider.  How much impact they have on the design is up for grabs, but there's the power supplies around the board, 26 address signals from the left side of the board, 18 data and control signals from the right side, SD (which I'm putting on the underside of the PCB) and audio jack at the top and DVI/HDMI, USB/PS2 need to be at the bottom.  Other than rotating the FPGA and shunting the modules whose position is only limited to one side of the PCB around, there's not a lot else I can do. (Purple areas are power supplies).

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1171032;image)

Please check Cyclone V Device Handbook: Volume 1: Device Interfaces and Integration, page 216, Figure 6-8: PHYCLK Networks in Cyclone V E A2 and A4 Devices to show you the PLL connection to the banks.  You want to select IO banks which share a PLL and whose PLL has a dedicated outputs directly to one of the bank.  Make sure that your reference clock oscillator input is on a positive clock pin which goes to that PLL.  Page 206/207 shows the connections to the DQS groups and which shared DLL have direct connections.

Banks 1 & 2 are fed solely by the left PLL and banks 5 & 6 are fed by the right PLL.  All other banks have access to both PLLs.  But you've said not to use bank 5A, so that writes off the right hand side.  Bank 1 doesn't seem to exist and the rest of the left hand side (bank 2A) has 10 DQ and 2 DQS IOs.

Banks 7 & 8 seem to be the best option as they have 32 IOs between them, plenty of DQ and DQS pins, the reference clock feeds into bank 7A and the only disruption to existing connections would be to the auxiliary equipment on the top edge of the board (SD card, audio output, PC serial and debug serial, LEDs) - none of which would suffer from longer traces to other parts of the FPGA or being relocated somewhere else on the PCB entirely (except for audio).

Unless the fact it would take a PLL out of the equation for one other side of the FPGA would be an issue?

Do you agree?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 03:01:11 pm
Not sure what I'd do with the DECA to be honest, let alone two of them, but it's very tempting! ;)
Same here - I'm not sure yet what to do with that, but the price is just too good to pass up! Just check how much FPGA itself is that's on the board - it's several times more expensive than entire board!

EDIT: Wrote that before I saw the rest of your conversation above.  So maybe getting one (or two!) would be a good idea for DDR3 controller testing etc?
Yea, I would definitely do that. But that's me as someone who never used Altera's DDR3 controller, which is why I see it as a big design risk. To me $37 * 2 = $74 is a very good price to be certain as I suspect that PCB + BOM cost for a single custom board will be in the same ballpark. And I think you can find some other uses for these boards once the prototyping is over. Peripheral set is very good on it - pretty much everything you'd need for a typical single-board computer, with microSD wired through voltage translator so that it partially supports SD 3.0 specification with 1.8 V signaling (except for the highest 104 MHz SDR clock, which is beyond spec for the voltage translation IC used). USB 2.0 ULPI PHY onboard allows implementing a full-on USB 2.0 host interface, which, if connected to a hub, can be used to connect keyboard/mouse and have some leftover ports for stuff like thumb drives. 100 Mbit Ethernet can be used to add networking support. And 512 MBytes of DDR3 is plenty for all RAM needs, including video/GPU framebuffers, scratch/DMA memory for Ethernet MAC or USB 2.0 EHCI modules, as well as general purpose RAM for the needs of applications.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 10, 2021, 03:28:00 pm
Not sure what I'd do with the DECA to be honest, let alone two of them, but it's very tempting! ;)
Same here - I'm not sure yet what to do with that, but the price is just too good to pass up! Just check how much FPGA itself is that's on the board - it's several times more expensive than entire board!

EDIT: Wrote that before I saw the rest of your conversation above.  So maybe getting one (or two!) would be a good idea for DDR3 controller testing etc?
Yea, I would definitely do that. But that's me as someone who never used Altera's DDR3 controller, which is why I see it as a big design risk. To me $37 * 2 = $74 is a very good price to be certain as I suspect that PCB + BOM cost for a single custom board will be in the same ballpark. And I think you can find some other uses for these boards once the prototyping is over. Peripheral set is very good on it - pretty much everything you'd need for a typical single-board computer, with microSD wired through voltage translator so that it partially supports SD 3.0 specification with 1.8 V signaling (except for the highest 104 MHz SDR clock, which is beyond spec for the voltage translation IC used). USB 2.0 ULPI PHY onboard allows implementing a full-on USB 2.0 host interface, which, if connected to a hub, can be used to connect keyboard/mouse and have some leftover ports for stuff like thumb drives. 100 Mbit Ethernet can be used to add networking support. And 512 MBytes of DDR3 is plenty for all RAM needs, including video/GPU framebuffers, scratch/DMA memory for Ethernet MAC or USB 2.0 EHCI modules, as well as general purpose RAM for the needs of applications.

Well you've persuaded me asmi,  I've pulled the trigger on ordering two of those cards. :-+  I had a quick look on AliExpress and they're selling the same cards (well, the picture is the same!) for £230 (your mileage may vary in your home currency) including shipping!  The DDR3-testing argument was what won me over, though.  If we do wind up writing our own DDR3 controller, I've got a way of testing it physically I suppose.  Plus it's general gadgetry that appeals to my (not so) inner geek.  ;)

EDIT: Holy cow!  I've just looked up the FPGA (on its own) on Mouser.  They don't do the -6 speed variant in the DECA, just slightly slower -7 and -8 variants.  The -8 speed variant is still over £100, with the -7 around £114!  :clap:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 03:45:12 pm
Well you've persuaded me asmi,  I've pulled the trigger on ordering two of those cards. :-+  I had a quick look on AliExpress and they're selling the same cards (well, the picture is the same!) for £230 (your mileage may vary in your home currency) including shipping!  The DDR3-testing argument was what won me over, though.  If we do wind up writing our own DDR3 controller, I've got a way of testing it physically I suppose.  Plus it's general gadgetry that appeals to my (not so) inner geek.  ;)
Just skimmed through the user guide, and it appears that the board comes with WiFi-BLE module and MIPI camera module! This is an absolute bargain! My order apparently had some issues, but after I called them they said they released it to the warehouse today, so hopefully they will arrive shortly.
Also if you can persuade BrianHG to buy one as well, he will be able to go beyond simulations and do an actual hardware checkout of stuff you guys are working on ;)

EDIT: Holy cow!  I've just looked up the FPGA (on its own) on Mouser.  They don't do the -6 speed variant in the DECA, just slightly slower -7 and -8 variants.  The -8 speed variant is still over £100, with the -7 around £114!  :clap:
Yea, that's what I meant. FPGA devkits are often subsidized (just check out Xilinx devboards - a lot of them are cheaper as a full kit than just FPGA on it), as they are prototyping platforms which lead to device sales once you go into production with your products using these chips, but never to that extent!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on February 10, 2021, 04:42:17 pm
Just skimmed through the user guide, and it appears that the board comes with WiFi-BLE module and MIPI camera module!

I'm afraid not, the package content is pretty clear.  It has a MIPI connector, but no camera and no WiFi-BLE are included.  Can you give a link please to the shop that includes all those?

Also, if you like to buy FPGA bargains, there is yet another one even better:  EBAZ4205 with (IIRC) Zynq 7010, ~25 kLE FPGA) plus 2 embedded hardcore ARMs/~700MHz, with 256MB DDR3/1066, LAN, microSD and a few optpcouplers:
https://www.eevblog.com/forum/fpga/ebaz4205-(zynq-7000-based-development-board)/ (https://www.eevblog.com/forum/fpga/ebaz4205-(zynq-7000-based-development-board)/)

Those boards are from former cryptocurrency miners, and a board is about $10-15 on AliExpress.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 05:01:44 pm

I'm afraid not, the package content is pretty clear.  It has a MIPI connector, but no camera and no WiFi-BLE are included.  Can you give a link please to the shop that includes all those?
I'm just reading a user guide which is linked in the item description on Arrow's website.

Also, if you like to buy FPGA bargains, there is yet another one even better:  EBAZ4205 with (IIRC) Zynq 7010, ~25 kLE FPGA) plus 2 embedded hardcore ARMs/~700MHz, with 256MB DDR3/1066, LAN, microSD and a few optpcouplers:
https://www.eevblog.com/forum/fpga/ebaz4205-(zynq-7000-based-development-board)/ (https://www.eevblog.com/forum/fpga/ebaz4205-(zynq-7000-based-development-board)/)

Those boards are from former cryptocurrency miners, and a board is about $10-15 on AliExpress.
No offence, but this board is utter garbage. No schematics, no datasheet, no support, no code/RTL examples, no nothing. I'd rather make my own board, that buy this noname crap. So - no, it's not "even better", it's much worse.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on February 10, 2021, 05:22:01 pm
That EBAZ board has a lot of value for the money, too.

Zynq has a hardcoded dual core ARM, while MAX10 will use FPGA resources to create a softcore processor (NIOS II).  Vivado seem to have all the required IP blocks for that board for free, while the MAX10 will need a payed NIOS license for some IPs you might want.

About the docs, there is a github repository for the EBAZ board, with all the docs and board support files for Vivado.  There is also a working Linux for it, while the Altera board doesn't seem to allow Linux for free (requires IP license for NIOS II softcore processor with MMU, also I'm not sure if the DDR3 IP is free or not for Altera).

Both boards are nice to have for their price. 

Not sure how useful that will be for this particular project.
Sorry for any offtopic, I didn't read the previous 96 pages before posting.   ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 05:48:42 pm
That EBAZ board has a lot of value for the money, too.
I don't think so. You are comparing a purpose-built devboard with some specialized board designed for anything except being an actual devboard. Which is why it's so limiting.

Zynq has a hardcoded dual core ARM, while MAX10 will use FPGA resources to create a softcore processor (NIOS II).  Vivado seem to have all the required IP blocks for that board for free, while the MAX10 will need a payed NIOS license for some IPs you might want.
About the docs, there is a github repository for the EBAZ board, with all the docs and board support files for Vivado.  There is also a working Linux for it, while the Altera board doesn't seem to allow Linux for free (requires IP license for NIOS II softcore processor with MMU, also I'm not sure if the DDR3 IP is free or not for Altera).
if your goal is to just run Linux, maybe you have a point, though I think this is a very pointless goal in and of itself. In embedded world Linux is a tool, not an end goal, so you use it if you need it to do something (for example USB support, or TCP/IP stack), but not just to run itself and just stare at a terminal being proud of your ability to enter few commands in a command line and follow well-defined instructions on how to get it up and running.

Both boards are nice to have for their price. 
Again, these are not comparable. Purpose-built devboards are far superior options because they are actually designed to be used as prototyping platforms, and so they usually have required facilities like integrated JTAG with live debugging support, some kind of expansion support and other specific features normally not present on production boards. Using random application-specific boards for prototyping is like using a microscope to drive in nails - yes, it can be done (microscope bases are heavy!), but nobody in their right mind would ever do that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on February 10, 2021, 07:02:08 pm
EBAZ has JTAG pins but can be programmed without additional programmers.  The Zynq board also has tens of I/O pins at its connectors.  There is a schematic and there is even Altium and Kicad PCB files.
https://github.com/xjtuecho/EBAZ4205/blob/master/HW/ebaz4205/EBAZ4205-SCH.pdf
https://github.com/xjtuecho/EBAZ4205

Also, free IP blocks are very important (Quartus seems to have less free IP) when one want to make use of the board for anything other than learning.  For example, nobody writes a DDR3 controller or a network stack, but uses available IP blocks instead.  If these blocks are not free to use, than they are certainly too expensive for hobby projects anyway, so it is very important to have them for free in the toolchain.  If we consider the free part of the software toolchain, then the Zynq become even more attractive.  I didn't really work with Quartus/Nios, but from reading the specs so far it seems Vivado has more free goodies and will be more productive for projects.

Same with Linux, very important not for exercising shell commands, but because it will allow access to all the drivers and tools and applications already existing for Linux.

I won't try to convince you any further about the value of that Zynq board, not trying to sell anything.   :)

I would also rather buy the Altera board, same as you, just that for different reasons (e.g. has a MIPI connector, or the two SMA for the ADC, good to improvise a DAQ if it only were a free Linux for it, and it seems it is one, but I'm too new to this board+toolchain to disseminate between facts and marketing hype).  In fact the only thing that kept me not to buy one yet was that I don't know what IP blocks are free for Quartus/Nios II.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 10, 2021, 07:21:31 pm
Also, free IP blocks are very important (Quartus seems to have less free IP) when one want to make use of the board for anything other than learning.  For example, nobody writes a DDR3 controller or a network stack, but uses available IP blocks instead.  If these blocks are not free to use, than they are certainly too expensive for hobby projects anyway, so it is very important to have them for free in the toolchain.  If we consider the free part of the software toolchain, then the Zynq become even more attractive.  I didn't really work with Quartus/Nios, but from reading the specs so far it seems Vivado has more free goodies and will be more productive for projects.
I'm sure folks from this thread will get a good laugh reading this, as I've been trying to convince them to switch to Xilinx FPGA pretty much entire time this thread exists :-DD

Same with Linux, very important not for exercising shell commands, but because it will allow access to all the drivers and tools and applications already existing for Linux.
What utility does it have with chip that's got only 25K gates?

I won't try to convince you any further about the value of that Zynq board, not trying to sell anything.   :)
And yet you're still trying  ;) I don't see the value of Zynq itself. I have a bunch of Zynq-030 chips which I snagged for cheap, but I'm yet to come up with an application for it.

I would also rather buy the Altera board, same as you, just that for different reasons (e.g. has a MIPI connector, or the two SMA for the ADC, good to improvise a DAQ if it only were a free Linux for it, and it seems it is one, but I'm too new to this board+toolchain to disseminate between facts and marketing hype).  In fact the only thing that kept me not to buy one yet was that I don't know what IP blocks are free for Quartus/Nios II.
What's with this attempts to shove Linux everywhere? You don't need it for most embedded projects. As a matter of fact, I've never had to use it in any of my FPGA projects, commercial or not.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 10, 2021, 11:13:20 pm
I'm sure folks from this thread will get a good laugh reading this, as I've been trying to convince them to switch to Xilinx FPGA pretty much entire time this thread exists :-DD

:-DD

Just so we're clear, I'm using Altera FPGAs because that's what the resident expert (BrianHG) is most familiar with and without whom this project would still be stuck at the 'coloured bars' stage.

What's with this attempts to shove Linux everywhere? You don't need it for most embedded projects. As a matter of fact, I've never had to use it in any of my FPGA projects, commercial or not.

This may not be a popular opinion, but I have to say that I absolutely HATE Linux with a passion normally reserved for genocidal maniacs and parking wardens.  It always seems to me that if there is a more convoluted way of doing things, Linux will make you do it.

In other news, looks like my USB interface is going to work (just need to set up and test the SPI interface), so I'll be scrubbing the PS/2 interface from the CV PCB to make some more room - maybe for another USB interface so I can use mouse and keyboard at the same time.  :o

If anyone was following along with the USB developments (I haven't really been updating the forum with it, but have mentioned it a couple of times), I've decided to drop the MAX3421E as it was proving to be a bit of a headache to get working with the FPGA - instead I'm using a SAMD21G microcontroller instead.  It's actually cheaper (I can buy two SAMD21Gs for one MAX3421E) and can send data to the FPGA via SPI, I2C or serial, so it makes the whole thing a lot simpler (at least for me anyway).  Yes, they're overpowered for the application, but then so is the FPGA.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 05:02:58 am
So, whats going on...
There are years of work ahead of us...
Changes to be made...
Swaps to new hardware...
New things to implement...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 12, 2021, 07:41:33 am
Everything else shouldn't be wired.  The DDR3 gets absolute priority, then you can think about everything else.

I do have some physical constraints with the board layout that I have to consider.  How much impact they have on the design is up for grabs, but there's the power supplies around the board, 26 address signals from the left side of the board, 18 data and control signals from the right side, SD (which I'm putting on the underside of the PCB) and audio jack at the top and DVI/HDMI, USB/PS2 need to be at the bottom.  Other than rotating the FPGA and shunting the modules whose position is only limited to one side of the PCB around, there's not a lot else I can do. (Purple areas are power supplies).

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1171032;image)

Please check Cyclone V Device Handbook: Volume 1: Device Interfaces and Integration, page 216, Figure 6-8: PHYCLK Networks in Cyclone V E A2 and A4 Devices to show you the PLL connection to the banks.  You want to select IO banks which share a PLL and whose PLL has a dedicated outputs directly to one of the bank.  Make sure that your reference clock oscillator input is on a positive clock pin which goes to that PLL.  Page 206/207 shows the connections to the DQS groups and which shared DLL have direct connections.

Banks 1 & 2 are fed solely by the left PLL and banks 5 & 6 are fed by the right PLL.  All other banks have access to both PLLs.  But you've said not to use bank 5A, so that writes off the right hand side.  Bank 1 doesn't seem to exist and the rest of the left hand side (bank 2A) has 10 DQ and 2 DQS IOs.

Banks 7 & 8 seem to be the best option as they have 32 IOs between them, plenty of DQ and DQS pins, the reference clock feeds into bank 7A and the only disruption to existing connections would be to the auxiliary equipment on the top edge of the board (SD card, audio output, PC serial and debug serial, LEDs) - none of which would suffer from longer traces to other parts of the FPGA or being relocated somewhere else on the PCB entirely (except for audio).

Unless the fact it would take a PLL out of the equation for one other side of the FPGA would be an issue?

Do you agree?

I think you might have missed my last post with the discussion on dev boards.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 08:06:35 am
Yes, 7&8 look good.
Remember, The 2 DQS (DQS&DQSn) in 7 and 8 go to the ram's UDQS and LDQS, while the bank with the bank wired to the UDQS gets the high word DQ bits [15:8] while the bank wired to the LDQS gets the [7:0] DQ bits.  When selecting the dedicated PLL output clock pins, make sure that same PLL also reaches your third IO bank where you will have the bulk of addressees and ram controls.  If a third bank is needed, it will probably be bank 5B.

Don't discount that dev board.  I know we can get 3 CV at 19$ (inflation) from LCSC, but, that's all for who knows how long.  I haven't played with Lattice (but I did install it), but, If it is possible to port the design over to their FPGA, the 45k gate LFE5U device is in mass production and it is 16$ at digikey, mouser, and future electronics.  For a public domain project, availability and price may be a plus.  Your current CV is 25k gate, 35$ at mouser and it is not guaranteed that it can be tricked into it's 50k gate equivilant.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 12, 2021, 11:53:32 am
Don't discount that dev board.  I know we can get 3 CV at 19$ (inflation) from LCSC, but, that's all for who knows how long.  I haven't played with Lattice (but I did install it), but, If it is possible to port the design over to their FPGA, the 45k gate LFE5U device is in mass production and it is 16$ at digikey, mouser, and future electronics.  For a public domain project, availability and price may be a plus.  Your current CV is 25k gate, 35$ at mouser and it is not guaranteed that it can be tricked into it's 50k gate equivilant.

I've no aversion to swapping to a better FPGA if you are happy to - I'm totally guided by the support I can receive on a particular FPGA family and am not experienced enough with this stuff to have any particular preference (other than being familiar with Cyclones now).  asmi has been singing the virtues of Xilinx for months now and if he's happy to help out where he can, perhaps it's not such a bad idea. Naturally, there'd be a huge learning curve for me with the tool chain etc, but maybe it's time to address that elephant in the room?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SMB784 on February 12, 2021, 02:17:46 pm
Don't discount that dev board.  I know we can get 3 CV at 19$ (inflation) from LCSC, but, that's all for who knows how long.  I haven't played with Lattice (but I did install it), but, If it is possible to port the design over to their FPGA, the 45k gate LFE5U device is in mass production and it is 16$ at digikey, mouser, and future electronics.  For a public domain project, availability and price may be a plus.  Your current CV is 25k gate, 35$ at mouser and it is not guaranteed that it can be tricked into it's 50k gate equivilant.

I've no aversion to swapping to a better FPGA if you are happy to - I'm totally guided by the support I can receive on a particular FPGA family and am not experienced enough with this stuff to have any particular preference (other than being familiar with Cyclones now).  asmi has been singing the virtues of Xilinx for months now and if he's happy to help out where he can, perhaps it's not such a bad idea. Naturally, there'd be a huge learning curve for me with the tool chain etc, but maybe it's time to address that elephant in the room?

Having worked with both Altera & Xilinx toolchains, I can honestly say the difference is not that substantial in terms of user interface.  The design flow is the same, and the buttons for the various workflow stages are even mostly in the same place.

The benefit I see with Vivado over Quartus Prime is that the simulation suite is built into the main design IDE, not separate from it like Modelsim.  I think you overestimate the learning curve between the two.  It took me less than a week to get a fair mastery of Vivado after only working with Quartus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 02:54:02 pm
Don't discount that dev board.  I know we can get 3 CV at 19$ (inflation) from LCSC, but, that's all for who knows how long.  I haven't played with Lattice (but I did install it), but, If it is possible to port the design over to their FPGA, the 45k gate LFE5U device is in mass production and it is 16$ at digikey, mouser, and future electronics.  For a public domain project, availability and price may be a plus.  Your current CV is 25k gate, 35$ at mouser and it is not guaranteed that it can be tricked into it's 50k gate equivilant.

I've no aversion to swapping to a better FPGA if you are happy to - I'm totally guided by the support I can receive on a particular FPGA family and am not experienced enough with this stuff to have any particular preference (other than being familiar with Cyclones now).  asmi has been singing the virtues of Xilinx for months now and if he's happy to help out where he can, perhaps it's not such a bad idea. Naturally, there'd be a huge learning curve for me with the tool chain etc, but maybe it's time to address that elephant in the room?
My concern is $ per K gate & availability.  I'd like to make code which runs on all 3 platforms like almost all of your current core code.
In Xilinx, how much does a ~45k gate, ~2 megabit part cost?

Right now, the CV 25k gate 5CEBA2F17C8N is 34.81$ at Mouser and it may be hack-able to the 50k gate 5CEBA4F17C8N which costs 50$.  LCSC has the 5CEBA2 at 19$, but they do not seem to have many unless you back order.

The lattice part is also a 256 pin BGA @ 15.86$.  It is a hair faster than the CV.  The lattice 25k gate variant isn't worth it as it is 9.29$.  Might as well pay the additional 6$ for double the size. The lattice LFE5U-85F-6MG285C is 30$ (finer 285 pin BGA which may be difficult for beginners and PCB price for finer pitch layout), that's 85k gate and 4 megabit for less than the 25k gate CV price.  These prices are to buy 1 at a time.

~25k gate will allow you to do almost everything under the sun fine.  ~45k gate will allow you to do it all and have breathing room.  Your Achilles heel would then be that limiting 256 pins unless you shove the Z80 CPU inside the FPGA or multiplex / IO expand the IO ports with 3 wire serial to parallel interface IO ICs which can also do the TTL conversion for you.

The 50k gate dev board while available is a fluke deal as it has a 50k gate, 484 pin 125$ FPGA on it.  However, this deal will soon end & you cannot expect anyone else out there to pay 100$ for a FPGA for a Z80.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 03:02:12 pm

The benefit I see with Vivado over Quartus Prime is that the simulation suite is built into the main design IDE, not separate from it like Modelsim.  I think you overestimate the learning curve between the two.  It took me less than a week to get a fair mastery of Vivado after only working with Quartus.
We have still yet to see anyone run my simulation code of the geometry unit on the previous page in Xilinx.  It has no altera dependencies and the way it is setup and I did post the compile time and execution time for 2 key scripts to be executed.  It would be nice to know if Xilinx can do the 13,851,400 ns runtime sim, 1,385,140 CLK cycles, in a reasonable amount of time and properly render / generate the .bmp picture.
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3456782/#msg3456782 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3456782/#msg3456782)
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3447916/#msg3447916 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3447916/#msg3447916)


If we are going to jump FPGA vendors, the most valuable choice here is $/k-gate as our code isn't too complex as it currently fits on a 10kgate chip and we only expect it to double it's current size.  Though, I would like whatever vendor we choose support IEEE754 floating point natively as Altera currently does.  We can add some nice geometry pre-processing so we can simulate all the functions of an analog vector graphics display including true rotation as well as provide a FPU for the Z80.  Though, recently I found on opencores a compact 2-3 clock cycle -29 to +24 exponent FPU, with 17 clock cycle divide which can operate on all vendors while the full -128 to +127 exponent unit exists, but has a huge pipeline penalty.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on February 12, 2021, 05:30:57 pm
Once I've designed a Z80 computer, it was made to be compatible with CP/M (to benefit from the software tools available for CP/M) and ZX Spectrum (for games). It was all on a single big perfboard.  Please allow me to show off, 'cause it's weekend!  ;D

(https://cdn.hackaday.io/images/2572221402262586660.jpg)

(https://cdn.hackaday.io/images/5382331402262596379.jpg)

https://www.youtube.com/watch?v=wdahLHINNcM (https://www.youtube.com/watch?v=wdahLHINNcM)

https://hackaday.io/project/1411-xor-hobby-a-vintage-z80-computer-prototype (https://hackaday.io/project/1411-xor-hobby-a-vintage-z80-computer-prototype)

Thought the output was for a TV back then.  The RAM chips were normal dynamic memories 16384 x 1bit (normal as in not dual port), double addressed by the processor and by the video controller using address demultiplexers, a few counters and some glue logic to carefully pause the Z80 clock to avoid memory accessing conflicts.

The control logic to implement that was roughly 30 TTL chips, and about 100 chips all together with the floppy disk interface, the RAM chips, EPROMs, buffers, processor, etc.

- 1. I don't understand, why a less than 50kLE FPGA would be a problem.  My guesstimation is that that amount should be enough for a video adapter, including a softcore Z80, too.  The original Z80 was less than 10 000 transistors, so I expect a Z80 IP to fit in less than 10 kLE, but never tested one, how big is the Z80 IP?  Why would, let's say a 20kLE, not be enough?

- 2. Why adding a whole VGA?  Wouldn't be easier to just control a HDMI chip (or alike), so to get video output without trying to align to the VGA standard?  Were there any Z80 computer with VGA back in the days?

- 3. Will this Z80 try to be compatible with certain computer models, so it can run old Z80 games and software?

- 4. For the questions in the OP, that missing website has many snapshots on the WaybackMachine Internet archive:
https://web.archive.org/web/20190713224608/http://searle.hostei.com/grant/z80/SimpleZ80.html (https://web.archive.org/web/20190713224608/http://searle.hostei.com/grant/z80/SimpleZ80.html)

- 5. My guess is the request from the OP has changed during the last ~100 pages of replies, can anybody make a short brief (2-3 phrases) of the current project, please?

Not trying to argue about what FPGA to use or anything alike, just curious about the current goal and status of the project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 12, 2021, 05:38:44 pm
We have still yet to see anyone run my simulation code of the geometry unit on the previous page in Xilinx. 
I did try it, and it crashed Vivado's builtin sim while parsing GPU_GEO_tb. I couldn't really figure out why in the time I had for this, but it seems like it's related to handling unpacked arrays vs packed vectors. That module is just way too large for me to go in and try fixing it, without breaking anything in a process.
Since there is no top level module, I didn't try running synthesis to see if that would work.
Vivado IDE supports integration with other simulators (including ModelSim), so if the issue is with simulator, that can be worked around.

If we are going to jump FPGA vendors, the most valuable choice here is $/k-gate as our code isn't too complex as it currently fits on a 10kgate chip and we only expect it to double it's current size.  Though, I would like whatever vendor we choose support IEEE754 floating point natively as Altera currently does.  We can add some nice geometry pre-processing so we can simulate all the functions of an analog vector graphics display including true rotation as well as provide a FPU for the Z80.  Though, recently I found on opencores a compact 2-3 clock cycle -29 to +24 exponent FPU, with 17 clock cycle divide which can operate on all vendors while the full -128 to +127 exponent unit exists, but has a huge pipeline penalty.
I disagree that gates per $ is the most important metric. To me it's actually not even in the top 3, the most important metrics are almost always raw performance and IO features (how many and how fast transceivers I need, how many IO and their configuration, which has implications to the kind of memory layouts I can implement). But I'm not the one making decisions here, so what do I know :)
As for Z80 softcore, why not design your own? This project is about learning right? I definitely learnt a lot as I was working on my own softcores, so I think this is a good project for learning.
That said, I still use Microblaze softcore in all of my "serious" FPGA designs, because - convenience. It's already there, completely free of charge, you can configure it however your want, there is a ready-to-go software toolchain with live visual debugging support, there are a ton of support libraries and drivers for different peripherals, you can even run Linux on it if you so desire. So as long as the focus of my project is not an actual softcore, using MB is really a no-brainer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 12, 2021, 07:26:26 pm
Once I've designed a Z80 computer, it was made to be compatible with CP/M (to benefit from the software tools available for CP/M) and ZX Spectrum (for games). It was all on a single big perfboard.  Please allow me to show off, 'cause it's weekend!  ;D

Wow - that's some wiring spaghetti! ;)  I started out on a breadboard, then moved to DIP soldering on PCBs and am now plummeting down the SMD rabbit hole into Wonderland, it seems.  Or at least BGA territory.  I wanted to see if I could build something more powerful than my first computer - one of these (https://en.wikipedia.org/wiki/Amstrad_CPC_464) - and it seems I've done that in spades, with the video output being the final hurdle.

- 1. I don't understand, why a less than 50kLE FPGA would be a problem.  My guesstimation is that that amount should be enough for a video adapter, including a softcore Z80, too.  The original Z80 was less than 10 000 transistors, so I expect a Z80 IP to fit in less than 10 kLE, but never tested one, how big is the Z80 IP?  Why would, let's say a 20kLE, not be enough?

We've filled a 10kLE FPGA and there's still more we could do with the GPU, let alone all the other bits.  I want to add an AY-8910 PSG (https://en.wikipedia.org/wiki/General_Instrument_AY-3-8910) into the FPGA as well, because that's what my first computer had and I like chiptunes. 8)  I'll probably end up adding a better, more capable PSG (Programmable Sound Generator) too.  Of course, there's always the possibility of putting a softcore Z80 into the FPGA too with the room we have, but that's not really my goal.

- 2. Why adding a whole VGA?  Wouldn't be easier to just control a HDMI chip (or alike), so to get video output without trying to align to the VGA standard?  Were there any Z80 computer with VGA back in the days?

We started with VGA as I knew nothing about it and it was the easiest introduction to video output.  As you've missed most of the last year's worth of thread, it's important that you understand that I'm not a professional programmer and my experience with electronics started with the project to build my DIY computer two years ago (nearly three now!)  I didn't really know what an FPGA was until I started this thread, my soldering skills extended to the SOIC chip and even that scared me!  I'm trying to learn all this on the fly, as it were.  Sometimes things stick and I get them straight away, sometimes BrianHG and everyone else on the forum have to put up with me being really thick and not getting something until it's repeated fifteen times, in fifteen different ways.  ;)

- 3. Will this Z80 try to be compatible with certain computer models, so it can run old Z80 games and software?

It runs CP/M 2.2 and CP/M 3, but it's not designed to be compatible with any particular old computer, it's just designed to be as simple as possible (until this thread started!)  This GPU project is by far the most complicated and modern part of it.  Whilst I'm designing a video card for my computer, we're also making it open source so that anyone building their own computer (be that Z80-based, 680x0-based, or Intel 4004-based) can use the HDL in their project.

- 4. For the questions in the OP, that missing website has many snapshots on the WaybackMachine Internet archive:
https://web.archive.org/web/20190713224608/http://searle.hostei.com/grant/z80/SimpleZ80.html (https://web.archive.org/web/20190713224608/http://searle.hostei.com/grant/z80/SimpleZ80.html)

Yep, that was answered over a year ago - but thanks. ;)  Grant Searle opened up another website after he had issues with the internet provider for the one that went down.

- 5. My guess is the request from the OP has changed during the last ~100 pages of replies, can anybody make a short brief (2-3 phrases) of the current project, please?

Well, I've pretty-much outlined most of the brief above, but basically I had a cheap Cyclone II FPGA board and was trying to find out what all this 'FPGA' stuff was about and see if I could build the FPGA computer from Grant Searle's website, my intention being to just use the VGA HDL to create a video card for my computer.

The thread quickly turned into an education on designing and building a VGA card using a Cyclone IV FPGA, which I did and it works wonderfully.  We pushed on from there after I asked a question about how would graphics acceleration work and now the GPU can draw lines, rectangles, quads, triangles, circles and arcs at rates my old computer couldn't even dream of.  It also has a PS/2 port for a keyboard and my little computer is completely standalone now.

We're at the stage now where I'm designing a 'version 2' of the GPU card, using a bigger FPGA to accommodate more features, with full HDMI output, proper audio output (the 1st version has a buzzer), SD card (hopefully to replace the CF card interface I created for my computer) and replacing the PS/2 port with a USB port so I can use modern keyboards, maybe a mouse, plus DDR3 RAM for even more graphics memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: iMo on February 12, 2021, 07:28:50 pm

- 1. I don't understand, why a less than 50kLE FPGA would be a problem.  My guesstimation is that that amount should be enough for a video adapter, including a softcore Z80, too.  The original Z80 was less than 10 000 transistors, so I expect a Z80 IP to fit in less than 10 kLE, but never tested one, how big is the Z80 IP?  Why would, let's say a 20kLE, not be enough?

Complete ZX Spectrum (incl. Z80 cpu, ula and video ram) fits into 3700 LEs (and 131kbits of internal ram) of a Cyclone II..

..That said, I still use Microblaze softcore in all of my "serious" FPGA designs, because - convenience. It's already there, completely free of charge, you can configure it however your want, there is a ready-to-go software toolchain with live visual debugging support, there are a ton of support libraries and drivers for different peripherals, you can even run Linux on it if you so desire. So as long as the focus of my project is not an actual softcore, using MB is really a no-brainer.

Long time back I ran some C code in order to compare MB (Spartan6) and pic32MX (because of their arch similarity) and got identical results. I doubt you can come with something "performing much better" than the MB..
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 08:51:01 pm
I disagree that gates per $ is the most important metric. To me it's actually not even in the top 3, the most important metrics are almost always raw performance and IO features (how many and how fast transceivers I need, how many IO and their configuration, which has implications to the kind of memory layouts I can implement). But I'm not the one making decisions here, so what do I know :)
These metrics have already been reached with the cheapest FPGA for a Z80 or even interfacing with a 16 bit 68k.
The size just means play room to make any code we like.
A lot of our gates are eaten up by the unusual layering system which allows multiple color depths at multiple resolutions which optional multiple tiles all to be superimposed.  I guess we could have gone cheap with a fixed small 64 16x16 sprites plus 1 or 2 background layers.
The only plus to having true 1.5gbit serial out for true 1080p at 60hz.  For now, 720p@60 and 1080p@30 is fine.

However, to add a simple 3D accelerator to the core, 25k gates wont cut it.  45k gates will.
Yes, it would be nice to have 800mhz ram with a 1.6gtps bus, (unfortunately we would want even double that for 1080p@60) or faster, but we want to do all of this with an under 20$ fpga.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 12, 2021, 08:57:26 pm
Yes, it would be nice to have 800mhz ram with a 1.6gtps bus, (unfortunately we would want even double that for 1080p@60) or faster, but we want to do all of this with an under 20$ fpga.
Where did that requirement came from? The kind of FPGA you can get for $20 (from official sources) is pretty useless.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 09:00:50 pm
We have still yet to see anyone run my simulation code of the geometry unit on the previous page in Xilinx. 
I did try it, and it crashed Vivado's builtin sim while parsing GPU_GEO_tb. I couldn't really figure out why in the time I had for this, but it seems like it's related to handling unpacked arrays vs packed vectors. That module is just way too large for me to go in and try fixing it, without breaking anything in a process.
No warnings, just plain up crash?  :-DD
If I ever go to Xilinx, this is the first thing I would post on their troubleshooting site...
This code does sim to work on ModelSim 10.1 through 20.1.  I only wish modelsim had a better integrated text editor, guess I got to use an external one.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 12, 2021, 09:03:00 pm
My concern is $ per K gate & availability.  I'd like to make code which runs on all 3 platforms like almost all of your current core code.
In Xilinx, how much does a ~45k gate, ~2 megabit part cost?

Right now, the CV 25k gate 5CEBA2F17C8N is 34.81$ at Mouser and it may be hack-able to the 50k gate 5CEBA4F17C8N which costs 50$.  LCSC has the 5CEBA2 at 19$, but they do not seem to have many unless you back order.

The lattice part is also a 256 pin BGA @ 15.86$.  It is a hair faster than the CV.  The lattice 25k gate variant isn't worth it as it is 9.29$.  Might as well pay the additional 6$ for double the size. The lattice LFE5U-85F-6MG285C is 30$ (finer 285 pin BGA which may be difficult for beginners and PCB price for finer pitch layout), that's 85k gate and 4 megabit for less than the 25k gate CV price.  These prices are to buy 1 at a time.

I seem to recall the Lattice Diamond software licensing put me off - I've just had a check on the Lattice website, and the free version of Diamond doesn't do SERDES-based Lattice FPGAs.  In fact, it doesn't support ECP5UM, ECP5UM5G, LatticeECP3, LatticeECP2M/S, LatticeECP2/S, LatticeSC or LatticeSCM.  Don't we need SERDES for the HDMI output?

Yes, it would be nice to have 800mhz ram with a 1.6gtps bus, (unfortunately we would want even double that for 1080p@60) or faster, but we want to do all of this with an under 20$ fpga.
Where did that requirement came from? The kind of FPGA you can get for $20 (from official sources) is pretty useless.

Well, the cheaper the better obviously.  My biggest concern regarding the cost of the FPGA so far has been my ability to solder one to a PCB, closely followed by my ability to design a PCB that it can work on.  I don't want to waste too much money learning to solder BGAs and I don't want to bulk-buy SMD-assembled boards as the PCB design I'm using is specific to my single use-case.  I only really need one or two at most.  Anyone else making use of this project will be doing so for their own project which likely won't match my layout at all.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 09:03:30 pm
Yes, it would be nice to have 800mhz ram with a 1.6gtps bus, (unfortunately we would want even double that for 1080p@60) or faster, but we want to do all of this with an under 20$ fpga.
Where did that requirement came from? The kind of FPGA you can get for $20 (from official sources) is pretty useless.
Nockieboy did not want to pay more than 20$ for an FPGA.
Lattice is good with density and price.  And this is from official sources.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 12, 2021, 09:06:36 pm
No warnings, jut plain up crash?  :-DD
It said something like access violation, and a long C++ stack trace, so it's definitely internal error.

If I ever go to Xilinx, this is the first thing I would post on their troubleshooting site...
I plan to do that, but I will need to invest some time into seeing what exactly is causing an issue. I doubt their devs would be thrilled to decipher 1.3 kloc to see what is wrong over there. I know I wouldn't.

This code does sim to work on ModelSim 10.1 through 20.1.  I only wish modelsim had a better integrated text editor, guess I got to use an external one.
I use VS code with plugin for SystemVerilog, it's far superior to anything else out there in my opinion.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 12, 2021, 09:18:44 pm
Well, the cheaper the better obviously.  My biggest concern regarding the cost of the FPGA so far has been my ability to solder one to a PCB, closely followed by my ability to design a PCB that it can work on.  I don't want to waste too much money learning to solder BGAs and I don't want to bulk-buy SMD-assembled boards as the PCB design I'm using is specific to my single use-case.  I only really need one or two at most.  Anyone else making use of this project will be doing so for their own project which likely won't match my layout at all.
One thing I like about Artix is that almost entire lineup is available in the same BGA256 package, so you can move up or down as you require without changing anything on a PCB. This package covers the range from 15T all the way up to 100T, with prices from ~27$ to ~$150 on Digikey. This allows using smaller part for the first board (so that you can verify the PCB works without risking too much money) before investing into larger device for the actual project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 09:27:26 pm
My concern is $ per K gate & availability.  I'd like to make code which runs on all 3 platforms like almost all of your current core code.
In Xilinx, how much does a ~45k gate, ~2 megabit part cost?

Right now, the CV 25k gate 5CEBA2F17C8N is 34.81$ at Mouser and it may be hack-able to the 50k gate 5CEBA4F17C8N which costs 50$.  LCSC has the 5CEBA2 at 19$, but they do not seem to have many unless you back order.

The lattice part is also a 256 pin BGA @ 15.86$.  It is a hair faster than the CV.  The lattice 25k gate variant isn't worth it as it is 9.29$.  Might as well pay the additional 6$ for double the size. The lattice LFE5U-85F-6MG285C is 30$ (finer 285 pin BGA which may be difficult for beginners and PCB price for finer pitch layout), that's 85k gate and 4 megabit for less than the 25k gate CV price.  These prices are to buy 1 at a time.

I seem to recall the Lattice Diamond software licensing put me off - I've just had a check on the Lattice website, and the free version of Diamond doesn't do SERDES-based Lattice FPGAs.  In fact, it doesn't support ECP5UM, ECP5UM5G, LatticeECP3, LatticeECP2M/S, LatticeECP2/S, LatticeSC or LatticeSCM.  Don't we need SERDES for the HDMI output?
That's for the dedicated hardware GBPS transceivers in the ECP5UM, ECP5UM5G, not the ECP5U-45 which we are using.  It is the same with Altera, you need the paid version of Quartus for the GBPS devices.  Right now, the altlvds_tx is actually just generating a software shift-register in DDR mode on a normal IO pins.  And since the IO pins are just about the same speed as the ones in the Cyclone series, you will get the same 720p.

Well, in the datasheet ECP5 -6=624mb -7=700mb, -8=800mb.  (smartly, the slowest one can handle DDR3's minimum 303MHz)
                      All Cyclone -8=640mb -7=740mb,  -6=840mb. on select IOs.
                                      -8=550mb -7=640mb, -6=640mb. on all IOs.  (This is why you need a -7 to officially run DDR3 meeting that 303MHz target, though, right now, we achieved 1080mb on a -8 550mb output.  I bet we would get nailed on bus-turn-around.  1080 was achieves in output only mode and we don't care about temperature skew drift.  IE, want to run DDR3 this fast, we need 1 extra clock delay between swapping from read to write and back as the tri-state might need extra time to release and engage.)

Now I am not saying to blindly build a lattice board.  I'm saying to take a look to see if a ECP5U eval board exists, don't yet buy, but then investigate if our code will work in lattice diamond and wont crash it's simulator.  If that looks ok, then a minimum ECP5U eval board would be useful to test our code with HDMI output, even if you have to wire your current HDMI tester by hand.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 09:28:44 pm
This code does sim to work on ModelSim 10.1 through 20.1.  I only wish modelsim had a better integrated text editor, guess I got to use an external one.
I use VS code with plugin for SystemVerilog, it's far superior to anything else out there in my opinion.
Thanks...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on February 12, 2021, 09:54:45 pm
now the GPU can draw lines, rectangles, quads, triangles, circles and arcs at rates my old computer couldn't even dream of.  It also has a PS/2 port for a keyboard and my little computer is completely standalone now.

We're at the stage now where I'm designing a 'version 2' of the GPU card, using a bigger FPGA to accommodate more features, with full HDMI output, proper audio output (the 1st version has a buzzer), SD card (hopefully to replace the CF card interface I created for my computer) and replacing the PS/2 port with a USB port so I can use modern keyboards, maybe a mouse, plus DDR3 RAM for even more graphics memory.

Wow, quite a journey already, indeed, great project!   :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 12, 2021, 10:36:13 pm
That's for the dedicated hardware GBPS transceivers in the ECP5UM, ECP5UM5G, not the ECP5U-45 which we are using.  It is the same with Altera, you need the paid version of Quartus for the GBPS devices.

Ahh, okay.  :-+  Still seems that there's very few low-end dev boards for the ECP5U, from the little research I've been able to do so far.  Also, this post (https://www.eevblog.com/forum/fpga/lattice-ecp5-opinion/msg3385426/#msg3385426) has concerned me a little as it seems to imply that we'll have to develop the DDR3 controller ourselves.  Having said that, I guess we'll be doing that anyway if the design is going to be fully FPGA-agnostic.  Using proprietary IP is vendor-specific, so I guess we'll be avoiding anything like that.

Now I am not saying to blindly build a lattice board.  I'm saying to take a look to see if a ECP5U eval board exists, don't yet buy, but then investigate if our code will work in lattice diamond and wont crash it's simulator.  If that looks ok, then a minimum ECP5U eval board would be useful to test our code with HDMI output, even if you have to wire your current HDMI tester by hand.

Unless anyone can point me to a Lattice ECP5U dev/eval board for less than $50, looks like I could be designing one from scratch. ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 12, 2021, 11:08:46 pm
That's for the dedicated hardware GBPS transceivers in the ECP5UM, ECP5UM5G, not the ECP5U-45 which we are using.  It is the same with Altera, you need the paid version of Quartus for the GBPS devices.

Ahh, okay.  :-+  Still seems that there's very few low-end dev boards for the ECP5U, from the little research I've been able to do so far.  Also, this post (https://www.eevblog.com/forum/fpga/lattice-ecp5-opinion/msg3385426/#msg3385426) has concerned me a little as it seems to imply that we'll have to develop the DDR3 controller ourselves.  Having said that, I guess we'll be doing that anyway if the design is going to be fully FPGA-agnostic.  Using proprietary IP is vendor-specific, so I guess we'll be avoiding anything like that.

Now I am not saying to blindly build a lattice board.  I'm saying to take a look to see if a ECP5U eval board exists, don't yet buy, but then investigate if our code will work in lattice diamond and wont crash it's simulator.  If that looks ok, then a minimum ECP5U eval board would be useful to test our code with HDMI output, even if you have to wire your current HDMI tester by hand.

Unless anyone can point me to a Lattice ECP5U dev/eval board for less than $50, looks like I could be designing one from scratch. ???
I know, lattice doesn't think like that, or are relying on the lower end Mach dev boards, or that the 99$ board with included programmer + including a limited time version their full compiler is good enough.

Yes, we are importing a public domain DDR3 controller, but for now, using Altera's binds you to the proper IO pins and generates for you an example .SDC file which sets-up the timing constraints for the IO pin, the 2 things missing in the public-domain controller.  As for the IO buffer, there's a standard DDR-DQS-BIDIR-IOBUF function port just like the altlvds_tx/rx which can be plugged into the DDR3.sv source file.  DDR3 is as simple to run as DDR2, DDR except for the different power-up settings and a few new commands and # of clock cycles.  Maybe a punishment for not writing your own HDMI transmitter would be writing your own DDR3.sv.  Micron does have a DDR3 Verilog testbench code which was designed to validate/verify functionality of your DDR3.sv controller which you can run in ModelSim.  Sorta like my testbench code which drives and tests the 3 Geometry unit sections wired together to render an output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 13, 2021, 01:03:28 am
DDR3 is as simple to run as DDR2, DDR except for the different power-up settings and a few new commands and # of clock cycles.  Maybe a punishment for not writing your own HDMI transmitter would be writing your own DDR3.sv.  Micron does have a DDR3 Verilog testbench code which was designed to validate/verify functionality of your DDR3.sv controller which you can run in ModelSim.  Sorta like my testbench code which drives and tests the 3 Geometry unit sections wired together to render an output.
I'm afraid that's not going to be quite that simple. Even the minimal DDR3 frequency (303 MHz) is beyond what's possible to statically capture (i.e. write IO constraints such that P&R will ensure IO timings are always held over entire PVT range) on all FPGAs available to hobbyists. That means you will have to do a runtime calibration to find the right delay to capture data safely, as well as ensure proper alignment of DQ to DQS signals at the memory device side. Also due to fly-by routing these delays are going to be different for each byte group. And you will have to repeat these calibrations every once in a while at runtime because data alignment is dependent on temperature of dies.
To help illustrate the complexity, take a look at attached table which shows resources required for various external memory types for the same 72 bit data bus. As you can see, DDR3 requires quite a bit more resources than DDR2, and pretty much all of that additional logic goes towards calibration. If you care to read, Xilinx UG586 has very detailed explanation of how memory controller works, and can provide you with some insights even if you will end up rolling out your own.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 13, 2021, 02:17:14 am
That double extra LUT and gates is not from the ZQ CALIBRATION Long and Short pattern generator, or for it's timeout timer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 13, 2021, 03:39:49 am
That double extra LUT and gates is not from the ZQ CALIBRATION Long and Short pattern generator, or for it's timeout timer.
Then what it is?

My point is I think you are trying to bite more than you can chew. To my knowledge, HW-agnostic DDR3 controller does not exist at this point, and there's got to be a reason for it.

Speaking of which - I have tried generating UniPHY-based DDR3 controller for MAX10 device (for the DECA boards I received today), and generator failed with some cryptic messages. Before I tried doing it for CV with the same results - it generates "something", but ultimately fails so I don't really know if whatever it's generated is usable or not. I've been using the most recent Quartus Lite version (20.1.1 I think) just to be sure. Have you tried generating it, and if so - did it work?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 13, 2021, 04:35:54 am
That double extra LUT and gates is not from the ZQ CALIBRATION Long and Short pattern generator, or for it's timeout timer.
Then what it is?

My point is I think you are trying to bite more than you can chew. To my knowledge, HW-agnostic DDR3 controller does not exist at this point, and there's got to be a reason for it.
Speaking of which - I have tried generating UniPHY-based DDR3 controller for MAX10 device (for the DECA boards I received today), and generator failed with some cryptic messages. Before I tried doing it for CV with the same results - it generates "something", but ultimately fails so I don't really know if whatever it's generated is usable or not. I've been using the most recent Quartus Lite version (20.1.1 I think) just to be sure.
Look at a DDR3 command table compared to a DDR2.  DDR2 has only 2 different read and write commands.  DDR3 has 4 different read and 4 different write commands depending on burst length you want to RX/TX.  That is 2 fold the difficulty for the state machine, so, double the LUTs, unless you want to sacrifice performance.  Yes, the calibration eats some additional gates, but not double the LUT unless ther developer of the new ram controller made some poor programming choices, or to achieve the higher required FMAX, there was no choice but to rely less on combinational logic and add LUTs.

The calibration is needed to the ram to work properly.  If you are operating <=400MHz, you can trick the calibration by transmitting the test pattern a little late, like 500ps, then move your clock DQ & DQS phase back to 0ps during operation if you want to avoid re-calibration.  There is no way running a 800MHz ram chip at 400MHz will make enough heat in the chip or your FPGA to throw out the timing by over over 500ps on a 800MHz ram chip with 1600mtps.  So long as your FPGA is generating and driving the DDR3 clocks.  With an external clock buffer, forget it, you need to continuously re-calibrate as too many uncertainties creep in over time.

As for the Quartus, if the DDR3 compiler give you a weird 'ERROR, like unfound linux command during generation', Nockieboy finally got his to compile.  The DDR3 generator needs Linux runtime/command shell environment for Win10 installed with an added 'path' setting in the system.  You would have to ask him as I'm still on Win7 and cannot use the latest Quartus ram compiler.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 13, 2021, 04:54:09 am
Lattice seems to have a configurable DDR3 verilog library function.

Also, with 1 single line change to my .bmp rendering test-bench, their Active_HDL runtime simulator seems to work fine.  The setup.do also needs a few changes to match the available feature set.  I'll upload the new testbench tomorrow which will support both ModelSim and ActiveHDL.  I don't think this bug is connected to Xilinx, unless Xilinx was having trouble with the $fwrite (fpointer,"%u",'a32bitX15word-array') command.  I had to change it to a loop which would point to each individual word in the array, 1 $frwite at a time to make ActiveHDL accept it.

I might have to install Xilinx to see why their RTL simulator wont work.
This testbench was not designed for gate level / timing simulation, purely RTL only.

Their simulation speed is comparable to ModelSim, just a little slower on the compile.  Something like 4 seconds VS 2 seconds.  Waveform view, scroll speed, command line functions are much better in modelsim.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 13, 2021, 05:08:09 am
There is no way running a 800MHz ram chip at 400MHz will make enough heat in the chip or your FPGA to throw out the timing by over over 500ps on a 800MHz ram chip with 1600mtps.
My FPGA gets up to 60°C (with heatsink attached!), and DDR3 chip is in mid-40. So there is quite a bit of temperature change. BGAs usually reject quite a bit of heat into the power/ground planes. And if your board is compact and has got other components which do the same (typically DC-DC converters are designed that way, and each FPGA board usually has a number of them), heat can actually ascend from those power/ground planes to chips and warm them up. Not no mention that heating reference planes and prepreg also changes their physical properties. I don't exactly know if it's bad enough for relatively low DDR3 frequencies (~400 MHz is very low as DDR3 JEDEC specs go all the way to 2133 MT/1066 MHz IIRC), but the effect is there, and can cause issues if your design is marginal to begin with.

I know that Xilinx DDR3 memory controller uses on-chip ADC with attached temperature sensor to help maintain calibration, and even with that it still does dummy reads every 1 ms (if the bus is idle) to maintain DQ/DQS timing. Again - not sure how necessary it really is for low frequencies, but the fact that they went into trouble implementing that tells me they think it's important enough for reliability. Their controller is guaranteed to work in entire PVT envelope, unlike many homebred ones which are typically only tested at "normal" lab conditions and so nobody knows what's gonna happen if you try running it in any other conditions.

As for the Quartus, if the DDR3 compiler give you a weird 'ERROR, like unfound linux command during generation', Nockieboy finally got his to compile.  The DDR3 generator needs Linux runtime/command shell environment for Win10 installed with an added 'path' setting in the system.  You would have to ask him as I'm still on Win7 and cannot use the latest Quartus ram compiler.
I have WSL2 installed, but it still doesn't work. Not sure about the "path" part though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 13, 2021, 05:17:42 am
Sorry, it's not a path, but bash which needs to be installed.  Discussion here:
https://community.intel.com/t5/Intel-Quartus-Prime-Software/DDR3-megawizard-generation-error-in-Quartus-20-1/td-p/1244332 (https://community.intel.com/t5/Intel-Quartus-Prime-Software/DDR3-megawizard-generation-error-in-Quartus-20-1/td-p/1244332)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 13, 2021, 05:46:34 am
but the effect is there, and can cause issues if your design is marginal to begin with.

:-DD Marginal?  My PCB are tested running in an insulated heated oven at 125 degrees Celsius operating with consumer grade IC, but 125 degree caps for 24 hours before release.  A single bit error is a fail.  Before I learned my lesson, yes, I had some embarrassing field failures.  Oven baked burn in is the only way to go when publicly releasing hardware.  Non of my heat treated units have failed in the field.

However, I do \know how to manipulate Quartus to layout all it's IO pin buffers to the actual final clocked logic cell offering the tightest timing with reference to the PLL.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 13, 2021, 01:41:42 pm
Sorry, it's not a path, but bash which needs to be installed.  Discussion here:
https://community.intel.com/t5/Intel-Quartus-Prime-Software/DDR3-megawizard-generation-error-in-Quartus-20-1/td-p/1244332 (https://community.intel.com/t5/Intel-Quartus-Prime-Software/DDR3-megawizard-generation-error-in-Quartus-20-1/td-p/1244332)
Did all of that - still doesn't work:
Code: [Select]
Info: DDR3C: Variation language : Verilog
Info: DDR3C: Output directory : D:\Andrey\Projects\Altera\DECA_DDR
Info: DDR3C: Generating variation file D:\Andrey\Projects\Altera\DECA_DDR\DDR3C.v
Info: DDR3C: Generating synthesis files
<html>Info: Generating <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>" for QUARTUS_SYNTH
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_pll</b> "<b>pll0</b>"
Info: Generating clock pair generator
Info: Generating altgpio
Info:
Info: *****************************
Info:
Info: Remember to run the DDR3C_p0_pin_assignments.tcl
Info: script after running Synthesis and before Fitting.
Info:
Info: *****************************
Info:
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_phy_core</b> "<b>p0</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_afi_mux</b> "<b>m0</b>"
Error: Error during execution of "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt": child process exited abnormally
Error: Execution of command "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt" failed
Error: /mnt/c/intelfpga_lite/20.1/quartus/bin64/uniphy_mcc.exe -ac_code sequencer_mc/ac_rom.s -inst_code sequencer_mc/inst_rom.s -ac_rom ../DDR3C_s0_AC_ROM.hex -inst_rom ../DDR3C_s0_inst_ROM.hex -header sequencer/sequencer_auto.h -vheader ../sequencer_auto_h.sv -ac_rom_init sequencer/sequencer_auto_ac_init.c -inst_rom_init sequencer/sequencer_auto_inst_init.c -DAC_ROM_USER_ADD_0=0_0000_0000_0000 -DAC_ROM_USER_ADD_1=0_0000_0000_1000 -DAC_ROM_MR0=0001000010001 -DAC_ROM_MR0_CALIB= -DAC_ROM_MR0_DLL_RESET=0001100010000 -DAC_ROM_MR1=0000001000100 -DAC_ROM_MR1_OCD_ENABLE= -DAC_ROM_MR2=0000000000000 -DAC_ROM_MR3=0000000000000 -DAC_ROM_MR0_MIRR=0001000001001 -DAC_ROM_MR0_DLL_RESET_MIRR=0001010001000 -DAC_ROM_MR1_MIRR=0000000100100 -DAC_ROM_MR2_MIRR=0000000000000 -DAC_ROM_MR3_MIRR=0000000000000 -DQUARTER_RATE=0 -DHALF_RATE=1 -DFULL_RATE=0 -DNON_DES_CAL=0 -DAP_MODE=0 -DGUARANTEED_READ_BRINGUP_TEST=0 -DMEM_ADDR_WIDTH=13 -DHARD_PHY=0
Error: UniPHY Sequencer Microcode Compiler
Error: Copyright (C) 2020  Intel Corporation. All rights reserved.
Error: Info: Reading sequencer_mc/ac_rom.s ...
Error: Info: Reading sequencer_mc/inst_rom.s ...
Error: Info: Writing ../DDR3C_s0_AC_ROM.hex ...
Error: Info: Writing ../DDR3C_s0_inst_ROM.hex ...
Error: Info: Writing sequencer/sequencer_auto_ac_init.c ...
Error: Info: Writing sequencer/sequencer_auto_inst_init.c ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing ../sequencer_auto_h.sv ...
Error: Info: Microcode compilation successful
Error: /mnt/c/intelfpga_lite/20.1/quartus/../nios2eds/sdk2/bin/nios2-bsp hal sequencer_bsp .. --default_sections_mapping sequencer_mem --use_bootloader DONT_CHANGE
Error: nios2-bsp: Using /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl to set system-dependent settings.
Error: nios2-bsp: Updating existing BSP because sequencer_bsp/settings.bsp exists.
Error: nios2-bsp: Using SOPC design file ../pre_compile.sopcinfo found in ..
Error: nios2-bsp: Running "nios2-bsp-update-settings --settings sequencer_bsp/settings.bsp --bsp-dir sequencer_bsp --sopc ../pre_compile.sopcinfo --script /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl default_sections_mapping sequencer_mem use_bootloader DONT_CHANGE "
Error: child process exited abnormally
Error: Cannot find sequencer/sequencer.elf
<html>Error: An error occurred<br>    while executing<br>"error "An error occurred""<br>    (procedure "_error" line 8)<br>    invoked from within<br>"_error "Cannot find $seq_file""<br>    ("if" then script line 2)<br>    invoked from within<br>"if {[file exists $seq_file] == 0} {<br> _error "Cannot find $seq_file"<br> }"<br>    (procedure "alt_mem_if::util::seq_mem_size::get_max_memory_usage" line 14)<br>    invoked from within<br>"alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf""<br>    invoked from within<br>"set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf"]]"<br>    ("if" then script line 2)<br>    invoked from within<br>"if { !$do_only_rw_mgr_mc && !($bfm_mode || $hps_mode)} {<br> set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequenc..."<br>    (procedure "generate_qsys_sequencer_sw" line 943)<br>    invoked from within<br>"generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name $ac_rom_init_file_name ..."<br>    invoked from within<br>"set seq_mem_size_list [generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name ..."<br>    ("if" else script line 2)<br>    invoked from within<br>"if {[::alt_mem_if::util::qini::qini_value alt_mem_if_seq_size_request 0] > 0} {<br> set seq_mem_size [::alt_mem_if::util::qini::qini_value alt_mem_if_se..."<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer" line 238)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}"<br>    invoked from within<br>"set qsys_sequencer_files_list [alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}]"<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_sequencer_files" line 3)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir QUARTUS_SYNTH"<br>    invoked from within<br>"foreach generated_file [alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir QUARTUS_SYNTH] {<br> set file_name [file tail $genera..."<br>    (procedure "generate_synth" line 8)<br>    invoked from within<br>"generate_synth DDR3C_s0"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_qseq</b> "<b>s0</b>"
Error: Generation stopped, 1 or more modules remaining
<html>Info: Done "<b>DDR3C</b>" with 7 modules, 29 files
Info: DDR3C: Generating simulation model
<html>Info: Generating <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>" for SIM_VERILOG
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_pll</b> "<b>pll0</b>"
Info: Generating clock pair generator
Info: Generating altgpio
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_phy_core</b> "<b>p0</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_afi_mux</b> "<b>m0</b>"
Error: Error during execution of "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt": child process exited abnormally
Error: Execution of command "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt" failed
Error: /mnt/c/intelfpga_lite/20.1/quartus/bin64/uniphy_mcc.exe -ac_code sequencer_mc/ac_rom.s -inst_code sequencer_mc/inst_rom.s -ac_rom ../DDR3C_s0_AC_ROM.hex -inst_rom ../DDR3C_s0_inst_ROM.hex -header sequencer/sequencer_auto.h -vheader ../sequencer_auto_h.sv -ac_rom_init sequencer/sequencer_auto_ac_init.c -inst_rom_init sequencer/sequencer_auto_inst_init.c -DAC_ROM_USER_ADD_0=0_0000_0000_0000 -DAC_ROM_USER_ADD_1=0_0000_0000_1000 -DAC_ROM_MR0=0001000010001 -DAC_ROM_MR0_CALIB= -DAC_ROM_MR0_DLL_RESET=0001100010000 -DAC_ROM_MR1=0000001000100 -DAC_ROM_MR1_OCD_ENABLE= -DAC_ROM_MR2=0000000000000 -DAC_ROM_MR3=0000000000000 -DAC_ROM_MR0_MIRR=0001000001001 -DAC_ROM_MR0_DLL_RESET_MIRR=0001010001000 -DAC_ROM_MR1_MIRR=0000000100100 -DAC_ROM_MR2_MIRR=0000000000000 -DAC_ROM_MR3_MIRR=0000000000000 -DQUARTER_RATE=0 -DHALF_RATE=1 -DFULL_RATE=0 -DNON_DES_CAL=0 -DAP_MODE=0 -DGUARANTEED_READ_BRINGUP_TEST=0 -DMEM_ADDR_WIDTH=13 -DHARD_PHY=0
Error: UniPHY Sequencer Microcode Compiler
Error: Copyright (C) 2020  Intel Corporation. All rights reserved.
Error: Info: Reading sequencer_mc/ac_rom.s ...
Error: Info: Reading sequencer_mc/inst_rom.s ...
Error: Info: Writing ../DDR3C_s0_AC_ROM.hex ...
Error: Info: Writing ../DDR3C_s0_inst_ROM.hex ...
Error: Info: Writing sequencer/sequencer_auto_ac_init.c ...
Error: Info: Writing sequencer/sequencer_auto_inst_init.c ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing ../sequencer_auto_h.sv ...
Error: Info: Microcode compilation successful
Error: /mnt/c/intelfpga_lite/20.1/quartus/../nios2eds/sdk2/bin/nios2-bsp hal sequencer_bsp .. --default_sections_mapping sequencer_mem --use_bootloader DONT_CHANGE
Error: nios2-bsp: Using /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl to set system-dependent settings.
Error: nios2-bsp: Updating existing BSP because sequencer_bsp/settings.bsp exists.
Error: nios2-bsp: Using SOPC design file ../pre_compile.sopcinfo found in ..
Error: nios2-bsp: Running "nios2-bsp-update-settings --settings sequencer_bsp/settings.bsp --bsp-dir sequencer_bsp --sopc ../pre_compile.sopcinfo --script /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl default_sections_mapping sequencer_mem use_bootloader DONT_CHANGE "
Error: child process exited abnormally
Error: Cannot find sequencer/sequencer.elf
<html>Error: An error occurred<br>    while executing<br>"error "An error occurred""<br>    (procedure "_error" line 8)<br>    invoked from within<br>"_error "Cannot find $seq_file""<br>    ("if" then script line 2)<br>    invoked from within<br>"if {[file exists $seq_file] == 0} {<br> _error "Cannot find $seq_file"<br> }"<br>    (procedure "alt_mem_if::util::seq_mem_size::get_max_memory_usage" line 14)<br>    invoked from within<br>"alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf""<br>    invoked from within<br>"set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf"]]"<br>    ("if" then script line 2)<br>    invoked from within<br>"if { !$do_only_rw_mgr_mc && !($bfm_mode || $hps_mode)} {<br> set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequenc..."<br>    (procedure "generate_qsys_sequencer_sw" line 943)<br>    invoked from within<br>"generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name $ac_rom_init_file_name ..."<br>    invoked from within<br>"set seq_mem_size_list [generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name ..."<br>    ("if" else script line 2)<br>    invoked from within<br>"if {[::alt_mem_if::util::qini::qini_value alt_mem_if_seq_size_request 0] > 0} {<br> set seq_mem_size [::alt_mem_if::util::qini::qini_value alt_mem_if_se..."<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer" line 238)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}"<br>    invoked from within<br>"set qsys_sequencer_files_list [alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}]"<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_sequencer_files" line 3)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir SIM_VERILOG"<br>    invoked from within<br>"foreach generated_file [alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir SIM_VERILOG] {<br> set file_name [file tail $generate..."<br>    (procedure "generate_verilog_sim" line 7)<br>    invoked from within<br>"generate_verilog_sim DDR3C_s0"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_qseq</b> "<b>s0</b>"
Error: Generation stopped, 1 or more modules remaining
<html>Info: Done "<b>DDR3C</b>" with 7 modules, 21 files
Info: Generated simulation scripts for Modelsim in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/mentor directory.
Info: Generated simulation scripts for VCS and VCS MX in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/synopsys directory.
Info: Generated simulation scripts for NCSIM in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/cadence directory.
Info: Generated simulation scripts for Riviera-PRO in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/aldec directory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 13, 2021, 02:08:46 pm
Sorry, it's not a path, but bash which needs to be installed.  Discussion here:
https://community.intel.com/t5/Intel-Quartus-Prime-Software/DDR3-megawizard-generation-error-in-Quartus-20-1/td-p/1244332 (https://community.intel.com/t5/Intel-Quartus-Prime-Software/DDR3-megawizard-generation-error-in-Quartus-20-1/td-p/1244332)
Did all of that - still doesn't work:
Code: [Select]
Info: DDR3C: Variation language : Verilog
Info: DDR3C: Output directory : D:\Andrey\Projects\Altera\DECA_DDR
Info: DDR3C: Generating variation file D:\Andrey\Projects\Altera\DECA_DDR\DDR3C.v
Info: DDR3C: Generating synthesis files
<html>Info: Generating <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>" for QUARTUS_SYNTH
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_pll</b> "<b>pll0</b>"
Info: Generating clock pair generator
Info: Generating altgpio
Info:
Info: *****************************
Info:
Info: Remember to run the DDR3C_p0_pin_assignments.tcl
Info: script after running Synthesis and before Fitting.
Info:
Info: *****************************
Info:
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_phy_core</b> "<b>p0</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_afi_mux</b> "<b>m0</b>"
Error: Error during execution of "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt": child process exited abnormally
Error: Execution of command "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt" failed
Error: /mnt/c/intelfpga_lite/20.1/quartus/bin64/uniphy_mcc.exe -ac_code sequencer_mc/ac_rom.s -inst_code sequencer_mc/inst_rom.s -ac_rom ../DDR3C_s0_AC_ROM.hex -inst_rom ../DDR3C_s0_inst_ROM.hex -header sequencer/sequencer_auto.h -vheader ../sequencer_auto_h.sv -ac_rom_init sequencer/sequencer_auto_ac_init.c -inst_rom_init sequencer/sequencer_auto_inst_init.c -DAC_ROM_USER_ADD_0=0_0000_0000_0000 -DAC_ROM_USER_ADD_1=0_0000_0000_1000 -DAC_ROM_MR0=0001000010001 -DAC_ROM_MR0_CALIB= -DAC_ROM_MR0_DLL_RESET=0001100010000 -DAC_ROM_MR1=0000001000100 -DAC_ROM_MR1_OCD_ENABLE= -DAC_ROM_MR2=0000000000000 -DAC_ROM_MR3=0000000000000 -DAC_ROM_MR0_MIRR=0001000001001 -DAC_ROM_MR0_DLL_RESET_MIRR=0001010001000 -DAC_ROM_MR1_MIRR=0000000100100 -DAC_ROM_MR2_MIRR=0000000000000 -DAC_ROM_MR3_MIRR=0000000000000 -DQUARTER_RATE=0 -DHALF_RATE=1 -DFULL_RATE=0 -DNON_DES_CAL=0 -DAP_MODE=0 -DGUARANTEED_READ_BRINGUP_TEST=0 -DMEM_ADDR_WIDTH=13 -DHARD_PHY=0
Error: UniPHY Sequencer Microcode Compiler
Error: Copyright (C) 2020  Intel Corporation. All rights reserved.
Error: Info: Reading sequencer_mc/ac_rom.s ...
Error: Info: Reading sequencer_mc/inst_rom.s ...
Error: Info: Writing ../DDR3C_s0_AC_ROM.hex ...
Error: Info: Writing ../DDR3C_s0_inst_ROM.hex ...
Error: Info: Writing sequencer/sequencer_auto_ac_init.c ...
Error: Info: Writing sequencer/sequencer_auto_inst_init.c ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing ../sequencer_auto_h.sv ...
Error: Info: Microcode compilation successful
Error: /mnt/c/intelfpga_lite/20.1/quartus/../nios2eds/sdk2/bin/nios2-bsp hal sequencer_bsp .. --default_sections_mapping sequencer_mem --use_bootloader DONT_CHANGE
Error: nios2-bsp: Using /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl to set system-dependent settings.
Error: nios2-bsp: Updating existing BSP because sequencer_bsp/settings.bsp exists.
Error: nios2-bsp: Using SOPC design file ../pre_compile.sopcinfo found in ..
Error: nios2-bsp: Running "nios2-bsp-update-settings --settings sequencer_bsp/settings.bsp --bsp-dir sequencer_bsp --sopc ../pre_compile.sopcinfo --script /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl default_sections_mapping sequencer_mem use_bootloader DONT_CHANGE "
Error: child process exited abnormally
Error: Cannot find sequencer/sequencer.elf
<html>Error: An error occurred<br>    while executing<br>"error "An error occurred""<br>    (procedure "_error" line 8)<br>    invoked from within<br>"_error "Cannot find $seq_file""<br>    ("if" then script line 2)<br>    invoked from within<br>"if {[file exists $seq_file] == 0} {<br> _error "Cannot find $seq_file"<br> }"<br>    (procedure "alt_mem_if::util::seq_mem_size::get_max_memory_usage" line 14)<br>    invoked from within<br>"alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf""<br>    invoked from within<br>"set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf"]]"<br>    ("if" then script line 2)<br>    invoked from within<br>"if { !$do_only_rw_mgr_mc && !($bfm_mode || $hps_mode)} {<br> set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequenc..."<br>    (procedure "generate_qsys_sequencer_sw" line 943)<br>    invoked from within<br>"generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name $ac_rom_init_file_name ..."<br>    invoked from within<br>"set seq_mem_size_list [generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name ..."<br>    ("if" else script line 2)<br>    invoked from within<br>"if {[::alt_mem_if::util::qini::qini_value alt_mem_if_seq_size_request 0] > 0} {<br> set seq_mem_size [::alt_mem_if::util::qini::qini_value alt_mem_if_se..."<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer" line 238)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}"<br>    invoked from within<br>"set qsys_sequencer_files_list [alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}]"<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_sequencer_files" line 3)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir QUARTUS_SYNTH"<br>    invoked from within<br>"foreach generated_file [alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir QUARTUS_SYNTH] {<br> set file_name [file tail $genera..."<br>    (procedure "generate_synth" line 8)<br>    invoked from within<br>"generate_synth DDR3C_s0"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_qseq</b> "<b>s0</b>"
Error: Generation stopped, 1 or more modules remaining
<html>Info: Done "<b>DDR3C</b>" with 7 modules, 29 files
Info: DDR3C: Generating simulation model
<html>Info: Generating <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>" for SIM_VERILOG
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_emif</b> "<b>DDR3C</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_pll</b> "<b>pll0</b>"
Info: Generating clock pair generator
Info: Generating altgpio
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_phy_core</b> "<b>p0</b>"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_afi_mux</b> "<b>m0</b>"
Error: Error during execution of "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt": child process exited abnormally
Error: Execution of command "{C:/intelfpga_lite/20.1/quartus//../nios2eds/Nios II Command Shell.bat} make all 2>> stderr.txt" failed
Error: /mnt/c/intelfpga_lite/20.1/quartus/bin64/uniphy_mcc.exe -ac_code sequencer_mc/ac_rom.s -inst_code sequencer_mc/inst_rom.s -ac_rom ../DDR3C_s0_AC_ROM.hex -inst_rom ../DDR3C_s0_inst_ROM.hex -header sequencer/sequencer_auto.h -vheader ../sequencer_auto_h.sv -ac_rom_init sequencer/sequencer_auto_ac_init.c -inst_rom_init sequencer/sequencer_auto_inst_init.c -DAC_ROM_USER_ADD_0=0_0000_0000_0000 -DAC_ROM_USER_ADD_1=0_0000_0000_1000 -DAC_ROM_MR0=0001000010001 -DAC_ROM_MR0_CALIB= -DAC_ROM_MR0_DLL_RESET=0001100010000 -DAC_ROM_MR1=0000001000100 -DAC_ROM_MR1_OCD_ENABLE= -DAC_ROM_MR2=0000000000000 -DAC_ROM_MR3=0000000000000 -DAC_ROM_MR0_MIRR=0001000001001 -DAC_ROM_MR0_DLL_RESET_MIRR=0001010001000 -DAC_ROM_MR1_MIRR=0000000100100 -DAC_ROM_MR2_MIRR=0000000000000 -DAC_ROM_MR3_MIRR=0000000000000 -DQUARTER_RATE=0 -DHALF_RATE=1 -DFULL_RATE=0 -DNON_DES_CAL=0 -DAP_MODE=0 -DGUARANTEED_READ_BRINGUP_TEST=0 -DMEM_ADDR_WIDTH=13 -DHARD_PHY=0
Error: UniPHY Sequencer Microcode Compiler
Error: Copyright (C) 2020  Intel Corporation. All rights reserved.
Error: Info: Reading sequencer_mc/ac_rom.s ...
Error: Info: Reading sequencer_mc/inst_rom.s ...
Error: Info: Writing ../DDR3C_s0_AC_ROM.hex ...
Error: Info: Writing ../DDR3C_s0_inst_ROM.hex ...
Error: Info: Writing sequencer/sequencer_auto_ac_init.c ...
Error: Info: Writing sequencer/sequencer_auto_inst_init.c ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing sequencer/sequencer_auto.h ...
Error: Info: Writing ../sequencer_auto_h.sv ...
Error: Info: Microcode compilation successful
Error: /mnt/c/intelfpga_lite/20.1/quartus/../nios2eds/sdk2/bin/nios2-bsp hal sequencer_bsp .. --default_sections_mapping sequencer_mem --use_bootloader DONT_CHANGE
Error: nios2-bsp: Using /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl to set system-dependent settings.
Error: nios2-bsp: Updating existing BSP because sequencer_bsp/settings.bsp exists.
Error: nios2-bsp: Using SOPC design file ../pre_compile.sopcinfo found in ..
Error: nios2-bsp: Running "nios2-bsp-update-settings --settings sequencer_bsp/settings.bsp --bsp-dir sequencer_bsp --sopc ../pre_compile.sopcinfo --script /mnt/c/intelfpga_lite/20.1/nios2eds/sdk2/bin/bsp-set-defaults.tcl default_sections_mapping sequencer_mem use_bootloader DONT_CHANGE "
Error: child process exited abnormally
Error: Cannot find sequencer/sequencer.elf
<html>Error: An error occurred<br>    while executing<br>"error "An error occurred""<br>    (procedure "_error" line 8)<br>    invoked from within<br>"_error "Cannot find $seq_file""<br>    ("if" then script line 2)<br>    invoked from within<br>"if {[file exists $seq_file] == 0} {<br> _error "Cannot find $seq_file"<br> }"<br>    (procedure "alt_mem_if::util::seq_mem_size::get_max_memory_usage" line 14)<br>    invoked from within<br>"alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf""<br>    invoked from within<br>"set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequencer" "sequencer.elf"]]"<br>    ("if" then script line 2)<br>    invoked from within<br>"if { !$do_only_rw_mgr_mc && !($bfm_mode || $hps_mode)} {<br> set calc_mem_size [alt_mem_if::util::seq_mem_size::get_max_memory_usage [file join "sequenc..."<br>    (procedure "generate_qsys_sequencer_sw" line 943)<br>    invoked from within<br>"generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name $ac_rom_init_file_name ..."<br>    invoked from within<br>"set seq_mem_size_list [generate_qsys_sequencer_sw $prepend_str $protocol $pre_compile_dir $fileset $inhdl_dir $rdimm $lrdimm 0 0  $nios_hex_file_name ..."<br>    ("if" else script line 2)<br>    invoked from within<br>"if {[::alt_mem_if::util::qini::qini_value alt_mem_if_seq_size_request 0] > 0} {<br> set seq_mem_size [::alt_mem_if::util::qini::qini_value alt_mem_if_se..."<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer" line 238)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}"<br>    invoked from within<br>"set qsys_sequencer_files_list [alt_mem_if::gen::uniphy_gen::generate_qsys_sequencer "${name}" $protocol $tmpdir $fileset {}]"<br>    (procedure "alt_mem_if::gen::uniphy_gen::generate_sequencer_files" line 3)<br>    invoked from within<br>"alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir SIM_VERILOG"<br>    invoked from within<br>"foreach generated_file [alt_mem_if::gen::uniphy_gen::generate_sequencer_files $name "DDR3" $tmpdir SIM_VERILOG] {<br> set file_name [file tail $generate..."<br>    (procedure "generate_verilog_sim" line 7)<br>    invoked from within<br>"generate_verilog_sim DDR3C_s0"
<html>Info: "<b>DDR3C</b>" instantiated <b>altera_mem_if_ddr3_qseq</b> "<b>s0</b>"
Error: Generation stopped, 1 or more modules remaining
<html>Info: Done "<b>DDR3C</b>" with 7 modules, 21 files
Info: Generated simulation scripts for Modelsim in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/mentor directory.
Info: Generated simulation scripts for VCS and VCS MX in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/synopsys directory.
Info: Generated simulation scripts for NCSIM in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/cadence directory.
Info: Generated simulation scripts for Riviera-PRO in D:/Andrey/Projects/Altera/DECA_DDR/DDR3C_sim/aldec directory.

Please make a separate thread.  8 bit GPU has nothing to do with a dev board's compilation errors.
And without Win10, I will obviously wont get that far unless I use an older version of Quartus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 14, 2021, 12:24:35 am
asmi has been singing the virtues of Xilinx for months now and if he's happy to help out where he can, perhaps it's not such a bad idea. Naturally, there'd be a huge learning curve for me with the tool chain etc, but maybe it's time to address that elephant in the room?
I would be happy to help. Also I do think you overestimate the learning curve - it's going to be much easier than you perhaps expect, because fundamentally it's the same flow - you add source files, you run simulations until everything works like it should (in Vivado it's possible to add simulation-only sources to reduce the clutter in the main tree), then you run elaboration and set up IO pin mapping, then you run place&route, generate bitstream - and that's it! You can also program FPGA straight from the IDE, as well as program attached flash devices.
There is additional flow through IP integrator, but you can leave it alone at first and do RTL-only designs. This is kind of Altera's qsys system builder flow, but implemented right IMHO. But if you want to see cool stuff you can do with IPI, I can guide you through that as well.
There are much more functionality in the IDE, but you can kind of ignore it at first until you are comfortable with the basics.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 15, 2021, 12:24:22 am
OK, I said I wouldn't do anything to the GPU Geometry testbench, but I been playing with Lattice Diamond FPGA who uses Active-HDL instead of ModelSim for code development and debugging.  I only had to make one change to the code and a new setup script for Active-HDL.  I've attached the updated test-bench which now works on both HDL simulators.

Here are the setup instructions for both environments:
(For Active-HDL, just run Active-HDL all on it's own outside Lattice Diamond, it is located in your start menu, Lattice/Accessories)
(Same for ModelSim, just run it on it's own, located in Intel FPGA/Modelsim)
Code: [Select]
/*
 * GPU_GEO_tb.sv, for ModelSim and ***NEW Active-HDL.
 *
 * Features control from a source ascii text file script,
 * and a 256 color .BMP picture file generator.
 * Tested on free Altera ModelSim 10 & 20.  Built in parameter
 * (USE_ALTERA_IP) when disabled prevents the use of any Altera specific IP functions.
 *
 * Written by Brian Guralnick.
 *
 * v 0.6.001   Feb 01, 2021
 *
 * To setup simulation, Start Modelsim, The goto 'File - Change Directory' and select this files directory.
 * Then in the transcript, type:
 * do setup_ms.do
 * (or if you want to enable the Altera megafunction IP, LPM_MULT & SCFIFO)
 * do setup_altera.do
 *
 * To change the 'TB_COMMAND_SCRIPT_FILE' source script file string and re-run the simulation, type:
 *
 * do test_8bitfont.do
 * do test_45deg.do
 * do test_art.do
 * do test_blitter.do
 * do test_blitter_hires.do
 * do test_vwait.do
 *
 *
 *****************************************************************************
 * For Active-HDL (Comes with Lattice Diamond FPGA developement enviroment.)
 *****************************************************************************
 *
 * Go to 'File - New / Design'
 *        Create an empty design.
 *        Choose Verilog for HDL language, ignore 'Target Technology'.
 *        Type in 'GPU_GEO_tb' for design name.
 *        Next/Finish.
 *       
 * Unzip all the files directly into the 'src' directory inside the 'GPU_GEO_tb' folder.
 * In the console, type:
 *
 * do setup_active-hdl.do
 *
 * *** The result 'xxxx.bmp' and 'GEO_tb_command_results.txt' files generated by
 *     the simulation will be located in the main 'GPU_GEO_tb' folder.
 *
 * Active-HDL does not support the changing of a string in a .sv file,
 * so to run the different tb ascii script demos, you need to copy the:
 *
 * GEO_tb_art.txt
 * GEO_tb_Blitter.txt
 * GEO_tb_Blitter_hires.txt
 * GEO_tb_45deg_zilog.txt
 * GEO_tb_8bit_font.txt
 * GEO_tb_vwait.txt
 *
 * over the 'GEO_tb_command_list.txt' file, then do a restart & run simulation.
 *
 */

Enjoy.
( Stand alone V4 ELLIPSE generator and .BMP generator here -> https://www.eevblog.com/forum/fpga/systemverilog-example-testbench-which-saves-a-bmp-picture-and-executes-a-script/msg3465172/#msg3465172 (https://www.eevblog.com/forum/fpga/systemverilog-example-testbench-which-saves-a-bmp-picture-and-executes-a-script/msg3465172/#msg3465172) )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 15, 2021, 11:24:56 am
The case for $/LE is a strong one, but also so is availability of the parts.  Both of these considerations work against the Cyclones.  So the real decision is:  Lattice or Xilinx?

I've done some quick research on Mouser (I'm REALLY busy with work for the next few weeks, but it seems pointless putting hours into the DDR3 controller until we decide which FPGA family we're moving to).  A straight filter search on Mouser for an FPGA with between 20k-50k LEs, more than 1600Kbits of internal RAM and more than 110 I/OS, then ordered by price to look at the cheapest result spits out the following:

Maker      Model                            LEs           Embedded memory     I/Os        Package         Price
Xilinx        XC7S25-1CSGA225C       23,360      1,620kbit                      150          CSBGA-225     £24.23
Lattice      LFE5U-45F-6BG256C       44,000      1,944kbit                      197          CABGA-256     £12.09

Based on these metrics, Lattice is the clear winner, unless there's hidden details in the datasheets that could swing it?  Also, bearing in mind my usual provisos (I've never soldered BGAs before, other than a cheap soldering iron and even cheaper AliExpress hot air gun, I've got no other special equipment), I think it would be wise and very beneficial for me to create a cheap dev board for the Lattice device.  This would double as learning/practice for BGA soldering, but also provide a test bed for developing the GPU HDL further and before going all-out on the next GPU card iteration.

Plus, as a minor side effect, it would also put an open-source Lattice dev board out in the wild for anyone else who might otherwise be put off trying Lattice FPGAs because of the lack of cheap dev boards.  ^-^

In other news, the DECA boards arrived just now.  Can confirm there is no camera module in the box, just the board, couple of USB cables, Ethernet cable and power supply.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 15, 2021, 11:40:51 am
Maker      Model                            LEs           Embedded memory     I/Os        Package         Price
Xilinx        XC7S25-1CSGA225C       23,360      1,620kbit                      150          CSBGA-225     £24.23
Lattice      LFE5U-45F-6BG256C       44,000      1,944kbit                      197          CABGA-256     £12.09
No, No, No, what is the price of the  LFE5U-85F-6BG381C, 84,000 & 3,744kbit, 205 IOs.


Don't you want 1080p full motion MJPEG200 video playback & a full 3D accelerator?

BTW, XC7A35T-1FTG256I would have been a bit larger.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 15, 2021, 12:07:58 pm
Lattice      LFE5U-45F-6BG256C       44,000      1,944kbit                      197          CABGA-256     £12.09

No, No, No, what is the price of the  LFE5U-85F-6BG381C, 84,000 & 3,744kbit, 205 IOs.

Don't you want 1080p full motion MJPEG200 video playback & a full 3D accelerator?

I knew I would miss something.  ???  The LFE5U-85F-6BG381C is £24, all but for a few pence.

BTW, XC7A35T-1FTG256I would have been a bit larger.

Bit more expensive at £30 too.  Until I'm happy that I can solder BGAs without screwing it up, I'm uncomfortable spending too much on an FPGA to learn on.   :-//

So the revised comparison looks like this:
 
Maker      Model                             LEs          Embedded memory      I/Os       Package         Price
Xilinx        XC7A35T-1FTG256I         33,280      1,800kbit                      170          FBGA-225       £24.23
Lattice      LFE5U-85F-6BG381C       84,000      3,744kbit                      205          CABGA-381     £23.83
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 15, 2021, 12:22:36 pm
Ok, then see if the 'LFE5U-45F-6BG381C' exists.  It should be pin-pin compatible with the -85F.  It only appears to be missing 2 IOs in total.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 15, 2021, 01:32:46 pm
XC7A35T-1FTG256I
"I" in the end stands for industrial temps, it's more expensive than "C" variant.
Also - if you want cheap, you've got to go here (https://www.aliexpress.com/wholesale?trafficChannel=main&d=y&CatId=0&SearchText=XC7A35T&ltype=wholesale&SortType=price_asc&page=1&groupsort=1) :D Or here (https://www.aliexpress.com/wholesale?trafficChannel=main&d=y&CatId=0&SearchText=XC7A50T&ltype=wholesale&SortType=price_asc&groupsort=1&page=1) for 50T part. They've got a full assortment of Artix'es. Quality - unknown, price - cheap ;) Should be good enough for soldering practice.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 15, 2021, 02:17:47 pm
In other news, the DECA boards arrived just now.  Can confirm there is no camera module in the box, just the board, couple of USB cables, Ethernet cable and power supply.
Yea, mine arrived too. BrianHG, if you want one, pls send me your address in PM and I will send it to you for free as a token of my appreciation for everything you've done over here to help others.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 15, 2021, 05:38:20 pm
Ok, then see if the 'LFE5U-45F-6BG381C' exists.  It should be pin-pin compatible with the -85F.  It only appears to be missing 2 IOs in total.

It does, right here (https://www.mouser.co.uk/ProductDetail/Lattice/LFE5U-45F-6BG381C/).  Just over £14.  This is the one you'd recommend starting with?  That's a 0.8mm-pitch package - would that be easy enough with a stencil, some light application of solder paste and a hot plate/air gun combination?  If I'm going to be soldering BGAs, I'm probably going to need to invest in a hot plate of some kind.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 15, 2021, 06:19:06 pm
With Lattice part you will face the same issue you have with CV, namely lack of memory controller IP (or any other useful IPs for that matter). So why switching then? What benefits will Lattice part have over CV that will justify the switch, as well as possibly higher expense of having to go for 6 layer board due to 0.8 mm ball pitch? Currently there is a BIG jump in price between 4 layer boards and 6 layer ones, and JLCPCB's 6 layer stackup is no good for high-speed designs which require all 4 signal layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 15, 2021, 08:16:12 pm
XC7A35T-1FTG256I
"I" in the end stands for industrial temps, it's more expensive than "C" variant.
Also - if you want cheap, you've got to go here (https://www.aliexpress.com/wholesale?trafficChannel=main&d=y&CatId=0&SearchText=XC7A35T&ltype=wholesale&SortType=price_asc&page=1&groupsort=1) :D Or here (https://www.aliexpress.com/wholesale?trafficChannel=main&d=y&CatId=0&SearchText=XC7A50T&ltype=wholesale&SortType=price_asc&groupsort=1&page=1) for 50T part. They've got a full assortment of Artix'es. Quality - unknown, price - cheap ;) Should be good enough for soldering practice.
The Lattice part prices are at Arrow, Digikey & Future Electronics, for single pieces, not Aliexpress...
Yes, I know 0.8mm makes things a little more difficult, but sacrificing some of those extra IOs we can squeeze a 4 layer PCB.  Our only time critical paths will be the DDR3.
\
Yes, looking at Lattice dev tools, there is a learning curve and documentation could be better as I use their version of a  Megafunction Wizard 'Clarity Designer' to work out a lot about configuring the function as I just got the HDMI_PLL module to work, but having trouble simulation & telling Diamond what the external clock input frequency to avoid warnings, warnings, warnings.  Perhaps I have yet to find the right documentation sources.  And we still appear to have a separate timing constraints file which needs to be separate of the source code like Quartus, but at least now, with a common cross compatible .sv test bench architecture, I know I can render a timing constraints file by running a sim TB of my code only once before adding it to the .sdc file.

Xilinx does make the DDR3 black box easy, but there is something specific I want to do with all this spare time, so, this is why I started to engineer my code to be bottom end SystemVerilog, targeting 3 way platform support, (4 way with GOWIN which will be last after finishing a number of other useful functions which would cost many some real $$$).

I left Xilinx third because I bet they will be MUCH less trouble than Lattice Diamond, as this will force my code to have a number of eccentricities already prepared/worked out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on February 16, 2021, 04:05:55 pm
With Lattice part you will face the same issue you have with CV, namely lack of memory controller IP (or any other useful IPs for that matter). So why switching then? What benefits will Lattice part have over CV that will justify the switch, as well as possibly higher expense of having to go for 6 layer board due to 0.8 mm ball pitch? Currently there is a BIG jump in price between 4 layer boards and 6 layer ones, and JLCPCB's 6 layer stackup is no good for high-speed designs which require all 4 signal layers.

Nope, there are a lot of Lattice IPs including memory controllers for DDR/DDR2/DDR3. Problem is, those memory controllers are NOT free. (Available on the Lattice IP server.) Whereas Xilinx ones are free to use AFAIK. I have no clue how much the licenses are - you need to contact sales. So sure Xilinx is ahead here.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 16, 2021, 04:31:11 pm
Nope, there are a lot of Lattice IPs including memory controllers for DDR/DDR2/DDR3. Problem is, those memory controllers are NOT free. (Available on the Lattice IP server.)
That's as good as non-existent in my book.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 20, 2021, 07:59:01 am
Has anyone used Efinix?
Take a look here: ' https://www.digikey.com/en/products/detail/efinix-inc/T85F484C3/11591358 (https://www.digikey.com/en/products/detail/efinix-inc/T85F484C3/11591358) '

That's 20.29$ for 1 single 84K-gate, 4 megabit, 256 IO FPGA, with 1066 MTPS DDR3 controller.
They use a regular FTDI usb chip for the programmer making it easy to place your own firmware programmer on your pcb.

Or, 25.37$ for 112K-gate, 5.5 megabit ram, 256 IO.
https://www.digikey.com/en/products/detail/efinix-inc/T120F484C3/11591376 (https://www.digikey.com/en/products/detail/efinix-inc/T120F484C3/11591376)

However, It's like I cannot find the software dev tool download or complete documentation other than some video walk through, available ICs and dev boards.

I guess it's kinda useless for a public domain project if no one can get the compiler utilities.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on February 20, 2021, 04:43:13 pm
Has anyone used Efinix?
Take a look here: ' https://www.digikey.com/en/products/detail/efinix-inc/T85F484C3/11591358 (https://www.digikey.com/en/products/detail/efinix-inc/T85F484C3/11591358) '

Nope, but I've heard of them and they looked interesting.

However, It's like I cannot find the software dev tool download or complete documentation other than some video walk through, available ICs and dev boards.

Same here. When I looked, I was unable to get anything really needed to get started. Looks like you need to contact the vendor to be able do do anything?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on February 20, 2021, 04:48:45 pm
Nope, there are a lot of Lattice IPs including memory controllers for DDR/DDR2/DDR3. Problem is, those memory controllers are NOT free. (Available on the Lattice IP server.)
That's as good as non-existent in my book.

Well, for a personal or open-source project, that's certainly an issue. For a commercial one, that's not much of an issue if the pricing is right (which I don't know) and if you get support with the license.
Despite relatively cheap and easy to use parts, that would fit well for personal/hobby/open source projects IMO, Lattice doesn't seem to care all that much for this market. The fact they recently increased the price of their dev boards drastically tends to confirm that.

There are a couple open-source boards with ECP5 FPGAs though, and at least one of them actually has a DDR3 memory chip. (The OrangeCrab board.) I haven't looked at it much so far, I'll be curious to see if there are example projects using this memory, and if so, how they managed to control it. Writing your own DDR3 controller is not exactly a picnic. I'll try to figure that out.

I admit I much prefer the free IP catalog from Xilinx.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 20, 2021, 05:23:02 pm
So it looks like the IDE is available here on the support page (https://www.efinixinc.com/support/index.php), but you have to complete a fairly detailed registration process to access it (I don't have time to check it out properly at the moment).  It also appears you get a year's licence to use the IDE if you purchase a dev board, so from that I'm gathering the IDE isn't free.

EDIT: Yeah, you have to purchase a dev board or software licence.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 20, 2021, 09:03:44 pm
The real question is - do you really want to design in a noname FPGA with no community, almost no public information and a vendor who doesn't seem to care about you unless you're buying a million chips?
To me the answer is very obvious, but I'm not sure about your guys.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 20, 2021, 09:29:03 pm
The real question is - do you really want to design in a noname FPGA with no community, almost no public information and a vendor who doesn't seem to care about you unless you're buying a million chips?
To me the answer is very obvious, but I'm not sure about your guys.

No, I totally agree.

EDIT:  After a brief chat with Efinix's head of marketing, I got access to their IDE.  Aside from it looking like a Python IDE, it appears a little basic compared to what I'm used to with Quartus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 22, 2021, 10:02:44 am
So where am I going with this then?  I feel a little directionless at the moment, not least because I've had little time to think about the project, let alone work on it.

If I'm honest, I feel more comfortable switching to Xilinx than Lattice if I have to switch at all (though I'm open to discussion).  If we keep the code as platform-agnostic as possible, it shouldn't pose too many issues for anyone wanting to port the project to a platform of their choosing.  If they're looking to do that then I'd expect a higher level of competence with FPGAs than I have anyway, so it shouldn't be too big a hurdle.

Whilst the Cyclone V may not have the supply and production stability of more modern FPGAs, the 5CEBA2 is available at a price point I'm comfortable with for my application and I can get JLCPCB to mount it for me if I chicken out of soldering the FBGA-256 package myself.  We've shown the Cyclone IV can handle 1080p output through a less stable test circuit than the final PCB will have, so HDMI/DVI isn't an issue.

I guess the TL;DR for this post is this:  do I need to switch to Lattice/Xilinx for the next board, because if not I need to get cracking on the DDR design for the Cyclone V.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2021, 04:34:09 pm
Give me 6 more days.  I'm solving a problem your gonna have no matter the platform you choose.
Stay away from Efinix.
Work on other things in the mean time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 23, 2021, 06:35:20 am
I guess the TL;DR for this post is this:  do I need to switch to Lattice/Xilinx for the next board, because if not I need to get cracking on the DDR design for the Cyclone V.
That's a your decision to make, since this is your project. Each way has it's own pro and contra, there is no universal answer. Also I suspect that a big factor in this decision would be the mid- to long-term plans, as they might require additional resources.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 24, 2021, 05:10:16 am
@Nockieboy, I hope you are doing those other things.  I'm doing a ton of leg work for you...

Remember, you haven't demonstrated the VWAIT command for smooth animation.
Reported that the last GPU upload I sent still works.
And verified I fixed the blitter bugs.  (Well, I was able to do some checking in the new simulator test bench.)
As well as some other more impressive things you could try.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 24, 2021, 01:55:54 pm
@Nockieboy, I hope you are doing those other things.  I'm doing a ton of leg work for you...

Remember, you haven't demonstrated the VWAIT command for smooth animation.
Reported that the last GPU upload I sent still works.
And verified I fixed the blitter bugs.  (Well, I was able to do some checking in the new simulator test bench.)
As well as some other more impressive things you could try.

I've been using the last GPU upload since you uploaded it - it's definitely working.  :-+  As for the VWAIT testing, it works fine with my blitted text test which I modified over lunch to use it - although I'm finding any values more than 1 for hw_position with a multiplier of 1 (so low-byte values more than 0x81) make the scrolling too slow.  I can do accelerated scrolling, but it slows down scrolling to a crawl and isn't desirable as a result.  Using a value of 0x81 however, effectively replaces the 8-bit delay loop I had before and results in a nice smooth scroll.  :-+

Video of VWAIT scrolling here. (https://youtu.be/UFW5X_jLQAs)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 24, 2021, 06:58:17 pm
@Nockieboy, I hope you are doing those other things.  I'm doing a ton of leg work for you...

Remember, you haven't demonstrated the VWAIT command for smooth animation.
Reported that the last GPU upload I sent still works.
And verified I fixed the blitter bugs.  (Well, I was able to do some checking in the new simulator test bench.)
As well as some other more impressive things you could try.

I've been using the last GPU upload since you uploaded it - it's definitely working.  :-+  As for the VWAIT testing, it works fine with my blitted text test which I modified over lunch to use it - although I'm finding any values more than 1 for hw_position with a multiplier of 1 (so low-byte values more than 0x81) make the scrolling too slow.  I can do accelerated scrolling, but it slows down scrolling to a crawl and isn't desirable as a result.  Using a value of 0x81 however, effectively replaces the 8-bit delay loop I had before and results in a nice smooth scroll.  :-+

Video of VWAIT scrolling here. (https://youtu.be/UFW5X_jLQAs)
How strange, at 640x480, or worse, 320x240 60fps, I expected it to be twice as fast.  Are you transmitting these 2 commands in this order?  Only once before or after a complete vertical shift.
Line# 113, VWAIT for  1 frames, until line number   1.
           TX CMD > $0f08  =  ( 15) - (  1) = (00001111 00000001).
           TX CMD > $0781  =  (  7) - (129) = (00000111 10000001).

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 24, 2021, 08:21:00 pm
How strange, at 640x480, or worse, 320x240 60fps, I expected it to be twice as fast.  Are you transmitting these 2 commands in this order?  Only once before or after a complete vertical shift.
Line# 113, VWAIT for  1 frames, until line number   1.
           TX CMD > $0f08  =  ( 15) - (  1) = (00001111 00000001).
           TX CMD > $0781  =  (  7) - (129) = (00000111 10000001).

Hmm, well I wasn't setting hw_position (using $0F) anyway.  I added that extra command in (0x0F08 as per your testbench example above) and it made... zero difference. :-//  I modified it to change hw_position from 15 down to 1 with each line scrolled - no difference.

If I modify the number of frames to wait (least-significant nybble of the low byte) on each line scrolled, I can make the scroll accelerate (or decelerate), but it takes about 1.5 seconds (haven't timed it) to scroll 16 pixels if I start with a 15 frame delay and decrement that by 1 with each line scrolled.  There would be a total delay of about 120 frames using that method - which is 2 seconds at 60 fps, so that sounds about right, actually.  I need to use smaller values - I'll take a closer look at your previous post when I have more time where you suggested some values.  :-/O

Here's my code:

Code: [Select]
    LD      BC,(SCRL_CNT) ; Get number of pixels to scroll
ROW_scrl:
    ; Blit screen
    LD      HL,0100H     ; blit command
    CALL    send_gpu
    ; Use VWAIT to delay the scrolling
    LD      HL,0781H     ; Insert wait for 1 frame
    CALL    send_gpu
    DEC     BC           ; DECrement line counter
    LD      A,B
    OR      C            ; Is it zero?
    JP      NZ,ROW_scrl  ; Loop if not zero
    ; End of scroll routine

So I'm blitting the screen, then calling VWAIT.  I'm not setting hw_position as it defaults to zero, so should provide the smallest delay before the next command is executed if I understand it correctly?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 24, 2021, 11:22:17 pm
Remember, if this is 1 scroll per frame being displayed, then all you can do is keep the 1 frame delay, but, jump vertically 2 lines in a single blit instead of one.

The the wait command slows down the scroll by more than 2x compared to no wait command, then the Z80 is issuing more blits than in 1/60th of a second.  There is no reason to force additional 1 line blits, just jump 2 lines in a blit and the animation will be smooth, bu double speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 26, 2021, 01:57:50 pm
Yay, after a ton of work, I have enough of my DDR3 controller working to drive Micron Memory's DDR3 Verilog simulation model located here: https://www.micron.com/products/dram/ddr3-sdram/part-catalog/mt41j64m16tw-093 (https://www.micron.com/products/dram/ddr3-sdram/part-catalog/mt41j64m16tw-093)  (Yes, the model supports all of Micron's DDR3's from 1gb to 8gb, x4, x8, x16 ICs at all frequencies.)

Yay, it finally compiles merged with my controller.
Yay, it reports the controls I send to the DDR3 ram bus.

Boo, now I need to clear up all the tiny violations.  (Well, the controller wasn't complete yet anyways, but the logging of an official manufacturers timing model was crucial for proper debugging...)

It will take a few more days to finish up and get it working on hardware.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 26, 2021, 02:52:56 pm
This is exactly why I prefer using Micron parts for my memory needs. Good simulation model goes a long way in making controller design a much more pleasant experience.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on February 26, 2021, 03:00:41 pm
I wasn't aware Micron had HDL simulation models. That's great. Do you guys know of any other vendor that does?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 26, 2021, 03:34:02 pm
I wasn't aware Micron had HDL simulation models. That's great. Do you guys know of any other vendor that does?
Cypress provides models for their HyperRAM devices, I've seen some models from ISSI too. So it's not exactly unprecedented, but still I think Micron's models are the best.
They also provide IBIS models for board level signal integrity simulations, which is also very helpful.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 26, 2021, 09:01:08 pm
I wasn't aware Micron had HDL simulation models. That's great. Do you guys know of any other vendor that does?
And stupid me, I created a module called : BrianHG_DDR3_GEN_tCK.sv
Which synthesizes all the data sheet's timing t## clock cycles based on ram chip selection in one of the main parameters.  However, Micron's own model Verilog code also has these 4 source codes:
1024Mb_ddr3_parameters.vh
2048Mb_ddr3_parameters.vh
4096Mb_ddr3_parameters.vh
8192Mb_ddr3_parameters.vh
Which almost does the same thing.  Though, mine 1 for all ram sizes including 512MB DDR3, and is also synthesizes the MRS MR# registers based on a few inputs to select the function state of the memory.  Mircon's ddr3.v verifies that these have been setup properly when I run the MRS commands.  Example:
Code: [Select]
#
#  Note : Cyclone IV E PLL locked to incoming clock
# Time: 2670000.0 ps  Instance: BrianHG_DDR3_PHY_SEQ_tb.DUT_DDR3_PLL.genblk3.HPLL1.cycloneiii_pll.pll3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.reset at time 2690000.0 ps WARNING: 200 us is required before RST_N goes inactive.
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.reset: at time 2690000.0 ps ERROR: CKE must be inactive when RST_N goes inactive.
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.reset: at time 2690000.0 ps ERROR: CKE must be maintained inactive for 10 ns before RST_N goes inactive.
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task at time 2691000.0 ps WARNING: 500 us is required after RST_N goes inactive before CKE goes active.
#
#
#     MR0 Settings:
#     M[12]      - Precharge PD                 = 1     = DLL On.
#     M[11:9]    - Write Recovery               = 1     = 5.
#     M[8]       - DLL Reset                    = 0     = No.
#     M[6,5,4,2] - CAS# Latency                 = 001,0 = 5.
#     M[3]       - BT Read Burst Type           = 0     = Sequential (nibble).
#     M[1:0]     - BL Burst Length              = 00    = Fixed BL8.
#
#
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0 Burst Length =  8
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0 Burst Order = Sequential
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0 CAS Latency =           5
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0 DLL Reset = Normal
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0 Write Recovery =           5
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3213000.0 ps INFO: Load Mode 0 Power Down Mode = DLL on
#
#
#     MR1 Settings:
#     M[12]      - Q Off                        = 0     = Enabled.
#     M[11]      - TDQS                         = 0     = Disabled.
#     M[9,6,2]   - Rtt                          = 0,1,0 = RZQ/2  (120 Ohm [NOM]) |  RZQ/2  (120 Ohm [NOM])
#     M[7]       - Write Levelization           = 0     = Disable (normal).
#     M[4:3]     - Additive Latency (AL)        = 00    = Disabled (AL = 0).
#     M[5,1]     - Output Drive Strength        = 0,0   = RZQ/6  (40 Ohm [NOM]).
#     M[0]       - Dll Enabke                   = 0     = Enable (normal).
#
#
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 DLL Enable = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 Output Drive Strength =          40 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 ODT Rtt =         120 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 Additive Latency = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 Write Levelization = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 TDQS Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3239000.0 ps INFO: Load Mode 1 Qoff = Enabled
#
#
#     MR2 Settings:
#     M[10:9]    - Dynamic ODT (Rtt(WR))        = 2     = RZQ/2  (120 Ohm [NOM]).
#     M[7]       - Self Refresh Temperature     = 0     = Normal (0c to 85c).
#     M[5]       - Auto Self Refresh (Optional) = 0     = Disabled: Manual.
#     M[5:3]     - CAS Write Latency (CWL)      = 0     = 5 CK (tCK >= 2.5ns).
#
#
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3265000.0 ps INFO: Load Mode 2
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3265000.0 ps INFO: Load Mode 2 Partial Array Self Refresh = Bank 0-7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3265000.0 ps INFO: Load Mode 2 CAS Write Latency =           5
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3265000.0 ps INFO: Load Mode 2 Auto Self Refresh = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3265000.0 ps INFO: Load Mode 2 Self Refresh Temperature = Normal
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3265000.0 ps INFO: Load Mode 2 Dynamic ODT Rtt =         120 Ohm
#
#
#     MR3 Settings:
#     M[2]       - Multipurpose Register MPR    = 0     = Normal DRAM Operations.
#     M[1:0]     - MPR_RF                       = 0     = Predefined Pattern.
#
#
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3291000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3291000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3291000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3355000.0 ps INFO: Refresh 
#
# End of command source ASCII file 'DDR3_SEQ_CMD_script.txt'.
#   79 lines processed.
#
# ** Note: $stop    : BrianHG_DDR3_PHY_SEQ_tb.sv(275)
#    Time: 3850 ns  Iteration: 1  Instance: /BrianHG_DDR3_PHY_SEQ_tb


The nicely spaced MR descriptions & settings are executed and sent out to the DDR3 bus by my code and reverse decoded by my code while the ugly:
Code: [Select]
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 3355000.0 ps INFO: *******

Is what the Micron ddr3.v model is reporting how a DDR3 ram chip is functioning.  As you can see at the top, the errors say I need to clean up my power-up and reset sequence.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 26, 2021, 11:06:47 pm
In other news, just published a short video demonstrating a bouncing ball.  This draws an ellipse for the ball multiple times per frame, I can vary the size of the ball on the fly (not shown in video as I don't have three arms!)

I'm trying to get my head around the VWAIT command.  It's flickery at the moment (specially with bigger balls, no pun intended) and VWAIT causes the ball to disappear as it appears the Z80 is sending multiple position updates on the ball in the time VWAIT is... waiting.. causing the blanking draw to not keep up with the ball draw and artefacts to appear.

Anyway, here's the demo:

https://www.youtube.com/watch?v=CZuyfZxz6EE (https://www.youtube.com/watch?v=CZuyfZxz6EE)

Next on my to-do list is sharpen the collision detection at the screen edges to use the ball width instead of the ball centre, or squish the ball on impact.  Might do a bit of both.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 26, 2021, 11:32:43 pm
Cool...
In other news, just published a short video demonstrating a bouncing ball.  This draws an ellipse for the ball multiple times per frame, I can vary the size of the ball on the fly (not shown in video as I don't have three arms!)

I'm trying to get my head around the VWAIT command.  It's flickery at the moment (specially with bigger balls, no pun intended) and VWAIT causes the ball to disappear as it appears the Z80 is sending multiple position updates on the ball in the time VWAIT is... waiting.. causing the blanking draw to not keep up with the ball draw and artefacts to appear.

Anyway, here's the demo (https://youtu.be/CZuyfZxz6EE).

Next on my to-do list is sharpen the collision detection at the screen edges to use the ball width instead of the ball centre, or squish the ball on impact.  Might do a bit of both.
Change the position of the VWAIT command to the begining or end of all the drawing.
Also, you can change the horizontal line where the VWAIT happens at.  Say make it on line 200 of the display instead of line 0.

Also, try {erase old ball, draw new ball, vwait}...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on February 27, 2021, 12:08:12 am
Yes, as it is, there is a lot of "ghosting", to the point of the bouncing shape not really being recognizable.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 27, 2021, 01:32:43 am
I'm trying to get my head around the VWAIT command.  It's flickery at the moment (specially with bigger balls, no pun intended) and VWAIT causes the ball to disappear as it appears the Z80 is sending multiple position updates on the ball in the time VWAIT is... waiting.. causing the blanking draw to not keep up with the ball draw and artefacts to appear.
Are you monitoring the 'CMD FIFO FULL' flag before you send new commands.  With the VWAIT, the Z80 will easily out-run the animation speed and commands will get lost in the fifo as you send more draw commands than what can be executed.

Remember, with ~512 instruction FIFO pipe, everything you have done up until now has never out-paced the geometry unit, so you could essentially ignore the CMD FIFO full flag and get away with it.  Even with the smooth scrolling text using the VWAIT, you are only sending around 40 commands per carriage return, so you would have to do over 50 carriage returns instantly to overflow the geometry input command fifo.

When animating, your Z80 is piping around 40 commands per ball erase/re-render move.  The Z80 will overflow the input command fifo by the second of third frame beginning to mess up the drawing as commands get dropped since the VWAIT command literally pauses all subsequent draw commands until the specified line on the specified frame.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 27, 2021, 09:40:10 am
Cool...
In other news, just published a short video demonstrating a bouncing ball.  This draws an ellipse for the ball multiple times per frame, I can vary the size of the ball on the fly (not shown in video as I don't have three arms!)

I'm trying to get my head around the VWAIT command.  It's flickery at the moment (specially with bigger balls, no pun intended) and VWAIT causes the ball to disappear as it appears the Z80 is sending multiple position updates on the ball in the time VWAIT is... waiting.. causing the blanking draw to not keep up with the ball draw and artefacts to appear.

Anyway, here's the demo (https://youtu.be/CZuyfZxz6EE).

Next on my to-do list is sharpen the collision detection at the screen edges to use the ball width instead of the ball centre, or squish the ball on impact.  Might do a bit of both.
Change the position of the VWAIT command to the begining or end of all the drawing.
Also, you can change the horizontal line where the VWAIT happens at.  Say make it on line 200 of the display instead of line 0.

Also, try {erase old ball, draw new ball, vwait}...

It'll be because I'm not monitoring the FIFO state.  I haven't had long to put this together, so there's a lot more I can do.  Have some time today, so will see about adding FIFO checks.  A quick glance at my GPU manual seems to indicate there's no way to get the status of the FIFO though, so have tweaked the Z80_bridge to provide that info on an IO request.

I didn't mention previously, but I can slow down or speed up the ball as well - when it goes over a certain speed, all the artefacts are appearing.  This is clearly the speed at which the FIFO is getting overrun.  Am just building a new FPGA core with the updated z80_bridge so I can get the FIFO status.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 27, 2021, 10:14:09 am
Would it be useful to know if the GPU is waiting for the next frame in a VWAIT state as well?

In any case, it appears I've not done the scFIFO full check properly in the GPU.  Still getting artefacts when I speed the ball up as commands are dropped from the buffer.

Obligatory video (https://youtu.be/d_Bw-b4-vlg) showing FIFO buffer overrun as the ball speeds up.

Every time I send a command to the GPU, the Z80 enters a loop waiting for the scFIFO buffer 'nearly full' flag to be zero before sending the command.

In the z80_bridge, I've added/amended these lines in the appropriate places:

Code: [Select]
parameter int FIFO_STAT = 248;      // IO address for GPU FIFO status on bit 0 - remaining bits free for other data

assign port_in_range       = ((Z80_addr_r[7:0] >= IO_DATA[7:0]) && (Z80_addr_r[7:0] <= FIFO_STAT[7:0])) ; // You are better off reserving a range of ports

if ( z80_read_port_1s && Z80_addr_r[7:0] == FIFO_STAT[7:0] ) begin   // Read_port 1 clock & GPU status
   
    Z80_rData  <= GEO_STAT_RD ;
     
end

It looks as though the status isn't being reported properly as the FIFO buffer is still getting overrun at higher speeds.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: dolbeau on February 27, 2021, 10:41:22 am
There are a couple open-source boards with ECP5 FPGAs though, and at least one of them actually has a DDR3 memory chip. (The OrangeCrab board.) I haven't looked at it much so far, I'll be curious to see if there are example projects using this memory, and if so, how they managed to control it.

LiteX (https://github.com/enjoy-digital/litex/) support the OrangeCrab, there's a platform file (https://github.com/litex-hub/litex-boards/blob/master/litex_boards/platforms/orangecrab.py) for it with DDR3 support. The LiteX memory controller litedram (https://github.com/enjoy-digital/litedram) has a PHY component specific to the ECP5 (https://github.com/enjoy-digital/litedram/blob/master/litedram/phy/ecp5ddrphy.py). There's other boards with ECP5 and DDR3 that are supported (TrellisBoard, Versa).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 27, 2021, 11:13:58 am
Would it be useful to know if the GPU is waiting for the next frame in a VWAIT state as well?

In any case, it appears I've not done the scFIFO full check properly in the GPU.  Still getting artefacts when I speed the ball up as commands are dropped from the buffer.

Obligatory video (https://youtu.be/d_Bw-b4-vlg) showing FIFO buffer overrun as the ball speeds up.

Every time I send a command to the GPU, the Z80 enters a loop waiting for the scFIFO buffer 'nearly full' flag to be zero before sending the command.

In the z80_bridge, I've added/amended these lines in the appropriate places:

Code: [Select]
parameter int FIFO_STAT = 248;      // IO address for GPU FIFO status on bit 0 - remaining bits free for other data

assign port_in_range       = ((Z80_addr_r[7:0] >= IO_DATA[7:0]) && (Z80_addr_r[7:0] <= FIFO_STAT[7:0])) ; // You are better off reserving a range of ports

if ( z80_read_port_1s && Z80_addr_r[7:0] == FIFO_STAT[7:0] ) begin   // Read_port 1 clock & GPU status
   
    Z80_rData  <= GEO_STAT_RD ;
     
end

It looks as though the status isn't being reported properly as the FIFO buffer is still getting overrun at higher speeds.
Make the addition in the attached block diagram.
Bit 0 will still be the GEO FIFO Star, but, bits 1 through 7 will be a frame counter.  You should be able to see it counting once per frame.  If so, then I need to check the FIFO status flag, maybe it is not wired or setup properly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 27, 2021, 11:58:47 am
Would it be useful to know if the GPU is waiting for the next frame in a VWAIT state as well?

In any case, it appears I've not done the scFIFO full check properly in the GPU.  Still getting artefacts when I speed the ball up as commands are dropped from the buffer.

Obligatory video (https://youtu.be/d_Bw-b4-vlg) showing FIFO buffer overrun as the ball speeds up.

Every time I send a command to the GPU, the Z80 enters a loop waiting for the scFIFO buffer 'nearly full' flag to be zero before sending the command.

In the z80_bridge, I've added/amended these lines in the appropriate places:

Code: [Select]
parameter int FIFO_STAT = 248;      // IO address for GPU FIFO status on bit 0 - remaining bits free for other data

assign port_in_range       = ((Z80_addr_r[7:0] >= IO_DATA[7:0]) && (Z80_addr_r[7:0] <= FIFO_STAT[7:0])) ; // You are better off reserving a range of ports

if ( z80_read_port_1s && Z80_addr_r[7:0] == FIFO_STAT[7:0] ) begin   // Read_port 1 clock & GPU status
   
    Z80_rData  <= GEO_STAT_RD ;
     
end

It looks as though the status isn't being reported properly as the FIFO buffer is still getting overrun at higher speeds.
Make the addition in the attached block diagram.
Bit 0 will still be the GEO FIFO Star, but, bits 1 through 7 will be a frame counter.  You should be able to see it counting once per frame.  If so, then I need to check the FIFO status flag, maybe it is not wired or setup properly.

Yes, it appears to be reading the frame counter okay.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 27, 2021, 10:49:33 pm
Well, at least now with an equality compare since the last reading, you know when the frame has just changed.

So, we need to figure out why the FIFO full flag isn't working.  That is unless the Z80 just cant send enough circles out, even within 1/60th of a second to fill it with the delays.

I'll check the Geometry Test Bench later tonight.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 28, 2021, 11:09:59 am
https://www.youtube.com/watch?v=H38bjuXU4KE (https://www.youtube.com/watch?v=H38bjuXU4KE)

Above link shows latest vid with basic vsync working.  Bouncing ball demo in all three modes (320x200x16, 320x240x4 and 640x400x2 in that order), showing some vsync timing issues at the top of the screen for larger circles.  Camera used was one I dug out of storage and haven't used for a while, so autofocus plays up halfway through, but excuse that. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 28, 2021, 10:35:45 pm
Man, I never thought I would see a Z80 drawing and erasing such a large filled circle at 640x480, animating it with ease, WITHOUT a double buffered background.

When using the 'VWAIT', try a frame count of '0', but a line number like 440 placing the 'pause' until the end of the frame.

To do this you will need to check the source verilog code to set a 'double' factor for the 'Horizontal line wait position' and use a line setting of 220.
Here is the verilog code lines 828 to 840:
Code: [Select]
   else if (cmd_in[15:8]  == 8'd7)  begin
                                              if (cmd_in[7:2]==6'd0) ellipse_quadrant  <= cmd_in[1:0]; // Set which ellipse quadrant to render.
                                              if (cmd_in[7]) begin
                                                             vw_counter[3:0]   <= cmd_in[3:0]; // Set the number of vertical frames to wait for.
                                                             if (cmd_in[3:0]!=4'd0) begin
                                                                                    wait_int           <= 1'd1 ; // Turn on the wait for vertical frames
                                                                                    plotter_busy       <= 1'd1 ; // Tell the rest of the geometry processor that the plotter is just busy
                                                                                    int_kill           <= 2'd2; // reset the wait timer killer
                                                                                    hw_position[10:0]  <= hw_pos_lat[7:0] << cmd_in[5:4] ;
                                                                                    end
                                                             end
                                    end
   else if (cmd_in[15:8]  == 8'd15) hw_pos_lat[7:0]   <= cmd_in[7:0]; // Set the wait for horizontal lines after display ends.

For the wait, you need to fill (CMD[15:8]==15) with 220.
And (CMD[15:8]==7) with 8'b10010000

As you can see, bits [5:4] in this line here:
Code: [Select]
hw_position[10:0]  <= hw_pos_lat[7:0] << cmd_in[5:4] ;
Shifts the 8 bit number 220 you placed in 'hw_pos_lat', placing the now 220 changed into 440 in the H-Wait line position 'hw_position[10:0]'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 06, 2021, 11:39:05 am
DDR3 Status update.

Arrrgggg, +3k lines of new code and finally.....  >:D
100% By the book!!!

Testbench script:
Code: [Select]
[at]CMD READ  <32'hex ADDR> <32'hex VECTOR>                  > Transmits a read request at address ADDR with the target vector set to VECTOR.
[at]CMD WRITE <32'hex ADDR> <32'binary MASK>  <256'hex DATA> > Transmits a read request at address ADDR with the target vector set to VECTOR.
[at]CMD DELAY <time in microseconds>                         > Adds a huge delay.


@LOG_FILE  DDR3_SEQ_CMD_script_log.txt

@CMD READ  00000000 0
@CMD READ  00000800 0
@CMD READ  00010820 0
@CMD READ  00000000 0
@CMD READ  00010800 0
@CMD READ  00011800 0
@CMD READ  00012000 0
@CMD READ  00012800 0
@CMD READ  00013000 0
@CMD READ  00013800 0
@CMD WRITE 00013800 11111111111111111111111111111111 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF
@CMD WRITE 00013820 11111111111111111111111111111111 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF
@CMD READ  00013800 0


Output from Micron's DDR3 Verilog Model:
Code: [Select]
#  Note : Cyclone IV E PLL was reset
# Time: 0.0 ps  Instance: BrianHG_DDR3_PHY_SEQ_tb.DUT_DDR3_PLL.genblk3.HPLL1.cycloneiii_pll.pll3
#  Note : Cyclone IV E PLL locked to incoming clock
# Time: 2670000.0 ps  Instance: BrianHG_DDR3_PHY_SEQ_tb.DUT_DDR3_PLL.genblk3.HPLL1.cycloneiii_pll.pll3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Partial Array Self Refresh = Bank 0-7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 CAS Write Latency =           6
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Auto Self Refresh = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Self Refresh Temperature = Extended
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Dynamic ODT = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203171000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203171000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203171000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 DLL Enable = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Output Drive Strength =          40 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 ODT Rtt =         120 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Additive Latency = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Write Levelization = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 TDQS Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Qoff = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Burst Length =  8
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Burst Order = Sequential
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 CAS Latency =           7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 DLL Reset = Reset DLL
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Write Recovery =           8
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Power Down Mode = DLL off
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203211000.0 ps INFO: ZQ        long = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203211000.0 ps INFO: Initialization Sequence is complete
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204235000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204235000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204235000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204259000.0 ps INFO: Read      bank 3 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204267000.0 ps INFO: Read      bank 3 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204272000.0 ps READ @ DQS MultiPurpose Register 0, col = 0,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204273000.0 ps READ @ DQS MultiPurpose Register 0, col = 1,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204274000.0 ps READ @ DQS MultiPurpose Register 0, col = 2,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204275000.0 ps READ @ DQS MultiPurpose Register 0, col = 3,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204276000.0 ps READ @ DQS MultiPurpose Register 0, col = 4,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204277000.0 ps READ @ DQS MultiPurpose Register 0, col = 5,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204278000.0 ps READ @ DQS MultiPurpose Register 0, col = 6,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204279000.0 ps READ @ DQS MultiPurpose Register 0, col = 7,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204280000.0 ps READ @ DQS MultiPurpose Register 0, col = 0,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204281000.0 ps READ @ DQS MultiPurpose Register 0, col = 1,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204282000.0 ps READ @ DQS MultiPurpose Register 0, col = 2,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204283000.0 ps READ @ DQS MultiPurpose Register 0, col = 3,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204284000.0 ps READ @ DQS MultiPurpose Register 0, col = 4,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204285000.0 ps READ @ DQS MultiPurpose Register 0, col = 5,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204286000.0 ps READ @ DQS MultiPurpose Register 0, col = 6,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204287000.0 ps READ @ DQS MultiPurpose Register 0, col = 7,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204291000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204291000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204291000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204315000.0 ps INFO: Activate  bank 0 row 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204331000.0 ps INFO: Read      bank 0 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204339000.0 ps INFO: Read      bank 0 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204344000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204345000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204345000.0 ps INFO: Activate  bank 1 row 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204346000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204347000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204348000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204349000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204350000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204351000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204352000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204353000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204354000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204355000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204356000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204357000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204358000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204359000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204361000.0 ps INFO: Read      bank 1 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204369000.0 ps INFO: Read      bank 1 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204374000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204375000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204376000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204377000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204378000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204379000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204380000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204381000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204381000.0 ps INFO: Precharge bank   1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204382000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204383000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204384000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204385000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204386000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204387000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204388000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204389000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204397000.0 ps INFO: Activate  bank 1 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204413000.0 ps INFO: Read      bank 1 col 010, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204421000.0 ps INFO: Read      bank 1 col 018, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204426000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000010 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204427000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000011 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204428000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000012 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204429000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000013 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204429000.0 ps INFO: Read      bank 0 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204430000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000014 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204431000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000015 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204432000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000016 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204433000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000017 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204434000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000018 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204435000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000019 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204436000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204437000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204437000.0 ps INFO: Read      bank 0 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204438000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204439000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204440000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204441000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204442000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204443000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204444000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204445000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204445000.0 ps INFO: Read      bank 1 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204446000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204447000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204448000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204449000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204450000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204451000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204452000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204453000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204453000.0 ps INFO: Read      bank 1 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204454000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204455000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204456000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204457000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204458000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204459000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204459000.0 ps INFO: Activate  bank 3 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204460000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204461000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204462000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204463000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204464000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204465000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204466000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204467000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204468000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204469000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204470000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204471000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204472000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204473000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204475000.0 ps INFO: Read      bank 3 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204483000.0 ps INFO: Read      bank 3 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204488000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204489000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204489000.0 ps INFO: Activate  bank 4 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204490000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204491000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204492000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204493000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204494000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204495000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204496000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204497000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204498000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204499000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204500000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204501000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204502000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204503000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204505000.0 ps INFO: Read      bank 4 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204513000.0 ps INFO: Read      bank 4 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204518000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204519000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204519000.0 ps INFO: Activate  bank 5 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204520000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204521000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204522000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204523000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204524000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204525000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204526000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204527000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204528000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204529000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204530000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204531000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204532000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204533000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204535000.0 ps INFO: Read      bank 5 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204543000.0 ps INFO: Read      bank 5 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204548000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204549000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204549000.0 ps INFO: Activate  bank 6 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204550000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204551000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204552000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204553000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204554000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204555000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204556000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204557000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204558000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204559000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204560000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204561000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204562000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204563000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204565000.0 ps INFO: Read      bank 6 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204573000.0 ps INFO: Read      bank 6 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204578000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204579000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204579000.0 ps INFO: Activate  bank 7 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204580000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204581000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204582000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204583000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204584000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204585000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204586000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204587000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204588000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204589000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204590000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204591000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204592000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204593000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204595000.0 ps INFO: Read      bank 7 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204603000.0 ps INFO: Read      bank 7 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204608000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204609000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204610000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204611000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204612000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204613000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204614000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204615000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204616000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204617000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204617000.0 ps INFO: Write     bank 7 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204618000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204619000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204620000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204621000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204622000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204623000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204625000.0 ps INFO: Write     bank 7 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.main: at time 1204625000.0 ps INFO: Sync On Die Termination Rtt_NOM =        120 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204630000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000000 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204631000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000001 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204632000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000002 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204633000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000003 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204633000.0 ps INFO: Write     bank 7 col 010, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204634000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000004 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204635000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000005 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204636000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000006 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204637000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000007 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204638000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000008 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204639000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000009 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204640000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000a data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204641000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000b data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204641000.0 ps INFO: Write     bank 7 col 018, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204642000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000c data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204643000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000d data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204644000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000e data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204645000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000f data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204646000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000010 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204647000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000011 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204648000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000012 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204649000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000013 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204650000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000014 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204651000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000015 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204652000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000016 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204653000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000017 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204654000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000018 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204655000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000019 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204656000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001a data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204657000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001b data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204658000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001c data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204659000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001d data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204660000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001e data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204661000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001f data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.main: at time 1204661000.0 ps INFO: Sync On Die Termination Rtt_NOM =          0 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204669000.0 ps INFO: Read      bank 7 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204677000.0 ps INFO: Read      bank 7 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204682000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000000 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204683000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000001 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204684000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000002 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204685000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000003 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204686000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000004 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204687000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000005 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204688000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000006 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204689000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000007 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204690000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000008 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204691000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000009 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204692000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000a data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204693000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000b data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204694000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000c data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204695000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000d data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204696000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000e data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204697000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000f data = ffff
#
# End of command source ASCII file 'DDR3_SEQ_CMD_script.txt'.
#   51 lines processed.
#
# ** Note: $stop    : BrianHG_DDR3_PHY_SEQ_tb.sv(321)
#    Time: 1205150 ns  Iteration: 1  Instance: /BrianHG_DDR3_PHY_SEQ_tb
# Break in Module BrianHG_DDR3_PHY_SEQ_tb at BrianHG_DDR3_PHY_SEQ_tb.sv line 321
#
run -all (continue...)
#
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge All
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   4
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   5
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   6
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205509000.0 ps INFO: Refresh 
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1206095000.0 ps INFO: Refresh 
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1207895000.0 ps INFO: Refresh 
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1209695000.0 ps INFO: Refresh 
# ** Note: $stop    : BrianHG_DDR3_PHY_SEQ_tb.sv(321)
#    Time: 1210270 ns  Iteration: 1  Instance: /BrianHG_DDR3_PHY_SEQ_tb
# Break in Module BrianHG_DDR3_PHY_SEQ_tb at BrianHG_DDR3_PHY_SEQ_tb.sv line 321

Not a single warning or error....

This is the core memory controler which basically does this:
Code: [Select]
// **********************************************************************************************************************************
// *** Inner Sequencer Running at DDR3_CK clock frequency.
// **********************************************************************************************************************************
// ---------------------------------------------------------------------------------------------------------------------------------------
// CMD         - Sequence
// ---------------------------------------------------------------------------------------------------------------------------------------
// RESET_ON/OFF- Clear all active bank flags & do a reset / power-up sequence.  Forced immediately...
// MRS         - If any banks are active, do a precharge all banks, then set MRS using the bank as the MR# and the upper address as the config.
// REFRESH     - If any active bank ID flags have been set, precharge all banks & clear all the activated bank ID flags, then do a REFRESH
// READ        - If current read req bank's row != the existing active bank ID's row, first ***ACTIVATE the requested row, then READ command
// WRITE       - Same as READ.
//               *** When ACTIVATING a new row, if the new chosen bank ID was already activated, first do a PRECHARGE to release that 1 bank,
//                   then do the ACTIVATE command & set that bank's ID to the new row.
// ZQCL        - Do a long form 512 clock ZQCL write level calibration.
// ZQCS        - Do a short form 64 clock ZQCS write level calibration.
// READ_CAL    - Skips row activate and does a CAS read of address 0 for read level/read timing calibration.
// NOP         - Just adds a dummy tCK nop.
// ---------------------------------------------------------------------------------------------------------------------------------------


Yes, this controler keeps track of multiple open banks and will smartly switch between them without sending additional 'ACTIVATE/RAS' commands & close (PRECHARGE) / open single banks as needed.  Great for partioning your memory where the ram controller would act like 8 different ram controllers only ACTIVATING a row as needed in each of your memory domains.

Next, get this part working on the DECA board.
Then, get the multiport COMMANDER module working.
Then, release the first version with a functioning demo.
Then, get it simulating on Lattice Diamond.
(Yes, it will be 100% free opensource...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SMB784 on March 06, 2021, 04:34:13 pm
DDR3 Status update.

Arrrgggg, +3k lines of new code and finally.....  >:D
100% By the book!!!

Testbench script:
Code: [Select]
[at]CMD READ  <32'hex ADDR> <32'hex VECTOR>                  > Transmits a read request at address ADDR with the target vector set to VECTOR.
[at]CMD WRITE <32'hex ADDR> <32'binary MASK>  <256'hex DATA> > Transmits a read request at address ADDR with the target vector set to VECTOR.
[at]CMD DELAY <time in microseconds>                         > Adds a huge delay.


@LOG_FILE  DDR3_SEQ_CMD_script_log.txt

@CMD READ  00000000 0
@CMD READ  00000800 0
@CMD READ  00010820 0
@CMD READ  00000000 0
@CMD READ  00010800 0
@CMD READ  00011800 0
@CMD READ  00012000 0
@CMD READ  00012800 0
@CMD READ  00013000 0
@CMD READ  00013800 0
@CMD WRITE 00013800 11111111111111111111111111111111 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF
@CMD WRITE 00013820 11111111111111111111111111111111 0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF
@CMD READ  00013800 0


Output from Micron's DDR3 Verilog Model:
Code: [Select]
#  Note : Cyclone IV E PLL was reset
# Time: 0.0 ps  Instance: BrianHG_DDR3_PHY_SEQ_tb.DUT_DDR3_PLL.genblk3.HPLL1.cycloneiii_pll.pll3
#  Note : Cyclone IV E PLL locked to incoming clock
# Time: 2670000.0 ps  Instance: BrianHG_DDR3_PHY_SEQ_tb.DUT_DDR3_PLL.genblk3.HPLL1.cycloneiii_pll.pll3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Partial Array Self Refresh = Bank 0-7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 CAS Write Latency =           6
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Auto Self Refresh = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Self Refresh Temperature = Extended
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203163000.0 ps INFO: Load Mode 2 Dynamic ODT = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203171000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203171000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203171000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 DLL Enable = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Output Drive Strength =          40 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 ODT Rtt =         120 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Additive Latency = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Write Levelization = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 TDQS Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203179000.0 ps INFO: Load Mode 1 Qoff = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Burst Length =  8
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Burst Order = Sequential
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 CAS Latency =           7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 DLL Reset = Reset DLL
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Write Recovery =           8
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203187000.0 ps INFO: Load Mode 0 Power Down Mode = DLL off
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203211000.0 ps INFO: ZQ        long = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1203211000.0 ps INFO: Initialization Sequence is complete
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204235000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204235000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204235000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Enabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204259000.0 ps INFO: Read      bank 3 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204267000.0 ps INFO: Read      bank 3 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204272000.0 ps READ @ DQS MultiPurpose Register 0, col = 0,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204273000.0 ps READ @ DQS MultiPurpose Register 0, col = 1,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204274000.0 ps READ @ DQS MultiPurpose Register 0, col = 2,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204275000.0 ps READ @ DQS MultiPurpose Register 0, col = 3,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204276000.0 ps READ @ DQS MultiPurpose Register 0, col = 4,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204277000.0 ps READ @ DQS MultiPurpose Register 0, col = 5,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204278000.0 ps READ @ DQS MultiPurpose Register 0, col = 6,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204279000.0 ps READ @ DQS MultiPurpose Register 0, col = 7,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204280000.0 ps READ @ DQS MultiPurpose Register 0, col = 0,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204281000.0 ps READ @ DQS MultiPurpose Register 0, col = 1,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204282000.0 ps READ @ DQS MultiPurpose Register 0, col = 2,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204283000.0 ps READ @ DQS MultiPurpose Register 0, col = 3,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204284000.0 ps READ @ DQS MultiPurpose Register 0, col = 4,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204285000.0 ps READ @ DQS MultiPurpose Register 0, col = 5,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204286000.0 ps READ @ DQS MultiPurpose Register 0, col = 6,  data = 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204287000.0 ps READ @ DQS MultiPurpose Register 0, col = 7,  data = 1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204291000.0 ps INFO: Load Mode 3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204291000.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204291000.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Disabled
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204315000.0 ps INFO: Activate  bank 0 row 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204331000.0 ps INFO: Read      bank 0 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204339000.0 ps INFO: Read      bank 0 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204344000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204345000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204345000.0 ps INFO: Activate  bank 1 row 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204346000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204347000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204348000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204349000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204350000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204351000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204352000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204353000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204354000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204355000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204356000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204357000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204358000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204359000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204361000.0 ps INFO: Read      bank 1 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204369000.0 ps INFO: Read      bank 1 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204374000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204375000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204376000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204377000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204378000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204379000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204380000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204381000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204381000.0 ps INFO: Precharge bank   1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204382000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204383000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204384000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204385000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204386000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204387000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204388000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204389000.0 ps INFO: READ @ DQS= bank = 1 row = 0000 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204397000.0 ps INFO: Activate  bank 1 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204413000.0 ps INFO: Read      bank 1 col 010, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204421000.0 ps INFO: Read      bank 1 col 018, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204426000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000010 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204427000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000011 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204428000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000012 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204429000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000013 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204429000.0 ps INFO: Read      bank 0 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204430000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000014 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204431000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000015 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204432000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000016 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204433000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000017 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204434000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000018 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204435000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000019 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204436000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204437000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204437000.0 ps INFO: Read      bank 0 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204438000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204439000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204440000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204441000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000001f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204442000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204443000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204444000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204445000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204445000.0 ps INFO: Read      bank 1 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204446000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204447000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204448000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204449000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204450000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204451000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204452000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204453000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204453000.0 ps INFO: Read      bank 1 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204454000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204455000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204456000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204457000.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204458000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204459000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204459000.0 ps INFO: Activate  bank 3 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204460000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204461000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204462000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204463000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204464000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204465000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204466000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204467000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204468000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204469000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204470000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204471000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204472000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204473000.0 ps INFO: READ @ DQS= bank = 1 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204475000.0 ps INFO: Read      bank 3 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204483000.0 ps INFO: Read      bank 3 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204488000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204489000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204489000.0 ps INFO: Activate  bank 4 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204490000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204491000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204492000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204493000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204494000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204495000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204496000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204497000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204498000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204499000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204500000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204501000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204502000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204503000.0 ps INFO: READ @ DQS= bank = 3 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204505000.0 ps INFO: Read      bank 4 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204513000.0 ps INFO: Read      bank 4 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204518000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204519000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204519000.0 ps INFO: Activate  bank 5 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204520000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204521000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204522000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204523000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204524000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204525000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204526000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204527000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204528000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204529000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204530000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204531000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204532000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204533000.0 ps INFO: READ @ DQS= bank = 4 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204535000.0 ps INFO: Read      bank 5 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204543000.0 ps INFO: Read      bank 5 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204548000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204549000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204549000.0 ps INFO: Activate  bank 6 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204550000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204551000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204552000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204553000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204554000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204555000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204556000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204557000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204558000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204559000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204560000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204561000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204562000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204563000.0 ps INFO: READ @ DQS= bank = 5 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204565000.0 ps INFO: Read      bank 6 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204573000.0 ps INFO: Read      bank 6 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204578000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204579000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204579000.0 ps INFO: Activate  bank 7 row 0004
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204580000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204581000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204582000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204583000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204584000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204585000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204586000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204587000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204588000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204589000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204590000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204591000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204592000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204593000.0 ps INFO: READ @ DQS= bank = 6 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204595000.0 ps INFO: Read      bank 7 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204603000.0 ps INFO: Read      bank 7 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204608000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000000 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204609000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000001 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204610000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000002 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204611000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000003 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204612000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000004 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204613000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000005 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204614000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000006 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204615000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000007 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204616000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000008 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204617000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000009 data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204617000.0 ps INFO: Write     bank 7 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204618000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000a data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204619000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000b data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204620000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000c data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204621000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000d data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204622000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000e data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204623000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000f data = xxxx
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204625000.0 ps INFO: Write     bank 7 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.main: at time 1204625000.0 ps INFO: Sync On Die Termination Rtt_NOM =        120 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204630000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000000 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204631000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000001 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204632000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000002 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204633000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000003 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204633000.0 ps INFO: Write     bank 7 col 010, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204634000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000004 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204635000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000005 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204636000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000006 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204637000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000007 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204638000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000008 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204639000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000009 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204640000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000a data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204641000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000b data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204641000.0 ps INFO: Write     bank 7 col 018, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204642000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000c data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204643000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000d data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204644000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000e data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204645000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000000f data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204646000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000010 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204647000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000011 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204648000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000012 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204649000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000013 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204650000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000014 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204651000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000015 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204652000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000016 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204653000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000017 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204654000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000018 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204655000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 00000019 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204656000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001a data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204657000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001b data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204658000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001c data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204659000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001d data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204660000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001e data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204661000.0 ps INFO: WRITE @ DQS= bank = 7 row = 0004 col = 0000001f data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.main: at time 1204661000.0 ps INFO: Sync On Die Termination Rtt_NOM =          0 Ohm
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204669000.0 ps INFO: Read      bank 7 col 000, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1204677000.0 ps INFO: Read      bank 7 col 008, auto precharge 0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204682000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000000 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204683000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000001 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204684000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000002 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204685000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000003 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204686000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000004 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204687000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000005 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204688000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000006 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204689000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000007 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204690000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000008 data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204691000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 00000009 data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204692000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000a data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204693000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000b data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204694000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000c data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204695000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000d data = ffff
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204696000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000e data = 0000
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.data_task: at time 1204697000.0 ps INFO: READ @ DQS= bank = 7 row = 0004 col = 0000000f data = ffff
#
# End of command source ASCII file 'DDR3_SEQ_CMD_script.txt'.
#   51 lines processed.
#
# ** Note: $stop    : BrianHG_DDR3_PHY_SEQ_tb.sv(321)
#    Time: 1205150 ns  Iteration: 1  Instance: /BrianHG_DDR3_PHY_SEQ_tb
# Break in Module BrianHG_DDR3_PHY_SEQ_tb at BrianHG_DDR3_PHY_SEQ_tb.sv line 321
#
run -all (continue...)
#
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge All
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   0
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   1
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   3
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   4
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   5
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   6
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205493000.0 ps INFO: Precharge bank   7
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1205509000.0 ps INFO: Refresh 
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1206095000.0 ps INFO: Refresh 
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1207895000.0 ps INFO: Refresh 
# BrianHG_DDR3_PHY_SEQ_tb.sdramddr3_0.cmd_task: at time 1209695000.0 ps INFO: Refresh 
# ** Note: $stop    : BrianHG_DDR3_PHY_SEQ_tb.sv(321)
#    Time: 1210270 ns  Iteration: 1  Instance: /BrianHG_DDR3_PHY_SEQ_tb
# Break in Module BrianHG_DDR3_PHY_SEQ_tb at BrianHG_DDR3_PHY_SEQ_tb.sv line 321

Not a single warning or error....

This is the core memory controler which basically does this:
Code: [Select]
// **********************************************************************************************************************************
// *** Inner Sequencer Running at DDR3_CK clock frequency.
// **********************************************************************************************************************************
// ---------------------------------------------------------------------------------------------------------------------------------------
// CMD         - Sequence
// ---------------------------------------------------------------------------------------------------------------------------------------
// RESET_ON/OFF- Clear all active bank flags & do a reset / power-up sequence.  Forced immediately...
// MRS         - If any banks are active, do a precharge all banks, then set MRS using the bank as the MR# and the upper address as the config.
// REFRESH     - If any active bank ID flags have been set, precharge all banks & clear all the activated bank ID flags, then do a REFRESH
// READ        - If current read req bank's row != the existing active bank ID's row, first ***ACTIVATE the requested row, then READ command
// WRITE       - Same as READ.
//               *** When ACTIVATING a new row, if the new chosen bank ID was already activated, first do a PRECHARGE to release that 1 bank,
//                   then do the ACTIVATE command & set that bank's ID to the new row.
// ZQCL        - Do a long form 512 clock ZQCL write level calibration.
// ZQCS        - Do a short form 64 clock ZQCS write level calibration.
// READ_CAL    - Skips row activate and does a CAS read of address 0 for read level/read timing calibration.
// NOP         - Just adds a dummy tCK nop.
// ---------------------------------------------------------------------------------------------------------------------------------------


Yes, this controler keeps track of multiple open banks and will smartly switch between them without sending additional 'ACTIVATE/RAS' commands & close (PRECHARGE) / open single banks as needed.  Great for partioning your memory where the ram controller would act like 8 different ram controllers only ACTIVATING a row as needed in each of your memory domains.

Next, get this part working on the DECA board.
Then, get the multiport COMMANDER module working.
Then, release the first version with a functioning demo.
Then, get it simulating on Lattice Diamond.
(Yes, it will be 100% free opensource...)

Fucking impressive man.  Well done indeed.  I look forward to using this as a stand alone unit in my designs in the future.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on March 06, 2021, 05:39:40 pm
Then, get it simulating on Lattice Diamond.

Diamond now ships with Modelsim so that shouldn' t be a problem.
If you ever want to synthesize it with Diamond though, just a quick tip: as far as I saw, you're using SystemVerilog? Lattice LSE (Lattice own synthesis engine) doesn't support SystemVerilog AFAIK, so you'll need to use Synplify Pro instead. Diamond comes with both, so it's just a matter of selecting Synplify as the synthesis tool. Just so you don't waste time looking that up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 06, 2021, 08:43:44 pm
Then, get it simulating on Lattice Diamond.

Diamond now ships with Modelsim so that shouldn' t be a problem.
If you ever want to synthesize it with Diamond though, just a quick tip: as far as I saw, you're using SystemVerilog? Lattice LSE (Lattice own synthesis engine) doesn't support SystemVerilog AFAIK, so you'll need to use Synplify Pro instead. Diamond comes with both, so it's just a matter of selecting Synplify as the synthesis tool. Just so you don't waste time looking that up.
Yes it does, well it seemed to.  I got my .SV ellipse generator & .BMP saver test bench working here working with ActiveHDL, so I know the 1 or 2 little changes needed:
https://www.eevblog.com/forum/fpga/systemverilog-example-testbench-which-saves-a-bmp-picture-and-executes-a-script/msg3465172/#msg3465172 (https://www.eevblog.com/forum/fpga/systemverilog-example-testbench-which-saves-a-bmp-picture-and-executes-a-script/msg3465172/#msg3465172)

I also got my HDMI_PLL.SV going in Lattice's Synplify-Pro.  It's their stupid arcane:
Code: [Select]
    EHXPLLL HPLL0     (.CLKI(clk_in),           .CLKFB(PLL0_clk_out[0]), // was an assigned wire (CLKOP_t)
                       .PHASESEL1(scuba_vlo0),  .PHASESEL0(scuba_vlo0),   .PHASEDIR(scuba_vlo0), .PHASESTEP(scuba_vlo0), .PHASELOADREG(scuba_vlo0),
                       .STDBY(scuba_vlo0),      .PLLWAKESYNC(scuba_vlo0), .RST(scuba_vlo0),
                       .ENCLKOP(scuba_vlo0),    .ENCLKOS(scuba_vlo0),     .ENCLKOS2(scuba_vlo0), .ENCLKOS3(scuba_vlo0),
                       .CLKOP(PLL0_clk_out[0]), .CLKOS(),                 .CLKOS2(),             .CLKOS3(),
                       .LOCK(LOCK0),            .INTLOCK(),               .REFCLK(REFCLK0),      .CLKINTFB())
             /* synthesis FREQUENCY_PIN_CLKOP  = "WTF MUST THIS NUMBER HERE BE AN ASCII NUMBER IN QUOTES" */
             /* synthesis FREQUENCY_PIN_CLKI   = "WTF MUST THIS NUMBER HERE BE AN ASCII NUMBER IN QUOTES" */
             /* synthesis ICP_CURRENT="6" */
             /* synthesis LPF_RESISTOR="16" */;
 defparam
 HPLL0.CLKOS3_DIV       = 1,          HPLL0.CLKOS2_DIV     = 1,          HPLL0.CLKOS_DIV       = 1,
 HPLL0.CLKOP_DIV        = PLL0_div,   HPLL0.CLKFB_DIV      = PLL0_mult,  HPLL0.CLKI_DIV        = 1,
 
 HPLL0.CLKOS3_FPHASE    = 0,          HPLL0.CLKOS3_CPHASE  = 0,
 HPLL0.CLKOS2_FPHASE    = 0,          HPLL0.CLKOS2_CPHASE  = 0,
 HPLL0.CLKOS_FPHASE     = 0,          HPLL0.CLKOS_CPHASE   = 0,
 HPLL0.CLKOP_FPHASE     = 0,          HPLL0.CLKOP_CPHASE   = (PLL0_div-1),

 HPLL0.FEEDBK_PATH      = "CLKOP",    HPLL0.PLL_LOCK_MODE  = 0,

 HPLL0.OUTDIVIDER_MUXD  = "DIVD",     HPLL0.CLKOS3_ENABLE  = "DISABLED",
 HPLL0.OUTDIVIDER_MUXC  = "DIVC",     HPLL0.CLKOS2_ENABLE  = "DISABLED",
 HPLL0.OUTDIVIDER_MUXB  = "DIVB",     HPLL0.CLKOS_ENABLE   = "DISABLED",
 HPLL0.OUTDIVIDER_MUXA  = "DIVA",     HPLL0.CLKOP_ENABLE   = "ENABLED",
 HPLL0.PLLRST_ENA       = "DISABLED", HPLL0.INTFB_WAKE     = "DISABLED", HPLL0.STDBY_ENABLE     = "DISABLED", HPLL0.DPHASE_SOURCE  = "DISABLED",
 HPLL0.CLKOS_TRIM_DELAY = 0,          HPLL0.CLKOS_TRIM_POL = "FALLING",  HPLL0.CLKOP_TRIM_DELAY = 0,          HPLL0.CLKOP_TRIM_POL = "FALLING";

It's that stupid comment  /* synthesis FREQUENCY_PIN_CLKOP/CLKI ="WTF MUST THIS NUMBER HERE BE AN ASCII NUMBER IN QUOTES" */ '
I cannot place a computed parameter there.  Only a fixed ASCII number in quotes, otherwise Diamond says my PLL is illegal configured to 0MHz, and it stops there.

Lattice tole me just to use their Clarity Designer to make to PLL, but, I told them there were was a possibility of around 100 different PLL configurations and I would need Clarity to make ~100 .V files, and selectively include one instead of properly doing things a true software selection route.

Diamond may have been always automatically pushing my .SV code through SynplifyPro and it's just been accepting things so far.  It would be kind of old and sad that Diamond cannot support at least an HDL language where I can use packed 2 dimensional registers.

Everything else I coded should be straight forward.

If a .V file would support a 2D array port, then my code is simple to change back to old fashioned Verilog.
EG:
reg [15:0]  BANK_ROW_LOCATION [0:7] = '{0,0,0,0,0,0,0,0};

Instead of 'logic'

This is the only reason I have been using SystemVerilog.  It's so I can have addressable regs like 8 x 16 bit bank_row_location s to scan in a simple for loop, or pass all 8 from 1 module to another.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on March 06, 2021, 08:53:28 pm
Then, get it simulating on Lattice Diamond.

Diamond now ships with Modelsim so that shouldn' t be a problem.
If you ever want to synthesize it with Diamond though, just a quick tip: as far as I saw, you're using SystemVerilog? Lattice LSE (Lattice own synthesis engine) doesn't support SystemVerilog AFAIK, so you'll need to use Synplify Pro instead. Diamond comes with both, so it's just a matter of selecting Synplify as the synthesis tool. Just so you don't waste time looking that up.
Yes it does, well it seemed to.  I got my .SV ellipse generator & .BMP saver test bench working here working with ActiveHDL, so I know the 1 or 2 little changes needed:

I dunno if my post was not clear enough, but it seems you're confusing synthesis with simulation here.

LSE (or Synplify) are synthesis tools. They don't do simulation and are not used for simulation. And AFAIK, LSE doesn't support SV, at least that's what is stated in the docs?

For simulation, yes ActiveHDL was bundled with Diamond before they switched to Modelsim (recently). ActiveHDL is a third-party simulation tool and has nothing in common with LSE that I know of.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 06, 2021, 09:08:12 pm
It's the 'SynplifyPro', I've been using it from day one as the instructional video I used only had designs compiled through 'SynplifyPro'.  So I never knew that Diamond didn't do SystemVerilog internally even though it took my SystemVerilog and compiled a FPGA.

This was my first introduction to Diamond:
https://www.youtube.com/watch?v=SmdEP_ZsBgM (https://www.youtube.com/watch?v=SmdEP_ZsBgM)

Right now, I need to finish my controler's multiport interface and prep a demo using the multiport to drive a 1080p video output with a geometry processor driving an alternate port & maybe an debug port on another port.

And one last issue is the generation of the .sdc file.  Just a bit of math, but needs to be done right.  Right now, I made the DDR3 IO port forced to the IO Pin;'s Flipflop for best possible IO timing at the expense of fabric routing.  I also saw that Diamond also has the same feature to specify that you want your IO logic to use the flipflop at the IO pin.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on March 06, 2021, 09:29:11 pm
It's the 'SynplifyPro', I've been using it from day one as the instructional video I used only had designs compiled through 'SynplifyPro'.  So I never knew that Diamond didn't do SystemVerilog internally even though it took my SystemVerilog and compiled a FPGA.

As I said - since you mentioned ActiveHDL - both ActiveHDL and Modelsim are two third-party simulation tools. None do synthesis and none are developed by Lattice. This was to reply to your remark that ActiveHDL took your SV whereas I was talking about synthesis.

Diamond has been offering two synthesis tools for a long time: LSE and Synplify Pro. LSE is Lattice's own synthesis tool. Synplify Pro is a well-known tool they licensed from Synopsys (and that is used by most other FPGA vendors too.)

LSE doesn't support SV AFAIK (at least so far), but I mentioned it not knowing which synthesis tool you were using or if you even were aware of it. I also think LSE is default when you create a new project in Diamond, hence my warning. Now if for some reason you've always selected Synplify Pro, you can ignore the warning.

But now you know Lattice have their own synthesis tool. And apart from not supporting SV and no (or very little) VHDL-2008, it's not bad. It's faster than Synplify and may even produce better results entirely depending on your design. It's sometimes interesting to compare results using both.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 11, 2021, 06:24:21 pm
DDR3 update:  Finally moved code from ModelSim to Quartus and set it up for the Deca board.  After a bunch of conflicts and even Quartus crashes.  It's finally in there, but, I first have to fix the 'FMAX' problem as attaining 320MHz operation with my current core wont make it.  It will take a few days to clean up the 'glut'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 15, 2021, 12:13:27 pm
DDR3 Update: Almost there.  I'm short 2MHz as shown in the photo, though, I still need to design it with some more breathing room.  Also still need to define the IO constraints, but the 'gate-level' simulation has finally passed read calibration.  It will be a few more days.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 15, 2021, 02:08:33 pm
Also still need to define the IO constraints
You might want to do it sooner rather than later, as routing delays can be quite significant. I have seen (and done) IO designs that have Fmax fluctuate as much as 20% depending on the pinout you choose.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 15, 2021, 06:02:24 pm
I've put together a basic Pong game in CP/M using the GPU with the limited spare time I've had recently.   Just need to display the score on the game screen and it'll be done.  It works in all three screen modes (that I currently have on the EP4CE10 GPU), though the video just shows 320x200.

Apologies for the focus in the video - my camera doesn't seem to want to play these days.  ::)

https://www.youtube.com/watch?v=OiJeM_Q5xAM (https://www.youtube.com/watch?v=OiJeM_Q5xAM)

EDIT: Oh - it'll be done when the scores are displayed and also when I adjust the return angle of the ball based on where it hits the bat, to add a little more complexity to the game.  At the moment it's more a proof-of-concept than anything else.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 15, 2021, 09:22:40 pm
Also still need to define the IO constraints
You might want to do it sooner rather than later, as routing delays can be quite significant. I have seen (and done) IO designs that have Fmax fluctuate as much as 20% depending on the pinout you choose.
My code has assignable pipe delays to the IO.  There wont be any routing problems.
The route for the DQ on the writes is already huge due to CWL.
The read CL and data ready toggle can be set from 0 on up generating an automatic sequential pipe from the pins to your core.

Also, only clocks C2 and C1 will be effected by IO pin timing.  And when I add just 1 single additional pipe-line delay to those guys, they max out at 500MHz (Core limit), IO 1GHz DDR rate.

The limiting FMAX is being cut down due to crossing clock domain boundaries and the way I'm running my 5 command timers which keep track of when the next requested command's earliest possible time to be sent.  Funny how it's the system global reset which has caused a huge problem up until now...

I'm just learning the limits of setting the 'multicycle' paths VS cutting clock domain paths.

I should be on the IO timing tomorrow which will finally yield real hardware communication.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 15, 2021, 09:25:36 pm
I've put together a basic Pong game in CP/M using the GPU with the limited spare time I've had recently.   Just need to display the score on the game screen and it'll be done.  It works in all three screen modes (that I currently have on the EP4CE10 GPU), though the video just shows 320x200.

Apologies for the focus in the video - my camera doesn't seem to want to play these days.  ::)

https://www.youtube.com/watch?v=OiJeM_Q5xAM (https://www.youtube.com/watch?v=OiJeM_Q5xAM)

EDIT: Oh - it'll be done when the scores are displayed and also when I adjust the return angle of the ball based on where it hits the bat, to add a little more complexity to the game.  At the moment it's more a proof-of-concept than anything else.  ;)
Wow, your first game.  :-+
How are you moving those paddles?
It almost looks as if you keep track of key-down and key-up...

And to think with the ellipse you could easily animate a ball squish/squeeze effect when it bounces off of the paddles and walls...  That would look cool with definition at 640x400.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 15, 2021, 10:07:55 pm
How are you moving those paddles?
It almost looks as if you keep track of key-down and key-up...

Well if I use CP/M's BIOS routines to read the keyboard, I can only read one key down at a time - so if one paddle is moving, the other can't, even if a key pressed for it.  Instead I'm using a hardware IO port that I put on the CPU card some time ago and a very basic (8 buttons) controller I made - each button grounds a bit on the IO port when pressed.  The Pong loop reads the IO port value - bits 4 & 7 are up/down for the left paddle, bits 0 and 3 are up/down for the right paddle, and all bits are acted upon each loop so simultaneous control of both paddles is possible.

And to think with the ellipse you could easily animate a ball squish/squeeze effect when it bounces off of the paddles and walls...  That would look cool with definition at 640x400.

Absolutely.  One for the to-do list.   :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 16, 2021, 04:08:50 am
How are you moving those paddles?
It almost looks as if you keep track of key-down and key-up...

Well if I use CP/M's BIOS routines to read the keyboard, I can only read one key down at a time - so if one paddle is moving, the other can't, even if a key pressed for it.  Instead I'm using a hardware IO port that I put on the CPU card some time ago and a very basic (8 buttons) controller I made - each button grounds a bit on the IO port when pressed.  The Pong loop reads the IO port value - bits 4 & 7 are up/down for the left paddle, bits 0 and 3 are up/down for the right paddle, and all bits are acted upon each loop so simultaneous control of both paddles is possible.

And to think with the ellipse you could easily animate a ball squish/squeeze effect when it bounces off of the paddles and walls...  That would look cool with definition at 640x400.

Absolutely.  One for the to-do list.   :-+
What happened to the key-down, key-up trick I mentioned way back using the MSB bit in the keyboard routine to send the key-ups which would be ignored by the normal CP/M routines, but, you may intercept them to respond to multiple key presses simultaneously?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 16, 2021, 11:18:29 am
What happened to the key-down, key-up trick I mentioned way back using the MSB bit in the keyboard routine to send the key-ups which would be ignored by the normal CP/M routines, but, you may intercept them to respond to multiple key presses simultaneously?

I forgot all about those! :o  I really haven't had a lot of time to do anything these past few weeks and that isn't going to change until after Easter, so no surprise I forgot about the extra bit to show key-ups.  I don't even remember if it was working or not - will have to go look at the HDL and see what I've got set up for it.  Also, reading the IO port directly for key presses will be quicker than going through the CP/M methods anyway.

EDIT:  Yes, it's active.  The ASCII code passed via the GPU's keyboard IO port has bit 7 set if it's a key-up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 19, 2021, 02:35:45 pm
The DDR3 is coming.... Having a scope would have saved me almost a week as the CLK out to the ram wasn't oscillating due to unknown BS as it simulated fine both at logic and gate level properly, sound design, but something about the MAX10 as the chosen IOs just generated dead output.  It's a pain avoiding a bunch of Altera's eccentricities as I avoid their built in DDRx PHY and do everything in a way which can be supported throughout all Altera FPGAs as well as be ported to other FPGA vendors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on March 19, 2021, 06:04:08 pm
The DDR3 is coming.... Having a scope would have saved me almost a week as the CLK out to the ram wasn't oscillating due to unknown BS as it simulated fine both at logic and gate level properly, sound design, but something about the MAX10 as the chosen IOs just generated dead output.  It's a pain avoiding a bunch of Altera's eccentricities as I avoid their built in DDRx PHY and do everything in a way which can be supported throughout all Altera FPGAs as well as be ported to other FPGA vendors.

Wow you're designing all this without a scope?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 19, 2021, 06:11:03 pm
Wow you're designing all this without a scope?
I design most of my projects without a scope, as IO speeds far exceed what my scope is capable of, while the kind of scopes which would be capable of displaying would cost insane money.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 19, 2021, 07:32:09 pm
I design most of my projects without a scope, as IO speeds far exceed what my scope is capable of, while the kind of scopes which would be capable of displaying would cost insane money.

And there I was a couple of years ago thinking a 20MHz analogue scope (that I bought for about £20 on eBay) would be more than enough for my project.  ;)  Actually, it was for the 8MHz Z80 computer I built (though a cheap logic analyser has replaced the scope for just about everything), but this stuff is just a whole other level.  A week or so back I thought - for a laugh - I'd see how much a good(-ish) oscilloscope would cost me that a YouTuber I watch uses (Ben Eater (https://www.youtube.com/channel/UCS0N5baNlQWJCUrhCEo8WlA)).  His Keysight DSOX1204G looks pretty smart, I thought to myself.  Then I found out it's over £1,300 and that's just a 70MHz model..  A 1GHz scope would cost as much as a half decent new car! :o

So yeah, unless you work in the EE industry and have access to professional equipment (and I certainly do not fulfil either of those requirements), I'd say using a scope for this work would be prohibitively expensive.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 19, 2021, 07:46:25 pm
And there I was a couple of years ago thinking a 20MHz analogue scope (that I bought for about £20 on eBay) would be more than enough for my project.  ;)  Actually, it was for the 8MHz Z80 computer I built (though a cheap logic analyser has replaced the scope for just about everything), but this stuff is just a whole other level.  A week or so back I thought - for a laugh - I'd see how much a good(-ish) oscilloscope would cost me that a YouTuber I watch uses (Ben Eater (https://www.youtube.com/channel/UCS0N5baNlQWJCUrhCEo8WlA)).  His Keysight DSOX1204G looks pretty smart, I thought to myself.  Then I found out it's over £1,300 and that's just a 70MHz model..  A 1GHz scope would cost as much as a half decent new car! :o

So yeah, unless you work in the EE industry and have access to professional equipment (and I certainly do not fulfil either of those requirements), I'd say using a scope for this work would be prohibitively expensive.
There is a good news though - Xilinx provides free "Integrated Logic Analyzer" IP, which is an excellent substitute for situations when your IO interface doesn't quite work and you are not sure why. In a way it's even better because unlike external scope/LA, it doesn't distort the signal when you connect it to traces you want to probe. You can use it to visualize internal signals in your design as well, but I use the core mostly to debug IO interfaces, as often peripheral devices datasheets leave a lot of be desired, forcing you to find out how it actually works using a good-ol' trial-and-error approach. For multi-gigabit serial transceivers there is also free IBERT core, which allows measuring and visualizing of a signal eye in real time - again, without disturbing transmission lines with probes.

I'm pretty sure Intel has similar cores, though I don't know if they are free or cost money.

The scope I have is 2 input 200 MHz bandwidth which is good enough for slower peripherals, but nowhere near enough for stuff like DDR3, not to mention multi-gigabit links.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on March 19, 2021, 07:53:27 pm
Wow you're designing all this without a scope?

There's not much an oscilloscope can tell with FPGAs.

The inside of the FPGA can not be probed, and routing internal signals to outside pins just to probe something is not an option.  That would change too much the design, might make the timing constraints to fail, etc., not to say big designs can take hours to build a new bitstream.

The workhorse in digital design is the simulator.  Once the simulation works, and the timing closure is satisfied, it should work.  If there is still something to debug, then ChipScope (Xilinx) / SignalTap (Altera) would the tool to capture and watch internal signals.  Sometimes a JTAG might help, too.  In rare situations, at low speed, a logic analyzer might also help.

Only in very rare situations one may want to probe FPGA signals with an oscilloscope, usually when hunting for signal integrity issues, for example to see how open is the eye on a high speed SERDES, or something alike.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 19, 2021, 09:06:32 pm
On single ended clocks you can detect DC bias with DMM. Say, with 3.3V signal, the DMM will read 1.6V if the clock is present.

Not so with differential signals terminated at VDD/2 :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 19, 2021, 11:50:57 pm
The DDR3 is coming.... Having a scope would have saved me almost a week as the CLK out to the ram wasn't oscillating due to unknown BS as it simulated fine both at logic and gate level properly, sound design, but something about the MAX10 as the chosen IOs just generated dead output.  It's a pain avoiding a bunch of Altera's eccentricities as I avoid their built in DDRx PHY and do everything in a way which can be supported throughout all Altera FPGAs as well as be ported to other FPGA vendors.

Wow you're designing all this without a scope?
Damn clean coding and proper simulation with the DDR3 model...

Yes, Altera offers 'SignalTap' logic analyzer through the J-Tag just like there is one in Lattice Diamond and Xilinx, however, this stupid bug was me using the CLK output pin as a DDR output,  1/2 clock signal high and the other low to reconstruct a parallel clock.  This is fine and works with most older Altera FPGAs like CycloneIV, but, the signal gets muted out for some reason on the MAX10s chosen IOs for the DDR3.

The Max10/CycloneV on the CK and DQS lines has a nice feature which offers 128x15ps taps on those IOs with a feedback so you may tune your sample times specifically for DDR3/4 interfaces.  This also means less taps on the PLL.  But, If I use the function, my code would not work older Cyclones & third party vendors FPGAs.  These 2 chips also offer a dedicated 2 way FIFOs on the DQ lines merges with DQS and CK for clocking which I am not using.  They can all be easily accessed and pre-packaged in 1 nice module by the free DDR2/3/4 PHY available with Quartus, but if I designed using it, where would the fun be in doing it all manually in a way which is cross-vendor compatible?

Right now, I'm phase-stepping on the PLL to create my required 3 clocks.  This is not as fine as 15ps steps, but right now I do get a valid data window of around 10 steps out of 64.  This should clean up as I'm now on the SDC file.  Yes, I'm getting good data now without any timing constraints other than 'multicycle path' for signals crossing of clock domain boundaries.

I've generated 3.5k line of code, all documented and explained with comments at almost every line...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 20, 2021, 04:53:26 am
 :palm: MAX 10 doesn't support the old altddio.  It does for input but not output.  No warnings, no compiler complaints.  It simulates properly as if the chip has the logic, but it totally ignores the output.

I have to use the ALTERA_GPIO_LITE which is specific to the newer MAX10 and above...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 20, 2021, 02:46:31 pm
The Max10/CycloneV on the CK and DQS lines has a nice feature which offers 128x15ps taps on those IOs with a feedback so you may tune your sample times specifically for DDR3/4 interfaces.  This also means less taps on the PLL.  But, If I use the function, my code would not work older Cyclones & third party vendors FPGAs.  These 2 chips also offer a dedicated 2 way FIFOs on the DQ lines merges with DQS and CK for clocking which I am not using.  They can all be easily accessed and pre-packaged in 1 nice module by the free DDR2/3/4 PHY available with Quartus, but if I designed using it, where would the fun be in doing it all manually in a way which is cross-vendor compatible?

Xilinx 7-series FPGAs also have delay lines and designated shallow FIFOs for IO.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 20, 2021, 03:01:33 pm
Xilinx 7-series FPGAs also have delay lines and designated shallow FIFOs for IO.
Also undocumented phasers which you will have to use for write leveling because there are no output delay blocks in HR banks.
So, yeah - I stand by my doubts about vendor-neutral PHYs...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 21, 2021, 12:03:19 am
The Max10/CycloneV on the CK and DQS lines has a nice feature which offers 128x15ps taps on those IOs with a feedback so you may tune your sample times specifically for DDR3/4 interfaces.  This also means less taps on the PLL.  But, If I use the function, my code would not work older Cyclones & third party vendors FPGAs.  These 2 chips also offer a dedicated 2 way FIFOs on the DQ lines merges with DQS and CK for clocking which I am not using.  They can all be easily accessed and pre-packaged in 1 nice module by the free DDR2/3/4 PHY available with Quartus, but if I designed using it, where would the fun be in doing it all manually in a way which is cross-vendor compatible?

Xilinx 7-series FPGAs also have delay lines and designated shallow FIFOs for IO.
Those are available in every FPGA's basic DDR phy toolkit.  It is the only way to ensure getting valid data in and out  from one phase to the next.  Note that there is a module in my code which gets swapped depending on selected vendor and it doe use each vendor's DDR IO buffers and dedicated first IO cells at the pins.  Otherwise this could never work.

The DDR3 provides test alignment Read and Write timing signals which can be used to align your time-of-flight feedback clocks.  Since I've designed an FPGA centric controller designed for 1 or 2 ram chips (4 of them in a row with the CK pins received inbetween them) with the DDR_CK which must be wired between them if you are using 2, I only do the read-back tuning/alignment, expecting all the signals to arrive at the ram based on the SDC constraints while the memory itself is an unknown device with unknown PCB characteristics which needs to be tuned for on powerup.  You wont be able to use DDR3 modules.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 21, 2021, 12:20:58 am
Since I've designed an FPGA centric controller designed for 1 or 2 ram chips (4 of them in a row with the CK pins received inbetween them) with the DDR_CK which must be wired between them if you are using 2, I only do the read-back tuning/alignment, expecting all the signals to arrive at the ram based on the SDC constraints while the memory itself is an unknown device with unknown PCB characteristics which needs to be tuned for on powerup.  You wont be able to use DDR3 modules.
This is a BIG limitation. Most DDR3 designs I've seen (and all designs I've done myself) use flyby routing for address/control lines because it's MUCH simpler from routing standpoint. So you can expect that address/control signals reach each module at the same time, but that time will be different for different modules.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 21, 2021, 02:51:06 am
There are DDR3 chips with multiple dies, where the dies are connected within the chip using the fly-by topology. For example, Micron's MT41K512M16VRN.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 23, 2021, 02:19:22 am
There are DDR3 chips with multiple dies, where the dies are connected within the chip using the fly-by topology. For example, Micron's MT41K512M16VRN.
Shouldn't be a problem as each die is 8 bit and they have separate DQS for each die.  My controller would only have trouble for widely spaced DDR3s with clocks fed from one side to the other, and when you run in dual channel mode where multiple ICs share the same DQ & DQS as I am currently sampling the DQS with the read data as a reset & latch enable/data valid signal.  This would change if I switched to using the DQS as a read clock, but, this will force much deeper use of each vendor's memory DQ/DQS PHYs.  Not impossible, but a lot more reading of the data sheets and potentially some setup control code.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 23, 2021, 03:07:45 pm
Shouldn't be a problem as each die is 8 bit and they have separate DQS for each die.  My controller would only have trouble for widely spaced DDR3s with clocks fed from one side to the other, and when you run in dual channel mode where multiple ICs share the same DQ & DQS as I am currently sampling the DQS with the read data as a reset & latch enable/data valid signal.  This would change if I switched to using the DQS as a read clock, but, this will force much deeper use of each vendor's memory DQ/DQS PHYs.  Not impossible, but a lot more reading of the data sheets and potentially some setup control code.

The reason they have DQS is that the phase of DQ may wander over time relative to the clock. If you sample with a separate shifted clock instead of sampling with DQS, you're making the window much smaller. Xilinx did a similar thing. They have a hardware PHASER elements which creates a free-running phase-shifted clock to sample DQ. To make it work they must synchronize their clock with DQS every us or so. As a result, their controller cannot write continuously for long because synchronizing reads are needed.

Regardless of how you sample, there's no reason why you can't handle multiple chips with any configuration. There are two possible way of connecting multiple chips:

- shared CLK and control, but non-shared DQ/DQS, which is usually fly-by. In this case everything is the same except the clock/DQS phase relationship is different for every byte. Whatever you do in your controller for one byte can be done for multiple bytes as well, only every byte will require its own (set of) clocks.

- shared DQ/DQS, often called multi-rank. In this case, each chip will have its own CS line (perhaps ODT as well), so by selecting different CS you just talk to one chip or another. This certainly can be done no matter how you sample.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 24, 2021, 04:25:39 am
Shouldn't be a problem as each die is 8 bit and they have separate DQS for each die.  My controller would only have trouble for widely spaced DDR3s with clocks fed from one side to the other, and when you run in dual channel mode where multiple ICs share the same DQ & DQS as I am currently sampling the DQS with the read data as a reset & latch enable/data valid signal.  This would change if I switched to using the DQS as a read clock, but, this will force much deeper use of each vendor's memory DQ/DQS PHYs.  Not impossible, but a lot more reading of the data sheets and potentially some setup control code.

The reason they have DQS is that the phase of DQ may wander over time relative to the clock. If you sample with a separate shifted clock instead of sampling with DQS, you're making the window much smaller. Xilinx did a similar thing. They have a hardware PHASER elements which creates a free-running phase-shifted clock to sample DQ. To make it work they must synchronize their clock with DQS every us or so. As a result, their controller cannot write continuously for long because synchronizing reads are needed.

Regardless of how you sample, there's no reason why you can't handle multiple chips with any configuration. There are two possible way of connecting multiple chips:

- shared CLK and control, but non-shared DQ/DQS, which is usually fly-by. In this case everything is the same except the clock/DQS phase relationship is different for every byte. Whatever you do in your controller for one byte can be done for multiple bytes as well, only every byte will require its own (set of) clocks.

- shared DQ/DQS, often called multi-rank. In this case, each chip will have its own CS line (perhaps ODT as well), so by selecting different CS you just talk to one chip or another. This certainly can be done no matter how you sample.

Yes, the window range of tDQSQ (DQS, DQS# to DQ skew, per access) is smaller (better) than tDQSCK (DQS, DQS# rising to/from rising CK, CK#).  I guess I am not having trouble here since the DECA board has 1600MHz ram and these figures shrink down to +/-0.23ns / 0.1ns where are the slower 800MHz ram is twice as bad.  The center and hold of the read data is a sweet huge 2.54ns.  It cannot drift outside this window with reference to the CK, otherwise the ram chip has failed.

Damn Altera and their incomplete TBD specs.  Well, the clock IO jitter on Altera's DDRIOs is in the 200ps range while the setup and hold requirement on data input is within the 1ns range (Older cyclone specs).  Since I am phase clocking using the true-pll in the FPGA fabric, I have a ~ +/-500ps safety window and my phase tuning steps with a wide-band PLL is 195.3125ps when operating at 320MHz.  This jives with my current tests having a ~7 pll tuning steps with clean data.  This is advanced info and I am seeking about incorporating an async reset into my read FIFO & control pointers which would allow read data clocking right from the DQS inputs.  This would eliminate the tDQSCK +/-0.23ns improving that read window opening by another 460ps and eliminating the PLL read RDQ clock and it's power-up tuning logic.  (May allow overclocking of a soft-ram controller for Altera reaching or passing the maximum 430/860MHz serial DDR input specs so long as the ram will accept a slightly mushy (wouldn't have been the case if the DECA board use the dedicated PLL output to clock the ram instead of the dedicated DDR_CK output which has a a lower FMAX spec, but has fine skew tuning, larger drive current) CK/CK# and the fitter can time the DDR3 address & command lines which aren't part of the DDR DQ pins section.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 27, 2021, 08:13:46 am
Update: Had to take a week break.  I'm on the SDC file and  either I can make the writes perfect, or the reads perfect...  But not both.  Gotta read up on the multicycle function and false_path.  Once this is setup, we will have a working ram controller...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 27, 2021, 04:08:37 pm
Update: Had to take a week break.  I'm on the SDC file and  either I can make the writes perfect, or the reads perfect...  But not both.  Gotta read up on the multicycle function and false_path.  Once this is setup, we will have a working ram controller...

You should use separate clocks for reads and writes.

When you read, the phase shift of DQ to your clock is determined by the FPGA -> CK/CK# -> DDR3 -> DQ/DQS -> FPGA path.

When you write, you need to synchronize DQ/DQS with the clock as it is seen inside the DDR3 chip, so the phase shift is determined by the difference between FPGA -> DQ/DQS -> DDR3  and FPGA -> CK/CK# -> DDR3 paths.

These phase shifts cannot be the same.

Not to mention that both of these clocks will be phase shifted relative to the clock used for address/control lines which is source-synchronous to CK/CK#.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 28, 2021, 12:29:17 am
Update: Had to take a week break.  I'm on the SDC file and  either I can make the writes perfect, or the reads perfect...  But not both.  Gotta read up on the multicycle function and false_path.  Once this is setup, we will have a working ram controller...

You should use separate clocks for reads and writes.

When you read, the phase shift of DQ to your clock is determined by the FPGA -> CK/CK# -> DDR3 -> DQ/DQS -> FPGA path.

When you write, you need to synchronize DQ/DQS with the clock as it is seen inside the DDR3 chip, so the phase shift is determined by the difference between FPGA -> DQ/DQS -> DDR3  and FPGA -> CK/CK# -> DDR3 paths.

These phase shifts cannot be the same.

Not to mention that both of these clocks will be phase shifted relative to the clock used for address/control lines which is source-synchronous to CK/CK#.
It's all configurable in the code.  The code was designed to adapt to other third party vendor's DDR IO blocks no matter how they jumble up the read/write order, endian, bus width, delay, clock direction, use or non use DQS as either clock or enable for reads and adapt to manual or automatic enable & disable paths, be it in a slave or master mode, both ways for read or write.  Everything I've done in the code is fully documented and explained so anyone can edit and make changes with relative ease.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 28, 2021, 12:40:15 am
Here is the DDR3 working perfectly (This is 100% true hardware, not a simulation...):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1203900)

I've been troubled with this 1 weird read bug where is I used DQS[0]n/p from the 16 bit ram chip to align the reads, 1 out of every 1 million reads or so, the 128bit (8 word burst) read would be shifted off by 1 byte.  This is not possible with a 16 bit ram, it should have been shifted off by 2 bytes if it were an alignment error.

Reading using only the second DQS[1]n/p, the reads are perfect and the writes have always been perfect where I generate the both DQS[1:0]n/p outs.

I'm hunting down the bug and believe that it looks like something in my .SDC timing file is being ignored or misinterpreted as the problem appears timing in nature exclusive to 1 single IO pin.

Once this final bug is cleared, the multiport interface bus should take a fraction of time to develop as all my issues have related to Quartus and the newer DDR IOBuf specific to MAX 10 FPGAs.  At that point I'll start a new thread dedicated to the DDR3 controller.  There should be no trouble getting this design to work on Cyclone V and IV.  In fact, Cyclone IV may clock up to 400MHz.  I cannot say if it will work on Cyclone III.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 28, 2021, 01:46:38 am
Is this running on hardware, or a sim? If it's the latter, it might be just a quirk of simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 28, 2021, 01:53:39 am
100% hardware.  No sim.

The glitch can not be verified in sim since the sim has been error free since day 1, like 3 weeks ago...

What you see is a utility which allows me to address read and write to the DDR3 through the RS232 port in and hex view in real-time.  I tied to a USB FT232 rs232 to LVTTL converter onto 2 pins of the DECA board's P6 header.

I will be creating a serious real demo which will use all the ram and the HDMI out on the DECA board.

Quartus is stingy with the .SDC as I used to use their old timing utility 20 years ago and I am learning the new language/specifications as we speak.  There is no proof anywhere that what I set is actually doing anything other than the final timing report saying it's a pass or fail.  The older CycloneIV allowed full timing accurate gate level simulations where I could see a true difference.  Not so for the MAX 10, you need to trust that what you have done in the SDC represents the truth.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 28, 2021, 02:23:54 am
Here is the DDR3 working perfectly (This is 100% true hardware, not a simulation...):

Very impressive.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 28, 2021, 10:24:29 am
Here is the DDR3 working perfectly (This is 100% true hardware, not a simulation...):

Awesome work, BrianHG.  :-+ :o

I have been consistently shocked and awed throughout this DDR section of the thread about the complexity of getting DDR RAM to work with the FPGA.  All of this stuff is well and truly so far above my head it's leaving contrails.  It also makes me even more impressed at the technology (and effort gone into making that tech) sitting in the black and orange box under my desk that I'm using to write this post with right now, running billions of fault-free memory accesses into DDR RAM on a system I threw together myself.  I'm looking to add DDR3 to an FPGA approximately 1cm away at worst.  The effort gone into designing a motherboard that can work with slot-in sticks of RAM in a variety of configurations in the gigahertz range is impressive, to say the least.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 28, 2021, 11:24:54 am
Is this running on hardware, or a sim? If it's the latter, it might be just a quirk of simulation.
Like I said, hardware.
Glitch already found & fixed.
It's now compiling and operating with multiple settings in a really robust manner.  No tuning at power-up even needed.  The latest better setup .sdc set to the DDR3 datasheet generates a functioning design where tuning the PLL read phase is already dead center set to the powerup 0 degrees, with an equal +/-4 tune-able steps to the left or right before there is any data corruption.  Same for the powerup write DQ clock phase of 90 degrees, though, that one has a ~ +/- 8 tuning steps before data is corrupted.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 28, 2021, 01:05:32 pm
I have been consistently shocked and awed throughout this DDR section of the thread about the complexity of getting DDR RAM to work with the FPGA.  All of this stuff is well and truly so far above my head it's leaving contrails.  It also makes me even more impressed at the technology (and effort gone into making that tech) sitting in the black and orange box under my desk that I'm using to write this post with right now, running billions of fault-free memory accesses into DDR RAM on a system I threw together myself.  I'm looking to add DDR3 to an FPGA approximately 1cm away at worst.  The effort gone into designing a motherboard that can work with slot-in sticks of RAM in a variety of configurations in the gigahertz range is impressive, to say the least.
This was also a somewhat unexpected for me, that once I got into FPGA board designs, I suddenly started understanding what exactly is going on a PC motherboard, or on video card. Now if you look at video card PCB, for example, you will see immediately - these are power supplies for the Vcore (in FPGA world this rail is typically called Vccint), these are for the memory, and here these serpentine tracks are length matched for the memory, etc. Same goes for the motherboard.

Also most motherboards are 6 layer ones, and I've done enough 6 layer boards that I can technically route a motherboard myself if I so desire. Also what's cool is that there are open source motherboards out there so that you can actually see full schematics and PCB and study all that stuff.

So all of what felt like a magic that made PC work, now suddenly makes perfect sense, and there are good technical reasons why certain things are done the way they are done. Now you can also understand why PC motherboards with a single DIMM slot per CPU channel tend to reach higher stable memory clocks (no stubs, shorter traces).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 28, 2021, 02:09:51 pm
It's now compiling and operating with multiple settings in a really robust manner.  No tuning at power-up even needed.  The latest better setup .sdc set to the DDR3 datasheet generates a functioning design where tuning the PLL read phase is already dead center set to the powerup 0 degrees, with an equal +/-4 tune-able steps to the left or right before there is any data corruption.  Same for the powerup write DQ clock phase of 90 degrees, though, that one has a ~ +/- 8 tuning steps before data is corrupted.

What's your clock frequency and how many degrees is your tunable step?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 28, 2021, 02:52:12 pm
It's now compiling and operating with multiple settings in a really robust manner.  No tuning at power-up even needed.  The latest better setup .sdc set to the DDR3 datasheet generates a functioning design where tuning the PLL read phase is already dead center set to the powerup 0 degrees, with an equal +/-4 tune-able steps to the left or right before there is any data corruption.  Same for the powerup write DQ clock phase of 90 degrees, though, that one has a ~ +/- 8 tuning steps before data is corrupted.

What's your clock frequency and how many degrees is your tunable step?
I already answered your question, see here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3527398/#msg3527398 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3527398/#msg3527398)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 28, 2021, 05:09:37 pm
What's your clock frequency and how many degrees is your tunable step?
I already answered your question, see here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3527398/#msg3527398 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3527398/#msg3527398)

I probably misunderstood something. As I understood, you're clocking DQS writes with the same clock as CK/#CK, and you clock DQ writes with the other clock which is nominally 90 degrees shifted, but can tolerate +/- 8 steps. If steps are 200 ps, this equals 1.6 ns, that's roughly 180 degrees with 320 MHz clock (0 to 180 relative to DQS). If you shifted by 9 steps, you would be in another bit's territory. Looks like you don't have any jitter zone between bits - close to 100% window. Is that really so?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 28, 2021, 11:48:41 pm
Just redid the tuning test with the latest firmware.
Write window = +1 to -3, 5 functional positions for DDR3_CLK_WDQ.
Read window = +2 to -4, 7 functional positions for DDR2_CLK_RDQ.

The WDQ center is off by 1, this needs to be fixed.  It's probably that stupid 'PHASE' int to string problem.  I'll look at that tonight.  I wont play with the RDQ yet as I am trimming a lot of fat in my code first.

I am not using any special timing or tuning, or fine DLL features available for a DDR PHY interface.  This is purely a set counter phase on the system PLL and an .SDC file to constrain the IO timing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on March 29, 2021, 12:39:31 am
Is it the same for both byte lanes?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 29, 2021, 07:12:05 am
When tuning from +2 to +3 on the reads, there is data corruption across many of the data bits, with jiggling bit errors.  However, strange enough, at the end of the 'BL8', the last 16bit word/2 bytes don't have any errors, it's just the first 7 of 8 with the errors.  I assume it's just capacitance on the DQ buss holding that last word steady since the DDR3 has placed the DQ outputs into tri-state mode.

-4, I can't see anything since my code detects a DQS timing violation and reports the error scrapping the data read all together.

Going from -4 to -5, no errors seen as my code detects the DQS fault.

As for writes, stepping outside the tuning range messes up everything randomly to hell, like shiftng data or complete gibberish.  I have a feeling some of this is due to internal clock domain cross-boundary issues in the FPGA, not on the ram bus as I would expect to see a clean 2 byte data shift as I continue to tune, not the 4/8 bytes I see with repetitious blocks.

Note that I am not using FPGA dual port ram to store and shift data between clock domains.   This code is 100% logic elements.  For those who want the dual clock multi-clock domain features of embedded ram blocks, you would just use them to feed my controller's command inputs with another one on my controller's output.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 30, 2021, 01:30:22 pm
Write window = +1 to -3, 5 functional positions for DDR3_CLK_WDQ.

This is only 200 ps off centre. The skew between different clocks from the same PLL might be around 100 ps.

I did some experiments with SODIMM modules few years back. As I remember, the skew between different traces of the same byte may  ps (although the IDELAY resolution was only 40 ps).

Also, as FPGA warms up by 30-40 degrees from ambient, the delay can easily increase by around 100 ps. The temperature shouldn't be a problem for writes, but when you read, it may shift the window. Same with voltage.

If your FPGA has an internal temperature sensor you can build a "thermostat" design which keeps FPGA at the desired temperature. Then you can investigate how the window changes with temperature.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 31, 2021, 03:22:33 am
Write window = +1 to -3, 5 functional positions for DDR3_CLK_WDQ.

This is only 200 ps off centre. The skew between different clocks from the same PLL might be around 100 ps.
Even ModelSim also shows it is off by 1 step when I measure the PLL clock output waveforms.  It's like Altera has forgotten that their phase tap calculation begins at 0, not 1, or it is an integer rounding error in their code.  These are not the only bugs I've encountered.  Coding the memory controller was the easy part and done in the first week running great in ModelSim.  In that part, nothing has changed since then.  Uncovering all these little undocumented, or erroneous documented functions, waiting for Quartus to compile and test was the other  > 90% of the work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: RoGeorge on March 31, 2021, 12:28:50 pm
waiting for Quartus to compile and test was the other  > 90% of the work.

Just curious, how much time does it take to complete a compilation, and how long to run the tests/simulations?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on March 31, 2021, 01:12:22 pm
Even ModelSim also shows it is off by 1 step when I measure the PLL clock output waveforms.  It's like Altera has forgotten that their phase tap calculation begins at 0, not 1, or it is an integer rounding error in their code.  These are not the only bugs I've encountered.  Coding the memory controller was the easy part and done in the first week running great in ModelSim.  In that part, nothing has changed since then.  Uncovering all these little undocumented, or erroneous documented functions, waiting for Quartus to compile and test was the other  > 90% of the work.

This is bizarre. May be Vivado is not that bad after all :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 31, 2021, 02:33:29 pm
waiting for Quartus to compile and test was the other  > 90% of the work.

Just curious, how much time does it take to complete a compilation, and how long to run the tests/simulations?
ModelSim in RTL takes around 1 seconds to compile.  To simulate, around 1 second when I have the power-up reset timer set to 200ns instead of the authentic 1000uS.

Quartus takes around 2 minutes total to full compile/fit.  Doing a gate-level simulation with the phony 200ns power-on reset timer, using my accidental discovery of bypassing the speed limiter put in place takes around 10 seconds to setup the sim, then 5 seconds of simulating before I reach the first refresh command after initialization and calibration of the DDR3.  It's ~3x slower if you let it run the normal way with the 'Altera-Modelsim' speed limiter in place.  Having the 1000uS powerup timer in place makes it take almost 1 minute, almost 4 with the speed limiter in place.  A timing-gate level sim is around 50% slower.

As you can see, working 100% within ModelSim, I can see the results of code edits within 2 seconds flat, less than a second if there were coding errors, and in FPGA terms, you can almost call this real-time.

All the above simulations had Micron's DDR3 simulation model wired into my test-bench code simulating the DDR3 ram chip.  It would report any timing/command violations and what the DDR3 ram chip is doing in the console window as each command went out.  All my code and simulation test bench files will be available in my DDR3 thread next week.

(Yes it is a fluke, but I did not know about the Model-Sim speed limiter in place for the FPGA Vendor versions instead of the full version of the simulator and without knowing, I accidentally been bypassing the speed limiter and only recently learned what it was.  My setup script for quick compiling and running my sims just happened to disable/bypass the limiter and made ModelSim simulate at full speed since day one.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 31, 2021, 02:43:46 pm
Even ModelSim also shows it is off by 1 step when I measure the PLL clock output waveforms.  It's like Altera has forgotten that their phase tap calculation begins at 0, not 1, or it is an integer rounding error in their code.  These are not the only bugs I've encountered.  Coding the memory controller was the easy part and done in the first week running great in ModelSim.  In that part, nothing has changed since then.  Uncovering all these little undocumented, or erroneous documented functions, waiting for Quartus to compile and test was the other  > 90% of the work.

This is bizarre. May be Vivado is not that bad after all :)
(In the ModelSim stage) 2 second turn around for compile and see your coded results is great.
Waiting 2 minutes a compile, and not even having a scope to tell you even your clock isn't coming out because you are using an outdated 'altddio_bidir' instead of the newer 'altera_gpio_lite' specifically designed for the MAX10 wasted 10 days.  Whats worse is that the 'altddio_bidir' (Used for all Cyclone and Arria fpgas) still compiled and was partially functional in the MAX10, fully functional in the simulations fu..ing everything up...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2021, 08:43:54 am
Just as an aside from the discussion on DRAM timings, I had a little time over the weekend to do some more work on Pong.  Sorry the video is a little long, but watch towards the end and you'll see the ball accelerates when hit nearly straight-on.

https://www.youtube.com/watch?v=wN7gDiCbQVk (https://www.youtube.com/watch?v=wN7gDiCbQVk)

Would have uploaded it much earlier, but the eevBlog servers were under water in Ogden.  :o  Speaking of, who uses water as a fire suppression agent (yes okay, unless it's water mist) in a room full of high-value (both financially and data-wise) electronics?  Most data centres use gas suppression systems for obvious reasons.  ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 14, 2021, 09:20:39 pm
Ok Nockieboy, it is time to wire up your DECA board to a Z80.  Please think of a sturdy way to get those connections to the TTL 5v translators.

Get the current project working.
Also, make sure the basics and !WAIT is wired with an NPN transistor so we may pause the Z80 if a read isn't ready in time.

Your current code should work as is + you will have access to >128 kilobytes onchip graphics ram and 15 MAGGIE layers.

Next week, expect to wire-in my DDR3 controller in a limited fashion since current GPU core will need updating as it was only designed to address 1 megabyte, but the DECA board has 512 megabytes.  There is a lot of crap to update all over the place.  Might as well bring everything up to 30-32 bit addressing supporting 1-4 gigabytes, though, I do not know how a Z80 can address all that...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on April 14, 2021, 11:34:44 pm
Next week, expect to wire-in my DDR3 controller in a limited fashion since current GPU core will need updating as it was only designed to address 1 megabyte, but the DECA board has 512 megabytes.  There is a lot of crap to update all over the place.  Might as well bring everything up to 30-32 bit addressing supporting 1-4 gigabytes, though, I do not know how a Z80 can address all that...
The simplest method I can think of is this: implement six memory-mapped 8 bit registers (Z80 is 8bit right?) -
4 registers for the address (32 bit address)
1 register for stride
1 data register
The idea is that once you set up address and stride, you just keep writing data into a single data register (or reading from it), and FPGA will auto-increment the address as per stride value after every successful read from or write to the data port. And now you can address any 32 bit location of the video memory, and pump the data at max CPU speed because it doesn't need to adjust address all the time. Using stride also allows for some advanced scenarios like writing every other byte (common with text modes, which encode each symbol position with two bytes of memory - one for the symbol itself, and another one for background/foreground color).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 15, 2021, 10:05:25 am
Ok Nockieboy, it is time to wire up your DECA board to a Z80.  Please think of a sturdy way to get those connections to the TTL 5v translators.

Get the current project working.
Also, make sure the basics and !WAIT is wired with an NPN transistor so we may pause the Z80 if a read isn't ready in time.

Your current code should work as is + you will have access to >128 kilobytes onchip graphics ram and 15 MAGGIE layers.

Next week, expect to wire-in my DDR3 controller in a limited fashion since current GPU core will need updating as it was only designed to address 1 megabyte, but the DECA board has 512 megabytes.  There is a lot of crap to update all over the place.  Might as well bring everything up to 30-32 bit addressing supporting 1-4 gigabytes, though, I do not know how a Z80 can address all that...

Okay, will get on that ASAP.  Can't say how long it will take as I'm really short on spare time at the moment :(.

Next week, expect to wire-in my DDR3 controller in a limited fashion since current GPU core will need updating as it was only designed to address 1 megabyte, but the DECA board has 512 megabytes.  There is a lot of crap to update all over the place.  Might as well bring everything up to 30-32 bit addressing supporting 1-4 gigabytes, though, I do not know how a Z80 can address all that...
The simplest method I can think of is this: implement six memory-mapped 8 bit registers (Z80 is 8bit right?) -
4 registers for the address (32 bit address)
1 register for stride
1 data register
The idea is that once you set up address and stride, you just keep writing data into a single data register (or reading from it), and FPGA will auto-increment the address as per stride value after every successful read from or write to the data port. And now you can address any 32 bit location of the video memory, and pump the data at max CPU speed because it doesn't need to adjust address all the time. Using stride also allows for some advanced scenarios like writing every other byte (common with text modes, which encode each symbol position with two bytes of memory - one for the symbol itself, and another one for background/foreground color).

Ditto.  It would be easy enough to set up an MMU or register-based access in the FPGA as you've suggested to allow the Z80 to access any part of an arbitrarily-sized RAM space - the question is how useful it would be.  Even if I start thinking about using the GPU RAM as a ram drive for the Z80's operating system (CP/M (https://en.wikipedia.org/wiki/CP/M)), it will only need a few megabytes of space (the 64MB CF card I'm currently using is way too big for it to fill any time soon and my BIOS provides 16 drives within that space, of which I'm using four that aren't even close to being filled yet).

However, where that kind of memory space would be more useful is if the host system is 16-bit.  This GPU card could be used with any homebrew computer system - if I ever get enough free time again I'll be building a 16-bit Motorola 68010 system which will use this GPU card.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on April 15, 2021, 05:04:49 pm
Ditto.  It would be easy enough to set up an MMU or register-based access in the FPGA as you've suggested to allow the Z80 to access any part of an arbitrarily-sized RAM space - the question is how useful it would be.  Even if I start thinking about using the GPU RAM as a ram drive for the Z80's operating system (CP/M (https://en.wikipedia.org/wiki/CP/M)), it will only need a few megabytes of space (the 64MB CF card I'm currently using is way too big for it to fill any time soon and my BIOS provides 16 drives within that space, of which I'm using four that aren't even close to being filled yet).

However, where that kind of memory space would be more useful is if the host system is 16-bit.  This GPU card could be used with any homebrew computer system - if I ever get enough free time again I'll be building a 16-bit Motorola 68010 system which will use this GPU card.
I think it will be useful if you combine it with DMA channel into VRAM from your storage, so that you can load assets directly into VRAM at high speed bypassing CPU (once it sets up the transfer).
This is actually quite common - a lot of my designs do very intensive data processing (like handling FullHD streams), but entire design is controlled by a fairy weak Microblaze CPU running at 100 MHz or even lower. The point is - since a CPU is only used to process user input and control/configure various processing blocks, but  is not directly involved in the data processing itself, you don't really need a beefy CPU.  Come to think of it - even in modern PCs a GPU is typically orders of magnitude more powerful than CPU, which is why a good application that efficiently utilizes GPU will make sure to offload as much of processing onto GPU as possible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 25, 2021, 09:06:43 am
It's been a while again (this is the busiest time of the year for me and working two jobs means I have even less time to do anything hobby-wise.  :-\ )  I hope everyone is fit and healthy and haven't given up on me just yet.  ;)

I've finally had some time to look at wiring the DECA up to my computer to start testing the GPU code on it and make some progress on the DRAM controller.  I was looking at my old Dupont leads that I used previously with the EasyFPGA Cyclone IV board to test the original GPU FPGA and realised they were terrible and caused me no end of headaches with loose connections, so I've designed a dedicated adapter PCB so that I can plug my DIY computer stack directly onto the DECA board, complete with 3.3V/5V translation and some additional features to allow future testing of more stuff on the FPGA (it'll be able to grab the bus from the Z80 and do DMA etc, so the entire address bus is now bidirectional).

I just want to check that I'm not making any silly mistakes with IO selection on the DECA.  From what I can gather, the Beaglebone Black-compatible headers P8 and P9 provide more than enough IO to do what I want, so I'm using P8 for all the address lines, outgoing control lines and I2C (these are for future features).  I'm using P9 for bidirectional data and incoming control signals.  I've referenced the DECA schematic and manual to choose the right pins.  I've done it this way because of the physical location of the address, data and control buses on the host computer.  Schematic attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 25, 2021, 03:11:35 pm
Also, make sure the basics and !WAIT is wired with an NPN transistor so we may pause the Z80 if a read isn't ready in time.

Ah yes, nearly missed this - added the WAIT driver in as well.  Schematic updated.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 26, 2021, 01:24:15 pm
PCBs are on order.  Have checked and cross-checked IO allocation in the DECA manual, all appears good.  Have drivers to pull all the 5V control lines low that I need for WAIT and to request and take control of the bus from the Z80 and perform memory and IO ops.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on May 26, 2021, 05:47:57 pm
 Nockieboy et al.

I have been watching this topic for several months and its great to see something like this being developed for homebrews or existing vintage systems, quite an awesome project.
I have read all 103 pages and am trying to sort some things out, I am a bit confused about the GPU RAM.

It looks like GPU RAM will now move on to the DECA board DDR3 for GPU operations and DMA to the Microcom can be done for additional DECA FPGA projects.
What I am asking is it now possible to use the GPU and terminal emulator for other 8 bits that only have 64k RAM and 256 or less I/O locations?

On a different note, could a .ttf font be used on the VT100 terminal emulator easily?
 
Thanks again for this awesome project
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on May 26, 2021, 06:21:39 pm
It looks like GPU RAM will now move on to the DECA board DDR3 for GPU operations and DMA to the Microcom can be done for additional DECA FPGA projects.
nockieboy will correct me if I'm wrong, but my understanding is that segway onto DECA board is just a way to validate DDR3 controller with other bits and pieces in hardware, with eventual goal of designing a custom PCB to house everything.

What I am asking is it now possible to use the GPU and terminal emulator for other 8 bits that only have 64k RAM and 256 or less I/O locations?
Again, as per my understanding right now the VRAM is mapped into CPU memory address space (because 6502 doesn't have dedicated I/O bus), but technically you can use a suggestion I offered just few posts above, when you map up to 6 8-bit locations into I/O space (4 for 32bit address, 1 register for stride, 1 data register), which will allow your CPU (which I assume is some variation of Z80) to access any 32bit address, and write bursts at the maximum IO speed. You will probably need to map a DMA controller's control registers into IO space as well. You will have to lean heavily on DMA and GPU hardware functions because there is no way you can achieve any sort of acceptable performance with the CPU itself.

I've been thinking for a while to create a system with a bunch of 8bitters in a sort of SMP system just for the hell of it, but unfortunately real life gets in the way so much so I don't have enough time to even complete my current projects :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 26, 2021, 07:30:06 pm
It looks like GPU RAM will now move on to the DECA board DDR3 for GPU operations and DMA to the Microcom can be done for additional DECA FPGA projects.
nockieboy will correct me if I'm wrong, but my understanding is that segway onto DECA board is just a way to validate DDR3 controller with other bits and pieces in hardware, with eventual goal of designing a custom PCB to house everything.
Correct.

I just finally got the multichannel/multiport 'BrianHG_DDR3_COMMANDER.sv' working.  It is the front end for my DDR3 controller providing 16 read and 16 write ports, each with a user set individual data widths and a DMA through function for all the read channels.  Right now, I just need to clean up the 'priority' selection encoder and I will post the entire DDR3 controller on a separate thread.  This should be enough for Nockieboy to add CPU data & program IO access ports to the controller, + video access, + audio access, + SD-Card read & write access, + Geometry processor access, + anything else he wants.  All accessed like a huge internal multiport FPGA static ram with the 1 caviot that you occasionally need to wait for a busy flag to clear, or read data ready flag on each individual port.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 26, 2021, 07:46:20 pm
Nockieboy et al.

I have been watching this topic for several months and its great to see something like this being developed for homebrews or existing vintage systems, quite an awesome project.

You're absolutely welcome - it's actually really great to hear from others who might find the project useful!  ^-^

It looks like GPU RAM will now move on to the DECA board DDR3 for GPU operations and DMA to the Microcom can be done for additional DECA FPGA projects.
What I am asking is it now possible to use the GPU and terminal emulator for other 8 bits that only have 64k RAM and 256 or less I/O locations?

ALL the GPU RAM is in the FPGA currently - this limits me to about 42KB (off the top of my head) with the current Cyclone IV EP4CE10 FPGA that I have in the prototype GPU card for the uCom (I've changed the name to uCom - or muCom; the 'u' is the Greek symbol mu, as apparently there was a Microcom in the late 70's or something similar).

You'll have read the discussions I've had with very knowledgeable and experienced FPGA users previously in this thread and will understand that to get more than 200KB of in-FPGA RAM will make the FPGA rather cost-prohibitive, pretty much whichever brand of FPGA I switch to.  My constraints for this project are quite tight, which isn't a bad thing in itself as it pushes the limits of what can be done.

The GPU intercepts memory reads and writes to a 512KB 'window' in the uCom's physical memory space (it equates to an empty socket on the memory card) and responds to RD/WR ops to its internal RAM within this 512KB window.  The HDL allows explicit definition of exactly where the window starts and its size in the physical memory space in which the GPU will intercept memory ops.  I have it set to present the GPU RAM within a 512KB window starting at 1.5MB, for example; I just map the appropriate 16KB bank into the Z80's 64KB logical memory space to read or write to it (my hardware MMU uses 16KB banks - but I might redesign this with 4KB banks in the GPU FPGA itself at some point).  You could just as easily set up and compile the HDL to present the GPU RAM within a 16KB window between 32-48KB if you wished, you'd just need to make sure your RAM/ROM select logic kept the RAM/ROM disabled when memory was accessed in this window, otherwise you'd have bus contention as the GPU fought with a memory chip to respond to the memory access.

We're looking at using DDR3 RAM to support the FPGA's internal RAM, or replace it entirely as the home for the GPU's RAM and frame buffer.  BrianHG has been working very hard on a platform-agnostic DDR3 controller we can use and the latest development steps require me to have a working testbed with DDR3 RAM so that we can test the new controller.  This is where the DECA comes in.  Previously, when testing with the EasyFPGA dev board on the Cyclone IV, I used a breadboard with level converters to bridge the 5V host bus to the 3.3V FPGA bus, with a rat's nest of Dupont leads connecting it all together.  It was unstable to say the least, so I've designed a proper card (PCB) that will sit on the bottom of the uCom's stack and I can just plug the whole thing onto the DECA.  It'll be just as good as having a prototype GPU card, just without the extras like PS2/USB/audio etc.

nockieboy will correct me if I'm wrong, but my understanding is that segway onto DECA board is just a way to validate DDR3 controller with other bits and pieces in hardware, with eventual goal of designing a custom PCB to house everything.

Yes, exactly.  The DECA will be the test-bed for the DDR3 controller, HDMI output and any further development on the GPU itself, as the Cyclone IV has effectively run out of space.

On a different note, could a .ttf font be used on the VT100 terminal emulator easily?
 
Thanks again for this awesome project

The font/character set is bitmapped, so a conversion program would have to be written to translate the TTF to a bitmap hex file that could be uploaded into the FPGA (or soft-loaded into the GPU RAM from the host when it's running).

Again, as per my understanding right now the VRAM is mapped into CPU memory address space (because 6502 doesn't have dedicated I/O bus), but technically you can use a suggestion I offered just few posts above, when you map up to 6 8-bit locations into I/O space (4 for 32bit address, 1 register for stride, 1 data register), which will allow your CPU (which I assume is some variation of Z80) to access any 32bit address, and write bursts at the maximum IO speed. You will probably need to map a DMA controller's control registers into IO space as well. You will have to lean heavily on DMA and GPU hardware functions because there is no way you can achieve any sort of acceptable performance with the CPU itself.

I've been thinking for a while to create a system with a bunch of 8bitters in a sort of SMP system just for the hell of it, but unfortunately real life gets in the way so much so I don't have enough time to even complete my current projects :(

I've mapped the VRAM into memory rather than IO space as it's memory, really.  The host has access to the entire GPU VRAM using the usual memory ops - so for a Z80, it has some pretty speedy memory access commands and can copy data to the GPU RAM/VRAM pretty quickly (for a late '70s 8-bit processor).  So setting up a text screen and outputting text to the screen is all done in memory.  The GPU, on the other hand, uses IO space and is controlled by sending data and commands via IO addresses.  Again, these are fully customisable and (currently) there are no plans to use anywhere near 256 IO address ports..  without checking I think we're using about 10.  :)

I just finally got the multichannel/multiport 'BrianHG_DDR3_COMMANDER.sv' working.  It is the front end for my DDR3 controller providing 16 read and 16 write ports, each with a user set individual data widths and a DMA through function for all the read channels.  Right now, I just need to clean up the 'priority' selection encoder and I will post the entire DDR3 controller on a separate thread.  This should be enough for Nockieboy to add CPU data & program IO access ports to the controller, + video access, + audio access, + SD-Card read & write access, + Geometry processor access, + anything else he wants.  All accessed like a huge internal multiport FPGA static ram with the 1 caviot that you occasionally need to wait for a busy flag to clear, or read data ready flag on each individual port.

You sir, are a legend.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on May 28, 2021, 03:39:50 pm
Thanks to everyone for the detailed explanation!

"The GPU intercepts memory reads and writes to a 512KB 'window' in the uCom's physical memory space (it equates to an empty socket on the memory card) and responds to RD/WR ops to its internal RAM within this 512KB window."

Yes makes sense to me now, wouldn't make sense to have the GPU constantly accessing screen RAM on the uCom's bus.

"The DECA will be the test-bed for the DDR3 controller,"

Yes proven hardware plus physical layout to test the new DDR3 controller

" there are no plans to use anywhere near 256 IO address ports..  without checking I think we're using about 10."

Good news as more than 16 bytes per I/O slot would be a bit cumbersome for my system

Just thinking out loud, in a 64k system with only 56k of RAM for the operating system there is not a lot of address space left for VRAM.
Would an approach like asmi suggests, sort of like the TMS9918 where you send a start address through an I/O port and subsequent reads or writes increment the internal address counter, be possible without a complete redesign?  This is just a curious question not a wish list.   :)

I was looking through your Github and found the "Z80_Bridge.v".  Is it still the same or close to the current version that you are using?
I am  considering going back to the start of this thread and try to understand how the bridge works.

Quote from: BrianHG on May 26, 2021, 07:30:06 pm
I just finally got the multichannel/multiport 'BrianHG_DDR3_COMMANDER.sv' working.  It is the front end for my DDR3 controller providing 16 read and 16 write ports, each with a user set individual data widths and a DMA through function for all the read channels.  Right now, I just need to clean up the 'priority' selection encoder and I will post the entire DDR3 controller on a separate thread.  This should be enough for Nockieboy to add CPU data & program IO access ports to the controller, + video access, + audio access, + SD-Card read & write access, + Geometry processor access, + anything else he wants.  All accessed like a huge internal multiport FPGA static ram with the 1 caviot that you occasionally need to wait for a busy flag to clear, or read data ready flag on each individual port.

You sir, are a legend.  ;D

Yes Brian has a considerable amount of work in this project. :clap:

Again thanks for this project

Ted - Patiently following the project  :popcorn:



Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 28, 2021, 03:56:43 pm
Just thinking out loud, in a 64k system with only 56k of RAM for the operating system there is not a lot of address space left for VRAM.
Would an approach like asmi suggests, sort of like the TMS9918 where you send a start address through an I/O port and subsequent reads or writes increment the internal address counter, be possible without a complete redesign?  This is just a curious question not a wish list.   :)

Yes, absolutely.  As you've already identified, the Z80_Bridge.sv module is what interfaces the GPU and video HDL to the host system.  This is the one module you really need to understand to get the GPU to work with another system.  Because it's specific to my uCOM and not just the Z80, there's a lot of specific addresses for IO and memory access - but these are all accessible and changeable in the Quartus schematic overview to make it easier to adjust/adapt to a different system.  There's also specific stuff like returning 0xFF if a read is attempted to the 512KB window, but outside of the RAM space for the GPU, or returning bytes from a preset string if the last 16 bytes of the 512KB window is read.  This is so that software on the uCOM can identify the presence of a graphics card.

I was looking through your Github and found the "Z80_Bridge.v".  Is it still the same or close to the current version that you are using?
I am  considering going back to the start of this thread and try to understand how the bridge works.

The github project is up-to-date with the latest Cyclone IV version of the HDL.  If you were to build a video card using the EP4CE10 for your system, the github repo has everything you need to get it working and doing everything we've talked about so far with regard to text and bitmapped graphics routines.  It doesn't yet have any of the work I've done around USB interfacing or BrianHG's DDR3 controller work.  It might have a folder for the Cyclone V project, but it won't work as I haven't got a Cyclone V (yet) to build it for.  This will probably be a last step, or next-to-last step once I get a prototype graphics card up and running with a Cyclone V on it.

In the meantime, all future dev work will be done on the DECA (MAX10 FPGA) until such time as I get the Cyclone V GPU card designed and built.  As well as DDR3 support, I've yet to really design the card (can continue where I left off a few pages back, but need to update for DDR3 and that'll take time as I don't have a clue at the moment!)  I also have to finalise the USB interface, which will now be using a SAMD21 microprocessor, and do some more research and work on the audio interface, so it'll be a while yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on May 28, 2021, 04:58:10 pm
Ok great,

I need to develop an interface like the frontend of a 6850 for the 6800-6809 in Verilog, fully test it and get it running on the DECA, then I will start looking at the "bridge" interface.

Have to finish my Quartus install first.....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 28, 2021, 09:23:37 pm
@Nockieboy, looking at your PONG video above, it looks like you are getting an impossible interlace artifact.  Do you actually see that in person, or is it just your video camera recording?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 29, 2021, 04:51:44 pm
@Nockieboy, looking at your PONG video above, it looks like you are getting an impossible interlace artifact.  Do you actually see that in person, or is it just your video camera recording?

Nope, not getting any artefacts on screen?  It's most probably the video recording, scan rates not matching up, something like that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 29, 2021, 08:29:51 pm
I'm talking about this 'zippery' artifact during the motion of the ball.  I assume it's not there in real life, correct?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1223326)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 29, 2021, 09:31:24 pm
No, that's definitely an artefact caused by my camera - or the video encoding/conversion.  :phew:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2021, 04:28:00 am
All software DDR3 controller update....

16 read, 16 write ports with smart cache, configurable priority encoding and data width per port done.
4096x2160 screen scrolling on a 1080p 32bit color out HDMI with geometry test drawing program done.
Auto DDR3 PLL calibration finally done.

 >:D !!!400MHz with data integrity!!! >:D  With a +/- 3 PLL tuning step valid data window.

Yes, Altera/Intel's software DDR3 solution is only rated at 300MHz.  Not even the minimum 303MHz rated by the DDR3 spec.
It also only has a single read and write port.

It's Altera's hardware dependent PHY which has multiport and runs at 400MHz.

Things left to do:
Upgrade my software FIFOs in my multiport module as they currently have a bottleneck of 125MHz because of the way they are written.
Improve the cross clock domain boundary as the DDR3 sequencer sends commands to the DDR3 CK clock domain.  (The solution I'm looking at might get the DDR3 running at 500MHz on a -6, but definitely working at >300MHz on a -8, even on old Cyclone III & IV.)
The goal for the above 2 is at least 300MHz allowing for a 'Full Rate' controller where as if you want the 400MHz (officially overclocking Altera's IOs), you will probably need to run it at 'Half Rate', or 'Quarter Rate'.

Without the Multiport module, IE, directly communicating with my DDR3 controller, 1 read & 1 write port, the controller consumes just under 3K logic gates for a 16bit DDR3 ram chip.  And it is smart, keeps banks open and aware when you access across banks, it will keep banks open if it can, only close and open individual banks as it needs to.

I should be ready to post the source next week.


Since your video output on the final board will be limited to 720p@60hz, or 1080p@30hz, and you will have 2 DDR3 16 bit ram chips, here is what the maximum video layers you can produce at the following bit depths:

Color depth ->  1080p@60Hz, 720p@60hz/1080p@30hz,  480p@60hz
32bit                4                , 8                                 ,   22
16bit                8                , 16                               ,   44
8bit                 16               , 32                               ,   88    (WTF can you do with 88 layers?)

This does not include the additional 15 layers you get with the core ram's 128kb memory.

Anyways, @nockieboy, make sure your DECA board works and you can at least output the HDMI test program by sending it just the .sof file in the deca example source code demos.  I will be providing a DDR3 demo .sof file in a few days.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on June 30, 2021, 12:20:21 pm
Brian,

Which version of Quartus Prime Lite would be the one to use with the DECA board and this project?
I read your caveat on the DECA thread about opening the examples with newer versions of Quartus and them being changed and wont work then with an older Quartus version afterwards.
If I have it correct.
I am ok with that, as I will use a copy of the DECA examples.

Thanks

Ted
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 30, 2021, 12:39:55 pm
All software DDR3 controller update....

16 read, 16 write ports with smart cache, configurable priority encoding and data width per port done.
4096x2160 screen scrolling on a 1080p 32bit color out HDMI with geometry test drawing program done.
Auto DDR3 PLL calibration finally done.

 >:D !!!400MHz with data integrity!!! >:D  With a +/- 3 PLL tuning step valid data window.

...

Since your video output on the final board will be limited to 720p@60hz, or 1080p@30hz, and you will have 2 DDR3 16 bit ram chips, here is what the maximum video layers you can produce at the following bit depths:

Color depth ->  1080p@60Hz, 720p@60hz/1080p@30hz,  480p@60hz
32bit                4                , 8                                 ,   22
16bit                8                , 16                               ,   44
8bit                 16               , 32                               ,   88    (WTF can you do with 88 layers?)

This does not include the additional 15 layers you get with the core ram's 128kb memory.

Anyways, @nockieboy, make sure your DECA board works and you can at least output the HDMI test program by sending it just the .sof file in the deca example source code demos.  I will be providing a DDR3 demo .sof file in a few days.

Err... Wow!  :o :o :clap: :-+

I've yet to test my uCOM/DECA interface, I've had no time at all to do anything recently other than build the interface card when the PCBs arrived.  As soon as I get a chance, I'll get the HDMI test program uploaded and check it and start making in-roads into porting the GPU project onto the DECA to test the interface with the uCOM.

(WTF can you do with 88 layers?)

Err... 88 sprites?  Some a-m-a-z-i-n-g parallax scrolling that knocks Shadow of the Beast into a cocked, Gouraud-shaded hat?  The mind boggles, but I'm sure someone out there could find a use for it!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2021, 02:28:18 pm
Brian,

Which version of Quartus Prime Lite would be the one to use with the DECA board and this project?
I read your caveat on the DECA thread about opening the examples with newer versions of Quartus and them being changed and wont work then with an older Quartus version afterwards.
If I have it correct.
I am ok with that, as I will use a copy of the DECA examples.

Thanks

Ted

The code I release should compile in DECA's original version 15 as well as the latest version 20.  I have both versions of Quartus installed.  My code should work in Quartus V13 as well for support of older Cyclone III.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2021, 03:01:13 pm
 >:D >:D >:D >:D Make that 450MHz / 900mtps  >:D >:D >:D >:D

Though, the FPGA is being overclocked...

500Mhz completely fails to do anything.  Though, an older Cyclone IV might work as their core is ever so slightly faster and we already successfully got a CycloneIV to output 1080mbps with my posted HDMI transmitter core.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 30, 2021, 03:09:42 pm
Err... 88 sprites?  Some a-m-a-z-i-n-g parallax scrolling that knocks Shadow of the Beast into a cocked, Gouraud-shaded hat?  The mind boggles, but I'm sure someone out there could find a use for it!

If it were small sprites, yes you have enough gates to do it.  But, since your sprites are actually over-window screen sized layers, you might chew up a good number of gates superimposing 88x256 color layers.  Though, this FPGA is kinda big compared to your 10k gate CIV board.

Also, you only have 16 read ports.  Though, you can multiplex a few read ports to multiply their number by, say 4 each for 480p.  If you use 10 ports to draw the screen, multiply those by 4 and you will have 40x 8bit or 16bit layers from the DDR3 on a 480p display.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 01, 2021, 09:35:48 pm
I now have a working HDMI test output on the DECA whilst it's plugged into the uCOM, so next step is to port the GPU project over and wire it up properly so it works with the uCOM and replaces the dedicated GPU card.  Then, get the HDMI output working.  Maybe some progress on this next week.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: NorthGuy on July 01, 2021, 10:59:05 pm
>:D >:D >:D >:D Make that 450MHz / 900mtps  >:D >:D >:D >:D

Good Job!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2021, 06:51:15 am
>:D >:D >:D >:D Make that 450MHz / 900mtps  >:D >:D >:D >:D

Though, the FPGA is being overclocked...

500Mhz completely fails to do anything.  Though, an older Cyclone IV might work as their core is ever so slightly faster and we already successfully got a CycloneIV to output 1080mbps with my posted HDMI transmitter core.

Sorry, missed this with my previous reply.  That's some serious performance out of a system that isn't specced to do more than 300MHz - well done!  Will there be any issues transferring that performance to a Cyclone V?  (I know currently we're using the MAX10 as the new testbed, but I'm assuming you're still working 'within' the specs of the CV?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 02, 2021, 07:09:09 am
>:D >:D >:D >:D Make that 450MHz / 900mtps  >:D >:D >:D >:D

Though, the FPGA is being overclocked...

500Mhz completely fails to do anything.  Though, an older Cyclone IV might work as their core is ever so slightly faster and we already successfully got a CycloneIV to output 1080mbps with my posted HDMI transmitter core.

Sorry, missed this with my previous reply.  That's some serious performance out of a system that isn't specced to do more than 300MHz - well done!  Will there be any issues transferring that performance to a Cyclone V?

Well, if you are using the -8, you will safely achieve the 300MHz mark.  The DECA board has a -6.  The Cyclone V should pretty much match the MAX10.  The number of layers I quoted was for running the ram at 300MHz, though, 400MHz would give you a additional nice margin.  Do not expect the -8 to achieve 450MHz and my multi-port module may also become a bottleneck unless you disable a number of the features which make it really smart.  Though, I'm coding right now trying to fix that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 02, 2021, 07:21:51 am
>:D >:D >:D >:D Make that 450MHz / 900mtps  >:D >:D >:D >:D

Though, the FPGA is being overclocked...

500Mhz completely fails to do anything.  Though, an older Cyclone IV might work as their core is ever so slightly faster and we already successfully got a CycloneIV to output 1080mbps with my posted HDMI transmitter core.

Sorry, missed this with my previous reply.  That's some serious performance out of a system that isn't specced to do more than 300MHz - well done!  Will there be any issues transferring that performance to a Cyclone V?

Well, if you are using the -8, you will safely achieve the 300MHz mark.  The DECA board has a -6.  The Cyclone V should pretty much match the MAX10.  The number of layers I quoted was for running the ram at 300MHz, though, 400MHz would give you a additional nice margin.  Do not expect the -8 to achieve 450MHz and my multi-port module may also become a bottleneck unless you disable a number of the features which make it really smart.  Though, I'm coding right now trying to fix that.

Availability of 5CEBA2s seems to have dropped through the floor with LCSC. Might have to hunt around for an alternative supplier when the time comes and, if I'm going to be spending 'big bucks' on a supplier like Mouser, may as well go for the -6 variant.

I've got some 'practice' test boards coming from JLCPCB so I can perfect my QFN-56 soldering skills and nail down my USB keyboard interface design.  I'm opting for an RP2040 microcontroller (https://datasheets.raspberrypi.org/rp2040/rp2040-datasheet.pdf) to handle the USB port, after finding the MAX3421E a bit too complex and low-level for my HDL skillset.  The RP2040 is massive overkill, but it's cheap (and newly available), without too many supporting components.  Plus I could off-load the PS/2 management to it if I decide to retain the PS/2 port (certainly not definite, but a nice-to-have if I have the room).

I may have asked this question before - but what would be the preferred interconnect between the RP2040 and the FPGA?  I could use I2C, SPI or UART and I've listed them in my order of preference, I guess.  Part of the reason for mentioning all this is that perhaps people may have ideas of alternative uses I could put the RP2040 (and it's 2MB flash memory) to use, other than just to manage the USB port for keyboard/mouse peripherals...?  It's highly flexible, easily programmable and the limit really is what I wire its GPIOs to on the final board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2021, 12:31:13 pm
For those who bought the MAX 10 DECA board, I have a graphics test demo here:
https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/msg3600487/#msg3600487 (https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/msg3600487/#msg3600487)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2021, 04:25:01 pm
Patched functioning version of the DDR3 demo found here:

https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/msg3601248/#msg3601248 (https://www.eevblog.com/forum/fpga/arrow-deca-max-10-board-for-$37/msg3601248/#msg3601248)

Just some house cleaning work needed on the code and I will release the source...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2021, 07:58:33 am
I've set up the pin assignments for the GPU project on the DECA board, have left out the PS/2, serial debug interface, R, G and B outputs and VGA signals for the moment as I just want to test if it will work with the uCOM without crashing it and respond to memory access.

I've also imported the pin assignments from the HDMI_TX DECA demo project, so that the MAX10 is set up with all the usual pin assignments specific to the DECA board, like clock inputs, switches, buttons, LEDs and other peripherals.  As a result there's two node names assigned to some pins - i.e. I've got all the Z80_ADDR[] nodes assigned to pins on the MAX10 that are also assigned to GPIO_D[] node names because of the DECA pin assignment import.  I'm assuming that won't cause any issues and I could use either node name in the project without issue, as long as there's no conflict in direction or I/O standard (i.e. trying to set a GPIO pin to output when it's already being used as an input for a Z80 address line)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2021, 08:19:19 am
All you need to use is the 'ASSIGN' verilog command.  The GPIOs should be a 3.3v IO pin.

IE: Addr inputs:

assign Z80_addr[21:0] = GPIO0_D[40:20] ;

to send data out:

assign  GPIO0_D[10] = Z80_245data_dir_r ;

For IOs, here is what you do, to send data out with an output enable:  (IE, when Z80_rData_ena_r is high, the Z80_rData_r is sent out, otherwise it is in HI-z state.)

assign GPIO0_D[7:0] = Z80_rData_ena_r ? Z80_rData_r : 8'bzzzzzzzz ;

And take data back in...
assign Z80_wData = GPIO0_D[7:0] ;

You can assign wire-by-wire if you need to because of PCB routing.

The pins should already be assigned as 'INOUT'...

You can always clean up your Z80 bridge verilog code to make the Z80 data bus an INOUT as well and handle the tristate inside the Z80 bridge code.  Then, instead of assign, you would just tie the correct 'GPIO0_D[x:x]' straight to the Z80_bridge port module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2021, 08:38:50 am
All you need to use is the 'ASSIGN' verilog command.  The GPIOs should be a 3.3v IO pin.

IE: Addr inputs:

assign Z80_addr[21:0] = GPIO0_D[40:20] ;

to send data out:

assign  GPIO0_D[10] = Z80_245data_dir_r ;

For IOs, here is what you do, to send data out with an output enable:  (IE, when Z80_rData_ena_r is high, the Z80_rData_r is sent out, otherwise it is in HI-z state.)

assign GPIO0_D[7:0] = Z80_rData_ena_r ? Z80_rData_r : 8'bzzzzzzzz ;

And take data back in...
assign Z80_wData = GPIO0_D[7:0] ;

You can assign wire-by-wire if you need to because of PCB routing.

Oh, so what I've done is wrong?  I've assigned all the GPU node names to the appropriate FPGA pins to match the GPIO they should be connected up to?  :-//

Can I put these assigns in a separate .sv file in the project or do they need to go into the relevant module where the nodes names are used?

The pins should already be assigned as 'INOUT'...

They don't seem to be?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1233914;image)

You can always clean up your Z80 bridge verilog code to make the Z80 data bus an INOUT as well and handle the tristate inside the Z80 bridge code.  Then, instead of assign, you would just tie the correct 'GPIO0_D[x:x]' straight to the Z80_bridge port module.

???  So I could remove the tri-state module from the design and connect the Z80_WR_data[7..0] bidir pins directly to the Z80_bridge?  Not sure what that should look like?  Need an input and an output from the Z80_bridge module and would only have one set of bidir pins?

Project attached if it helps to view the pin assignments.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2021, 10:19:18 am
Before starting, open your GPU_EP4CE10 and from the GPU.bdf, make a GPU.v to replace it.
Actually, cancel that.  You will need a GPU.sv since it has an array 'GPU_HW_REGS_BUS' and Altera skips that net name everywhere since it isn't supported in an old verilog .v.  I've attached an untested .sv I made.  Use that file.  You should try to clean it up once you basic GPU is working.

Now, for the DECA board, copy the project 'DECA_HDMI_TX', rename and take a look at file HDMI_TX.v.

Rename it to GPU_TOP.sv.
Rename in the 'module HDMI_TX' to 'module GPU_TOP'.
Set that file to top hierarchy.

Inside there, place an intimation of your GPU.sv #(.parametersnames(),.,.,...) GPU_CORE (.GPUIOS,.,.,...) ;

Wire all the IO.  Also, the Z80_data is already combined here into a tristate INOUT port, so you do not need to do what I said in the last post.

Most of the GPUIOs can be tied directly to the DECA's IO labeled in GPU_TOP.sv which was once HDMI_TX.sv.

Include my attached GPU.sv source file plus all the other .sv source files you have & add them to the project. 

If you are still having trouble, then I will look at your source code.


Once working, you will need to go through the my GPU.sv, look at your original GPU.bdf and rename all the 'SYNTHESIZED_WIRE_#'s to something more sensible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2021, 10:24:14 am
This is the code you place in GPU_TOP.sv which was the HDMI_TX.v:

Code: [Select]
GPU #(
    .HW_REGS     ( 9  )
) GPU_CORE (
.clk54m      (    ),
.uart_rxd    (    ),
.Z80_CLK     (    ),
.Z80_M1      (    ),
.Z80_MREQ    (    ),
.Z80_WR      (    ),
.Z80_RD      (    ),
.Z80_IORQ    (    ),
.IEI         (    ),
.Z80_RST     (    ),
.RESET_PIN   (    ),
.Z80_ADDR    (    ),
.hs          (    ),
.vs          (    ),
.uart_txd    (    ),
.LED_txd     (    ),
.LED_rdx     (    ),
.vde         (    ),
.pixel_clk   (    ),
.Z80_INT_RQ  (    ),
.IEO         (    ),
.SPEAKER     (    ),
.EA_DIR      (    ),
.EA_OE       (    ),
.STATUS_LED  (    ),
.DIR_245     (    ),
.OE_245      (    ),
.PS2_CLK     (    ),
.PS2_DAT     (    ),
.b           (    ),
.g           (    ),
.r           (    ),
.Z80_data    (    )  );

Just place in the correct IO pins inside the empty brackets...
Also, vertically sort and organize the IOs by section and priority...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2021, 10:47:40 am
Just use the attached file, here you go:
Edit the net names in the brackets located on line 439.

You will want to pass the core ram size parameters to the top of the module GPU.sv and pass them to the top of GPU_TOP.sv where I left room right at the top of the file as well as the number of layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 11:08:48 am
Okay, I think I'm following what you've said to do.  I've just copied the HDMI_TX project, inserted your GPU_TOP.sv file and set it as the top-level design entity, then copied all the .sv, .v, .MIF files and the SDC1.sdc file from the GPU project into the new project.  So I guess all the pin assignments will remain the same as specified by the DECA example project I've hijacked, I just need to wire up the node names in GPU_CORE  in GPU_TOP.sv to the appropriate DECA board IO names. :-/O

One question, though - GPU_TOP.sv specifies all GPIO0_D and GPIO1_D IOs as bidirectional INOUTs.  I assume it won't be an issue if I specify certain GPIOx_Ds as inputs or outputs - is there a cleaner way to do that other than just 'breaking out' the lines...

Code: [Select]
    inout             [43:0]        GPIO0_D,
    inout             [22:0]        GPIO1_D,

... and doing something like this:

Code: [Select]
    input             [21:0]        GPIO0_D,
    inout             [29:22]       GPIO0_D,
    output            [43:30]       GPIO0_D

(for example)?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 11:29:50 am
Do not change the DECA definitions.  INOUT is either direction.  If you tie a pin, even part of a port, to an output, it will be changed into an output.  If you tie it to an input, it will become an input.

Yes, at line 439, just place in the correct partial buss name from 'GPIO0_D[x:y]'.

Also, if the bus is broken up on the connector, you can use as an example:

Code: [Select]
Unbroken bus:
.Z80_data    (  GPIO0_D[15:8]  )

Broken bus due to wiring Example A:

.Z80_data    (  {GPIO0_D[15:12],GPIO0_D[3:0]} )

Example B:

.Z80_data    (  {GPIO0_D[20],GPIO0_D[29],GPIO0_D[15],GPIO0_D[7],GPIO0_D[6],GPIO0_D[2],GPIO0_D[30],GPIO0_D[21]} )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 03:12:40 pm
I'm assuming it's okay to leave assignments empty where there is no connection required?

I'm getting an error when I try to compile:

Error (10228): Verilog HDL error at altpll0.v(39): module "altpll0" cannot be declared more than once

The HDMI_TX project that I've used as the 'donor' for the new GPU project obviously has a PLL module in it, but if nothing's referring to it (i.e. in GPU_TOP or GPU.sv) then will the compiler still try to build it, or am I barking up the wrong tree?

Project attached for info.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 03:32:49 pm
See photo...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 03:36:12 pm
Don't forget to remove the old HDMI_TX.v from your project as well.

Also, in the GPU_TOP.sv file, rename to module name from

GPU_top

to

GPU_TOP
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 03:37:21 pm
That sorted it, thanks.  :-+

I'm now getting complaints about the part-select direction being opposite from prefix index direction.  This is an issue with wiring the Z80_ADDR and Z80_data buses.  The bit order is opposite to the GPIOx_D[] index direction:

Code: [Select]
.Z80_ADDR    ( {GPIO0_D[14:21], GPIO0_D[26:31], GPIO0_D[34:41]} ),

.Z80_data    ( GPIO1_D[11:18] ),

Am I going to have to specify each bit individually?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 03:46:45 pm
Yup, if it is backwards, name them individually...

There is another way out, but is it worth the 2 for loops and another temporary logic array.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 03:49:11 pm
Yup, if it is backwards, name them individually...

There is another way out, but is it worth the 2 for loops and another temporary logic array.

Probably not... I've already named them individually. ;)

Okay, the project nearly builds, but the fitter is throwing a... fit... complaining about illegal location assignments.  Here's a sample (there's over a hundred of these - one for every node I'm guessing):

Error (171016): Can't place node "HDMI_TX_D[11]" -- illegal location assignment PIN_C15

EDIT:  This doesn't look good, either:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1234279;image)

EDIT 2:  Ah... it's compiling for a smaller FPGA by default for the demo project.  :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 03:55:35 pm
Wrong MAX10, you do not have an 08, you have a 50... -6.

This guy:

set_global_assignment -name DEVICE 10M50DAF484C6GES
set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 6
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE IMAGE WITH ERAM"

Close the project, edit the .qsf file with notepad, change to my lines above, then re-open the project.

This happens when you click on Change FPGA because the original .qsf had a 'DEVICE_FILTER_SPEED_GRADE' set to 7 when that FPGA no longer exists, so Quartus shoved you on the smallest MAX10 by default.  Placing a 6 on that line solves that problem.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 04:01:28 pm
The fitter is named appropriately, it seems.  It's complaining about this now:

Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_p[0]
Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_p[1]
Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_n[0]
Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_n[1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 04:05:38 pm
The fitter is named appropriately, it seems.  It's complaining about this now:

Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_p[0]
Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_p[1]
Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_n[0]
Error (169008): Can't turn on open-drain option for differential I/O pin DDR3_DQS_n[1]


For now, just comment out those 2 lines in my DDR3 code.
Don't forget to erase the ' , ' on the line before.

You will also need to comment out the DDR3_CK_p/n.


Now it should compile.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 04:23:18 pm
Now it should compile.

It sure does.  :-+  I'll update you later when I get a chance to test the project on the hardware.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 04:25:55 pm
Oh, the only thing I haven't done is pass the core ram size parameters through to GPU.sv.  Though it looks like that's being done anyway from the flow summary, as it's using 344,159 memory bits (21%).  Once it's working, will be nice to increase that so I can do a full-screen 640x480 mode, even if it's only for testing.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 04:46:30 pm
Oh, the only thing I haven't done is pass the core ram size parameters through to GPU.sv.  Though it looks like that's being done anyway from the flow summary, as it's using 344,159 memory bits (21%).  Once it's working, will be nice to increase that so I can do a full-screen 640x480 mode, even if it's only for testing.  ;D

In the Assignment settings, Advanced Compile synthesis settings, turn 'OFF' the auto-ram replacement and auto-shift register replacement.  This will leave you with the maximum available ramto allocate for the GPU screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 06:20:11 pm
It seems I have more available RAM in the FPGA than I can address in the gpu_RAM module / altsyncram module.  I've tried setting the video RAM to 96K, but this results in 48K per 'side' in the altsyncram which requires more than 15 address lines.

I'm a little hesitant to just wade into the vid_osd_generator.sv module and up the address lanes to 16, as there's likely to be many more places I'll need to make that change and probably some knock-on effects I haven't even considered yet.  Any advice?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 07:03:42 pm
I could have sworn we made room for 20 bit addressing, 1 megabyte...
Also, the addressing for the ram is 16 bit.
I would need to look at the design...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 07:15:20 pm
Funny, everywhere, I see:

host_addr[19:0]
h_addr[19..0]
geo_ram_addr[19..0]
RS232_addr[19..0]
output logic [19:0] gpu_addr
output logic [19:0] gpu_address,
input  logic [19:0] address_geo,
input logic [19:0] address_a,
input logic [19:0] address_b,
input [19:0] addr_in[14:0],
output reg [19:0] addr_out[14:0],
input  [19:0]  addr_host_in,

Do I need to go on?

Where on earth did you see a 16 bit limit?
Everything here has a 1 megabyte 20 bit limit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 07:53:35 pm
Current project attached.

Where on earth did you see a 16 bit limit?

vid_osd_generator:

Code: [Select]
output wire [15:0] host_rd_data,
I think that's it (as in I think that's the issue?), but there may be others?

These are the errors I'm getting:

Error (272006): Insufficient address lines in altsyncram megafunction design -- 48640 memory words in side A specified but total number of address lines is 15
Error (272006): Insufficient address lines in altsyncram megafunction design -- 48640 memory words in side B specified but total number of address lines is 15
Error (287078): Assertion error: The current megafunction is configured for use with the clear box feature and cannot be used when the clear box feature is disabled
Error (12152): Can't elaborate user hierarchy "GPU:GPU_CORE|vid_osd_generator:b2v_inst9|sixteen_port_gpu_ram:gpu_RAM|gpu_quad_port_ram:gpu_RAM|gpu_dual_port_ram_INTEL:dual_port|altsyncram:altsyncram_component"
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2021, 08:08:44 pm
Did you adjust all these parameters in the 'vid_osd_generator.sv'?

Code: [Select]
parameter PIPE_DELAY = 11;                // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.
parameter HW_REGS_SIZE  = 9;              // default size for hardware register bus - set by HW_REGS parameter in design view
parameter ADDR_SIZE     = 15; // 15 = 32KB, 16 = 64KB etc
parameter NUM_WORDS     = 24576; // Video RAM up to 5FFFh (default for EP4CE6)
parameter NUM_LAYERS    = 7;              // This parameter defines the number of MAGGIE graphics layers.
parameter PALETTE_ADDR  = (2 ** ADDR_SIZE) - 1024 ;   // Base address where host Z80 may access the palette memory, usually located in the last 1024 bytes of addressable memory
parameter GPU_RAM_MIF   = "GPU_MIF.mif" ; // MIF file for the main GPU ram.

Namely the parameter ADDR_SIZE ?

Take a look at lines 652 to 658 in GPU.sv.

Code: [Select]
);
defparam b2v_inst9.ADDR_SIZE = 16;
defparam b2v_inst9.GPU_RAM_MIF = "GPU_MIF_CE10_10M.mif";
defparam b2v_inst9.HW_REGS_SIZE = HW_REGS;
defparam b2v_inst9.NUM_LAYERS = 5;
defparam b2v_inst9.NUM_WORDS = 40960;
defparam b2v_inst9.PALETTE_ADDR = 40960;
defparam b2v_inst9.PIPE_DELAY = 11;
It's set to 16, so your max is 64k.
Dont forget to set the num_words and place the palette above or equal to the num_words.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2021, 10:00:48 pm
Did you adjust all these parameters in the 'vid_osd_generator.sv'?

Code: [Select]
parameter PIPE_DELAY = 11;                // This parameter selects the number of pixel clocks to delay the VDE and sync outputs.  Only use 2 through 9.
parameter HW_REGS_SIZE  = 9;              // default size for hardware register bus - set by HW_REGS parameter in design view
parameter ADDR_SIZE     = 15; // 15 = 32KB, 16 = 64KB etc
parameter NUM_WORDS     = 24576; // Video RAM up to 5FFFh (default for EP4CE6)
parameter NUM_LAYERS    = 7;              // This parameter defines the number of MAGGIE graphics layers.
parameter PALETTE_ADDR  = (2 ** ADDR_SIZE) - 1024 ;   // Base address where host Z80 may access the palette memory, usually located in the last 1024 bytes of addressable memory
parameter GPU_RAM_MIF   = "GPU_MIF.mif" ; // MIF file for the main GPU ram.

Namely the parameter ADDR_SIZE ?

Ah, how did I miss that? :palm:  Yes, it compiles now. With 96KB set aside for video RAM for 640x480 with 4 colours, it's still only using 47% of the MAX10's memory.  It should manage 640x480 with 16 colours easily. :-+

Dont forget to set the num_words and place the palette above or equal to the num_words.

Yeah, I've added a couple of parameters to GPU_TOP.sv:

Code: [Select]
parameter int        GPU_MEMORY              = 98304,            // Defines total video RAM in the FPGA, including 1KB palette
                                                                 // For EP4CE10, use 41984
parameter int        NUM_MAGGIES             = 9,                // Number of MAGGIE layers available to GPU

GPU_MEMORY is a quick and easy way to set the total memory to use in the FPGA.  GPU.sv subtracts 1024 bytes from that figure to set the maximum video RAM and specify the start of the palette.

It's late here, so I'll start testing the hardware tomorrow. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2021, 02:28:03 am
I guess you can update your pong game to hires, some color & maybe a nice hires font.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2021, 09:05:50 am
Current project attached.

Where on earth did you see a 16 bit limit?

vid_osd_generator:

Code: [Select]
output wire [15:0] host_rd_data,
I think that's it (as in I think that's the issue?), but there may be others?

That's DATA, not address.  We have a 16bit data bus in the GPU's ram.  This is why you can generate a 16bit true color display.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 08, 2021, 10:13:18 am
That's DATA, not address.  We have a 16bit data bus in the GPU's ram.  This is why you can generate a 16bit true color display.

Yes, I know, as soon as I saw your post about the ADDR_SIZE parameter, I realised my mistake.  ::)

On a slight tangent, is there an easy, simple way to upload the GPU project to the DECA's CFM?  It would make my testing of the uCOM/DECA interface vastly easier if the DECA ran the GPU project at power-on, rather than having to write it directly to the FPGA via JTAG every time it is reset or power-cycled.

The manual talks about compressed images and dual-boot shenanigans.  Doesn't help that I'm trying to read it whilst taking part in a Teams meeting. >:D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2021, 10:30:23 am
In the programmer, click on the .sof file.
Click on change file.
Select the .pof file instead.
Check the program-configure 'CFM0'
And, go...

When developing with the FPGA, the .sof is better as you are not wasting Write erase cycles.
When you get a code you want to continuously reboot from, then use the .pof file.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2021, 10:33:35 am
There is a tiny flat SMD switch hidden under the DECA board to select whether you power up from CFM0, or CFM1.
So, you can have 2 different power-up programs in the DECA board.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 08, 2021, 10:53:03 am
In the programmer, click on the .sof file.
Click on change file.
Select the .pof file instead.
Check the program-configure 'CFM0'
And, go...

When developing with the FPGA, the .sof is better as you are not wasting Write erase cycles.
When you get a code you want to continuously reboot from, then use the .pof file.

Oh jeez, it's that easy!  :-[ ;D  Thanks.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2021, 02:16:03 pm
Okay, can I just check something?

I need to set some of the GPIOs to specific values in GPU_TOP.sv - namely the direction and output-enables for the various bus buffers.  Only the EA and DATA buffers are actually controlled by the GPU currently, I need to set the rest to values compatible with interfacing to the uCOM.  No matter what I do at the moment, if I power up the DECA and the uCOM together, it locks up and I get no output on the serial console (although the DECA indicates it's running the GPU without issues).

I've checked and double-checked that I'm assigning the correct GPIOs to the right uCOM signals, taking into account the Backbone connectors on the DECA and the routing on the DECA/uCOM interface card.

This is what I'm doing in GPU_TOP.sv - outside of any module instantiations:

Code: [Select]
always @( posedge MAX10_CLK1_50 ) begin

LED[6] <= 1; // Turn the LEDs off that aren't being used
LED[5] <= 0;
LED[4] <= 1;
LED[3] <= 1;
LED[2] <= 1;
LED[1] <= 1;
LED[0] <= 1;

end

// Set default values for Address Bus buffers
assign   GPIO0_D[23] = 1; // EA_DIR
assign   GPIO0_D[22] = 1; // EA_OE
assign   GPIO1_D[20] = 0; // DIR_245
assign   GPIO1_D[19] = 1; // OE_245
assign GPIO0_D[32] = 1; // HI_OE - LOW to enable
assign GPIO0_D[33] = 1; // HI_DIR - HIGH for A>B direction (to FPGA)
assign GPIO0_D[42] = 1; // LO_OE - LOW to enable
assign GPIO0_D[43] = 1; // LO_DIR - HIGH for A>B direction (to FPGA)
// Set default values for unused Control Bus Outputs
assign GPIO0_D[8]  = 0; // WAIT output
assign GPIO0_D[9]  = 0; // WR output
assign GPIO0_D[10] = 0; // M_REQ output
assign GPIO0_D[11] = 0; // RD output
assign GPIO0_D[12] = 0; // BUS_REQ output
assign GPIO0_D[13] = 0; // IO_REQ output

The LEDs are not illuminated apart from LED5 and LED7 (which is wired to the STATUS_LED output in the GPU module), as expected.

I'm just trying to work out what's wrong with the bus interface currently.  The uCOM boots fine if the DECA isn't powered, but if it is then I get nothing on the serial console.  So I've modified GPU_TOP.sv slightly to disable ALL the bus buffers and set the DATA direction to the DECA, and turn off all the transistors driving the 5V control lines for WAIT, WR, M_REQ, RD, BUS_REQ and IO_REQ so they SHOULD be floating at the DECA interface (actually pulled high thanks to the pullups on the CPU card).  I've attached GPU_TOP.sv for info - I'm assuming that I'm assigning values to the GPIOs correctly as per the code above?

If not, that would explain why the uCOM is locking up when the DECA has power.

Otherwise, I'm going to have to dig the logic analyser out and hunt down a wall-wart power supply for the DECA (I guess there's a chance there's not enough juice getting to the system via one shared USB lead).

UPDATE:  Have got the uCOM booting up to the start menu.  Just need to do some work to get to the DMI (my custom monitor) so I can start testing the GPU.  Still not 100% yet, but getting there.  Interestingly, I've not changed anything except wired the Z80_CLK and Z80_RST GPIOs to the GPU module.  Am going to continue adding connections step-by-step.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2021, 03:59:22 pm
I'm curious, did you verify that the IO are producing 3.0-3.3v out.  If they are 2.5v out, you may need to lower the 3.3v voltage regulator on your PCB just in case.

Quote
UPDATE:  Have got the uCOM booting up to the start menu.  Just need to do some work to get to the DMI (my custom monitor) so I can start testing the GPU.  Still not 100% yet, but getting there.  Interestingly, I've not changed anything except wired the Z80_CLK and Z80_RST GPIOs to the GPU module.  Am going to continue adding connections step-by-step. 

Yes, not wiring the Z80 CLK and reset would freeze up your data bus.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2021, 04:10:44 pm
I'm curious, did you verify that the IO are producing 3.0-3.3v out.  If they are 2.5v out, you may need to lower the 3.3v voltage regulator on your PCB just in case.

No, haven't verified that yet.  The buffers are powered by the 3.3v supply from the DECA board, though.  Is the IO voltage specified in the Pin Manager in Quartus, or should I be checking elsewhere?

The Pin Manager shows all the GPIOs set to 3.3-V LVTTL.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 12, 2021, 04:31:15 pm
Quartus actually doesn't care.  Changing any pin IO voltages or buffer type there only effects the pins reported FMAX and potentially slightly skew the input threshold trigger point.  And any IO type chosen will run circles around a Z80's 8MHz.  It's how it's VCCIO is wired on the DECA board and I was curious.  I know on my side that if it were actually 2.5v, it would have no effect on the connected RS232-USB dongle I'm using as it's RXD input threshold is around 1v.

Driving 3.3v into a 2.5v IO pin wont do damage as the difference is 0.8v, though the over-voltage limit is 0.7v, the series resistance of the CMOS logic gates feeding the MAX10 input right at the top 3.3v just wont have enough current to really do anything.  You would be driving the input protection diodes with probably < 1 ma.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2021, 04:44:58 pm
I'm going to have to dig the oscilloscope out, and/or the logic analyser, to be sure I guess.  :-DMM

All I can say is that the DECA is clearly able to drive the OE pins high on the 245 buffers, and/or the DIR pins on same, as I'm able to get the uCOM to the bootstrap menu now.  Unfortunately it's locking up when I try to switch to the DMI, but that's probably something to do with the DMI starting up (although it worked fine without a GPU or DECA attached previously).

I need some more time to plod through this step-by-step and see where the issue is, but have made some progress today.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 13, 2021, 01:36:46 pm
I've almost got the DECA working with the uCOM now, the only issue I'm facing is that bit 3 on the data bus seems to be permanently high when reading from the DECA, and no writes are possible.  When I read a 16K bank of RAM from the GPU, all returned bytes have bit 3 set, whether they should have or not.  Writing to GPU RAM isn't working at all - the values aren't changed when read back.

The bit 3 issue could be a damaged 245 data buffer.  There's no issue with the data bus on the uCOM side - everything else is running without fault on the Z80, so it seems either the 245 buffer is faulty, there's a short on the DECA side of the 245 buffer, or the DECA GPIO (GPIO1_D[15]) isn't working as expected.

I can't build another DECA interface board just yet (I'm lacking the key 46-pin Beaglebone headers), so I'll conduct some more tests for shorts and see if I can replace the data buffer without damaging the PCB.  :-/O

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 13, 2021, 01:39:08 pm
Time to get out that DVM continuity tester.
Test for shorts on the PCB.
Also, go over the schematic.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 13, 2021, 04:19:23 pm
My DDR3 controller is now available here:

https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415
 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 12:42:22 pm
My DDR3 controller is now available here:

https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415
 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415)

I don't think I'm making an overstatement if I say how blown away I am at the level of complexity and work that has gone into that piece of work.  I think it'd take me a university course and ten years of working in the industry to understand all of the considerations and technicalities you're accounting for in that project.  Mind. Blown.  :o :o :o

And a massive 'thank you'.  :-+

In other news, I've sorted the D3 HIGH issue.  I was prepping to remove the LVC245 that was buffering the data bus when I just had the mad impulse to drag the soldering iron over the pins on the 5V side, as the DQ3 pin looked a little poorly connected.  That seems to have fixed the issue.  :-+  Though I'm not sure why a poor connection would result in consistent HIGHs on the line.  :-//

Now the uCOM is reading from the GPU on the DECA perfectly, I just need to sort out why it won't write data to the GPU.  Give me another day or two and hopefully I'll have that nailed down, then I can sort out the HDMI output (which should just be messing with Quartus) and we can get started with testing the DDR3 controller.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 01:28:07 pm
Write problem almost sorted.  I'd assigned Z80_WR to the wrong GPIO (the WR output instead of the WR input!)  :palm:

I can now write to the GPU RAM, but I can only write 0xFF.  Whatever I write to GPU RAM, it looks like it's writing 0xFF instead of the value I'm sending. ???  Bearing in mind that the uCOM can read the GPU's RAM with no issues or faults, it doesn't appear to be an issue reading the written data back, it appears that the GPU is taking the written value as 0xFF and nothing else.  Any ideas what could cause this? :-//

I'll go check the DATA 245 buffer again, in case there's an issue with the DIR line (the DATA 245 seems to have caused me all my problems so far).  :-/O

EDIT:  I'm just wondering if this bit of HDL could be the cause of the problem?  Lines 305-312 in GPU.sv:

Code: [Select]
assign Z80_WR_data[7] = data_en ? Z80_RD_data[7] : 1'bz;
assign Z80_WR_data[6] = data_en ? Z80_RD_data[6] : 1'bz;
assign Z80_WR_data[5] = data_en ? Z80_RD_data[5] : 1'bz;
assign Z80_WR_data[4] = data_en ? Z80_RD_data[4] : 1'bz;
assign Z80_WR_data[3] = data_en ? Z80_RD_data[3] : 1'bz;
assign Z80_WR_data[2] = data_en ? Z80_RD_data[2] : 1'bz;
assign Z80_WR_data[1] = data_en ? Z80_RD_data[1] : 1'bz;
assign Z80_WR_data[0] = data_en ? Z80_RD_data[0] : 1'bz;

I'm just trying to work out exactly what's going on here to ascertain if this is the cause of the problem.  Would certainly explain the 0xFF's being written to GPU RAM if there's an issue with data_en...  :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 01:56:55 pm
Ah, BrianHG - going to need your input on this one as the HDL is confusing me more than a schematic would do.

It looks (to my untrained eye) that the code I pasted above is the cause of the problem.  data_en is being used to determine if the data written to GPU RAM is the data written by the Z80, or a HIGH-Z bus?  But it looks as though there's an issue with how the data buses are wired up in GPU.sv or GPU_TOP.sv - I can't figure out if data is coming or going to GPU.sv, but it looks as though there could be a typo in the way the READ or WRITE data bus is being assigned in GPU.sv?  If you have a second later, could you confirm for me that it is wired correctly in the GPU.sv?

I'll keep plugging away at it, but I'm struggling to understand what's going on.  This is why I always liked the schematic top-level file.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 02:09:12 pm

EDIT:  I'm just wondering if this bit of HDL could be the cause of the problem?  Lines 305-312 in GPU.sv:

Code: [Select]
assign Z80_WR_data[7] = data_en ? Z80_RD_data[7] : 1'bz;
assign Z80_WR_data[6] = data_en ? Z80_RD_data[6] : 1'bz;
assign Z80_WR_data[5] = data_en ? Z80_RD_data[5] : 1'bz;
assign Z80_WR_data[4] = data_en ? Z80_RD_data[4] : 1'bz;
assign Z80_WR_data[3] = data_en ? Z80_RD_data[3] : 1'bz;
assign Z80_WR_data[2] = data_en ? Z80_RD_data[2] : 1'bz;
assign Z80_WR_data[1] = data_en ? Z80_RD_data[1] : 1'bz;
assign Z80_WR_data[0] = data_en ? Z80_RD_data[0] : 1'bz;

I'm just trying to work out exactly what's going on here to ascertain if this is the cause of the problem.  Would certainly explain the 0xFF's being written to GPU RAM if there's an issue with data_en...  :-\

Ok, what's going on here is if the signal 'data_en' is low, then the wires 'Z80_WR_data[ x ]' will be tristate.

If 'data_en' is high, then the wires 'Z80_WR_data[ x ]' will output the 'Z80_RD_data[ x ]'.

This means the the 'Z80_WR_data[ x ]' should be sent directly to your FPGA IO pins.

Now, to write data, this means you need to send the IO pins to the Z80 bridge,,,, wait

This does sound fishy as the line should really read:

Code: [Select]
assign Z80_data[7] = data_en ? Z80_RD_data[7] : 1'bz;
assign Z80_data[6] = data_en ? Z80_RD_data[6] : 1'bz;
assign Z80_data[5] = data_en ? Z80_RD_data[5] : 1'bz;
assign Z80_data[4] = data_en ? Z80_RD_data[4] : 1'bz;
assign Z80_data[3] = data_en ? Z80_RD_data[3] : 1'bz;
assign Z80_data[2] = data_en ? Z80_RD_data[2] : 1'bz;
assign Z80_data[1] = data_en ? Z80_RD_data[1] : 1'bz;
assign Z80_data[0] = data_en ? Z80_RD_data[0] : 1'bz;

Or, make your life easier:
Code: [Select]
assign Z80_data = data_en ? Z80_RD_data : 8'bzzzzzzzz;
And for the other direction,

However, you will need to kill line 684:
Code: [Select]
assign Z80_data = Z80_WR_data;
And change line 243 in 'Z80_bridge_v2.sv' from:
Code: [Select]
.Z80_wData(Z80_WR_data),to:
Code: [Select]
.Z80_wData(Z80_data),This ties the Z80_data pins directly to your 'Z80_bridge_v2.sv' Z80 data input.

Remember, the GPU.sv I gave you was generated automatically by Quartus from the original GPU.bdf, hence the reason I said you need to go through it, compare it to your original .bdf and relable some of the wires to make more sense.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 02:15:15 pm
Yes, a lot of the coding on the GPU wasn't organized to be viewed strictly from text source code.

IE, the Z80 bridge should directly drive the Z80 io pins and should have handled the tristate internally.

If you look at my HDMI DDR3 example, it reads much easier than this Quartus auto-generated GPU.sv.

I made it so even you can follow it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 02:16:12 pm
I made it so even you can follow it.

Gee, thanks.  :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 02:19:04 pm
Or, make your life easier:
Code: [Select]
assign Z80_data = data_en ? Z80_RD_data : 8'bzzzzzzzz;
And for the other direction,

However, you will need to kill line 684:
Code: [Select]
assign Z80_data = Z80_WR_data;

Sorry, what should go for 'the other direction'?

Shouldn't it be something like this?

Code: [Select]
assign Z80_data = data_en ? Z80_RD_data : Z80_WR_data;

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 02:31:15 pm
No, Z80 data pins must be set to a value, or HI-z so that those pins become an input.

The 'Z80_data[ x ]' are the IO pins.  Reading this wire will always tell you the number whether it is an input of output.

This is why this one is tied to the read data in on the Z80 bridge.

Now, when you say 'Z80_data[ x ]' = [something], if that something isn't a 'z', it becomes an output.

So my code changes I recommended are correct.

Quartus made the booboo of making the output pins = to the assigned 'Z80_WR_data[ x ]' which was correct.  But, there was no way to reverse send the data from the Z80 IO pins when set to 'z'  back into the bridge unless the original line '684' was a bi-directional assign.  If that assign is bi-directional, then there was nothing wrong with the original code and we need to look for the error elsewhere.

Question: are you able to write valid changes to the control registers, IE screen position offset, zoom size.  These are logic registers and are not part of the core memory.  Do the settings take effect properly, yet read 'FF'?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 02:36:50 pm
Does the RS232 debugger work?
Can you read and write valid data there?
This will at least tell you the core ram is receiving and writing valid data internally.

As for the Z80 receiving 'FF' writes, usually in tristate, the inputs on the FPGA have a weak pull-up, so, if the 245's is set to the wrong direction, or the245's  OE is disabled, you will always write all 'FF'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 02:38:35 pm
No, Z80 data pins must be set to a value, or HI-z so that those pins become an input.

The 'Z80_data[ x ]' are the IO pins.  Reading this wire will always tell you the number whether it is an input of output.

This is why this one is tied to the read data in on the Z80 bridge.

Now, when you say 'Z80_data[ x ]' = [something], if that something isn't a 'z', it becomes an output.

So my code changes I recommended are correct.

Quartus made the booboo of making the output pins = to the assigned 'Z80_WR_data[ x ]' which was correct.  But, there was no way to reverse send the data from the Z80 IO pins when set to 'z'  back into the bridge unless the original line '684' was a bi-directional assign.  If that assign is bi-directional, then there was nothing wrong with the original code and we need to look for the error elsewhere.

Okay, so just to confirm my understanding of the required changes:

I change all the previous assigns:
Code: [Select]
assign Z80_WR_data[7] = data_en ? Z80_RD_data[7] : 1'bz;
assign Z80_WR_data[6] = data_en ? Z80_RD_data[6] : 1'bz;
assign Z80_WR_data[5] = data_en ? Z80_RD_data[5] : 1'bz;
assign Z80_WR_data[4] = data_en ? Z80_RD_data[4] : 1'bz;
assign Z80_WR_data[3] = data_en ? Z80_RD_data[3] : 1'bz;
assign Z80_WR_data[2] = data_en ? Z80_RD_data[2] : 1'bz;
assign Z80_WR_data[1] = data_en ? Z80_RD_data[1] : 1'bz;
assign Z80_WR_data[0] = data_en ? Z80_RD_data[0] : 1'bz;

to this:
Code: [Select]
assign Z80_data = data_en ? Z80_RD_data : 8'bzzzzzzzz;
And the remove line 684:
Code: [Select]
assign Z80_data = Z80_WR_data;
And change line 243 to:
Code: [Select]
.Z80_wData(Z80_data),
Seems to make sense. :-+

Question: are you able to write valid changes to the control registers, IE screen position offset, zoom size.  These are logic registers and are not part of the core memory.  Do the settings take effect properly, yet read 'FF'?

It seems ALL writes were passed through as 0xFF.  I confirmed that the block of code I originally identified was the problem by changing some of the values from 1'bz to 1'b0 so that instead of 0xFF, 0XD7 would be written instead and - lo and behold - the uCOM was reading back 0xD7 all over the place where it had written to.  ;)

Does the RS232 debugger work?
Can you read and write valid data there?
This will at least tell you the core ram is receiving and writing valid data internally.

I haven't gotten that far with debugging, I'm fairly sure I've found the issue.  I'm just in the process of compiling and testing the code changes you've suggested now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 02:40:40 pm
As for the Z80 receiving 'FF' writes, usually in tristate, the inputs on the FPGA have a weak pull-up, so, if the 245's is set to the wrong direction, or the245's  OE is disabled, you will always write all 'FF'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 02:56:02 pm
Those code changes fixed the issue.  The uCOM is able to read and write GPU RAM with no issues now.  :-+

Might have some time to start on converting the video output to use the HDMI connector on the DECA.  Without the schematic overview, this might cause me to be a little more confused than usual.  ::)

I guess all the components needed are already in the project, as it's a hijacked HDMI_TX project.  I just need to wire up the RGB outputs from the pixel pipeline into the HDMI inputs somewhere on the HDMI_TX components.  Will have more time to look at this tomorrow.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 04:01:05 pm
Man, the HDMI is the easiest part.
I already left the I2C config in there to power up the HDMI IC.
Just connect the IOs to your module.

Look at my DDR3 1080p output demo to see which IO drive the IC.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 04:12:50 pm
Look at my DDR3 1080p output demo to see which IO drive the IC.

Did you post the full project for that?  ???  I've only seen the .sof files?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 15, 2021, 04:24:10 pm
Look at my DDR3 1080p output demo to see which IO drive the IC.

Did you post the full project for that?  ???  I've only seen the .sof files?
Uhh, did you download my DDR3 project on my DDR3 thread.
There are full projects there, 4 of them + 2 additional source directories.
My instructions tell you which folders you can open in Quartus as a project.
Then go to the top file in the project and look.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 15, 2021, 04:33:48 pm
Uhh, did you download my DDR3 project on my DDR3 thread.
There are full projects there, 4 of them + 2 additional source directories.
My instructions tell you which folders you can open in Quartus as a project.
Then go to the top file in the project and look.

Ah, no.  I was hunting back in this thread and the Arrow DECA thread.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2021, 04:12:34 pm
Okay, the DECA GPU is working as expected with full access to the GPU memory for the host and a good, stable HDMI output (note: I've returned the I2C_HDMI_Config.v setting to HDMI from DVI).  The whole setup is infinitely more stable than the mess of wires I had previously bridging the old EasyFPGA EP4CE10 board via converters/buffers to the uCOM when developing the VGA output! :-+

Next step is to test the WAIT signal and see if the GPU can stall the Z80 for time during memory reads and writes.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2021, 04:49:02 pm
Does your Z80 system have a clock/timing chip somewhere on it?

IE, can you test/time the speed of your reads?

This way, if we artificially enter a read delay with wait, can you tell is the performance slows down.

What I am thinking is during read cycle, add a timer/counter to delay placing the correct data on the Z80 output bus holding the wait and see if you can still read correct data.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 16, 2021, 05:14:29 pm
Does your Z80 system have a clock/timing chip somewhere on it?

IE, can you test/time the speed of your reads?

This way, if we artificially enter a read delay with wait, can you tell is the performance slows down.

What I am thinking is during read cycle, add a timer/counter to delay placing the correct data on the Z80 output bus holding the wait and see if you can still read correct data.

It does - a Z80 CTC - but I'm wondering if it would be much easier to just add a constant delay in the GPU before returning any data, then up that delay until it becomes a noticeable slowdown when reading a 256-byte block of GPU RAM, for example?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 16, 2021, 08:16:20 pm
Does your Z80 system have a clock/timing chip somewhere on it?

IE, can you test/time the speed of your reads?

This way, if we artificially enter a read delay with wait, can you tell is the performance slows down.

What I am thinking is during read cycle, add a timer/counter to delay placing the correct data on the Z80 output bus holding the wait and see if you can still read correct data.

It does - a Z80 CTC - but I'm wondering if it would be much easier to just add a constant delay in the GPU before returning any data, then up that delay until it becomes a noticeable slowdown when reading a 256-byte block of GPU RAM, for example?
Proceed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 21, 2021, 04:21:28 pm
Update on progress - below are my musings, not really seeking help unless anyone can point me to a fast transistor to replace a 2N3904?

The GPU is able to pull WAIT low in response to memory accesses by the host Z80.  It's not rock-solid yet, though - I can adjust the delay for each memory access by setting a value in a GPU register accessible via an IO port, and turn the test on or off via that same register (bit 0 controls whether or not to apply WAIT states).

Most of the time it works fine - but every now and again it locks up with frenetic activity on the WAIT line.  I need to spend some more time looking into the specific timings of what's going, but here's what I've found so far:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1238203)

What you see above is a nanosecond-accurate timing chart for a typical memory read operation by the host Z80 (in the uCOM's case, a 10MHz Z80 running at 8MHz), with the FPGA's clock (asynchronous to the Z80's) at the bottom.  Pay special attention to the red bar - this denotes the amount of time the FPGA has to detect a memory read op and set the WAIT signal high to trigger the 2N3904 transistor to pull the Z80_WAIT line low.

TsWAIT(Cf) is the critical timing, the time for WAIT to stabilise LOW before it is sampled by the Z80 on the falling edge of its T2 clock cycle - on the above diagram, it has been extended to include the 2N3904's Td (activation delay), so instead of 20ns as quoted in the Z80's specifications for the 10MHz variant, it is 55ns because of the additional 35ns required by the 2N3904 to pull the WAIT line low.  This is an approximation - I'm no expert at reading or understanding datasheets, this is my best guess and is likely a ballpark figure at best.

So this explains some of the crashes I was experiencing when I first tried inserting WAIT states, as I was waiting to decode a memory read, which requires RD to go low, and as you can see in the chart above it doesn't leave enough time to get WAIT pulled low in time.  Instead, the FPGA is now pulling WAIT low the cycle it sees MREQ go low and the address lines match the GPU RAM address range.  It's a lot more stable now, but I'm still getting occasional crashes - or certain crashes if I do a memory op with LDIR, one of the Z80's fast block-memory op commands.

So timing is still an issue.  It just surprises me that it is an issue at all, because (to me) the FPGA is fast, but I guess not as fast as dedicated, discrete chips decoding the memory op and address range (or a chip select, more likely) in old peripheral equipment back in the day.

Is there anything faster than a 2N3904, I wonder?  That 35ns delay is a killer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 21, 2021, 05:00:37 pm
Have you considered learning about using Quartus' Signal Tap?
Since the FPGA you are using has free ram, and space, you can use the built in logic analyzer and see what the Z80 bus is doing in real time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on July 21, 2021, 05:22:17 pm
Have you considered learning about using Quartus' Signal Tap?
Since the FPGA you are using has free ram, and space, you can use the built in logic analyzer and see what the Z80 bus is doing in real time.

Other vendors have something similar. Never used that though. Something I would expect it that it would tend to make routing more difficult - especially in complex, or congested designs - and thus, hinder Fmax. Do you have experience with this and can you confirm or OTOH tell me that it usually has very little impact?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 21, 2021, 07:10:10 pm
Have you considered learning about using Quartus' Signal Tap?
Since the FPGA you are using has free ram, and space, you can use the built in logic analyzer and see what the Z80 bus is doing in real time.

Other vendors have something similar. Never used that though. Something I would expect it that it would tend to make routing more difficult - especially in complex, or congested designs - and thus, hinder Fmax. Do you have experience with this and can you confirm or OTOH tell me that it usually has very little impact?

The FMAX is only hindered by the maximum M9K/M10K memory block speed unless your FPGA is too full, or you are grasping signals from multiple clock domains simultaneously.  Nockieby's design is only 125MHz for the Z80 bus and everything else.  A breeze for the -6 Max10 he is using.

My guess they are just sampling the data into 1 or more memory blocks which a programmable latch enable.  The second side of that memory port is just JTAG scanned in real-time during operation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 21, 2021, 09:40:04 pm
Have you considered learning about using Quartus' Signal Tap?
Since the FPGA you are using has free ram, and space, you can use the built in logic analyzer and see what the Z80 bus is doing in real time.

Ah, no, I hadn't thought of that - certainly sounds promising.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on July 22, 2021, 04:44:44 pm
"Is there anything faster than a 2N3904, I wonder?  That 35ns delay is a killer."

Not to distract the signal tap, just a passing thought, how about the SN74LVC07A Hex Buffer and Driver With Open-Drain Outputs?
It has a propagation delay of around 4ns and can sink 24ma I believe.
It is a hex package and might replace all 6 3904's on on your pcb.

Curious, 55ns seems a bit of a short response time, don't know the Z80 though

Best
Ted
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 22, 2021, 10:18:35 pm
"Is there anything faster than a 2N3904, I wonder?  That 35ns delay is a killer."

Not to distract the signal tap, just a passing thought, how about the SN74LVC07A Hex Buffer and Driver With Open-Drain Outputs?
It has a propagation delay of around 4ns and can sink 24ma I believe.
It is a hex package and might replace all 6 3904's on on your pcb.

That sounds very promising, assuming I've identified the correct issue in the first place of course. ;)  An SN74LVC07A sounds like it could be perfect for the task.  The WAIT line is pulled high by a 10K resistor connected to 5V, so that's 0.5mA that the '07 would need to sink if my maths (and understanding of basic electronics) is correct? :o

Curious, 55ns seems a bit of a short response time, don't know the Z80 though

Well, like I've said many times before, I'm no expert at this stuff and am purely self edu-ma-cated, so there's a good chance I've made a mistake somewhere or missed something, but I know enough to say that the Z80 is pretty tight on its timings, even for a 40+ year old chip running at 8MHz.

The 10MHz Z80 requires a minimum 20ns setup and hold for WAIT before the falling edge of T2, the clock cycle where the Z80 samples the WAIT line - this leaves about 45ns without any propagation delays in line drivers to pull WAIT low from when RD goes low.  This could be up to 55-80ns (eyeballing from the timing chart) if I pull WAIT low the instant I see MREQ fall on its own, instead of waiting for MREQ then RD to fall.  The reality is, I'm going to be applying WAIT states to memory writes AND reads, not just reads, so it makes sense to pull WAIT low the instant I see MREQ go low and have a relevant address - which is what I'm doing now as a result of making the timing chart above.  It's still not perfectly stable though, so perhaps version 2 of the uCOM/DECA with the extra 30ns an SN74LVC07A would provide would make the difference.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 22, 2021, 10:27:09 pm
I have a ver.0.95 of my DDR3 controller to get out tonight, then I can take a look at your code.

Also, what's the series resistor from the FPGA to the base of the 2N3904.  A lower value means a faster turn on time.  Using a small value like 220ohm will mean the 2N3904 will probably be on and pulling down within <10ns or even closer to 5ns.  It's truly a fast little bugger capable of over 200MHz if you drive the base with enough current.  If you are using 1k series resistor to the base, when driving a 3v logic at the other end, expect a 15-20ns delay.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 22, 2021, 10:37:43 pm
I have a ver.0.95 of my DDR3 controller to get out tonight, then I can take a look at your code.

Also, what's the series resistor from the FPGA to the base of the 2N3904.  A lower value means a faster turn on time.  Using a small value like 220ohm will mean the 2N3904 will probably be on and pulling down within <10ns or even closer to 5ns.  It's truly a fast little bugger capable of over 200MHz if you drive the base with enough current.  If you are using 1k series resistor to the base, when driving a 3v logic at the other end, expect a 15-20ns delay.

It's stuff like this that I miss.  ::)  The transistor circuit was a cut 'n' paste from somewhere else - I think the series resistor was to prevent overloading the IO output of whatever was driving the transistor, but what you've said makes perfect sense now that I think about it.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 22, 2021, 10:38:09 pm
Go Google on how to use SignalTap I & II.  Google tutorials and search on youtube for videos so you can set something up.  It will be useful in the future as you add much more complicated things to your GPU.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 22, 2021, 10:41:22 pm
I have a ver.0.95 of my DDR3 controller to get out tonight, then I can take a look at your code.

Also, what's the series resistor from the FPGA to the base of the 2N3904.  A lower value means a faster turn on time.  Using a small value like 220ohm will mean the 2N3904 will probably be on and pulling down within <10ns or even closer to 5ns.  It's truly a fast little bugger capable of over 200MHz if you drive the base with enough current.  If you are using 1k series resistor to the base, when driving a 3v logic at the other end, expect a 15-20ns delay.
It's stuff like this that I miss.  ::)  The transistor circuit was a cut 'n' paste from somewhere else - I think the series resistor was to prevent overloading the IO output of whatever was driving the transistor, but what you've said makes perfect sense now that I think about it.  :-+
Just look at the 2N3904 data sheet.  I believe delay and rise time is 35ns+35ns if you drive the base with 1ma.  220 Ohm would drive the base with around 10ma.  Don't go below 100Ohm as the IO on the FPGA might not like a constant ~20ma current.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 23, 2021, 09:55:59 pm
Just look at the 2N3904 data sheet.  I believe delay and rise time is 35ns+35ns if you drive the base with 1ma.  220 Ohm would drive the base with around 10ma.  Don't go below 100Ohm as the IO on the FPGA might not like a constant ~20ma current.

390 ohms is the nearest I have to 220 without going below 100.  Have tried it out and can't see any difference in the crash rate... will need to spend some time learning to use Signal Tap.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 23, 2021, 11:23:20 pm
What's the pull up resistor on the bus?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 24, 2021, 09:35:25 am
What's the pull up resistor on the bus?

On the Z80 side?  There's a 10K pullup.

I've got a 10K pull-down on the FPGA signal line to the transistor as I didn't want the WAIT line to default to LOW all the time the FPGA was starting up.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1238961)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 24, 2021, 01:06:06 pm
What's the pull up resistor on the bus?

On the Z80 side?  There's a 10K pullup.

I've got a 10K pull-down on the FPGA signal line to the transistor as I didn't want the WAIT line to default to LOW all the time the FPGA was starting up.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1238961)
Yes, on the Z80 side.  Try a 1k pullup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 25, 2021, 06:47:00 pm
Note that the 'turn-off' time of a 2N3904 my not be unavoidable.  Though, in the past, our Z80 problems have been narrowed down and connected to code in the bridge.

You need to get the SignalTap going so you can trap what happens before a freeze event.

My guess is that you are applying a wait when there is a read or write of an op-cope elsewhere outside the address of the display GPU.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 26, 2021, 01:05:22 pm
Note that the 'turn-off' time of a 2N3904 my not be unavoidable.  Though, in the past, our Z80 problems have been narrowed down and connected to code in the bridge.

I don't think the turn-off time is an issue - the WAIT line is designed to work asynchronously to the Z80's clock, so it shouldn't make any difference (to my inexperienced mind) if takes 2ns to go high again or 20ns.  I'd like to think there's some form of Schottky effect on the Z80's WAIT input, so slow rises don't result in issues when the line is sampled, but it's either high or low when the WAIT line is sampled on the falling edge of T2.  :-//

You need to get the SignalTap going so you can trap what happens before a freeze event.

My guess is that you are applying a wait when there is a read or write of an op-cope elsewhere outside the address of the display GPU.

This makes a lot more sense to me - it's far more likely to be an HDL issue in z80_bridge.   It does look as though the WAIT line is getting out of synch with what the z80_bridge thinks it should be doing.

Will start taking a look at Signal Tap this week hopefully.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2021, 03:44:43 pm
Wow, SignalTap is pretty handy - easy enough to understand and setup, too.  :-+

The results, on the other hand, require some interpretation, but I've fixed a glitch thanks to SignalTap already.  I was using a wire (mem_in_range) that went HIGH whenever the Z80 address bus held an address in the GPU's RAM range.  What I didn't realise before SignalTap was that there are some fast transitions in the address bus, about a quarter of a Z80 clock cycle long, in which the address is unstable/random and these sometimes trigger the mem_in_range signal, causing unwanted behaviour in the Z80_bridge.  I've fixed that now, replacing the wire with a three-register pipeline so that mem_in_range is only HIGH when the address has been stable for three clocks.  That's eliminated some unwanted signals.

The next thing I'm seeing is a little odd - but I guess it's explainable by delays in the WAIT line going HIGH after the transistor is switched off, which BrianHG alluded to in a previous post recommending the reduction of the pullup resistor on the WAIT line from 10K to something smaller.  According to SignalTap, it's taking approximately 8 Z80 CLK cycles for WAIT to go high enough for the Z80 to detect it as HIGH:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1240065)

That purple-ish area is nearly 900 nanoseconds long (45 GPU clock cycles, give or take), showing the delay from when the Z80_bridge's internal Z80_WAIT signal goes low (to turn the transistor off that is pulling the Z80's WAIT line low) and when the Z80's actual WAIT line gets high enough for the Z80 to detect it.

In itself, this shouldn't be an issue other than WAIT states being far longer than necessary, but I'm still getting the odd lockup with WAIT fluctuating on and off.  Testing continues.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2021, 05:37:06 pm
Can I see you latest code for driving the 'wait' line?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2021, 06:16:36 pm
Can I see you latest code for driving the 'wait' line?
If you have a spare TTL-3.3v input on your PCB-DECA board, try tying the bus side 'wait' to an input and add that input to the Signal tap so you can see when the 'wait' timing looks like after the 2N3904.  This will show you if all those TW wait states are due to the buss signal, or due to internal Z80 processing.

You might also be able to use a series 100k resistor from the Z80 buss wait line to an input as 100k series wont load an input protection diode too much.  But, you would probably have to shrink the 10k pull-up as that 100k would be equal to a pull-down to a 3.3v rail.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2021, 09:53:13 pm
Can I see you latest code for driving the 'wait' line?
If you have a spare TTL-3.3v input on your PCB-DECA board, try tying the bus side 'wait' to an input and add that input to the Signal tap so you can see when the 'wait' timing looks like after the 2N3904.  This will show you if all those TW wait states are due to the buss signal, or due to internal Z80 processing.

You might also be able to use a series 100k resistor from the Z80 buss wait line to an input as 100k series wont load an input protection diode too much.  But, you would probably have to shrink the 10k pull-up as that 100k would be equal to a pull-down to a 3.3v rail.

I have a WAIT input to the FPGA from the Z80 bus already as part of the control buffer on the uCOM/DECA interface card, so this is not an problem.  I'll take a look at what's going on with the Z80's WAIT line tomorrow.  Didn't have time today.

Uh, what am I talking about - no I don't have a WAIT input from the Z80 bus.  Well, I think I'll start by reducing the 10K pullup on the WAIT line anyway, see if it makes a difference dropping it to 1K.

Can I see you latest code for driving the 'wait' line?

The latest version of Z80_bridge_v2.sv is attached, but to save you sifting through the haystack:

LINE/S   NOTES
205-207  Sets up flags and address-valid pipeline
225         Sets up buffer to store read value from GPU before returning it to Z80 at end of WAIT period
227-228  Sets up signal to indicate when WAIT timer is zero
252-253  Update 3-clock address-valid pipeline to filter jitter on the address bus
309-340  Manages start of GPU RAM read and write ops
432-436  Manages updating the WAIT counter value via an IO port address
438-455  Manages updating the WAIT counter during a memory op and manages the end of a GPU RAM read or write op
461-468  Manages returned data from GPU RAM read

Probably not the best way to do it, but it's the second iteration of my initial attempt and, hopefully, there aren't too many obvious mistakes. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 29, 2021, 12:06:25 pm
So my pullups on the Z80's lines are all 4k7s, not 10k as in the schematic, including the WAIT line.  The resistors are all under the Z80 chip itself and I didn't remember that I'd put lower values in until I lifted the chip earlier this morning.  I've still replaced the WAIT 4k7 pullup with a 1K resistor, but now I seem to be getting problems with the GPU.  The system locks up with WAIT constantly asserted.  I've made the WAIT-insertion HDL optional and compiled without it and the system runs fine - but I haven't changed anything since last night other than reducing the pull-up from 4k7 to 1k.   :-//

I'm still able to use SignalTap on the 'locked up' system, and it looks like changing to 1k may have pulled two WAIT states (Tw) back, but there's still 6 additionals.

I've compared Z80_bridge_v2's code from today and last night (when it worked) and, if I remove the checks making WAIT-insertion optional, the HDL is identical.  So it appears the change to a 1k pullup on WAIT is causing these issues?  I'll confirm this later today if I get to replace the 4k7 resistor.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 29, 2021, 02:44:42 pm
Yes, I can confirm that fitting a 1k pullup to the WAIT line causes the system to lock up with the DECA/GPU attached, but not as long as it doesn't try to mess with the WAIT line.

I've refitted the 4k7 pullup and it's fine again now.  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on July 31, 2021, 11:53:02 am
Another trick you could try for speeding up the transistor is to put a smallish capacitor across the base resistor.

Yes, I can confirm that fitting a 1k pullup to the WAIT line causes the system to lock up with the DECA/GPU attached, but not as long as it doesn't try to mess with the WAIT line.

Maybe you have some kind of logic error that's being masked when the wait state is unusually long? Could the FPGA be releasing the WAIT line too early, before it's actually ready for the Z80 to continue doing stuff?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 31, 2021, 12:31:02 pm
Another trick you could try for speeding up the transistor is to put a smallish capacitor across the base resistor.

Smallish as in 100nF or 100pf? Across the 1K base resistor?  How does that work?  Isn't that setting up some sort of RC oscillator? (Genuine questions, I have no idea!)  :o

Yes, I can confirm that fitting a 1k pullup to the WAIT line causes the system to lock up with the DECA/GPU attached, but not as long as it doesn't try to mess with the WAIT line.

Maybe you have some kind of logic error that's being masked when the wait state is unusually long? Could the FPGA be releasing the WAIT line too early, before it's actually ready for the Z80 to continue doing stuff?

I'm wondering if it could be a code or logic error, but there are no interrupts running, so no reason why the Z80 couldn't be held in WAIT for as long as I wanted.  I'm suspecting that it could be a false triggering of the HDL in the FPGA, thinking a valid memory read or write is occurring when it isn't - so WAIT is getting pulled low but not getting released at the end of the 'memory op' , causing the straight behaviour and flickering of the WAIT line that I'm seeing now when it happens.

Note that it's the FPGA making the Z80 wait - not the other way around - there's no actual requirement for the Z80 to wait at all, I'm just forcing WAIT states to be inserted for testing, and the Z80's WAIT line is asynchronous so it can be released at any time - the Z80 will pick up the high WAIT line on the next Tw cycle's falling clock edge.  I'm going to have to continue testing - what I really need is to somehow trigger SignalTap to capture some traces when the problem occurs, but that's like trying to find a needle in a haystack on the first attempt.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2021, 03:34:42 pm
Okay, WAIT insertion is done.  It'll be a simple matter to refactor the HDL to allow the GPU to remove the WAIT state as soon as it's ready to progress the memory operation, but in the meantime it's using a counter to delay operation of the Z80 during a memory operation to GPU RAM.  Here's a memory op with no wait states:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1241451)

It's stable, so long as I don't set too high a value on the WAIT counter, but works with no WAITs at all and then starts at a minimum of 2 WAIT states - this seems to be the minimum time it takes the 2N3904 to release the WAIT line on the Z80:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1241453)

If I up the timer to 20 (GPU clock cycles), I get 6 WAIT states.  Bearing in mind each of these WAITs is 125 nanoseconds at the Z80's 8 MHz clock, that's 750 nanoseconds - I'm hoping that will be plenty of time for the GPU to interrogate the SDRAM and get (or set) a value from external RAM.  It does seem to be the upper limit for reliability - higher values tend to crash the system.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1241455)

The issue with reliability previously was to do with WAITs not being applied in time for a write operation from the Z80 - it wasn't picking up the WAIT in time and was sometimes picking it up on the next memory op after the one triggering the WAIT, causing 'undocumented behaviour'.  ;)  :-BROKE

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2021, 06:39:47 pm
Many read and writes will be in time, so, no wait will be necessary.

The real problem is only with the reads.  When you do a read request, occasionally, if the ram controller just sent a refresh command, your read can take as long as 360ns+150ns+? when using the largest 8gb DDR3 ram chips, or 90ns+150ns+? for a 512mb DDR3 ram chips with the Z80's read channel priority set to max, or above all other channels (recommended).  At max priority, the reads will typically take 100ns to 150ns unless the read is a cache hit where the read will only take around 20ns or if the read is within the same activated page where the read will take around 50ns.  Since there is a nasty extended penalty when using the 'wait', you need to find out when is the latest you can issue a wait so that if a read can makes it back in time, you will not need to pulse the 'wait' line to the Z80.  It's also not that the ram want have your data within 750ns, it's that you really cant release the wait until the ram has delivered the read data, as in you cannot predict in advance and disable the wait early before the read acknowledge has come in.

Since the you will have a 2 word write cache and the Z80 is so slow, I doubt you will ever need a wait state during a write, however, for the writes, you will know in advance if that cache is full when you receive a write command.  It is also easy enough to increase the write cache size by a byte or 2 meaning the Z80 will not be able to out-pace the DDR3 no matter what the DDR3 may be doing elsewhere.

(Yes, smaller DDR3 ram chips refresh much faster than the larger ones.  Here is your selection:)
Code: [Select]
//                                512mb,    1gb,    2gb,    4gb,                 8gb   **** Refresh time for each size of DDR3 Ram.
localparam int  ttRFC   [0:8] = '{90000, 110000, 160000, 260000, 260000, 360000, 360000, 360000, 360000}; // minimum time in picoseconds
The DECA board right now has the 4gb chip, or 260ns.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 02, 2021, 07:08:28 pm
Well I don't necessarily intend on using anything bigger than 512MB - not for an 8-bit system, anyway.  Anything more seems like a massive waste of silicon.  But given how it's cheaper to buy a 512KB chip these days than a 16KB one (if you can even find one), I guess it's just a matter of time before anything less than 4GB dries up completely.

Given the parameter you've provided for ttRFC, it'll be easy enough to insert the appropriate number of WAIT states into a memory read if it's a cache miss.  In terms of the latest time to get WAIT pulled low, it's not long - it's the falling edge of T2 (that being the second clock cycle of the memory operation).  I need to detect a stable address in the GPU's RAM range and MREQ going low to signify the start of a valid memory op - in the image below, that's the first vertical dotted line at time 0.  The Z80 samples the WAIT line on the falling edge of T2 - the second vertical dotted line at time 6.  Each of those time steps is approximately 20ns - so it would appear I have a maximum of 120ns to get the WAIT line low enough that the Z80 will detect it as low on the falling edge of T2.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1241547)

Have attached latest z80_bridge_v2 for information.  Need to tidy it up a little, but hopefully there's no major issues with anything in it.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2021, 07:16:06 pm
You can try a Diodes inc mosfet 'DMN53D0LQ' in place of the 3904 as it's turn on is ~20ns, but it's turn off + fall is also around 30ns instead of having that 10x hold time of 200ns.

NXPs NX138AK mosfet is also good and it's also completely on on when the gate-source reaches 3v.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2021, 07:21:55 pm
Well I don't necessarily intend on using anything bigger than 512MB - not for an 8-bit system, anyway.  Anything more seems like a massive waste of silicon.  But given how it's cheaper to buy a 512MB chip these days than a 64MB one (if you can even find one), I guess it's just a matter of time before anything less than 4GB dries up completely.
Anyways, you would also be using 2 of them in parallel.
512mb (64 megabytes) and 1gb are still in high circulation, also remember you are using x16 width.

So, your smallest system size will be 2x512mb, or 128 megabytes.

(The 2x chips is for memory speed for video, though, you can still do a lot with 1, but loose rendering speed with high res 32bit color screens.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2021, 07:54:39 pm
You can try a Diodes inc mosfet 'DMN53D0LQ' in place of the 3904 as it's turn on is ~20ns, but it's turn off + fall is also around 30ns instead of having that 10x hold time of 200ns.

NXPs NX138AK mosfet is also good and it's also completely on on when the gate-source reaches 3v.
The NXP mosfet is faster...
But we are talking just over 5ns faster.

However, they are drop-in replacements for the 3904 transistors and you can change the series base resistor to 0-100 ohm for top speed.


Diodes inc 'DMN2230UQ' is also good and there exist a lot of fast mosfets with will turn on really hard at 3v g-s.  Though I think your final solution may be a logic IC with open-drain output so you have a few outputs on 1 device at your disposal.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2021, 12:49:05 pm
You can try a Diodes inc mosfet 'DMN53D0LQ' in place of the 3904 as it's turn on is ~20ns, but it's turn off + fall is also around 30ns instead of having that 10x hold time of 200ns.

NXPs NX138AK mosfet is also good and it's also completely on on when the gate-source reaches 3v.
The NXP mosfet is faster...
But we are talking just over 5ns faster.

However, they are drop-in replacements for the 3904 transistors and you can change the series base resistor to 0-100 ohm for top speed.


Diodes inc 'DMN2230UQ' is also good and there exist a lot of fast mosfets with will turn on really hard at 3v g-s.  Though I think your final solution may be a logic IC with open-drain output so you have a few outputs on 1 device at your disposal.

I'll get some of the NXP parts and the Diodes Inc ones in case one works and the other doesn't.  For a final solution, I'm looking to use something like the 74LVC07 to provide the open-drain outputs I require to pull various lines low, including WAIT.  It seems to be pretty responsive, with tPZL and tPLZ times in single-digit nanosecond ranges (https://www.mouser.co.uk/datasheet/2/916/74LVC07A-1319858.pdf#page=5).  Hopefully it's appropriate for the task.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2021, 12:48:40 am
You can try a Diodes inc mosfet 'DMN53D0LQ' in place of the 3904 as it's turn on is ~20ns, but it's turn off + fall is also around 30ns instead of having that 10x hold time of 200ns.

NXPs NX138AK mosfet is also good and it's also completely on on when the gate-source reaches 3v.
The NXP mosfet is faster...
But we are talking just over 5ns faster.

However, they are drop-in replacements for the 3904 transistors and you can change the series base resistor to 0-100 ohm for top speed.


Diodes inc 'DMN2230UQ' is also good and there exist a lot of fast mosfets with will turn on really hard at 3v g-s.  Though I think your final solution may be a logic IC with open-drain output so you have a few outputs on 1 device at your disposal.

I'll get some of the NXP parts and the Diodes Inc ones in case one works and the other doesn't.  For a final solution, I'm looking to use something like the 74LVC07 to provide the open-drain outputs I require to pull various lines low, including WAIT.  It seems to be pretty responsive, with tPZL and tPLZ times in single-digit nanosecond ranges (https://www.mouser.co.uk/datasheet/2/916/74LVC07A-1319858.pdf#page=5).  Hopefully it's appropriate for the task.

I would test to make sure, however, you would want to scope the output to ensure the 'pull-down' does indeed drop the bus signal below ~0.5v with that 4.7k pull-up.  Otherwise, you may meed to run 2 or 3 outputs in parallel to really clamp down the signal line as being a CMOS open drain output, it behaves differently than an open-collector TTL output.

My recommended mosfets have at least 10x the pull of the 50ma 74LVC07, so, you just need to make sure.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 04, 2021, 06:27:01 am
I would test to make sure, however, you would want to scope the output to ensure the 'pull-down' does indeed drop the bus signal below ~0.5v with that 4.7k pull-up.  Otherwise, you may meed to run 2 or 3 outputs in parallel to really clamp down the signal line as being a CMOS open drain output, it behaves differently than an open-collector TTL output.

My recommended mosfets have at least 10x the pull of the 50ma 74LVC07, so, you just need to make sure.

Some back-of-an-envelope maths indicates (if I'm doing it right - I'm using V=IR from my school days) about 1mA of current needs to be sunk on the WAIT line (using I=V/R, where V=5v and R=4.7Kohms).  I guess without knowing the capacitance of the physical trace connecting the open-drain output to the Z80's WAIT pin, there's no way to calculate rise/fall times?  It would probably help if I minimised the trace length to the system bus header on the PCB too.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2021, 06:49:09 am
I just finished a few improvements to the DDR3 controller.  Patched most of the main issues.  Tomorrow for me, later today for you, once I documented the changes, I will upload it to the DDR3 thread.  You should think about wiring the DDR3 directly to the Z80 bridge as a test.  However, in this state, the GPU wont be accessible, so only do this if you have access to a terminal mode to test the Z80 read and write to DDR3.

Let's see what you come up with for wiring the thing together.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2021, 02:12:33 am
V0.95 of the DDR3 controller has been released:
https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3621074/#msg3621074 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3621074/#msg3621074)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 16, 2021, 08:56:36 am
 >:D  >:D  >:D  >:D  >:D  >:D
 >:D 500MHz/1GTPS >:D
 >:D  >:D  >:D  >:D  >:D  >:D

@Nockieboy, please give this DECA board ellipse demo .sof programming file a test:
https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3630084/#msg3630084 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3630084/#msg3630084)
I just want to make sure that this isn't a fluke which only works on my eval board...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2021, 01:01:32 am
Well, my DDR3 controller is now good enough to run at 300MHz on Altera's slowest speed grade -8, perfect for the cheapest Cyclone V GPU.

Seen here: https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3631179/#msg3631179 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3631179/#msg3631179)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 27, 2021, 08:42:55 am
BrianHG_DDR3_Controller V1.00 has been released.
https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3649396/#msg3649396 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3649396/#msg3649396)

Sad news about Cyclone V, see here:
https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3649318/#msg3649318 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3649318/#msg3649318)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 27, 2021, 09:07:28 am
That's an amazing piece of work, BrianHG, and one that's going to be appreciated by a LOT of people - well done and thank you.  ;D :-+

I haven't had any time at all to work on hobby projects since I last posted - hoping for some time next week to look at wiring the DDR3 controller up to the existing DECA GPU build, but was wondering about your C-V FMax results.  If they don't turn out to be a bug in the Quartus software (I'm guessing you don't have a C-V sitting around you can do a build test on to verify if it works or not) then I'm wondering if it's worth moving up to a C-V for my GPU at all, given that the reason for moving to a C-V was purely based on the internal RAM size which is a need that is now negated by the use of external DDR3 RAM?

Staying with a C-IV, but a larger one than the CE10 I'm using in my existing prototype GPU card, may be preferable given those FMax results if they're going to affect performance.  Alternatively, switching from Altera altogether may be preferable?  What do you think?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 27, 2021, 09:27:48 am
Staying with a C-IV, but a larger one than the CE10 I'm using in my existing prototype GPU card, may be preferable given those FMax results if they're going to affect performance.  Alternatively, switching from Altera altogether may be preferable?  What do you think?

Give me a week to fiddle with Lattice Diamond.
They supposedly upgraded to using Modelsim for simulation and my DDR3 code was designed to work on any FPGA with a dumb DDR IO port and a PLL where I can phase shift one of the PLL clock outputs.

I'll see what Intel says about the Cyclone V, but, don't get your hopes up there.  It's FPGA fabric is different from the earlier Cyclones and with a lower 1.1v core, but, identical cell nanometer node size, I bet it just might be a slower FPGA at certain tasks.  Or, since it is a newer 'fitter' within Quartus, it may just be programmed lousily by a different team.  I guess we will see.  It is too bad as the Cyclone V's PLL can do 712MHz officially and that means that with the internal HDMI serializer, there was a good shot of achieving true 1080p output.  Cyclone IV's PLL max was rated at 475 MHz and we made it to 540, IE 1080mbps.  (CV's 712 might have made it to 742.5, 1080p's official 1485mbps.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 05, 2021, 08:09:03 am
Finally!!!!  (Damn javascript bug finally bypassed...)

My GitHub repository release:
https://github.com/BrianHGinc/BrianHG-DDR3-Controller (https://github.com/BrianHGinc/BrianHG-DDR3-Controller)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 12, 2021, 10:45:41 pm
Attached is the GPU Geometry testbench V1.0.

Here is the original v0.6 with instructions: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3465124/#msg3465124 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3465124/#msg3465124)

Remember, after running a test script, the sent commands are stored in: 'GEO_tb_command_results.txt'
And the results are stored in the .bmp as requested in the executed 'GEO_tb_***.txt'.

A lot of work was put into this, you should be using it to verify bugs you may be having when programming the GPU itself.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 13, 2021, 12:48:08 am
Here you go Nockieboy:

https://github.com/BrianHGinc/GPU_GEOMETRY_Testbench (https://github.com/BrianHGinc/GPU_GEOMETRY_Testbench)

Don't forget to 'Fork' the repository into your repo listings.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on September 13, 2021, 01:24:20 pm
Another trick you could try for speeding up the transistor is to put a smallish capacitor across the base resistor.
Smallish as in 100nF or 100pf? Across the 1K base resistor?  How does that work?  Isn't that setting up some sort of RC oscillator? (Genuine questions, I have no idea!)  :o
Something about that size, yes. Depends on the details of the circuit, you'd have to try it to find out how much you need. It's not creating a feedback path, so it shouldn't make anything oscillate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 13, 2021, 05:10:45 pm
Quick question BrianHG - this is probably something we've covered before, but I've forgotten.  ???

I'm finishing off the last few bugs and glitches in the full-graphics display mode for CP/M and my DMI, and have discovered that blitting characters appear to use the inverse of the colours used when drawing shapes?  i.e. I'm drawing a rectangle to clear the screen in 1 bpp mode, which uses colour index 00 to clear to black.  However, blitting a character from the character table also uses colour index 00 to blit the character in as a white char on a black square (colour index 1 draws black on white).  This is with CP and PM off (blitter mode 1).  What have I forgotten that's causing this confusion?  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 13, 2021, 08:54:45 pm
When blitting, you have the paste/draw color which does a flip/invert/bit-wise XOR of the source data.  In other words, blit paste with color 0 for output 0=0 and 1=1.  Also, you have the transparency color which also flips/inverts bits around.  And you also have transparency enable.  Disable the transparency and the color 0 and 1 both get piped through though to the screen, but the paste mask color transparency setting will still do it's first stage XOR invert color bits of the source data.

If it were replace color when selecting the paste color, then how do you manipulate multicolor blits where the source data has 16 or 256 colors?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 13, 2021, 09:49:02 pm
Ah, that's it - I knew there'd be an explanation that I'd just plain forgotten about! ;)  Thank you. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 14, 2021, 06:51:40 am
If you ever wanted to re-implement your line drawing engine with floating point (this means triangles as well as quads and ellipses which you can rotate), here is a key to providing different Bézier curves:

https://www.youtube.com/watch?v=enNfb6p3j_g (https://www.youtube.com/watch?v=enNfb6p3j_g)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 14, 2021, 10:29:53 am
Am I right in thinking that the geometry unit won't draw objects outside the bounds of the visible screen?  This poses a slight issue for clearing the screen.  It appears that the best method for clearing the screen (a CLS subroutine, basically) is to draw a rectangle on it in the background colour, as this handles all the nuances of the screen mode and its specific bpp setting, instead of just writing zero bytes (for 1 bpp) to GPU RAM for a calculated screen size.

The issue I've got is that the rectangle will not fill the screen - there's a vertical line on the far right edge where it won't draw.  This looks like something I've missed when I tested the geometry unit whilst we developed it - I'm off to go and dive into the HDL and add 1 to wherever the bounds check is for drawing pixels, but thought I'd raise it here as it's a bug in the existing GPU code.

Also, I need to clear a horizontal line of pixels past the bottom edge of the visible area (used for vertical scrolling) - I'll need to tweak the HDL to allow for drawing past ALL edges by a pixel or two to cater for scrolling, I guess?  Let me know if I'm walking into a bear trap or something.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 14, 2021, 10:47:06 am
Am I right in thinking that the geometry unit won't draw objects outside the bounds of the visible screen?  This poses a slight issue for clearing the screen.  It appears that the best method for clearing the screen (a CLS subroutine, basically) is to draw a rectangle on it in the background colour, as this handles all the nuances of the screen mode and its specific bpp setting, instead of just writing zero bytes (for 1 bpp) to GPU RAM for a calculated screen size.

The issue I've got is that the rectangle will not fill the screen - there's a vertical line on the far right edge where it won't draw.  This looks like something I've missed when I tested the geometry unit whilst we developed it - I'm off to go and dive into the HDL and add 1 to wherever the bounds check is for drawing pixels, but thought I'd raise it here as it's a bug in the existing GPU code.

Also, I need to clear a horizontal line of pixels past the bottom edge of the visible area (used for vertical scrolling) - I'll need to tweak the HDL to allow for drawing past ALL edges by a pixel or two to cater for scrolling, I guess?  Let me know if I'm walking into a bear trap or something.  :-+
You may blank the a bottom line after a vertical scroll, or,
just expand the max X&Y limits beyond the bottom of the display area.
However, so be warned, you will allow pixels to be written into ram off the screen, so make sure you have spare memory there.

IE, have 8 spare lines of blank data in the Y direction so that you may use a single blit including the blank ram so you do not have to do the actual rectangle clr at the bottom of the screen.

You may also have a full line of text text, 8 y pixels, below the display area pre-printed if you want a TV type vertical smooth scroll where the text begins off the bottom of the screen.  You may also have 1 spare line above the top of the screen if you want an up-down web-page like smooth scroll for a text reader/word processor or spreadsheet.

You may also do this horizontally as well and it need not be only 1 line and 1 row of text, you may buffer 2 or 4 characters off the borders if you like or even an entire page.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 14, 2021, 12:35:12 pm
Of course, there's loads of ways I could have implemented the scrolling.  Why I went with the extra line/s off the screen I don't know, probably the first idea that sprang to mind at the time - other than that I can clear those lines once, then not worry about having to clear every bottom line when I blit the screen upwards one line.  You're right though, if memory is tight then it's not the best solution, but with megabytes to play with in the DDR3, that shouldn't be a concern.

Have sorted the CLS not clearing the rightmost column without resorting to changing HDL in the end.  I'd gotten mixed up with which registers are 0-based and which aren't, and had set the max_x value to 639 instead of 640 in the setup. :palm:  It's the MAGGIE HW registers that are 0-based, not the GPU registers. Sorted now. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 25, 2021, 04:51:30 pm
Okay, nearly there with the CP/M graphics driver after a little time to work on it again today.  I can now change modes (between 640x480x1 and 640x480x2 anyway) and 4-colour mode is working.  I could do a 640x480x4 mode but the MAX10 doesn't have enough block RAM for a power-of-2 to allow for it and would involve some HDL hacks that aren't necessary if I'm going to move up to DDR3 shortly.

An issue has arisen which I'd like to address before I move on to connecting the DDR3 up - and it links directly to the previous question I had last week (or recently, anyway) about the XOR-ing of colours when blitting text characters.

I'd like to be able to blit a 1-bit text character to any number of bitplanes in the target, and change the values of 0s and 1s in the source to arbitrary values in the target.  i.e. I'd like to be able to blit the source 1bpp image so that the text could be white on black, or black on white, or green on a different shade of green, depending on which pen/paper values the user has set (and not solely by editing the palette).  The current setup doesn't appear to allow this, at least as far as my understanding of it goes?  It just seems to be able to alternate between colours immediately adjacent to each other in the palette thanks to the XOR-ing? (i.e. palette entries 0 and 1, 2 and 3, 4 and 5 etc)

Is there a setting that I haven't worked out yet that will allow me to (for example) blit blue text with black background (palette entries 2 and 0)?  At the moment all I can do is black on black, or its inverse, or blue on green, or its inverse.  I can obviously edit the palette so that 0 is black, 1 is white, or 2 is light green, 3 is dark green etc, but that's not very flexible if bitmaps are also in play).  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 25, 2021, 10:44:31 pm
For the paste, maybe we can change XOR to ADD in the HDL.

Though, if you want to have different background colors, you would need to do 2 blits, one with a 0 transparency, and the next with a 1 transparency, while pasting both with a different ADD value.

This will work fine for 1 bit source data.
For more bits, you would need to think things through to ensure you can get the color functionality you want if you make the 'ADD' change.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 26, 2021, 01:04:29 pm
For the paste, maybe we can change XOR to ADD in the HDL.

Though, if you want to have different background colors, you would need to do 2 blits, one with a 0 transparency, and the next with a 1 transparency, while pasting both with a different ADD value.

This will work fine for 1 bit source data.
For more bits, you would need to think things through to ensure you can get the color functionality you want if you make the 'ADD' change.

I'm just thinking purely for text - so 1-bit blits.  I've just been reformatting and tidying the code in geometry_xy_plotter whilst thinking about this (I think the word is procrastinating ;)).

The XOR-ing is done in the geo_pixel_writer, right?  I'm looking at these lines specifically:

Code: [Select]
colour_sel_miss  = 16'(wc_paste_pixel ? (PX_COPY_COLOUR ^ {8'd0,wc_colour}) : {8'd0,(wc_colour & LUT_mask[wc_bpp])}) ; // select between copy buffer color for paste XORed with immediate color, or immediate color
colour_sel_hit   = 16'(paste_pixel    ? (PX_COPY_COLOUR ^ {8'd0,colour   }) : {8'd0,(colour    & LUT_mask[bpp   ])}) ; // select between copy buffer color for paste XORed with immediate color, or immediate color

So colour_sel_miss and colour_sel_hit refer to cache hits or misses on the read pixel, applying the XOR operation on PX_COPY_COLOUR and colour, or just returning colour ANDed with the LUT_mask?


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 27, 2021, 12:59:52 am
Yes, you found it.

Now, there is the issue that when adding, it only goes in the positive direction and you have a bit limit based on color depth.

I think you should try:

Code: [Select]
colour_sel_miss  = 16'(wc_paste_pixel ? (PX_COPY_COLOUR + {8'd0,wc_colour}) : {8'd0,(wc_colour & LUT_mask[wc_bpp])}) ; // select between copy buffer color for paste XORed with immediate color, or immediate color
colour_sel_hit   = 16'(paste_pixel    ? (PX_COPY_COLOUR + {8'd0,colour   }) : {8'd0,(colour    & LUT_mask[bpp   ])}) ; // select between copy buffer color for paste XORed with immediate color, or immediate color

Keep an eye on the FMAX.
Also, I guess it may also be possible to prevent the color overflow paste problem like this (IE: meaning when the final paste color exceeded the available bit depth on the display, trim the extra bits out to prevent garble graphics, this should also allow you to subtract a color value by when adding, a result number greater than the available colors on the screen will be clipped to the available color bits.):

Code: [Select]
colour_sel_miss  = 16'(wc_paste_pixel ? (PX_COPY_COLOUR + {8'd0,wc_colour}) : {8'd0,(wc_colour)})  & LUT_mask[wc_bpp]; // select between copy buffer color for paste XORed with immediate color, or immediate color
colour_sel_hit   = 16'(paste_pixel    ? (PX_COPY_COLOUR + {8'd0,colour   }) : {8'd0,(colour)})     & LUT_mask[bpp   ]; // select between copy buffer color for paste XORed with immediate color, or immediate color

You will need to test and verify the 2.
Also check FMAX for the 125MHz clock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 27, 2021, 09:07:21 am
Yes, you found it.

Now, there is the issue that when adding, it only goes in the positive direction and you have a bit limit based on color depth.

True, but I'm tending to mask input values according to the current mode (or bitplane setting) in software.

I think you should try:

Code: [Select]
colour_sel_miss  = 16'(wc_paste_pixel ? (PX_COPY_COLOUR + {8'd0,wc_colour}) : {8'd0,(wc_colour & LUT_mask[wc_bpp])}) ; // select between copy buffer color for paste XORed with immediate color, or immediate color
colour_sel_hit   = 16'(paste_pixel    ? (PX_COPY_COLOUR + {8'd0,colour   }) : {8'd0,(colour    & LUT_mask[bpp   ])}) ; // select between copy buffer color for paste XORed with immediate color, or immediate color

Keep an eye on the FMAX.

Okie dokie.  This is the normal project Timings result (with NO changes) for comparison:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1283248)


And this is the Timings results with the changes mentioned above:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1283254)

No real benefit to the text, to be honest.  I'm still getting blocks of colour for blitted character where the 'background' of the source character isn't being remapped to the preferred background colour, etc.

Also, I guess it may also be possible to prevent the color overflow paste problem like this (IE: meaning when the final paste color exceeded the available bit depth on the display, trim the extra bits out to prevent garble graphics, this should also allow you to subtract a color value by when adding, a result number greater than the available colors on the screen will be clipped to the available color bits.):

Code: [Select]
colour_sel_miss  = 16'(wc_paste_pixel ? (PX_COPY_COLOUR + {8'd0,wc_colour}) : {8'd0,(wc_colour)})  & LUT_mask[wc_bpp]; // select between copy buffer color for paste XORed with immediate color, or immediate color
colour_sel_hit   = 16'(paste_pixel    ? (PX_COPY_COLOUR + {8'd0,colour   }) : {8'd0,(colour)})     & LUT_mask[bpp   ]; // select between copy buffer color for paste XORed with immediate color, or immediate color

Timing results for above change:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1283260)

So there's an incremental negative change in Fmax for the GPU core with these changes.  Neither stops the GPU running with the current testing I'm doing, but I'm only requesting 640x480 from the GPU;  most likely it will introduce artefacts when pushed or fail to produce HDMI-compatible higher-resolutions.
Perhaps it would make sense to create an additional blitter mode specifically for text (if possible)?  One that takes a 1-bit source and pastes pixels to the target based on the current foreground and background colours, replacing 1s and 0s accordingly.  That would allow any colour text to be printed against any colour background (within bpp limits of the current mode, obviously).  This wouldn't need to be massively performant due to it being used solely for text, so two blits wouldn't be a deal breaker?  Is that possible? 

Or is it just a play on the transparency blit mode, treating 0's in the source as transparent and replacing 1's with the foreground colour?  That would be preferable, to be honest.  Perhaps I'm testing the wrong blit mode or something?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 27, 2021, 09:40:49 am
Remember, you have the 'transparency color' setting where when you place a '1', this will invert the font.

Blit 1 time without the invert, selecting an appropriate 'paste add color' will paint your foreground color.
Blit a second time with the transparency inverted, selecting a new 'paste add color' color will render the background outline color of your choice.

After you get the initial DDR3 functioning, you will want to redo the geometry to run at 200MHz instead of 125 since you will want the ram core to operate at 400MHz.  This will most likely need some changes to the 'ellipse' module and a few changes to the 'pixel_writer' module.  You will have to deal with selecting how the deep color modes are processed when reading from the DDR3 and probably leave the accelerated tile modes to any spare FPGA core memory.  This will probably mean something like having only 128kb for hardware tiles/sprite on the larger FPGA with all of the DDR3 memory available for the blitter accelerated style sprites.  But, if I could make a faster 'multi-port' module, it could theoretically be possible to make the blitter run at 800 million 32bit pixels a second (32bit ram, 400m read, 400m write) if not at least half that with the blitter pixel collision disabled, but only with 8bit, 16bit, or 32 bit pixels.

The next change after that would be to generate a sequence processor which will read a chunk of DDR3 and feed the 'geometry' units input FIFO instead of having your Z80 always do from a port.  The goal is to have enough command functions in this sequencer to select, loop, copy, stop and go, add/subtract/mult/divide 16 and 32 bit 4x4 matrices so that you can have pre-compiled rendered sequences to render graphics where the Z80 only has to send a 'begin program at DDR3 address' and let the GPU hardware do all the work at 200MHz.

IE, such a program in the DDR3 may be loop and read a section of ram at x address, with a width and height of 80x25 bytes, with another for foreground and background colors, and render a screen of text driving the geo unit and blitter.  And do so once every frame.  Now the Z80 can just access that 80x25 bytes as ascii text and the sequence processor will render that contents as text on a graphics screen software emulating a text mode while the Z80 wont know the difference.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 27, 2021, 11:05:37 am
Remember, you have the 'transparency color' setting where when you place a '1', this will invert the font.

Blit 1 time without the invert, selecting an appropriate 'paste add color' will paint your foreground color.
Blit a second time with the transparency inverted, selecting a new 'paste add color' color will render the background outline color of your choice.

Ah yes, I've been testing with Paste Mask off.  When I turn it on, I'm able to get more variety with the fore/background combinations.  I think I'll leave it at that for the moment given the potential future need to redo stuff.

After you get the initial DDR3 functioning, you will want to redo the geometry to run at 200MHz instead of 125 since you will want the ram core to operate at 400MHz.

Yeah, best I stop ducking this next task and crack on with it.  Expect questions in the near future.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1283323)

This will most likely need some changes to the 'ellipse' module and a few changes to the 'pixel_writer' module.  You will have to deal with selecting how the deep color modes are processed when reading from the DDR3 and probably leave the accelerated tile modes to any spare FPGA core memory.  This will probably mean something like having only 128kb for hardware tiles/sprite on the larger FPGA with all of the DDR3 memory available for the blitter accelerated style sprites.  But, if I could make a faster 'multi-port' module, it could theoretically be possible to make the blitter run at 800 million 32bit pixels a second (32bit ram, 400m read, 400m write) if not at least half that with the blitter pixel collision disabled, but only with 8bit, 16bit, or 32 bit pixels.

Well, the existing font tiles don't take up a vast amount of room, but with more screen resolution comes the need to step up to a font bigger than 8x16 pixels in the future, I guess.  Also, if you're trying to impress me with big numbers, it's working. ;D  16-bit pixels should be fine for anything I'd ever want to do.  :o

The next change after that would be to generate a sequence processor which will read a chunk of DDR3 and feed the 'geometry' units input FIFO instead of having your Z80 always do from a port.  The goal is to have enough command functions in this sequencer to select, loop, copy, stop and go, add/subtract/mult/divide 16 and 32 bit 4x4 matrices so that you can have pre-compiled rendered sequences to render graphics where the Z80 only has to send a 'begin program at DDR3 address' and let the GPU hardware do all the work at 200MHz.

This sounds a bit like the 'copper' in the old Amiga systems, but more advanced?  So the Z80 could just set up a load of graphics commands and set the sequence processor running whilst it does something else.  That sounds awesome...  :o

IE, such a program in the DDR3 may be loop and read a section of ram at x address, with a width and height of 80x25 bytes, with another for foreground and background colors, and render a screen of text driving the geo unit and blitter.  And do so once every frame.  Now the Z80 can just access that 80x25 bytes as ascii text and the sequence processor will render that contents as text on a graphics screen software emulating a text mode while the Z80 wont know the difference.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1283329;image)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on September 27, 2021, 06:57:51 pm
Have you considered stuffing a CPU core inside FPGA too and doing away with a silicon? I think the softcore will work much faster than the hard silicon. :popcorn:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 27, 2021, 08:51:38 pm
Have you considered stuffing a CPU core inside FPGA too and doing away with a silicon? I think the softcore will work much faster than the hard silicon. :popcorn:

Oh yes, I'm fully aware that this is possible (with a T80 core?) but I started out building my own computer and I'll continue with that for the time being, even though the technology I'm using for the GPU is far superior to the rest of the 'stack'.  I do have plans to replace the hardware MMU with one based in the FPGA at some point - and where does the migration onto FPGA end? - but I've found I actually quite enjoy designing and building PCBs and pushing my soldering skills, so all the time I've got hardware (CPUs) sitting around I'll design and build for those first before I go "full FPGA" and do it all there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on September 28, 2021, 02:14:05 am
Oh yes, I'm fully aware that this is possible (with a T80 core?) but I started out building my own computer and I'll continue with that for the time being, even though the technology I'm using for the GPU is far superior to the rest of the 'stack'.  I do have plans to replace the hardware MMU with one based in the FPGA at some point - and where does the migration onto FPGA end? - but I've found I actually quite enjoy designing and building PCBs and pushing my soldering skills, so all the time I've got hardware (CPUs) sitting around I'll design and build for those first before I go "full FPGA" and do it all there.
It just seems to me that the hard silicon is a serious drag for performance, also internal connections are much easier and (if done right) won't have any glitches or timing issues. As for soldering - there will be plenty of it in any case :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 28, 2021, 07:33:32 am
It just seems to me that the hard silicon is a serious drag for performance, also internal connections are much easier and (if done right) won't have any glitches or timing issues. As for soldering - there will be plenty of it in any case :)

Fortunately performance (other than in the GPU) isn't a real concern for me with this particular system.  I started out with the objective of building something more powerful than the first computer I had (whilst learning about electronics at the same time), which I've done in spades (or will have done once I've sorted out the audio).  Even the GPU in its current iteration (with no DDR3) is massively more powerful.

The audio is a function I will be migrating to the FPGA, though.  AY-3-8912 PSGs (the YM2149 is a Yamaha copy) - as used in my original computer - seem to be a dwindling commodity, and whilst I've got a hardware audio card I built around the AY-3-8910 (not much different, more IO), I built it a few years ago before I progressed to SMD parts etc and it's not my best work.  I don't understand analogue electronics at all.  I also don't particularly want yet another card on the stack, particularly one for a single chip like the 8910, so I'll be looking to incorporate an HDL YM2149 instead and hope to output that via the PCM5101A, though I'm not sure how I'm going to do that yet (or even if it's practical to).

The only other thing on my FPGA to-do list is replace the CompactFlash card on the stack with a slightly newer SD (preferably micro-SD) slot on the GPU card - maybe even a USB flash drive.  I've had a lot of difficulty with the last two iterations of the GPU card (for the EP4CE10) matching a micro-SD card socket with a PCB footprint for some reason.  If anyone can recommend a particular micro-SD card socket that is available on EasyEDA and has a decent supplier (Mouser preferably), then please let me know!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on September 28, 2021, 11:15:12 am
Fortunately performance (other than in the GPU) isn't a real concern for me with this particular system.  I started out with the objective of building something more powerful than the first computer I had (whilst learning about electronics at the same time), which I've done in spades (or will have done once I've sorted out the audio).  Even the GPU in its current iteration (with no DDR3) is massively more powerful.
Well it's up to you of course, but as far as I'm concerned, there is no such thing as too much performance. More performance means better graphics, more advanced gameplay (for games), etc.

The audio is a function I will be migrating to the FPGA, though.  AY-3-8912 PSGs (the YM2149 is a Yamaha copy) - as used in my original computer - seem to be a dwindling commodity, and whilst I've got a hardware audio card I built around the AY-3-8910 (not much different, more IO), I built it a few years ago before I progressed to SMD parts etc and it's not my best work.  I don't understand analogue electronics at all.  I also don't particularly want yet another card on the stack, particularly one for a single chip like the 8910, so I'll be looking to incorporate an HDL YM2149 instead and hope to output that via the PCM5101A, though I'm not sure how I'm going to do that yet (or even if it's practical to).
I think I already recommended in the past to just connect any I2S DAC to FPGA and implement a sound card inside. This way you have an easy growth path as any DAC of the past decade or so supports 48k@24bps and better audio stream, so if at some point you will want to implement stuff like mp3/ogg/wav playback, you can easily do so. But initially you can just bit-stuff extra bits if you want to stick to "historical" sound.

The only other thing on my FPGA to-do list is replace the CompactFlash card on the stack with a slightly newer SD (preferably micro-SD) slot on the GPU card - maybe even a USB flash drive.  I've had a lot of difficulty with the last two iterations of the GPU card (for the EP4CE10) matching a micro-SD card socket with a PCB footprint for some reason.  If anyone can recommend a particular micro-SD card socket that is available on EasyEDA and has a decent supplier (Mouser preferably), then please let me know!
You will have to learn how to create footprints yourself. That is a crucial skill for anyone aspiring to do any half-decent PCBs. One bit of advice from me - pick parts from manufacturers which provide 3D STEP models of their products, this way you can "virtually" verify a footprint by adding a 3D model on top of it and seeing if it fits.
As for specific model, the one I've been using for a while is GCT's MEM2075-00-140-01-A, it's available via both Mouser and Digikey, and manufacturer provides (https://gct.co/connector/mem2075) 3D models and footprints for many eCAD systems (but I don't think EasyEDA is one of them). The reason I like this specific part is because it's a push-push socket, meaning you push the card in for it to lock inside, and push it in again to release - this guarantees that will be properly secured and won't fall out or lose contact, also it's quite affordable at about US$1.6 for quantity 10 - I bought a 100 of them back in the day as I use them quite often, so I know I will use them up eventually.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2021, 09:21:03 am
I think I already recommended in the past to just connect any I2S DAC to FPGA and implement a sound card inside. This way you have an easy growth path as any DAC of the past decade or so supports 48k@24bps and better audio stream, so if at some point you will want to implement stuff like mp3/ogg/wav playback, you can easily do so. But initially you can just bit-stuff extra bits if you want to stick to "historical" sound.

Yes, you did. I'm going to need to give some significant thought to interfacing the YM2149 HDL to an output compatible with an I2S DAC though.  I'm planning on using a PCM5102 or something similar.  Chip supplies are severely drying up now though, but it looks like I can get these DACs as part of breakout boards and 'reclaim' the chips for use in my own project for cheaper than actually buying (and waiting half a year) for new stock.  Wish the same were true of the FPGAs, but I can't get too annoyed about that as I don't really know exactly which FPGA I'm going to be using yet.  I nearly pulled the trigger on the last EP4CE22F17C7N in Mouser stock the other day (it's gone now), given BrianHG's recent comments that the CV actually doesn't seem to be any faster despite having more LEs and block RAM, but since block RAM is no longer a real concern if I can get this DDR3 controller working with my GPU, I have a lot more freedom (it seems) in choosing an FPGA. :-/O

The only other thing on my FPGA to-do list is replace the CompactFlash card on the stack with a slightly newer SD (preferably micro-SD) slot on the GPU card - maybe even a USB flash drive.  I've had a lot of difficulty with the last two iterations of the GPU card (for the EP4CE10) matching a micro-SD card socket with a PCB footprint for some reason.  If anyone can recommend a particular micro-SD card socket that is available on EasyEDA and has a decent supplier (Mouser preferably), then please let me know!
You will have to learn how to create footprints yourself. That is a crucial skill for anyone aspiring to do any half-decent PCBs. One bit of advice from me - pick parts from manufacturers which provide 3D STEP models of their products, this way you can "virtually" verify a footprint by adding a 3D model on top of it and seeing if it fits.

Oh I can create footprints with no issue from datasheets etc., just wondered if anyone had a recommendation to save me the trouble...

As for specific model, the one I've been using for a while is GCT's MEM2075-00-140-01-A, it's available via both Mouser and Digikey, and manufacturer provides (https://gct.co/connector/mem2075) 3D models and footprints for many eCAD systems (but I don't think EasyEDA is one of them). The reason I like this specific part is because it's a push-push socket, meaning you push the card in for it to lock inside, and push it in again to release - this guarantees that will be properly secured and won't fall out or lose contact, also it's quite affordable at about US$1.6 for quantity 10 - I bought a 100 of them back in the day as I use them quite often, so I know I will use them up eventually.

...like that one. ;)  I can get them from Mouser and there's footprints available on EasyEDA for them too which I can verify from the datasheet, thanks very much asmi. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2021, 11:15:58 am
*** DDR3 Controller Setup Questions ***

@BrianHG - I've made a start on connecting the BrianHG_DDR3_Controller to the rest of the GPU this morning in some spare time.  I'm using the BrianHG_DDR3_DECA_test1 project as a guide as I figure the way the RS232 debugger is connected to the controller should emulate (in some way) how the Z80_Bridge will need to be connected in the GPU to the DDR3 controller.  Is that a good starting point?

I note there's some discrepancy between the _test1 project's top-level file parameters and the GPU's top-level file parameters, so I've copied the params from the _test1 project to the GPU top-level as that's more up-to-date with your v1.0 DDR3_Controller than the GPU_top file was.

Also, do I need to include and tweak the two additional modules, DDR3_CMD_ENCODE_BYTE and DDR3_CMD_DECODE_BYTE in _test1_top into GPU_top?  Looks like they're decoding/encoding data to/from the RS232 port and the DDR3_controller, but with only a 5-bit wide address?  Is that because it's reading/writing 32 bytes at a time and it allows the host to specify which byte it's accessing from that cache, or something else...?

Finally, it looks like the data_mux_geo would mirror the rs232_debugger's connection to the DDR3 RAM, where it currently connects to internal block RAM.  data_mux_geo isn't instantiated in GPU_TOP.sv where the DDR3_Controller resides, though - it's a level down in GPU.sv, so I'm going to need to connect all the DDR3_Controller's IO through to GPU.sv and from there into the data_mux_geo - is that right?

Have attached GPU.sv (have spent some time tidying it up) and GPU_TOP.sv for info if required.  GPU_TOP has the DDR3_Controller stuff commented out currently as I've just built the project to make sure my tidying of GPU.sv hasn't broken anything.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2021, 11:51:37 am
You are using the wrong project as an example.
You should be using 'BrianHG_DDR3_DECA_RS232_DEBUG_TEST' from V1.0.

You need to use that full project and it's internal RS232 debugger will replace the one inside your GPU one.

Increase it's read and write port total by 1.
Raise the read and write port #2's priority to max.
Set the new port 2's to 8 bit each.

Wire the write port to the Z80 bridge write -> gpu ram output to my DDR3 write channel #2.

Next, test to see if the Z80 is writing to the DDR3 by looking at RS232 debugger while running Z80 code.

Next for the Z80 read data from gpu ram, disconnect it's read data from the data_mux_geo and wire it to my DDR3 read port #2.

Verify you can now read and write up to 1 megabyte.  Also, I have not checked if the core GPU ram has checks in it to prevent writing above your set limit.

Remember, any control signals you disconnect, or ones you are not using should be disabled to 0.

Follow these steps after merging your GPU project into your renamed:
'BrianHG_DDR3_DECA_RS232_DEBUG_TEST' project.
Use it's top hierarchy.

This current setup will not allow the geometry unit to access the DDR3 as this will require a change or new 'data_mux_geo' module to deal with the partitioning of FPGA core ram VS DDR3.  But it will allow you to generate the next step which will require the addition of adding the Z80 wait-states.  Since the DDR3 is doing nothing else, I doubt you will get corrupt reads, but, we will try to find a way to test this.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 29, 2021, 02:57:17 pm
You need to use that full project and it's internal RS232 debugger will replace the one inside your GPU one.

Increase it's read and write port total by 1.
Raise the read and write port #2's priority to max.
Set the new port 2's to 8 bit each.

Okay, so I'm using the BrianHG_DDR3_DECA_RS232_DEBUG_TEST project (renamed to GPU_DECA_DDR3) and I'm using the donor project's _top file.  I've changed these lines:

Code: [Select]
parameter int        PORT_R_TOTAL            = 2,                // Set the total number of DDR3 controller read ports, 1 to 16 max.
parameter int        PORT_W_TOTAL            = 2,                // Set the total number of DDR3 controller write ports, 1 to 16 max.
parameter int        PORT_VECTOR_SIZE        = 8,                // Sets the width of each port's VECTOR input and output.

Hopefully that's correct?  What you've said implies that I can set different PORT_VECTOR_SIZEs for each R/W port.  Am hoping that's just a 'lost in translation' thing. ;)

How do I change the priority of the read and write ports?  This is confusing me:

Code: [Select]
parameter bit [2:0]  PORT_R_PRIORITY      [0:15] = '{  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
parameter bit [2:0]  PORT_W_PRIORITY      [0:15] = '{  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},

Wire the write port to the Z80 bridge write -> gpu ram output to my DDR3 write channel #2.

This is where I'm going to need to pass through some buses and controls from GPU.sv up to GPU_DECA_DDR3_top.sv, I'm guessing, so I can wire the Z80_bridge into the DDR3_Controller?

Files attached for info.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on September 29, 2021, 04:05:21 pm
I'm planning on using a PCM5102 or something similar. 
That chip supports I2S, and left- and right-justified formats, just like pretty much any other audio DAC I've seen. You can pick pretty much any of them you will find in stock (Cirrus Logic makes quite a bit of different P/Ns) - they all are input-compatible for the most part, and fundamentally work the same way.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on September 29, 2021, 05:30:49 pm
I'm planning on using a PCM5102 or something similar. 
That chip supports I2S, and left- and right-justified formats, just like pretty much any other audio DAC I've seen. You can pick pretty much any of them you will find in stock (Cirrus Logic makes quite a bit of different P/Ns) - they all are input-compatible for the most part, and fundamentally work the same way.

Yep. There won't be any difference as far as I2S is concerned - just be aware that any 24-bit or higher DAC these days will take 32-bit data sample through I2S (64-bit data per stereo frame), with the lower unused bits ignored. Some (now less common) 16-bit DACs may only take 16-bit data sample/32-bit per frame, so regarding I2S, that would be your incompatibility here. But if you stick to 24-bit or higher DACs, then it will be basically plug and play as far as I2S is concerned.

Differences may be with how the chips are configured (hardware config via pins, software config via I2C or SPI...), the master clock, but those can be handled separately. As far as I remember, the PCM5102 (probably 5102A as the 5102 is now obsolete if I'm not mistaken) can generate the master clock internally from the I2S bit clock, so it's very easy to interface.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on September 29, 2021, 07:54:47 pm
Yep. There won't be any difference as far as I2S is concerned - just be aware that any 24-bit or higher DAC these days will take 32-bit data sample through I2S (64-bit data per stereo frame), with the lower unused bits ignored. Some (now less common) 16-bit DACs may only take 16-bit data sample/32-bit per frame, so regarding I2S, that would be your incompatibility here. But if you stick to 24-bit or higher DACs, then it will be basically plug and play as far as I2S is concerned.
Typically this doesn't matter because there is always quite a bit of "nothingness" at the tail end of each channel's sample value, so higher-resolution DAC will recognize these as trailing zeros.

Differences may be with how the chips are configured (hardware config via pins, software config via I2C or SPI...), the master clock, but those can be handled separately. As far as I remember, the PCM5102 (probably 5102A as the 5102 is now obsolete if I'm not mistaken) can generate the master clock internally from the I2S bit clock, so it's very easy to interface.
That stuff usually boils down to find a table in the datasheet which tells you what values you need to assign to config pins/config interface registers to get the mode and frequency you want. So it's a one-time task (unless you need to change these on the fly, which is quite rare) for a specific P/N.
The cool part is that some newer DACs (for example CS4344) will auto-detect sampling frequency, so that means less configuration hassle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 29, 2021, 10:03:34 pm
I did not say change the port vector size.
Code: [Select]
// ************************************************************************************************************************************
// ****************  BrianHG_DDR3_COMMANDER configuration parameter settings.
parameter int        PORT_R_TOTAL            = 2,                // Set the total number of DDR3 controller read ports, 1 to 16 max.
parameter int        PORT_W_TOTAL            = 2,                // Set the total number of DDR3 controller write ports, 1 to 16 max.
parameter int        PORT_VECTOR_SIZE        = 16,               // Sets the width of each port's VECTOR input and output.

I said change the data_width to 8 for the read and write on port 2.
Code: [Select]
// PORT_'feature' = '{array a,b,c,d,..} Sets the feature for each DDR3 ram controller interface port 0 to port 15.
parameter bit [8:0]  PORT_R_DATA_WIDTH    [0:15] = '{  8,  8,128,128,128,128,128,128,128,128,128,128,128,128,128,128},
parameter bit [8:0]  PORT_W_DATA_WIDTH    [0:15] = '{  8,  8,128,128,128,128,128,128,128,128,128,128,128,128,128,128},
                                                            // Use 8,16,32,64,128, or 256 bits, maximum = 'PORT_CACHE_BITS'
                                                            // As a precaution, this will prune/ignore unused data bits and write masks bits, however,
                                                            // all the data ports will still be 'PORT_CACHE_BITS' bits and the write masks will be 'PORT_CACHE_WMASK' bits.
                                                            // (a 'PORT_CACHE_BITS' bit wide data bus has 32 individual mask-able bytes (8 bit words))
                                                            // For ports sizes below 'PORT_CACHE_BITS', the data is stored and received in Big Endian. 


And I said raise the priority of read and write port 2 to the max.

Code: [Select]
parameter bit [2:0]  PORT_R_PRIORITY      [0:15] = '{  1,  7,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
parameter bit [2:0]  PORT_W_PRIORITY      [0:15] = '{  2,  7,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
                                                            // Use 1 through 6 for normal operation.  Use 7 for above refresh priority.  Use 0 for bottom
                                                            // priority, only during free cycles once every other operation has been completed.
                                                            // Open row policy/smart row access only works between ports with identical
                                                            // priority.  If a port with a higher priority receives a request, even if another
                                                            // port's request matches the current page, the higher priority port will take
                                                            // president and force the ram controller to leave the current page.
                                                            // *(Only use 7 for small occasional access bursts which must take president above
                                                            //   all else, yet not consume memory access beyond the extended refresh requirements.)

These are the changes to make all the IO read and write port 2 into an 8 bit ram port compatible with the Z80 and make sure that the Z80 on port 2 has a top read priority above all else.

(*** Note that port 2 is really [ 1 ] while port 1 where the RS232 debugger is tied to is on [ 0 ] )

Don't forget to enable the write mask 'CMD_wmask' on port 2 so the Z80 actually achieves a write.

Also remember to remove all traces of your original RS232 debugger buried inside your GPU core.

And, just in case, these are all your DDR3 controller interface IO ports:
Code: [Select]
// ****************************************
// DDR3 Controller Interface Logic.
// ****************************************
logic                         CMD_R_busy          [0:PORT_R_TOTAL-1];  // For each port, when high, the DDR3 controller will not accept an incoming command on that port.
logic                         CMD_W_busy          [0:PORT_W_TOTAL-1];  // For each port, when high, the DDR3 controller will not accept an incoming command on that port.


logic                         CMD_write_req       [0:PORT_W_TOTAL-1];  // Write request for each port.

logic [PORT_ADDR_SIZE-1:0]    CMD_waddr           [0:PORT_W_TOTAL-1];  // Address pointer for each write memory port.
logic [PORT_CACHE_BITS-1:0]   CMD_wdata           [0:PORT_W_TOTAL-1];  // During a 'CMD_write_req', this data will be written into the DDR3 at address 'CMD_addr'.
                                                                       // Each port's 'PORT_DATA_WIDTH' setting will prune the unused write data bits.
logic [PORT_CACHE_BITS/8-1:0] CMD_wmask           [0:PORT_W_TOTAL-1];  // Write mask for the individual bytes within the 256 bit data bus.
                                                                       // When low, the associated byte will not be written.
                                                                       // Each port's 'PORT_DATA_WIDTH' setting will prune the unused mask bits.


logic [PORT_ADDR_SIZE-1:0]    CMD_raddr           [0:PORT_R_TOTAL-1];  // Address pointer for each read memory port.
logic                         CMD_read_req        [0:PORT_R_TOTAL-1];  // Performs a read request for each port.
logic [PORT_VECTOR_SIZE-1:0]  CMD_read_vector_in  [0:PORT_R_TOTAL-1];  // The contents of the 'CMD_read_vector_in' during a 'CMD_read_req' will be sent to the
                                                                       // 'CMD_read_vector_out' in parallel with the 'CMD_read_data' during the 'CMD_read_ready' pulse.

logic                         CMD_read_ready      [0:PORT_R_TOTAL-1];  // Goes high for 1 clock when the read command data is valid.
logic [PORT_CACHE_BITS-1:0]   CMD_read_data       [0:PORT_R_TOTAL-1];  // Valid read data when 'CMD_read_ready' is high.
logic [PORT_VECTOR_SIZE-1:0]  CMD_read_vector_out [0:PORT_R_TOTAL-1];  // Returns the 'CMD_read_vector_in' which was sampled during the 'CMD_read_req' in parallel
                                                                       // with the 'CMD_read_data'.  This allows for multiple post reads where the output
                                                                       // has a destination pointer.
logic [PORT_ADDR_SIZE-1:0]    CMD_read_addr_out   [0:PORT_R_TOTAL-1];  // A return of the address which was sent in with the read request.


logic                        CMD_R_priority_boost [0:PORT_R_TOTAL-1];  // Boosts the port's 'PORT_R_PRIORITY' parameter by a weight of 8 when set.
logic                        CMD_W_priority_boost [0:PORT_W_TOTAL-1];  // Boosts the port's 'PORT_W_PRIORITY' parameter by a weight of 8 when set.

Remember, all control inputs need to be wired to a control, or a 0 or 1.
Yes you need to pass some of the output from the Z80 bridge to the top of your GPU module to feed this new TOP where the DDR3 controller and new RS232 debugger exists.
Also, you may need to change where I wired the new RS232 debugger's RXD/TXD to your chosen IOs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2021, 08:07:39 am
And I said raise the priority of read and write port 2 to the max.

Code: [Select]
parameter bit [2:0]  PORT_R_PRIORITY      [0:15] = '{  1,  7,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
parameter bit [2:0]  PORT_W_PRIORITY      [0:15] = '{  2,  7,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
                                                            // Use 1 through 6 for normal operation.  Use 7 for above refresh priority.  Use 0 for bottom
                                                            // priority, only during free cycles once every other operation has been completed.
                                                            // Open row policy/smart row access only works between ports with identical
                                                            // priority.  If a port with a higher priority receives a request, even if another
                                                            // port's request matches the current page, the higher priority port will take
                                                            // president and force the ram controller to leave the current page.
                                                            // *(Only use 7 for small occasional access bursts which must take president above
                                                            //   all else, yet not consume memory access beyond the extended refresh requirements.)

These are the changes to make all the IO read and write port 2 into an 8 bit ram port compatible with the Z80 and make sure that the Z80 on port 2 has a top read priority above all else.

Ahh okay - didn't understand how the PORT_x_PRIORITY array worked (i.e. didn't realise it was { PORT 1, PORT 2, PORT 3, etc... }).

Don't forget to enable the write mask 'CMD_wmask' on port 2 so the Z80 actually achieves a write.

So I'm going to need to edit this section:

Code: [Select]
// Latch the read data from port 0 on the CMD_CLK clock.
always_ff @(posedge CMD_CLK) begin

   if (RST_OUT) begin // RST_OUT is clocked on the CMD_CLK source.

for(int i = 0; i < PORT_R_TOTAL; i++) begin // Clear all the read requests.

CMD_read_req[i]         <= 0 ;
CMD_raddr[i]            <= 0 ;
CMD_read_vector_in[i]   <= 0 ;
CMD_R_priority_boost[i] <= 0 ;

end

for(int i = 0; i < PORT_W_TOTAL; i++) begin // Clear all the write requests.

CMD_write_req[i]        <= 0 ;
CMD_waddr[i]            <= 0 ;
CMD_wdata[i]            <= 0 ;
CMD_wmask[i]            <= 0 ;
CMD_W_priority_boost[i] <= 0 ;

end

   end else begin
                                                 
      // Wire the 8 bit write port.  We can get away with crossing a clock boundary with the write port.
      // Since there is no busy for the RS232 debugger write command, write port[0]'s priority was made 7 so it overrides everything else.

      CMD_waddr[0]     <= (PORT_ADDR_SIZE)'(DB232_addr)     ; // Set the RS232 write address.
      CMD_wdata[0]     <= (PORT_CACHE_BITS)'(DB232_wdat)    ; // Set the RS232 write data.
      CMD_wmask[0]     <= (PORT_CACHE_BITS/8)'(1)           ; // 8 bit write data has only 1 write mask bit.     

      DB232_wreq_dly   <=  DB232_wreq                       ; // Delay the write request as we are crossing clock boundaries and we want the
                                                              // address and data setup 1 clock early.  We know this can work as the RS232 debugger module
                                                              // holds the data and address for at least 1 clock.
      CMD_write_req[0] <=  DB232_wreq_dly && !CMD_W_busy[0] ; // 1 clock delayes write request.

      // Wire the 8 bit read port address.  When changing clock domains, we rely on a trick where the RS232 debugger keeps the
      // DB232_rreq high until it receives a result from the CMD_read_ready.  BrianHG_DDR3_CONTROLLER_top will see this as
      // many continuous requests at the same address and provide a continuous CMD_read_ready result as the internal
      // smart cache has only a clock cycle delay once the initial DDR Ram has been read.

      DB232_rreq_dly   <=  DB232_rreq                       ; // Create a delayed read request.  Same idea as above...
      CMD_read_req[0]  <=  DB232_rreq_dly && !CMD_R_busy[0] ; // Read request.
      CMD_raddr[0]     <= (PORT_ADDR_SIZE)'(DB232_addr)     ; // Set the RS232 read address.

      if (CMD_read_ready[0]) begin                        // If the read data is ready
     
         p0_data   <= 8'(CMD_read_data[0]) ; // Clean latch the read data.
         p0_drdy   <= 1 ;                    // Set the data ready flag
         
      end else
     
         p0_drdy   <= 0 ;
         
      end

   end // !reset

end // @CMD_CLK

I've already modified the RESET function at the top to clear ALL ports, not just Port 1, as we've got two ports now.  Hopefully that's right.

I'm going to have to duplicate the section for non-reset conditions (after the 'end else begin' midway through the code snippet) to wire the second port to the Z80_bridge.  If I insert something like this?

Code: [Select]
      // Wire the 8 bit write port.  We can get away with crossing a clock boundary with the write port.

      CMD_waddr[1]     <= (PORT_ADDR_SIZE)'(Z80_addr)       ; // Set the Z80 write address.
      CMD_wdata[1]     <= (PORT_CACHE_BITS)'(Z80_wdat)      ; // Set the Z80 write data.
      CMD_wmask[1]     <= (PORT_CACHE_BITS/8)'(1)           ; // 8 bit write data has only 1 write mask bit.     

      Z80_wreq_dly     <=  Z80_wreq                         ; // Delay the write request as we are crossing clock boundaries and we want the
                                                              // address and data setup 1 clock early.  We know this can work as the RS232 debugger module
                                                              // holds the data and address for at least 1 clock.
      CMD_write_req[1] <=  Z80_wreq_dly && !CMD_W_busy[1]   ; // 1 clock delays write request.

      Z80_rreq_dly     <=  Z80_rreq                         ; // Create a delayed read request.  Same idea as above...
      CMD_read_req[1]  <=  Z80_rreq_dly && !CMD_R_busy[1]   ; // Read request.
      CMD_raddr[1]     <= (PORT_ADDR_SIZE)'(Z80_addr)       ; // Set the Z80 read address.

      if (CMD_read_ready[1]) begin                        // If the read data is ready
     
         p1_data   <= 8'(CMD_read_data[1]) ; // Clean latch the read data.
         p1_drdy   <= 1 ;                    // Set the data ready flag
         
      end else
     
         p1_drdy   <= 0 ;
         
      end

Would that be okay or have I misunderstood something?

Also remember to remove all traces of your original RS232 debugger buried inside your GPU core.

I'll be honest, I'm not finding this easy working from HDL files instead of the graphical design we used previously for the EP4CE10 version of the GPU. :-/O

And, just in case, these are all your DDR3 controller interface IO ports:
...
Remember, all control inputs need to be wired to a control, or a 0 or 1.
Yes you need to pass some of the output from the Z80 bridge to the top of your GPU module to feed this new TOP where the DDR3 controller and new RS232 debugger exists.
Also, you may need to change where I wired the new RS232 debugger's RXD/TXD to your chosen IOs.

Righto.  They need to be interfaced to the Z80_bridge, so are we bypassing the data_mux_geo as the DDR3_Controller has two ports?

I actually don't have RXD/TXD set up on the current DECA interface card.  I've ordered an updated PCB that brings out all the spare IOs to a header and also provides a TXD/RXD port for the debugger, both raw and via a CH340 if I don't have a spare RS232/TTL handy.  In the meantime, I can just hotwire the RXD/TXD IOs up to a loose header and hot-glue it to the PCB.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 30, 2021, 08:59:11 am
The Z80 write/output still goes to the MUX so you can write to FPGA core ram in parallel with the DDR3.

Yes, my multiport has a separate read and write port.
IE, if the Z80 bridge has a single address output, you will wire that to both the read and write addr [ 1 ].
Next you have the read and write req ports, IE read / write enable.

OOops, I forgot, you are running your code on a separate PLL.

Ok, we got a new problem.  I was going to say you did not need the delays I have in my example code as they were put there for clock domain crossing.  This really craps everything up.

Your current core needs 125 and 250MHz and this is the speed coming out of your Z80 bridge.  But, running the DDR3 at 400MHz means my IO ports are running at 100Mhz.  A slower speed.  To be 1:1 compatible, you need tyo run the ram at 250MHz in half mode, or 500MHz in quarter mode.

Ok, let's try the overclock method.
This now means that you need to remove your PLL in your GPU and use the following 2 clocks coming out of my design to replace them.

First change this line:
Code: [Select]
parameter int        CLK_IN_MULT             = 32,               // Multiply factor to generate the DDR MTPS speed divided by 2.
parameter int        CLK_IN_DIV              = 4,                // Divide factor.  When CLK_KHZ_IN is 25000,50000,75000,100000,125000,150000, use 2,4,6,8,10,12.
to:
Code: [Select]
parameter int        CLK_IN_MULT             = 40,               // Multiply factor to generate the DDR MTPS speed divided by 2.
parameter int        CLK_IN_DIV              = 4,                // Divide factor.  When CLK_KHZ_IN is 25000,50000,75000,100000,125000,150000, use 2,4,6,8,10,12.

This will make the DDR3 run at 500MHz.

Disable your PLL in your GPU and now, these will be your clock signals:
DDR3_CLK      = 500MHz.
DDR3_CLK_50 = 250MHz.  -> This will new feed your GPU 'clk_2x'
DDR3_CLK_25 = 125MHz.  ->  This will new feed your GPU 'clk'
DDR3_CLK_25 = 125MHz.  ->  This will new feed your GPU 'clk_2x_phase' *** you may need to invert this one.
CLK_IN           = 50MHz    -> This will feed your GPU 'com_clk'

As for your code, it should look like this:
Code: [Select]
      CMD_waddr[1]       <= (PORT_ADDR_SIZE)'(gpu_addr)       ; // Set the Z80 write address.
      CMD_wdata[1]       <= (PORT_CACHE_BITS)'(gpu_wdata)      ; // Set the Z80 write data.
      CMD_wmask[1]      <= (PORT_CACHE_BITS/8)'(1)           ; // 8 bit write data has only 1 write mask bit.     
      CMD_write_req[1]  <=  gpu_wr_ena                         ;
 
      CMD_read_req[1]  <=  gpu_rd_req ;
      CMD_raddr[1]      <= (PORT_ADDR_SIZE)'(gpu_addr)       ; // Set the Z80 read address.

      gpu_rd_rdy         <= CMD_read_ready[1] ;
      gpu_rData[7:0]     <= 8'(CMD_read_data[1]) ;
*** The net labels I listed above are what you called them on the Z80 bridge.


Now, I did not touch the 'R/W_busy' for now which in combination with waiting for the ' CMD_read_ready[ 1 ] ' will drive the Z80 hold.  This will be added to the Z80 bridge code.

Now, about overclocking the DDR3 to 500MHz.  The true goal is to get it back down to 400MHz and make an asynchronous VGA section which will have the 25MHz for the video pixel clock.  The means your GPU core will slow down to 100MHz and 200MHz, but, just the final VGA output section will have it's own 25MHz clock with it's own PLL done in the same way I did my random bouncing ellipse demo.

I'm sorry about the missing graphic view you are used to.  Beginning that way has made you unfamiliar with the module net names.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 30, 2021, 09:38:58 am
 :palm:  I mean your code should look like:

Code: [Select]
always_comb begin
      CMD_waddr[1]       = (PORT_ADDR_SIZE)'(gpu_addr)       ; // Set the Z80 write address.
      CMD_wdata[1]       = (PORT_CACHE_BITS)'(gpu_wdata)      ; // Set the Z80 write data.
      CMD_wmask[1]      = (PORT_CACHE_BITS/8)'(1)           ; // 8 bit write data has only 1 write mask bit.     
      CMD_write_req[1]  =  gpu_wr_ena                         ;
 
      CMD_read_req[1]  =  gpu_rd_req ;
      CMD_raddr[1]      = (PORT_ADDR_SIZE)'(gpu_addr)       ; // Set the Z80 read address.

      gpu_rd_rdy          = CMD_read_ready[1] ;
      gpu_rData[7:0]    = 8'(CMD_read_data[1]) ;
end

This is direct wiring, no clock delay.

assign x = y ; on every line
instead of always_comb will also work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2021, 09:51:56 am
Your current core needs 125 and 250MHz and this is the speed coming out of your Z80 bridge.  But, running the DDR3 at 400MHz means my IO ports are running at 100Mhz.  A slower speed.  To be 1:1 compatible, you need tyo run the ram at 250MHz in half mode, or 500MHz in quarter mode.

Ok, let's try the overclock method.
This now means that you need to remove your PLL in your GPU and use the following 2 clocks coming out of my design to replace them.

First change this line:
Code: [Select]
parameter int        CLK_IN_MULT             = 32,               // Multiply factor to generate the DDR MTPS speed divided by 2.
parameter int        CLK_IN_DIV              = 4,                // Divide factor.  When CLK_KHZ_IN is 25000,50000,75000,100000,125000,150000, use 2,4,6,8,10,12.
to:
Code: [Select]
parameter int        CLK_IN_MULT             = 40,               // Multiply factor to generate the DDR MTPS speed divided by 2.
parameter int        CLK_IN_DIV              = 4,                // Divide factor.  When CLK_KHZ_IN is 25000,50000,75000,100000,125000,150000, use 2,4,6,8,10,12.

This will make the DDR3 run at 500MHz.

All done. :-+

Disable your PLL in your GPU and now, these will be your clock signals:
DDR3_CLK      = 500MHz.
DDR3_CLK_50 = 250MHz.  -> This will new feed your GPU 'clk_2x'
DDR3_CLK_25 = 125MHz.  ->  This will new feed your GPU 'clk'
DDR3_CLK_25 = 125MHz.  ->  This will new feed your GPU 'clk_2x_phase' *** you may need to invert this one.
CLK_IN           = 50MHz    -> This will feed your GPU 'com_clk'

Okay, I've removed the altpll0 instance (b2v_inst17) from GPU.sv and added the clock outputs it produced as inputs on GPU.sv and wired as below:

Code: [Select]
) GPU_CORE (

   //.clk54m      ( MAX10_CLK1_50 ),
.clk         ( DDR3_CLK_25   ),
.clk_2x      ( DDR3_CLK_50   ),
.clk_2x_phase( !DDR3_CLK_25  ),
.com_clk     ( CLK_IN        ),

I'm sorry about the missing graphic view you are used to.  Beginning that way has made you unfamiliar with the module net names.

Oh don't apologise, it's just me finding it easier to look at an image with wires linking modules rather than blocks of HDL and trying to search for wire names between modules.  I see why we switched to HDL instead of design view - I loaded up the EP4CE10 project earlier to help my understanding and it took a full 20 seconds or so to open the GPU.bdf file.  I still feel you can't beat a visual representation, but it's personal preference I guess.

:palm:  I mean your code should look like:

Code: [Select]
always_comb begin
      CMD_waddr[1]       = (PORT_ADDR_SIZE)'(gpu_addr)       ; // Set the Z80 write address.
      CMD_wdata[1]       = (PORT_CACHE_BITS)'(gpu_wdata)      ; // Set the Z80 write data.
      CMD_wmask[1]      = (PORT_CACHE_BITS/8)'(1)           ; // 8 bit write data has only 1 write mask bit.     
      CMD_write_req[1]  =  gpu_wr_ena                         ;
 
      CMD_read_req[1]  =  gpu_rd_req ;
      CMD_raddr[1]      = (PORT_ADDR_SIZE)'(gpu_addr)       ; // Set the Z80 read address.

      gpu_rd_rdy          = CMD_read_ready[1] ;
      gpu_rData[7:0]    = 8'(CMD_read_data[1]) ;
end

This is direct wiring, no clock delay.

assign x = y ; on every line
instead of always_comb will also work.

No worries. Teams meeting in 10, so won't be able to do much more until this afternoon, but will take a look at this and passing through the appropriate connections from the Z80_bridge to the top level then. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2021, 10:18:30 am
Yep. There won't be any difference as far as I2S is concerned - just be aware that any 24-bit or higher DAC these days will take 32-bit data sample through I2S (64-bit data per stereo frame), with the lower unused bits ignored. Some (now less common) 16-bit DACs may only take 16-bit data sample/32-bit per frame, so regarding I2S, that would be your incompatibility here. But if you stick to 24-bit or higher DACs, then it will be basically plug and play as far as I2S is concerned.
Typically this doesn't matter because there is always quite a bit of "nothingness" at the tail end of each channel's sample value, so higher-resolution DAC will recognize these as trailing zeros.

Differences may be with how the chips are configured (hardware config via pins, software config via I2C or SPI...), the master clock, but those can be handled separately. As far as I remember, the PCM5102 (probably 5102A as the 5102 is now obsolete if I'm not mistaken) can generate the master clock internally from the I2S bit clock, so it's very easy to interface.
That stuff usually boils down to find a table in the datasheet which tells you what values you need to assign to config pins/config interface registers to get the mode and frequency you want. So it's a one-time task (unless you need to change these on the fly, which is quite rare) for a specific P/N.
The cool part is that some newer DACs (for example CS4344) will auto-detect sampling frequency, so that means less configuration hassle.

Yes, the PCM5102A can generate an internal master clock.  I'm happy interfacing the FPGA with the DAC and sorting out I2S (at least it sounds easy enough and there's HDL examples about), my only concern is matching the output from the YM2149 HDL module to a serial signal the DAC will accept.  I haven't really looked in any detail at this yet (it's a little further down the task list, after getting the GPU and DDR3 working how we want), but I'll need to go take a close look at the YM2149 HDL module and see what it outputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 30, 2021, 05:55:25 pm
Okay, there's probably wiring errors and more things I need to do (I think I still need to do something with the DDR3 Controller wiring logic?) but it builds with no errors, which is a start. :-/O

Takes 3 min 32 seconds, uses 18,533 LEs and 10,582 registers.

Attached files for info.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 30, 2021, 11:23:42 pm
Ok, really minor addition for the DDR3 controller, see the last 3 lines (just to makes things implicit):

Code: [Select]
assign   CMD_waddr[1]            = (PORT_ADDR_SIZE)'(gpu_addr)   ; // Set the Z80 write address.
assign   CMD_wdata[1]            = (PORT_CACHE_BITS)'(gpu_wdata) ; // Set the Z80 write data.
assign   CMD_wmask[1]            = (PORT_CACHE_BITS/8)'(1)       ; // 8 bit write data has only 1 write mask bit.     
assign   CMD_write_req[1]        = gpu_wr_ena                    ;
assign   CMD_read_req[1]         = gpu_rd_req                    ;
assign   CMD_raddr[1]            = (PORT_ADDR_SIZE)'(gpu_addr)   ; // Set the Z80 read address.
assign   gpu_rd_rdy              = CMD_read_ready[1]             ;
assign   gpu_rData               = 8'(CMD_read_data[1])          ;

assign   CMD_read_vector_in[1]   = 0 ; // When not in use, just set to 0.
assign   CMD_R_priority_boost[1] = 0 ; // When not in use, just set to 0.
assign   CMD_W_priority_boost[1] = 0 ; // When not in use, just set to 0.

Also, in GPU.sv, you will need to check lines:
274,312,291,292, 425,426
Remember, you still want to feed the Z80 -> mux geo writes (FPGA blockram and control registers will shadow the DDR3), but, the reads will exclusively come from the DDR3.

I know these modules IO ports are un-sorted due to the auto-generated nature of having Quartus generate the GPU.sv.  I think you should vertically sort and group each module's IOs so it is much easier to deal with.

IE, for the 'Z80_bridge_v2', group sort the IO into all the Z80 IOs (sort these too), then double space with a comment and group the GPU ram IO port, then double space and comment and add the geometry access port, then double space and comment and add the keyboard port, sound port...

Do the same for the data_mux_geo, space out and have first all of port a IOs, port B IOs, geo port IOs, gpu core ram IOs.

Reading and debugging will really help once this is done.
I noticed your keyboard isn't connected, how do you type?

(*My time might become very limited after next week, so, now is the time to get everything to work...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 01, 2021, 03:22:24 pm
Sorry for delay replying, have had a busy day.

Also, in GPU.sv, you will need to check lines:
274,312,291,292, 425,426
Remember, you still want to feed the Z80 -> mux geo writes (FPGA blockram and control registers will shadow the DDR3), but, the reads will exclusively come from the DDR3.

Okay, bit confused about all this.  Doesn't line 281 also need to be changed?  For some reason I'm having trouble with this - Z80_WR_data seems to be non-existent now (I've commented-out the only mention of it).  I'm worried I'm losing the thread of which wires went where and which I need to change and which need to be kept.  I think Z80_WR_data was a remnant from the EP4CE10 project.  Either way, I'm going to have to take a look at this with fresh eyes in the morning, I think.  :o

So to check my understanding, let's look at line 274.  Z80_rd_rdy signals to the Z80_bridge that data is ready from block RAM for the Z80 to read.  I need to replace this wire with p1_drdy from GPU_DECA_DDR3_top.sv?

I noticed your keyboard isn't connected, how do you type?

I use the serial console - it's quicker than messing around digging out the keyboard and plugging it in every time I have five minutes to work on it.  EDIT:  Plus, there's no PS2 connector on the DECA.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 01, 2021, 10:49:48 pm
My recommendation is to document as comments EXACTLY what each of these IO ports actually do and where they go:

Code: [Select]
Z80_bridge_v2  b2v_inst10(
   .reset             ( reset          ),
   .GPU_CLK           ( clk            ),
   .Z80_CLK           ( Z80_CLK        ),
   .Z80_M1n           ( Z80_M1         ),
   .Z80_MREQn         ( Z80_MREQ       ),
   .Z80_WRn           ( Z80_WR         ),
   .Z80_RDn           ( Z80_RD         ),
   .gpu_rd_rdy        ( Z80_rd_rdy     ),
   .sel_pclk          ( out3[7]        ),
   .sel_nclk          ( out3[6]        ),
   .PS2_RDY           ( PS2_DAT_RDY    ),
   .Z80_IORQn         ( Z80_IORQ       ),
   .Z80_IEI           ( IEI            ),
   .GEO_STAT_RD       ( geo_stat_rd    ),
   .gpu_rData         ( dat_to_Z80     ),
   .PS2_DAT           ( key_dat        ),
   .PS2_STATUS        ( DFF_inst33     ),
   .RD_PX_CTR         ( collision_rd   ),
   .WR_PX_CTR         ( collision_wr   ),
   .Z80_addr          ( Z80_ADDR       ),
   .Z80_wData         ( Z80_data       ),
   .Z80_245data_dir_r ( DIR_245        ),
   .Z80_rData_ena_r   ( data_en        ),
   .Z80_245_oe_r      ( OE_245         ),
   .gpu_wr_ena        ( gpu_wr_enable  ),
   .gpu_rd_req        ( gpu_rd_request ),
   .Z80_INT_REQ_r     ( Z80_INT_RQ     ),
   .Z80_WAIT          ( Z80_WAIT       ),
   .Z80_IEO_r         ( IEO            ),
   .EA_DIR_r          ( EA_DIR         ),
   .EA_OE_r           ( EA_OE          ),
   .SPKR_EN           ( SP_EN          ),
   .VIDEO_EN          ( video_en       ),
   .snd_data_tx       ( snd_data_tx    ),
   
   .GEO_WR_HI_STROBE ( send_geo_cmd    ),
   .WR_PX_CTR_STROBE ( wr_px_ctr_rs    ),
   .RD_PX_CTR_STROBE ( rd_px_ctr_rs    ),
   
   .GEO_STAT_WR      ( geo_stat_wr     ),
   .GEO_WR_HI        ( geo_cmd[15:8]   ),
   .GEO_WR_LO        ( geo_cmd[7:0]    ),
   .gpu_addr         ( gpu_addr        ),
   .gpu_wdata        ( gpu_wdata       ),
   .snd_data         ( snd_data        ),
   .Z80_rData_r      ( Z80_RD_data     )
);

Then sort and group them like I told you to in my lat post.  This should help you out.

Remember, you want the Z80 write to GPU ram to feed the DDR3 and the current MUX port.  But for the Z80 reads, you no longer need to activate the MUX port, but have the DDR3 respond to the read request and have the DDR3 send the response to the Z80 bridge.

Also, do the same for the:

Code: [Select]
data_mux_geo   b2v_inst25(
   .clk           ( clk            ),
   .reset         ( reset          ),
   .wr_ena_a      ( gpu_wr_enable  ),
   .rd_req_a      ( gpu_rd_request ),
   .wr_ena_b      ( 1'b0           ), // RS232_wr_ena
   .rd_req_b      ( 1'b0           ), // RS232_rd_req
   .geo_rd_req_a  ( geo_rd_req_a   ),
   .geo_rd_req_b  ( geo_rd_req_b   ),
   .geo_wr_ena    ( geo_wr_ena     ),
   .address_a     ( gpu_addr       ),
   .address_b     (                ), // RS232_addr
   .address_geo   ( geo_ram_addr   ),
   .data_in_a     ( gpu_wdata      ),
   .data_in_b     (                ), // RS232_wDat
   .data_in_geo   ( geo_wr_data    ),
   .gpu_data_in   ( h_rdat         ),
   .gpu_wr_ena    ( h_wena         ),
   .gpu_ena_16bit ( h_16bit        ),
   .gpu_rd_rdy_a  ( Z80_rd_rdy     ),
   .gpu_rd_rdy_b  ( 1'b0           ), // RS232_rd_rdy
   .geo_rd_rdy_a  ( geo_rdy_a      ),
   .geo_rd_rdy_b  ( geo_rdy_b      ),
   .geo_port_full ( geo_port_full  ),
   .data_out_a    ( dat_to_Z80     ),
   .data_out_b    (                ), // RS232_rDat
   .data_out_geo  ( geo_r_data     ),
   .gpu_address   ( h_addr         ),
   .gpu_data_out  ( h_wdat         )
);

Now, I want real explanations exactly like all the notes I have at every port inside my DDR3 source code.  And I want those ports sorted and bundled by function.  (Only sort vertically, you do not need to do the fancy 'tabs' which I have done because of the huge number of ports in my design)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 02, 2021, 03:06:04 pm
See attached update to GPU.sv.  Have added comments for the data_mux_geo module and Z80_bridge, as well as possibly some others as I'm working my way through the entire module. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2021, 01:45:21 am
Ok, I re-did you Z80_bridge section.  Tell me if this will help you properly wire the DDR3 ram controller.
Sadly, the port names used could have been better chosen, but the way grouped the ports and simplified their descriptions should help.

If not, you may need to cleanly label a bit more from the Data_mux_geo.

Beginning on line 196, you basically need to focus on lines 240-250 :    // *** Z80 <-> GPU RAM Access ***

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2021, 10:38:57 am
Okay, here's my first attempt at wiring up the DDR3_Controller as suggested.  The Z80's writes should be duplicated to both the DDR3_Controller AND block RAM, with reads only coming from the DDR3_Controller.

I've disconnected rd_req_a from data_mux_geo, so any read requests by the Z80 will be ignored by block RAM.

Lines 708-758 handle the connection to the DDR3_Controller.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2021, 10:48:40 am
Well?
Does it do anything?

When disabling an input port control, do not:
Code: [Select]
//.rd_req_a      ( gpu_rd_request ), // When HIGH, Z80_Bridge is signalling a valid address on address_a input and requesting a READ to the Z80.

Instead do this:
Code: [Select]
.rd_req_a      ( 1'b0 ), // When HIGH, Z80_Bridge is signalling a valid address on address_a input and requesting a READ to the Z80.

You want to be certain that the control is disabled and that for whatever reason, the default set for an undefined port may possibly be a 1 instead of a 0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2021, 11:11:33 am
Lines 708-758 handle the connection to the DDR3_Controller.
The attached code is only 674 lines long...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2021, 11:32:40 am
Lines 708-758 handle the connection to the DDR3_Controller.
The attached code is only 674 lines long...

Yeah, not sure what happened but it seems I pasted the wrong code into the file attachment.  I've attached both gpu.sv and GPU_DECA_DDR3_top.sv to this post.  It's GPU_DECA_DDR3_top that has the changes to connect up the DDR3.  I've attached GPU.sv for info in case you need it to cross-reference any connections.

Well?
Does it do anything?

Don't know yet - I'd assumed there'd be a multitude of errors and changes required, so I haven't tested it. :-//

When disabling an input port control, do not:
Code: [Select]
//.rd_req_a      ( gpu_rd_request ), // When HIGH, Z80_Bridge is signalling a valid address on address_a input and requesting a READ to the Z80.

Instead do this:
Code: [Select]
.rd_req_a      ( 1'b0 ), // When HIGH, Z80_Bridge is signalling a valid address on address_a input and requesting a READ to the Z80.

You want to be certain that the control is disabled and that for whatever reason, the default set for an undefined port may possibly be a 1 instead of a 0.

There's a line like that in the GPU.sv code, but immediately below it is the line you're pointing out that it should be.  I commented-out the first connection to .rd_req_a so that I could easily see what was connected to, if I needed to change it later.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2021, 11:44:17 am
Why do you have all that BS code from lines 709 to 758?

Why is it there?

What happened to the 'assign's, or, just placing the correct ' CMD_R/W_*** ' right inside the brackets  ' .gpu_*** ( CMD_R/W_*** ) ' of lines 507-517?

Why do you keep on complicating things beyond belief?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2021, 01:20:34 pm
I forgot that the RS232 interface was crossing a clock domain but presumably the Z80_bridge doesn't, hence all the extra gubbins at the end of the file.

Attempt 2 attached.

Lines 508-509 are where the DDR3_Controller data out connects to the GPU.sv module.
Lines 513-517 are unchanged from the GPU, but...
...lines 458-465 connect the GPU to the DDR3_Controller for writes and read requests, allowing sharing of the lines with the existing block RAM via data_mux_geo.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 03, 2021, 07:34:12 pm
Well, if you have lines 464 & 465, then, you may place the wires in lines 509-509.

Why didn't you declare wires for gpu_addr, gpu_wdata, gpu_wr_ena, & gpu_rd_req like you did for gpu_rd_rdy and gpu_rData at lines 455 & 456?

Quote
...lines 458-465 connect the GPU to the DDR3_Controller for writes and read requests, allowing sharing of the lines with the existing block RAM via data_mux_geo.

No, the sharing with the data_mux_geo happens inside the GPU.sv.
Inside GPU.sv, lines 52 isn't wired anywhere, and I didn't even need a compiler to tell me this. m You have a typo at line 162.


Get this working...


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 03, 2021, 10:10:29 pm
Why didn't you declare wires for gpu_addr, gpu_wdata, gpu_wr_ena, & gpu_rd_req like you did for gpu_rd_rdy and gpu_rData at lines 455 & 456?

Ah I missed those declarations.  The project compiled as well - I guess Quartus just inferred the connections as wires?

Inside GPU.sv, lines 52 isn't wired anywhere, and I didn't even need a compiler to tell me this. m You have a typo at line 162.

The typo is the cause for line 52 not going anywhere, then.  Are there any other connection issues?  I'll have a little more time tomorrow to test the project on the hardware.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Wilksey on October 03, 2021, 11:35:08 pm
I've not read the entire thread, at 110 pages i'd be here a while, but Grant has his pages here: http://searle.wales/ (http://searle.wales/) apologies if you already have this link.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 12:08:31 am
I've not read the entire thread, at 110 pages i'd be here a while, but Grant has his pages here: http://searle.wales/ (http://searle.wales/) apologies if you already have this link.

Nockieboy would have been happy with Grant Searle's Z80 GFX board only up to around then end of his opening post [HINT] of this thread...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 12:15:53 am
Why didn't you declare wires for gpu_addr, gpu_wdata, gpu_wr_ena, & gpu_rd_req like you did for gpu_rd_rdy and gpu_rData at lines 455 & 456?

Ah I missed those declarations.  The project compiled as well - I guess Quartus just inferred the connections as wires?

Inside GPU.sv, lines 52 isn't wired anywhere, and I didn't even need a compiler to tell me this. m You have a typo at line 162.

The typo is the cause for line 52 not going anywhere, then.  Are there any other connection issues?  I'll have a little more time tomorrow to test the project on the hardware.
Without a full project and Z80, I cannot tell you much more.
Check all Quartus warnings.
Do not let it infer  wires as it makes mistakes there when dealing with multiple bit wide wires.

Get past this as you need to deal with adding and testing the 'WAIT' next.
Then you will need to decide how to re-incorporate the geometry unit and handle / create a new MAGGIE architecture for the DDR3.
There is a ton of work needed to upgrade the 12bit coordinate system to 16bit and upgrade the 20 bit address system to at least 30bit if not 32bit.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 08:20:36 am
Without a full project and Z80, I cannot tell you much more.

Check all Quartus warnings.

I'll attach the latest project shortly.  I'm just working through the Quartus warnings.  I've found this one which makes me wonder if there's a long-dormant mistake in the MAGGIE?

Warning (10036): Verilog HDL or VHDL warning at maggie.sv(69): object "inc_addr_x" assigned a value but never read

After checking the maggie.sv module - inc_addr_x is a 16-bit wire declared at the start of the module, with the first 4 bits assigned a value of hw_regs[X_SCALE][7:4], but that's the last time it's mentioned.  Shouldn't it be used here?
Code: [Select]
Line 176: if (font_y_pos == font_y_size) begin
Line 177:        ram_read_pointer_y   <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 - pixel_16_bit));  // vertical increment display position in backup buffer
Line 178:        ram_read_pointer_x   <= ram_read_pointer_y + (inc_addr_y[15:0] << (3 - pixel_16_bit));  // vertical increment display position in current display address

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 08:27:53 am
I don't think so based on the comments.

What about the Z80 <-> DDR3 ?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 08:45:38 am
Latest version of project attached.  Compiles successfully.  Was part-way through checking the warnings, so still have some more to check. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 08:46:24 am
Is the DDR3 working?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 09:22:47 am
Is the DDR3 working?

No - at boot up, I'm getting a blank screen with just the two HW trigger lines on the screen - so no screen setup information is getting to the GPU.  There's not even any image or ASCII text appearing on the screen either.

On the DECA, LED2-LED7 are illuminated.

EDIT:  2nd attempt, LED3-LED7 are illuminated.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 09:29:13 am
Ok, the DDR3 booted properly.

Next, the GPU, remember I told you to:

Code: [Select]
assign clk_2x_phase = clk ;
well, make it:
Code: [Select]
assign clk_2x_phase = !clk ;
If that doesn't work, then better:

Code: [Select]
always_ff @(posedge clk_2x) begin
clk_2x_phase <= !clk_2x_phase ;
end

or:

Code: [Select]
always_ff @(posedge clk_2x) begin
if (reset) clk_2x_phase  <= 0;
else clk_2x_phase <= !clk_2x_phase ;
end

or:

Code: [Select]
always_ff @(posedge clk_2x) begin
if (reset) clk_2x_phase  <= 1;
else clk_2x_phase <= !clk_2x_phase ;
end

or

Code: [Select]
always_ff @(posedge clk_2x) begin
clk_2x_phase <= !clk ;
end

or

Code: [Select]
always_ff @(posedge clk_2x) begin
clk_2x_phase <= clk ;
end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 09:33:30 am
In GPU_DECA_DDR3_top, I'd done this on line 489:
Code: [Select]
.clk_2x_phase( !DDR3_CLK_25  ),
Would that not do the same thing?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 09:34:24 am
Try in reverse order...
The last simple one first:

Code: [Select]
always_ff @(posedge clk_2x) begin
clk_2x_phase <= clk ;
end
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 09:35:54 am
the clk_2x_phase needs to be driven by a DFF clocked on the clk_2x domain for proper operation.

It just may need inverting, so you might need to make it <= !clk.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 09:46:14 am
Try in reverse order...
The last simple one first:

Code: [Select]
always_ff @(posedge clk_2x) begin
clk_2x_phase <= clk ;
end

Okay, tried this one first.  This is the result with the above code added to gpu.sv.

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 09:49:11 am
Did you get the same without the DDR3?

Maybe try the inverted version.

Is the GPU still locked up, or, is it that just the graphics are messed up now.

Does your current code rely on reading GPU data?  Or is it all write only?

Some DDR3 reads may be messed up without the 'WAIT' command setup.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 09:51:00 am
Did you get the same without the DDR3?

Without DDR3 it worked fine - full screen.

Maybe try the inverted version.

Okay, compiling for this right now.

Is the GPU still locked up, or, is it that just the graphics are messed up now.

No, not locked up at all.  Working almost fine, it seems - I can see screen text scrolling in that little top-left window etc. and behaving as I would expect it if it were working properly.

Will update in a sec with the results of the inverted clock build.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 09:56:52 am
With the inverted clock, I'm getting nothing but the HW trigger lines.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 09:58:12 am
Does your current code rely on reading GPU data?  Or is it all write only?

Some DDR3 reads may be messed up without the 'WAIT' command setup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 10:13:09 am
Does your current code rely on reading GPU data?  Or is it all write only?

Some DDR3 reads may be messed up without the 'WAIT' command setup.

Not really, no.  The only GPU data that is read is the BANK_ID string at the very top of GPU RAM.  Everything else is written to the RAM, unless there's some obscure routine that I've forgotten about, but at these early stages in the uCOM boot, the first page of GPU RAM is just cleared and a set of specific values are written to set up the HW registers, trigger values and MAGGIEs to display text-tiled mode initially, then full graphics mode with blitted characters when I get into the DMI or CP/M (both of which show up in the top corner and scroll perfectly as well).

I've just compiled the non-inverted clk version again and uploaded it to the GPU.  As soon as the JTAG upload has finished, the uCOM hangs as it usually does when I program the GPU but the screen displays the Z80 chip image, character set table and multi-colour text title perfectly.

When I reset the uCOM, I just get the HW trigger lines and part of the video display in that top-left corner.  When I go into the DMI and take a look at the first page of the GPU RAM (via the serial console) (the first page of GPU DDR3 RAM, in reality), it just gives me a page of $7Es, or bad reads basically.  Looks like something is going wrong due to the reads not returning true values, and that I need to get WAITs running?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 10:24:31 am
If you read the same address twice, the second read should be correct as that read would have been cached and responded as fast as a core ram read.

Same goes for reads within the same 16 byte block.

Can you run the RS232 debugger to see what is inside the DDR3 ram?

Seeing that the graphics are in the wrong place, but you are getting text there means writes to the FPGA core are making it and if that text I saw was blitter generated, this means the geo unit is still accessing the core ram.

You can try a dummy 'WAIT' just to give time for my controller to give you the right data.  But if you are reading sequential bytes, the answer should eventually change from 1 value.
 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 10:26:18 am
Can you setup the SignalTap to monitor the ' Z80 <-> DDR3 ' read and write bus?

Try sending me the latest project after you run the above tests.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 11:06:51 am
If you read the same address twice, the second read should be correct as that read would have been cached and responded as fast as a core ram read.

I'll have to go to the metal and write an assembly program to test that as my tests in the DMI all write to GPU inbetween successive reads to the GPU, unfortunately, which probably throws the cache.  What I'm seeing is the same value repeated - $7E - for all values read.

The BANK_ID is being returned properly, however.

Can you run the RS232 debugger to see what is inside the DDR3 ram?

This will require some hardware modification to the interface card.  Won't be able to do this until later (or tomorrow, possibly).

Seeing that the graphics are in the wrong place, but you are getting text there means writes to the FPGA core are making it and if that text I saw was blitter generated, this means the geo unit is still accessing the core ram.

Yes, that first image was using blitted text.  This next one shows the DMI in text-tile mode, but clearly shows that the third MAGGIE is being properly set up to display the 'Z80 Inside' logo.

[attach=1]

You can try a dummy 'WAIT' just to give time for my controller to give you the right data.  But if you are reading sequential bytes, the answer should eventually change from 1 value.

Well, yes, it should do - it looks more like a Z80 interface timing issue?  The Z80 is reading the data bus but valid data isn't there at the right time?

I've attached the latest project below, including (very) basic setup of a SignalTap.  Please excuse any issues with the SignalTap setup - I've literally thrown it together as I'm doing three different things at once.  One thing I've noticed is that the timescale seems to be picoseconds, which doesn't produce many meaningful results.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 11:32:43 am
You have typos in 'GPU.sv', lines 260-262...
Your read is still wired to the FPGA core ram.

First enable line 334 and see if everything works like it used to.  It should, or, something else went wrong.

If everything now works ok, we then know your Z80 code is reading some memory from the GPU.

Verify DDR3 contents with RS232 debugger, or verify writes using the SignalTap connected to the CMD_CLK, CMD_R/W_REQ as triggers, and monitor the CMD_R/W address and data for channel [ 1 ].

Arrrg, you didn't vertically group sort the 'data_mux_geo' IO ports.  It makes following things disruptively difficult.

Next, fix lines 260-262 so it is connected to the DDR3 read port.
Just assign the old ' gpu_rd_request = 0 ' to disable the read from the data_mux_geo.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 03:32:19 pm
Latest GPU.sv attached, with grouped input/output for the data_mux_geo to (hopefully) make troubleshooting a little easier.

Think I found the issue with the reads - haven't tested it yet, but looks like I've still got the gpu_rd_rdy input on the Z80_bridge connected to the data_mux_geo's gpu_rd_rdy_a output.  Replacing this:

Code: [Select]
   .gpu_rd_rdy        ( Z80_rd_rdy     ), // INPUT:  Read request data byte is ready / valid input.
   .gpu_rData         ( dat_to_Z80     ), // INPUT:  Read request GPU RAM returned 8 bit data byte.

with this:

Code: [Select]
   .gpu_rd_rdy        ( gpu_rd_rdy     ), // INPUT:  Read request data byte is ready / valid input.
   .gpu_rData         ( gpu_rData      ), // INPUT:  Read request GPU RAM returned 8 bit data byte.

in GPU.sv.  This results in the following - the DMI is actually able to read SOME memory, but looks like only the first half of a page.

[attach=2]

And if you look closely, you'll see the first byte of each 16-byte row is $7E (the value the uCOM seems to give for a bad read by chance), but remaining bytes in each row has a valid value, so it looks like the DDR3 is returning values, just not in time for the first 'non-cache' hit.  All those $B0's should be $00s.

[attach=3]

There's random 'snow' on the screen, too - with some odd 'noise'-type effects in vertical columns down the screen, as seen below.  These are not static, they're 'animated', looking exactly like an interference pattern or static on a badly-tuned analogue TV image.

[attach=4]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 03:48:05 pm
Strange.  The display has no connection to the DDR3.  It is currently exclusively 100% core FPGA memory.

Maybe we stressed the core's FMAX too high.

Or, it is the:
Code: [Select]
always_ff @(posedge clk_2x) begin
clk_2x_phase <= clk ;
end

In the original PLL code, I had a special phase setup to feed the clk_2x_phase which does not exist here.

There are 2 things to try...

a)  Try both a '1' and a '0'.
Code: [Select]
always_ff @(posedge clk_2x) begin
if (reset) clk_2x_phase  <= 1 ;
else clk_2x_phase <= !clk_2x_phase ;
end

b)  Switch compiler to Optimization mode to 'Performance - High Effort'.

If A & B doesn't work, then we will slow down the DDR3 PLL to 400MHz and test, though, you video out will be 48Hz instead of 60Hz.  The compiler may be trying too hard to reach the impossible 500 MHz and it is ignoring some crucial paths down at the 250MHz and 125MHz.  If your monitor cannot sync up to 48 Hz, we can also try 250Mhz and run the DDR3 in half speed mode instead of quarter speed mode.

(The odd video frame rate will be temporary as we upgrade the video output path.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 04:23:10 pm
In the original PLL code, I had a special phase setup to feed the clk_2x_phase which does not exist here.

There are 2 things to try...

a)  Try both a '1' and a '0'.
Code: [Select]
always_ff @(posedge clk_2x) begin
if (reset) clk_2x_phase  <= 1 ;
else clk_2x_phase <= !clk_2x_phase ;
end

Okay, with a '1', the display initially shows a corrupted version of the initial RAM contents (the Z80 CPU image), then reverts back to just the HW trigger lines and a tiny portion of the (blitted-text) screen in the top-left quadrant.  No 'snow' or interference though, what I can see is clean.

Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C010 7E 10 B0 10 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C020 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C030 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C040 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C050 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C060 7E B0 0F B0 12 B0 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 7E 01 0F B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C080 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C090 FE B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0A0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0B0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0C0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0D0 FE B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0E0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0F0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
Page dump from the first page of RAM returned by the GPU.

With a '0', I get a 'snow'-free display, nice clear 'test page' with the initial memory image and character set, but when the uCOM tries to set up the screen how it wants, it just goes black with the HW trigger lines.  The first page of GPU RAM (DDR3) indicates that 0x00's are being read as 0xB0s, with the usual 0x7E for the first byte in each row.  Values that have been set by the uCOM are being read okay, it's just the rest of the page that's 0xB0's. :-//

Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C010 7E 10 B0 10 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C020 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C030 FE B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C040 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C050 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C060 7E B0 0F B0 12 B0 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 7E 01 0F B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C080 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C090 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0A0 FE B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0B0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0C0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0D0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0E0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0F0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
Page dump from the first page of RAM returned by the GPU.

Let me know if you want me to continue on to the B) test, but at the moment it doesn't seem it'll be of much value.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 04:34:20 pm
The corrupt snow is because the FPGA cannot reach the requested speed along certain critical paths.

Revert the clk_2x_phase and try slowing down the system:

Code: [Select]
// ****************  System clock generation and operation.
parameter int        CLK_KHZ_IN              = 50000,            // PLL source input clock frequency in KHz.
parameter int        CLK_IN_MULT             = 32,               // Multiply factor to generate the DDR MTPS speed divided by 2.
parameter int        CLK_IN_DIV              = 4,                // Divide factor.  When CLK_KHZ_IN is 25000,50000,75000,100000,125000,150000, use 2,4,6,8,10,12.
parameter int        DDR_TRICK_MTPS_CAP      = 600,              // 0=off, Set a false PLL DDR data rate for the compiler to allow FPGA overclocking.  ***DO NOT USE.

Right at the top of the _top.sv, the _MULT = 32,  will run the system at 400MHz instead of 500MHz.
Also, change the compiler optimization to my option 'B'.

If your monitor cannot run at 48Hz, try a _MULT = 34,  . This should output a 50Hz video signal.

If this doesn't work, I'll show you how to do the 250MHz mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 04:40:20 pm
The first page of GPU RAM (DDR3) indicates that 0x00's are being read as 0xB0s, with the usual 0x7E for the first byte in each row. 

Ok, the first 7E means for reading that byte, you need a 'WAIT' state for my DDR3 to retrieve the 16 byte block of ram while the other bytes are correct since they are cached & read as fast as core FPGA memory, so they appear fine until you enter a new block of ram.

Now for the rest of the '0B'.  This is actually because reading the DDR3, the DDR3 is actually blank or filled with random data.  Originally when you read the FPGA ram, that ram at power-up had the .mif initialization file with it's power-up data.  This is no longer the case with the DDR3 which does not contain any such data in it.  You need to fill write everything into the DDR3 if you want to see all the data.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 05:30:21 pm
I don't get it, are you saying that when the text window is up to the left, the text is ok without garbage.
Maybe your code is reading the GPU ram and editing the window coordinates, but because the DDR3 has lemon values since there is no .mif file, the screen is messed up.  Yet, everything else is ok.

Just a possibility.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 05:45:43 pm
I don't get it, are you saying that when the text window is up to the left, the text is ok without garbage.
Maybe your code is reading the GPU ram and editing the window coordinates, but because the DDR3 has lemon values since there is no .mif file, the screen is messed up.  Yet, everything else is ok.

Just a possibility.

Yes, text is okay, no garbage:

[attach=1]

Latest project version attached so we're on the same page.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 06:01:17 pm
Have you tried editing the first 32 bytes where the video window positions and cursors are located?
Can you tell if  this corruption happen before the Z80 boots up?
I'll check your code later tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 04, 2021, 06:10:00 pm
I've cleared a page of RAM to zero, set it up as per the startup of the graphics driver (i.e. setting up HW triggers and MAGGIE0), then I've copied that page of RAM into the GPU RAM.  Below is the source, after is the result read back from the DDR3:

Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
8000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8010 00 10 00 10 00 00 00 00 00 00 00 00 00 00 00 00  ................
8020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8060 08 00 0F 00 12 00 00 00 02 7F 01 DF 00 00 00 00  ................
8070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
8090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
80A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
80B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
80C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
80D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
80E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
80F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Here's what I'm reading back from the DDR3:

Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C010 7E 10 00 10 00 00 00 00 00 00 00 00 00 00 00 00  ................
C020 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C030 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C040 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C050 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C060 7E 00 0F 00 12 00 00 00 02 7F 01 DF 00 00 00 00  ................
C070 7E 01 0F 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C080 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C090 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0A0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0B0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0C0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0D0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0E0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0F0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

The screen is black, but I see flickers of vertical white lines here and there when text (should) scroll up the screen - but only when the text should scroll.  It looks like the blitter isn't set up properly, but there's no reason why it should be having issues as *nothing* has changed on that side - the blitter doesn't use DDR3 for its settings and I've not changed how the Z80_bridge handles IO writes/reads, which is how the blitter is set up.

Have you tried editing the first 32 bytes where the video window positions and cursors are located?
Can you tell if  this corruption happen before the Z80 boots up?
I'll check your code later tonight.

Yes - have just been playing with the HV triggers.  I can get additional H/V lines on the screen by setting values in the first 32 bytes.  i.e.:

Code: [Select]
POKE &C001,&80
Ready
POKE &C003,&F0
Ready
DUMP &C000
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 7E 80 00 F0 00 00 00 00 00 00 00 00 00 00 00 00  ................
C010 7E 10 00 10 00 00 00 00 00 00 00 00 00 00 00 00  ................
C020 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C030 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C040 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C050 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C060 7E 00 0F 00 12 00 00 00 02 7F 01 DF 00 00 00 00  ................
C070 7E 01 0F 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C080 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C090 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0A0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0B0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0C0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0D0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0E0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0F0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

So the above shows that I've poked 0x80 into the first horizontal trigger and 0xF0 into the first vertical trigger.  This results in the screen below, but all the text above should also be visible on the screen below, but isn't.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1289785)

EDIT: Hopefully will have some time tomorrow to put into SignalTap and see what's going on.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 10:39:41 pm
Ok, the first 7E means for reading that byte, you need a 'WAIT' state for my DDR3 to retrieve the 16 byte block of ram while the other bytes are correct since they are cached & read as fast as core FPGA memory, so they appear fine until you enter a new block of ram.

Ok, could you try adding the dummy wait-state during any and all Z80 read GPU ram.

If done, this might fix the $7E read byte errors.

Could you setup Signaltap to capture a Z80 read cycle showing the added CMD_R/W bus, including the 'busy' signals.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 04, 2021, 10:46:44 pm
Could you also send me a .bin of the last default power-up .mif.
Get the rs232 debugger working.
I will add a patch where the DDR3 writes will be copied to the 'data_mux_geo's .wr_ena_b, .address_b & .data_in_b  so it will affect the core GPU ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 06:54:05 am
@Nockieboy, are you getting a really dim image on the DECA board?

IE, do you need to boost your monitor's contrast really high?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 08:06:55 am
Ok, the first 7E means for reading that byte, you need a 'WAIT' state for my DDR3 to retrieve the 16 byte block of ram while the other bytes are correct since they are cached & read as fast as core FPGA memory, so they appear fine until you enter a new block of ram.

Ok, could you try adding the dummy wait-state during any and all Z80 read GPU ram.

If done, this might fix the $7E read byte errors.

First page of GPU RAM (DDR3) without WAITs inserted:

Code: [Select]
Ready
DUMP &C000
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C010 7E 10 B0 10 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C020 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C030 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C040 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C050 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C060 7E B0 0F B0 12 B0 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 7E 01 0F B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C080 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C090 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0A0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0B0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0C0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0D0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0E0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0F0 7E B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................


Same page with WAITs inserted for all GPU memory ops:

Code: [Select]
OUT 249,1    <---- set minimum WAIT insertion time
Ready
DUMP &C000
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 00 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C010 B0 10 B0 10 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C020 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C030 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C040 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C050 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C060 08 B0 0F B0 12 B0 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 B0 01 0F B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C080 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C090 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0A0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0C0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0D0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0E0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................
C0F0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  ................

I'd call that a preliminary 'win' for WAITs. :-+

All those 0xB0s are annoying, though.  I can write 0x00 with individual POKE commands, or even by copying RAM as I showed in a previous post, but for some reason the DDR3 isn't taking to LDIR block memory ops without corrupting 0x00s into 0xB0s.

Could you setup Signaltap to capture a Z80 read cycle showing the added CMD_R/W bus, including the 'busy' signals.

Will get started on that this morning. :-+

Could you also send me a .bin of the last default power-up .mif.

Sorry, not sure I understand what you're asking for here?  You mean the GPU_MIF_CE10_10M.mif file that's in the project?  Do you mean a download via the debugger from the FPGA?

Get the rs232 debugger working.
I will add a patch where the DDR3 writes will be copied to the 'data_mux_geo's .wr_ena_b, .address_b & .data_in_b  so it will affect the core GPU ram.

Hopefully will get that done today.

@Nockieboy, are you getting a really dim image on the DECA board?

IE, do you need to boost your monitor's contrast really high?

Whoah.  How did you know that?  I've had my TV's brightness at 60 and contrast at 70 all this time since using the DECA's HDMI output.  Normal values of 50/50 give a very dim screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 08:14:03 am
@Nockieboy, are you getting a really dim image on the DECA board?

IE, do you need to boost your monitor's contrast really high?

Whoah.  How did you know that?  I've had my TV's brightness at 60 and contrast at 70 all this time since using the DECA's HDMI output.  Normal values of 50/50 give a very dim screen.
You honestly didn't think I haven't already gotten the GPU working with the RS232 debugger...

I'll sen you an updated project with a few fixes in an hour.

In the mean time, the SignalTap trace of reading byte 0x00000 is important to see what's going on internally.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 08:27:41 am
Take a look at C06C and C000, why are those 2 = to 0x00?
Are you sure you haven't poked all 0s to the ram?

Also, the Z80 bridge might not know for how long to hold the output enable if the DDR3 controller reads back data immediately.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 08:57:20 am
Take a look at C06C and C000, why are those 2 = to 0x00?
Are you sure you haven't poked all 0s to the ram?

They're set to zero with two 16-bit register (HL) writes from the Z80.  Here's the code in my graphics driver:

Code: [Select]
    ; X & Y scale (set to 0 for 1:1 scaling)
    LD      HL,0000H
    LD      (GPU_RAM+6CH),HL
    ; X & Y sub-pixel position (set to 0,0)
    LD      (GPU_RAM+6EH),HL

EDIT: Not sure why the first byte (C000) is zero.  This is probably because the very first write to DDR3 RAM is accepted, but each subsequent one performed by LDIR is causing timing issues and winding up as 0xB0s?

Also, the Z80 bridge might not know for how long to hold the output enable if the DDR3 controller reads back data immediately.

Surely it only holds it open as long as it's waiting for gpu_rd_rdy to go high?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 09:08:52 am
Okay, hoping these provide something useful.  These are the Signal Tap results from reading C000 (0x0000 in GPU RAM) and C010 (0x0010 in GPU RAM).  If you check the memory dumps in my earlier posts, you'll see C000 should be 0x00 and C010 should be 0xB0.

Reading from 0x0000:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290151;image)

Reading from 0x0010:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290157;image)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 09:21:35 am
I need to see the Z80 clk input plus disable the 'wait'.

Is the rd_DAT_ready tied to my CMD_read_ready?

Where are the CMD_R/W_busy signals?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 09:50:18 am
Is the rd_DAT_ready tied to my CMD_read_ready?

Where are the CMD_R/W_busy signals?

I'm not sure, but it looks like they're getting optimised away?  I've been selecting nodes with the Signal Tap: post-fitting filter.  Have had to switch to Signal Tap: pre-synthesis to find the extra nodes you've requested.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290190;image)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 10:12:35 am
Okay, no WAITs, added what I could to the node list with the proviso mentioned in my previous post about Quartus seeming to optimise out certain signals.

This below trace is the result of reading C000 (0x0000):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290205)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 10:38:46 am
Hang on, need to find my Z80 data sheets...

Where are the output enable and the 245 dir controls?

My guess the transition from 81h to 00h at time 22 is happening too late.

Your labels are messing me up.  Need to analyze...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 10:51:34 am
Hmmm, considering that what we see already has additional delays involved...

It may be possible to get the read to return in time without the wait state, but, it looks like we will still need it on occasion no matter what.

Let me just update you with some code fixing the other problems and we will look at the Z80 bridge tomorrow.

Take a look at what happens when you read 2 adjacent GPU ram bytes.  Lets see how fast the second byte (which would be in my DDR3 controller's cache unless you read outside the 16 byte read cache) returns the data.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 11:05:03 am
Okay, no WAITs, added what I could to the node list with the proviso mentioned in my previous post about Quartus seeming to optimise out certain signals.

This below trace is the result of reading C000 (0x0000):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290205)

Go into Z80 Bridge, line 259 and make this change:

Code: [Select]
Z80_CLKr           <= !Z80_CLK            ; // Register delay the Z80_CLK input.
Redo the test and post a new Signaltap screenshot please.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 11:49:32 am
Here you go, a bunch of little patches.

Everything seems to work OK, other than I cannot test the Z80 interface.

Note that you will need to move the RS232 debugger's RXD/TXD pins.  They are located on lines 561-563 in file 'GPU_DECA_DDR3_top.sv'.

Also, to disable my forced video ON even without a Z80 connected, goto line 555 and enter ( 1'b0 ) for that input.

I have not included the inverted Z80 clock test with these files.
Your picture brightness should now be correct.
You might need to re-enter your latest signal-tap nets.

Lest's get the Z80 working fine with the DDR3.  Once done, we will move the geometry unit over to the DDR3, then, we will need to make the new MAGGIE & OSD / PALETTE system which will then run a display right from the DDR3 releasing you from your tiny 128k screen memory limit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 12:00:19 pm
Where are the output enable and the 245 dir controls?

I can only find the 245_dir_r signal - the z80_245_oe_r signal isn't in the post-fitting node list...

My guess the transition from 81h to 00h at time 22 is happening too late.

Highly likely looking at the Signal Tap output, yes.  The data bus is sampled on the falling edge of the last clock pulse before RD and MREQ go high. 

Take a look at what happens when you read 2 adjacent GPU ram bytes.  Lets see how fast the second byte (which would be in my DDR3 controller's cache unless you read outside the 16 byte read cache) returns the data.

Below are the results of a sequential read to C000 and C001, using an 8-byte program that immediately reads from C000, then the next command reads from C001, so there are no reads/writes to GPU RAM inbetween:

Read from C000:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290244;image)

Following read from C001:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290250)

Both merged, with the Z80's prefetch step removed:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290256)

Here you go, a bunch of little patches.

Everything seems to work OK, other than I cannot test the Z80 interface.

Note that you will need to move the RS232 debugger's RXD/TXD pins.  They are located on lines 561-563 in file 'GPU_DECA_DDR3_top.sv'.

Also, to disable my forced video ON even without a Z80 connected, goto line 555 and enter ( 1'b0 ) for that input.

I have not included the inverted Z80 clock test with these files.
Your picture brightness should now be correct.
You might need to re-enter your latest signal-tap nets.

Lest's get the Z80 working fine with the DDR3.  Once done, we will move the geometry unit over to the DDR3, then, we will need to make the new MAGGIE & OSD / PALETTE system which will then run a display right from the DDR3 releasing you from your tiny 128k screen memory limit.

Thank you.  :) :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 01:51:14 pm
Update on your patched version of the project:

Compiled with no issues.  I've made the changes you mentioned for the RS232_debugger.  Upon resetting the uCOM after writing to the FPGA, got the same issue with the HW trigger lines and small quarter display in the top left.

BUT:

If I reset the uCOM or just restart the DMI (and thus set up the screen again), every now and again it will work.  Here's a couple of pics to prove it (and yes, it's much brighter - thanks!):

Here's the bootstrap, which uses text-tile mode:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290313)

And here's the DMI, running in 1bpp 640x480 graphics mode with blitted text, showing the first page of GPU RAM:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290319)

So it seems randomly (about 1 time in 8 if was forced to make a guess) the screen (or blitter) setup works as intended.  Note the lack of 0xB0s in the first half of the page - perhaps this is related to the screen not being set up properly?

I'm off to try and get the UART debug port wired on the current DECA interface card.  I think being able to see the contents of GPU RAM as well is a must now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 02:22:23 pm
RS232 debugger is now connected via a wire hack I'm not proud of, but once the new PCBs arrive it'll all be good. ;)

First time I reset the uCOM, it worked fine.  ;D

Here's the output from a bad start-up:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290331)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 09:17:19 pm
Well, the debugger should be reading and writing memory properly.

So, where are those '0B' errors coming from.  They must be from Z80 writes.  They cannot be from blits as those do not yet access the DDR3, they go exclusively to the FPGA block ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 05, 2021, 09:18:43 pm
Well, the debugger should be reading and writing memory properly.

So, where are those '0B' errors coming from.  They must be from Z80 writes.  They cannot be from blits as those do not yet access the DDR3, they go exclusively to the FPGA block ram.

But nothing has changed on the Z80 side.  The pre-DDR3 project worked perfectly, with no errors in reads or writes to GPU RAM.   :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 09:27:34 pm
Well, the debugger should be reading and writing memory properly.

So, where are those '0B' errors coming from.  They must be from Z80 writes.  They cannot be from blits as those do not yet access the DDR3, they go exclusively to the FPGA block ram.

But nothing has changed on the Z80 side.  The pre-DDR3 project worked perfectly, with no errors in reads or writes to GPU RAM.   :-//

Try editing/clearing the DDR3 in the debugger.  Read back with the Z80 hex display.  Re-check after a Z80 write and block write fill.
Try signaltap capturing the writes.
The DDR3 may be responding to bad/multiple write requests or a deleayed data byte.

Remember, the RS232 debugger has identical 8 bit access to the DDR3.
The old mux_geo module at one time had some tweaking to make the Z80 work error free before feeding the FPGA blockram which is no longer there with the properly functioning high speed DDR3 multiport controller.  We might be seeing the effect here.

It is most likely a bug in the Z80 bridge which just needs fixing.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 09:33:45 pm
Reset bug/glitch may be connected to the 'B0' error writes.
For now, let's live around it until we solve the other issues.

Note that the DDR3 takes around 0.1 second to boot up.  There is a signal coming from my controller called 'DDR3_READY'.  Your Z80 should be held in reset until that signal goes high.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 05, 2021, 11:58:21 pm
Ok, according to the Z80 datasheet,

The 'WAIT' needs to be set 70ns prior to fall of Z80_CLK cycle T2, yet we only get the valid read req 90ns after the fall of T1.

(Worst case 4MHz Z80...)

So, we need to make a decision of whether to output the 'wait' prior/within 1 Z80 next clock.

As you can see, when I have the data ready in my DDR3 cache, the read is fast enough to handle this.
However, when it is not, with some modding to the Z80 bridge, to react on the fall of the Z80_rd_n, we can still make it so long as the time read_ack time you see remains constant.  This wont always hold true.  So, since we cannot predict that delay in advance, we will have not choice to set the 'wait' if the read isn't ready within 1/2 of a Z80_clk just to make sure the Z80 stops.

It looks like it is time for a new Z80_bridge_v3.sv.  It also looks like I will have to stay up tonight and make it for you if we expect to make headway here at any speed.  Then, you will need to debug it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 09:21:18 am
Try editing/clearing the DDR3 in the debugger.  Read back with the Z80 hex display.  Re-check after a Z80 write and block write fill.

Single-byte edits by the Z80 (POKE-ing individual bytes) works without error and is reflected correctly by the debugger and DDR3 RAM (viewed by the Z80).

A block copy (using LDIR) seems to have worked just fine as well, copying 256 bytes of data from the uCOM's memory to the GPU.

This just leaves the 'block clear' routine the bootstrap and DMI uses to clear out the first page of GPU RAM before setting up...

I've just tried to clear the first page of GPU memory and the page is corrupted again, but now I know what's going on.  I've tested my theory in code and it's confirmed what I thought:  it's not LDIR itself, but the way I'm using it to clear the screen and the underlying issue with DDR3 reads.  When my driver clears the screen it uses a technique for faster clearing of the RAM block - instead of loading 0x00 into the accumulator and writing that value to every byte required to clear the screen, I'm using a trick with LDIR that writes 0x00 to the first byte (hence the first byte is always 0x00 at C000), then uses LDIR to copy that byte to the next memory position, increments both pointers (source and target), then copies the 0x00 from the new position to the next position and so on.

Problem is, writing the first byte is fine as we've seen, but when LDIR copies that byte to the next position, could it be hitting the cache miss problem and getting a value of 0xB0 back instead of 0x00?  Once it's got 0xB0, it writes it to position 2, then moves on and copies 0xB0 to position 3 and so on, resulting in a page of 0xB0s with an 0x00 at the start.

I've replaced the 'block clear' routine with a slower one that just writes the value (0x00 in the case of a block clear) to every byte in the specified range, so it doesn't rely on reading back the value written and bad values can't be introduced due to cache misses.

This has fixed the corrupted screen every time I've tried it.  I'm now getting valid screen displays and stable DMI and CP/M screen output. :-+

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1290940)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 12:40:58 pm
Ok, here is an update to the Z80_bridge now called 'Z80_Bus_Interface.sv'

Now, I cleaned up a bunch of junk and relabeled things.  I've gone all the way PRIOR to the point of adding my 'wait' routine.
I need you to test the design.  If it runs and Signaltap works, let me know so I can add the smart 'wait' routine.
There are also some other extra useless regs in it most likely originally for security reasons, but now with signaltap, we can properly tune the module and get rid of some of the junk.

You'll probably need to re-setup the signal tap.

Modules changed:
Z80_Bus_Interface.sv
GPU.sv
GPU_DECA_DDR3_top.sv   (Don't forget to change you RS232 RXD/TXD IO pins at lines 553-555)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 01:19:44 pm
I need you to test the design.  If it runs and Signaltap works, let me know so I can add the smart 'wait' routine.

It's not working properly, unfortunately.  My screen looks like this:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1291120)

A memory dump of the first page of GPU RAM (as read by the Z80) indicates that the majority of the time, the first byte in a row is being returned as valid - only had one $7E (C0B0 in first dump) in two reads of the page:

Code: [Select]
dump &C000
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C010 00 10 00 10 00 00 00 00 00 00 00 00 00 00 00 00  ................
C020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C060 08 00 0F 00 12 00 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 00 01 0F 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0B0 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Ready
DUMP &C000
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C010 00 10 00 10 00 00 00 00 00 00 00 00 00 00 00 00  ................
C020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C060 08 00 0F 00 12 00 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 00 01 0F 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Ready

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 01:24:41 pm
What in the world?
I get a good picture on my side...

In GPU.SV, please change line 265 to a 1 and re-test.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 01:27:54 pm
Also, in the new Z80_bus_interface, change line 349 from:

Code: [Select]
  if ( (z80_read_memory_1s || z80_read_opcode_1s) && mem_in_bank && memrange[2:0] == 3'b111 ) begin  // *** START OF Z80 READ OP FROM GPU RAM ***
to:

Code: [Select]
  if ( (z80_read_memory_1s) && mem_in_bank && memrange[2:0] == 3'b111 ) begin  // *** START OF Z80 READ OP FROM GPU RAM ***
Dont forget to read my previous post on the previous page.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 02:37:07 pm
It doesn't like those settings either.  I've made both changes and all I'm getting is a blank screen.  The debugger and Z80 both agree on the contents of GPU RAM page 0 and it looks all good, just the cache miss read errors at the start of each row for the Z80.

Sometimes after a reset I see the two HW trigger lines (as previously) but without any fragment of a screen display in the top-left corner.

The default RAM contents screen looks like this at power-up:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1291180)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 02:49:29 pm
It doesn't like those settings either.  I've made both changes and all I'm getting is a blank screen.  The debugger and Z80 both agree on the contents of GPU RAM page 0 and it looks all good, just the cache miss read errors at the start of each row for the Z80.

Sometimes after a reset I see the two HW trigger lines (as previously) but without any fragment of a screen display in the top-left corner.

The default RAM contents screen looks like this at power-up:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1291180)
Are you saying that with no Z80 access at all, the video looks like that?
On my unit, I get the B&W Z80 image with the top right logo in blue and 10 layer text.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 02:56:22 pm
No, that's the display I get immediately after writing a new binary to the FPGA completes.  Normally, I get the B&W Z80 image and colour text.  Every time I reset the system, I get either a black screen or - occasionally - the two yellow lines of the HW triggers.

I'm just getting a black screen when the Z80 completes the GPU initialisation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 03:21:11 pm
 :palm:  And I though it was the Z80 bridge, so I did a whole bunch of things which might be for nothing...
Try this one...


Dont forget to move the debugger IO pins...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 03:41:41 pm
Aaaand that seems to work perfectly. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 03:45:15 pm
Ok, in GPU.sv, on line 265, switch the parameter USE_Z80_CLK to 0, and grab a read and write signal tap.

If that works, then I will add my 'wait' algorithm.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 04:29:13 pm
No issues with that change.  Here's a RD op:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1291237)

And here's a WR op:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1291243)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 06, 2021, 06:59:02 pm
Ok, give this one a try.
I've added 'reset' support and trimmed a few delays.
Provide a signaltap read capture please.

If it still works, I'll add the 'wait' next, then trim the remaining fat.

(ARRGGG what did you do with your 'wait' code???  Getting rid of it all.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 06, 2021, 09:44:11 pm
Okay, well the display is still working so writes to GPU RAM are presumably still working okay, but reading from DDR3 RAM by the Z80 results in page 0 being displayed as all 0x7Es, so there's a timing issue.

The Signal Tap output below was from the Z80 attempting to read C000 - byte 0 in page 0.  The returned value should have been 0x00, but instead was 0x1A.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1291384)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2021, 02:23:08 am
Ok, I missed setting the data output.

Question:  How do you get the upper addresses above A[ 15 ] ?

Without hardware, doing this right is a pain.
I'm throwing together a ModelSim TB for the Z80.

I would have liked to separate the Z80 bridge into 3 pieces.

1. Handle the Z80 bus, with a mem & port R&W IO plus interrupt.  (This handle the bus phy)
2. mem addr R&W to DDR3/GPU.  (Basically address range filter.)
3. port R&W (Basically your multiple ports, but maybe not even needed as this might be part/inside of your IO peripherals)

We have been reading the Z80 datasheet wrong.  Every read/write with the 'TW' cycle in the data sheet isn't actually there unless we we actually apply a 'wait'.  This does not count the 'TWA' in the port read.  All our mem reads have been on the edge of valid since I thought we had 1 more clock cycle.  Looking at the Signaltap, and counting the CLK, I see this now.  Also, it explains our read port problem from way back as we would return the port data too early because of TWA, but the FPGA would return the port data instantly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 07, 2021, 07:48:56 am
Ok, I missed setting the data output.

Question:  How do you get the upper addresses above A[ 15 ] ?

EA14-EA21 are all generated by the hardware MMU that sits on the memory card - a couple of 74LS670s basically, although I plan on replacing these (increasingly hard-to-find) chips with an internal MMU in the FPGA.  The control hardware is already in place on the interface card (EA_dir pin and signal in HDL can change the FPGA from reading the extended address bus to setting it - I just need to remove/disable the hardware MMU to do this, which I was planning to do as a future task whilst also making the MMU mappings readable).

Without hardware, doing this right is a pain.
I'm throwing together a ModelSim TB for the Z80.

I've not had a lot of luck building another set of cards for some reason and hadn't gone back to problem-solve or start another set for well over a year, but recently I've been seriously thinking about building a second system to send over to you - it's the least I can do to say thanks for all this work, if nothing else.  Expect a PM at some point over the next few weeks asking for a postal address.

We have been reading the Z80 datasheet wrong.  Every read/write with the 'TW' cycle in the data sheet isn't actually there unless we we actually apply a 'wait'.  This does not count the 'TWA' in the port read.  All our mem reads have been on the edge of valid since I thought we had 1 more clock cycle.  Looking at the Signaltap, and counting the CLK, I see this now.  Also, it explains our read port problem from way back as we would return the port data too early because of TWA, but the FPGA would return the port data instantly.

I hadn't noticed as I'm still a noob at reading these traces and understanding what the heck is going on in the HDL.  That would explain a lot actually.  Yes, the Z80 inserts a WAIT state into every IO op to give the peripheral time to get its ducks in line and pull WAIT low if it needs to, but there's no such consideration for memory devices.  Even though the Z80 is a slow 8-bit processor from the late '70s, it still places some strict demands on timings.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on October 07, 2021, 08:53:07 am
Why do you use a MMU with a z80 CPU? and for what?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 07, 2021, 09:40:28 am
Why do you use a MMU with a z80 CPU?

The Z80 has a 16-bit address bus, so it can only address up to 64KB of memory.  My MMU expands the 16-bit address bus to 22 bits, allowing the Z80 to access up to 4MB of memory by treating the original 64KB that it can address as four 16KB 'areas'.  Each one of those areas can be swapped with, or mapped to, any 16KB 'bank' in the 4MB physical address space.

...and for what?

To allow CP/M 3 to run, for starters - it uses extra memory for program space and so on.  With the MMU, I can map the first 16KB of GPU RAM into the Z80's logical memory space (the 64KB it can address) and allow software on the Z80 to access the GPU, for example.  By swapping in the correct 16KB banks, the Z80 has access to the entire GPU RAM even though it's not part of the Z80's memory in any way.  I can also give it access to the megabytes of storage on the DDR3 chip/s on the GPU card by the same process.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2021, 02:18:12 pm
OK, I got Modelsim to do a Z80 read an write memory by the datasheet numbers.

OMG, how on earth do they expect up to get that wait out in time if the time between the 'RD' going low and the setup time required to pull wait low is only ~10ns.  Unless you pre-emptively drive the 'wait', you cannot guarantee you will make it in time even with an FPGA.  At least the timing snapshotd you sent me using SignalTap doesn't look as bad/tight, though we still need to decide to get the 'wait' out within 2-3 125MHz clocks of deciding if a read needs to take place.  Though the datasheets are worst case scenario, we would have to get the 'wait' out within 1 clock.

I have to add read/write port, read instruction op-code and make the Z80 simulator respond to the 'WAIT'.

Then I can see and clean up the Z80_bus_interface.
Then I can tie it to my DDR3 controller simulator and see full true round-trip access and timing.

First, some sleep time, then I finish up tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2021, 04:25:49 pm
Ok, here is the beta Modelsim Z80 buss simulator.

// Instructions:
//
// Open ModelSim 20.x
// Select ' File / Change Directory ' -> 'Z80_Interface_TB'
//
// In transcript, type:
// do setup_z80.do
//
// Every time you edit code or ascii script and you want to re-run the simulation, type:
// do run_z80.do
//
// Ascii file 'Z80_cmd_stimulus.txt' allows you to enter Z80 commands to be simulated.
//

If it simulates to your liking, it appears to read and write memory ok, then copy the 'Z80_Bus_Interface.sv' source to you GPU folder and test, plus grab a Signaltap of 2 read requests, 1 cached and 1 uncached, + 1 write.

If everything is ok, I'll finish-up and add the 'wait' tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 07, 2021, 10:04:56 pm
Well, from what I can tell the timings look okay on ModelSim (though it's late here and I've had a looong evening).  However, testing on the hardware hasn't gone well at all.  Screen setup corruption and random 'snow' on the screen - see attachment.

I don't have time to do Signal Tap traces tonight, but will get them done ASAP when I'm back tomorrow afternoon, unless you know what the issue is of course.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 07, 2021, 11:20:11 pm
Strange.  I haven't changed the 'Z80_bus_interface' since the last time except putting in the missing read-data return.
Yes, all I have done was make the ModelSim xxx_tb, in the bus interface, I only commented in 1 line.
Could you check the RS232 debugger to see if the Z80 is writing to ram correctly.

This might be an issue with with the 'reset'.
Try J-Tag programming the board a few times, IE, hard reset to see what happens.

This might be a stability issue.  In that case, I might try making a change in the .sdc file to help things.
Because of the way we are using the PLL, there are a few things in the CLK[4] domain which are being ignored from the 'CLK_IN' 50 MHZ domain.  Or, it's that pesky 'clk_2x_phase' where we used to have a special PLL tap feeding it to guarantee error free power-up.  I might need to make a special PLL for the DDR3 to include that output, or, go back to using 2 PLLs.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 01:31:07 am
Ok, I changed my .sdc file and I got the static red center box junk.

Though the DDR3 reads and writes correctly, it is the FPGA core block ram and and registers which are not receiving the proper written values.  And this bug exists even when writing bytes with the RS232 debugger, so, it will be the same is the Z80 writes bytes.  It is not a problem with the Z80_bus_interface.

LOL, the DDR3 is working flawless, but the older core memory contents is messing up.
Because of the error, the problem is in the geo_mux module, or 4 port memory driver which is running at 250MHz linked to the 125MHz clock zones.

Now that I can replicate the problem, I can hunt down a temp fix as the geo_mux and method of driving the old core ram & control regs is about to become completely obsolete.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 04:42:19 am
Ok, replace these 2, gpu.sv and GPU_DECA_DDR3.sdc files.
I think it should solve the build stability.

It's a sorry pain we have to deal with this as the new design bypasses this old main section which relies on the entire core ram running at 2x core speed so we may achieve 4 simultaneous ports.

The new design should be easier except for the 4 palettes which will require a single m9k block read port running at 300MHz.
However, this is easier to achieve than the equivalent 128k running at 250mhz.  (larger ram blocks and the address steering eats up the FMAX.)

If your monitor will display 48Hz, you can also try running the compiling core to the proper 400Mhz.  Only 3 signals in the GPU core red at 85C model.  This is part of the earlier mentioned GPU 250MHz blockram.  But you can be assured that the DDR3 is 100% in the black timing wise.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 05:50:07 am
Z80 wait rubbish.

Looking at the attached photo:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292545)

You can see the grey highlighted RD signal.  Once that drops, then I know a read is taking place.
The red box which highlights the 'Z80_wait_sh' is the time the FPGA code needs to drive the wait and hold it driven for at least that amount of time to guarantee a 'WAIT' takes place.  The red box is positioned with the time of the FPGA IO round trip taken into consideration assuming that your open-drain IC takes less than 5ns to pull the Z80_WAIT low.

As you can see, with a fast 20MHz Z80 running at 8MHz, I have a huge amount of time to decide to and drive the 'WAIT'.  But with a 8MHz Z80, that time is in the negative.  If the FPGA and your open-drain IC was infinite in speed, you would have +5ns to begin driving the 'WAIT'.  (This is assuming that there are no timing errors in the data sheet as my Z80 sim uses those figures to generate the ModelSim waveform.)

Lets see what happens with the new code I will have ready in a few hours.
First, test and measure the new code I sent in 1 post above fixing the red box.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 08, 2021, 07:18:36 am
Ok, replace these 2, gpu.sv and GPU_DECA_DDR3.sdc files.
I think it should solve the build stability.

It's a sorry pain we have to deal with this as the new design bypasses this old main section which relies on the entire core ram running at 2x core speed so we may achieve 4 simultaneous ports.

The new design should be easier except for the 4 palettes which will require a single m9k block read port running at 300MHz.
However, this is easier to achieve than the equivalent 128k running at 250mhz.  (larger ram blocks and the address steering eats up the FMAX.)

If your monitor will display 48Hz, you can also try running the compiling core to the proper 400Mhz.  Only 3 signals in the GPU core red at 85C model.  This is part of the earlier mentioned GPU 250MHz blockram.  But you can be assured that the DDR3 is 100% in the black timing wise.

Have just tested these two files in the five minutes spare I've got before I head out, and can confirm a clean, stable image. :-+

Haven't tried the core at 400 MHz yet - might have time later today.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: gcewing on October 08, 2021, 09:25:40 am
OMG, how on earth do they expect up to get that wait out in time if the time between the 'RD' going low and the setup time required to pull wait low is only ~10ns.
Where do you get that from? The Z80 timing diagram I'm looking at has RD going low in the middle of T1 and WAIT being sampled in the middle of T2. At 8MHz that gives you 125ns.

Are you perhaps looking at an I/O cycle diagram and imagining the TW cycle not being there? Note that RD goes low at different times for memory and I/O cycles.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 10:05:01 am
Here is the diagram for a read data:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292626)

You can see the the RD falls tc(13)ns after the fall of clock cycle T1. (Clock cycle names in both ModelSim waveform and datasheet.)
You can also see that the setup time for the 'WAIT' signal mus be driven tc(17)ns prior to the fall clock cycle T2.
You can also see that we must hold the 'WAIT' signal for at least tc(18)ns after the fall of clock cycle T2.

Code: [Select]
// Timings found in Zilog Z8400/Z84C00 NMOS/CMOS Z80 CPU Product Specification data sheet.
//                                      4 MHz,  6 MHz,  8 MHz, 10 MHz, 20 MHz
localparam  int  tc13       [0:4] = '{  95000,  80000,  70000,  65000,  40000}; // TdCf(RDf)  - Time in picoseconds
localparam  int  tc17       [0:4] = '{  70000,  60000,  50000,  20000,   7500}; // TsWAIT(Cf)
localparam  int  tc18       [0:4] = '{  10000,  10000,  10000,  10000,  10000}; // ThWAIT(Cf)

Now, to be sure I don't have a typo, here is the snapshot of Zilog's Z80 datasheet timings.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292632)

Did I make a mistake in my code's parameter's worst case timings as given to me by the Z80 datasheet?

In the Modelsim waveform, the 'red box' 'Z80_wait_sh' sample window is shifted left by 10ns which covers the FPGA output delay + LVCT opendrain buffer which pulls-down the 'WAIT' line.  This allows me to see if my bus interface's output is early enough to still meet the timing by the time it reaches the Z80 bus as ModelSim's IO view is infinite in speed / IE has no delay.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 10:17:39 am
Look at the 3 arrows, at the fall of T1 in the simulation, until Z80_RD, it does measure 70ns just like my setting in my code and data sheet.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292638)

The setup time for the 'WAIT' is also correct except shifted to the left by 10ns.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 05:05:27 pm
Ok, give this a shot.

I re-did the Z80_Bus_Interface.sv completely.
The simulator now supports everything except the 'WAIT' management.

Things to test and check:

Lines 362-364: Is this the correct way to handle the bank ID?
Lines 425-450: I hope I got the sound and keyboard correct since all the IO ports are now stored and decoded in an array seen on lines 154-177.

I will need SignalTap shots or reads (cached & uncached) and writes.

If this new bus interface works like the old one, then I will add in the wait.

I've attached the Modelsim Project and a new gpu.sv and xxxx.sdc files.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 08, 2021, 09:23:24 pm
Okay, this version works, but not as well as before these changes.  By that, I mean that the DMI is able to correctly set up the screen without using the LDIR clear-screen trick, but the bootstrap screen is corrupted (that uses the LDIR trick), so read timing isn't quite right.

First write for a cache miss:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292956)

Second write for a cache hit:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292962)

First read for a cache miss:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292968)

Second read for a cache hit:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1292974)

Port writes and reads seem to work okay (haven't been able to test the PS2 or sound though).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 08, 2021, 10:47:27 pm
Is it just me, or, does the 'cmd_read_req' look inverted?

It's odd as the 'CMD_read_ready[1]' seems to be positive polarity.

Well, going by that, on CH_C011, you can see at the fall of Z80_RDn_r & Z80_MREQn_r, the read req is sent out on the same clock.  The read ready comes back in 2 clocks, and 1 clock later, 245 dir is set while the data outputs 1 clock later.

CH_C010 shows a slow read...

Ok, I need to see why that read is inverted there.

Also, please provide the latched Z80_addr_r input instead of the mem-range.  Something is fishy about the not in cache read req.

And I want to see a port read and port write.  We will save the read-op-code for when the 'wait' is functioning.

Except for the inverted 'cmd_read_req', it looks like I can add the 'WAIT' tonight which should fix the last read data problem.
The only problem is that I need to assert it immediately as I send the read req.

Well, I guess the time accurate Modelsim Z80 bus generator was really needed to generate a real Z80 bus interface which works as fast as possible without all that old code we had to filter the bus signals.


*** What does the read DDR3 data look like on the Z80 display hex.  Does it read correct data?

Also, I need to make the read_req and the write_req send out a single command instead of a whole bunch.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 09:22:49 am
Ok, here you go, the hopefully final Z80 interface with 'WAIT' processing.

The new simulator has 2 setups.

do setup_z80.do / run_z80.do
Will simulate the Z80 bus interface on it's own and will work with any FPGA vendor's version of ModelSim.

do setup_z80_to_DDR3.do / run_z80_to_DDR3.do
Will simulate the Z80 bus with my DDR3 ram controller, completely so you can see how the waits are effected.
This simulation requires Altera/Intel's version of ModelSim.

Things to read in the module parameter settings:
Code: [Select]
// Z80 bus timing settings.
   .READ_PORT_CLK_POS     ( 2       ), // Number of Z80_CLK cycles before the bus interface responds to a Read Port command.
   .WRITE_PORT_CLK_POS    ( 2       ), // Number of Z80_CLK cycles before the bus interface samples the Write Port command's data.

// 0 to 3, Number of CMD_CLK cycles to wait for DDR3 read before asserting the WAIT during a Read Memory cycle.
// Use 0 for an instant guaranteed 'WAIT' every read.  (Safest for Read Instruction Opcode cycle.)
// Use 3 for compatibility with waiting for a BrianHG_DDR3 read cache hit before asserting the 'WAIT'.

   .Z80_DELAY_WAIT_RI     ( 0       ), // 0 to 4, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
   .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 4, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Memory cycle.
   .Z80_WAIT_QUICK_OFF    ( 1       ), // 0 (Default) = WAIT is turned off only during a low Z80_CLK.  1 = WAIT is turned off as soon as a read_ready is received.

and

Code: [Select]
// Read IO port addresses range.
   .READ_PORT_BEGIN       ( 240     ), // Sets the beginning port number which can be read.
   .READ_PORT_END         ( 249     ), // Sets the ending    port number which can be read.

and new IO port when you are ready to get rid of the legacy IO port stuff inside the Z80 bus controller:

Code: [Select]
// ***********************************
// *** Z80 IO Read and Write ports ***
// ***********************************

   output logic [255:0] WRITE_PORT_STROBE          = 0 , // The bit   [port_number] in this 256 bit bus will pulse when the Z80 writes to that port number.
   output logic   [7:0] WRITE_PORT_DATA   [0:255]      , // The array [port_number] will hold the last written data to that port number.
   output logic [255:0] READ_PORT_STROBE           = 0 , // The bit   [port_number] in this 256 bit bus will pulse when the Z80 reads from that port number.
   input  wire    [7:0] READ_PORT_DATA    [0:255]      , // The array [port_number] will be sent to the Z80 during a port read so long as the read port
                                                         // number is within parameter READ_PORT_BEGIN and READ_PORT_END.

This was 3 solid days of work, so you better appreciate it.


I need read and write snapshots.  I hope everything works now.
If not, play with the  Z80_WAIT_QUICK_OFF     and/or make  Z80_DELAY_WAIT_RM     =0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 09:29:00 am
Signaltap these signals:

Z80_CLK_r, 
Z80_ADDR_r,
Z80_M1n_r, 
Z80_IORQn_r,
Z80_MREQn_r,
Z80_RDn_r, 
Z80_WRn_r, 
Z80_wData_r,
Z80_fpga_data_oe,
Z80_fpga_data_out,
CMD_read_req, 
CMD_read_ready,
Z80_WAIT,

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 09:36:38 am
****** This post is a little useless now, as I was writing it whilst you posted your last two updates, but I'll post it anyway. ********

Also, please provide the latched Z80_addr_r input instead of the mem-range.  Something is fishy about the not in cache read req.

And I want to see a port read and port write.  We will save the read-op-code for when the 'wait' is functioning.

Is Z80_addr_r[0..15] not what you're wanting to see?  I'd added it to the write traces after I'd done the reads, so I'll do a couple more reads.

Here's a cache miss read at 0000:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293307)

And here's a cache hit read 0001:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293313)


*** What does the read DDR3 data look like on the Z80 display hex.  Does it read correct data?

Without any WAITs added, I'm getting good clean data in the DMI for the most part, but read timings are still not quite there.  As you can see with the page 0 dump below, a single 0x7E is snuck into the returned data:

Code: [Select]
DUMP &C000
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C010 00 10 00 10 00 00 00 00 00 00 00 00 00 00 00 00  ................
C020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C060 08 00 0F 00 12 00 00 50 02 7F 01 DF 00 00 00 00  .......P........
C070 00 01 0F 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C080 7E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C0F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

This is pretty rare, but it's enough to throw the LDIR clear-screen function and corrupt the screen setup data in the bootstrap every time.

Port reads and writes

Here's a port write - I can't get a port read at the moment without modifying the Z80_Interface as Quartus seems to be optimising everything away on that side.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293319)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 09:53:23 am
Here is a Sim with DDR3 of the worst case scenario.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293334)

This is where read problems will occur without the WAIT.
Notice that during the refresh-write-read, there are 3 TW clock cycles added.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 09:59:33 am
Ok, here you go, the hopefully final Z80 interface with 'WAIT' processing.

Okay, just a real quick update on this build.  The initial screen is fine as set up by the bootstrap, so it seems reads are working well now (at least LDIR clear screen is having no issues).

The only issue is that I have to press space to get to the menu, and when I do, the system locks up with WAIT permanently low (the CPU card has an LED for WAIT).  I'll look to get more traces later.

EDIT: Same issue with WAIT_QUICK set to 1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 10:12:41 am
Give this a try.  I'm now maintaining a read continuous request until the read ready is received.

If this doesn't work, I'll make it so that if at any time a read_ready comes in, the wait will clear.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 10:33:04 am
No, same issue with that build.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 10:43:16 am
Ok, this one is going to hurt if it works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 10:46:00 am
No, that does the same thing.   :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 11:00:25 am
Hun?
How is that possible unless a read is totally missed?

Note that each of these are simulating fine...

Holy crap, this one must work...
It is self clearing...

Line 346 is the wait algorithm...

There must be something going wrong with the Z80 bus reads.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 11:17:57 am
Yep, that works. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 11:20:40 am
Ok, before I make final changes, please go through a flurry of tests.

Signaltap & Z80 read/write...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 12:03:07 pm
Ok, before I make final changes, please go through a flurry of tests.

Signaltap & Z80 read/write...

Okay, page dumps are all good from the Z80.  Signal Taps as follows.

Cache miss, writing to 0000:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293382)

Cache hit, writing to 0001:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293388)

Cache miss, reading from 0000:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293394)

Cache hit, reading from 0001:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1293400)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 12:16:17 pm
Looking at the CMD_read_ready[1], the length of those extended wait TW cycles are absurd.
Are you still using that junk transistor with the 200ns turn off?

What about the 'LDIR' clear screen trick?

If you cant get all the test signals, maybe we need to find their root source to tap.

Like, I really want to see the 'Z80_WAIT' output in the signaltap.  It is kinda the important thing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2021, 12:22:59 pm
Here is another test.
It should stop flooding the DDR3 read requests after a read_ready has been received.  (It's my multiport's cache system which prevents this trick from making my DDR3 controller PHY from going on a non-stop reading rampage.)
And one-shot the DDR3 writes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2021, 03:16:40 pm
Looking at the CMD_read_ready[1], the length of those extended wait TW cycles are absurd.
Are you still using that junk transistor with the 200ns turn off?

Well, I swapped it with an NX138 (https://www.mouser.co.uk/ProductDetail/771-NX138AKR) a few weeks ago and it hasn't made much difference.  I'm waiting on the latest version of the DECA interface card to arrive and I'll try out the 74LVC06 then.

What about the 'LDIR' clear screen trick?

That's working fine.  When the uCOM resets, or first powers up, it boots into the bootstrap.  That uses the LDIR trick to clear the GPU's page 0 before setting up the screen, so I know straight away if the LDIR trick works with the latest build or not.

If you cant get all the test signals, maybe we need to find their root source to tap.

Like, I really want to see the 'Z80_WAIT' output in the signaltap.  It is kinda the important thing.

I'm not likely to have the time to do that today, unless it's much later tonight.  Failing that, maybe tomorrow.  Got a busy weekend unfortunately.

Here is another test.
It should stop flooding the DDR3 read requests after a read_ready has been received.  (It's my multiport's cache system which prevents this trick from making my DDR3 controller PHY from going on a non-stop reading rampage.)
And one-shot the DDR3 writes.

This one works fine as well. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 10, 2021, 06:09:07 am
Ok, here is V1.10 of the Z80 bus testbench and bus interface.  Test it to see if it works and also fixes the read cache as last read cache you showed me here https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3737161/#msg3737161 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3737161/#msg3737161) didn't work, it sent the 'wait' anyways when it didn't need to.

By the way, there is no such thing as a write cache hit.  Writes are always a cache hit.  It's a question of if you can completely fill the write cache.  To do this, the Z80 will need to be clocked at 4.8GHz if it were doing nothing but writing data in a straight line.  But since it needs to read op-code to do the writing, make that >9GHz Z80.

I need to know if you can test reading opcode from GPU ram.  It is important as it is worth running read opcodes through a second DDR3 read channel so they have their own separate 16 instruction cache compared to the read and write memory instructions.  This might effect the either the maximum MAGGIE layers or GEO performance if you store OP-code in the DDR3.  It's just a consideration.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 10, 2021, 11:07:27 am
Ok, here is V1.10 of the Z80 bus testbench and bus interface.  Test it to see if it works and also fixes the read cache as last read cache you showed me here https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3737161/#msg3737161 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3737161/#msg3737161) didn't work, it sent the 'wait' anyways when it didn't need to.

No worries, will try to get this done later today if I can.

By the way, there is no such thing as a write cache hit.  Writes are always a cache hit.  It's a question of if you can completely fill the write cache.  To do this, the Z80 will need to be clocked at 4.8GHz if it were doing nothing but writing data in a straight line.  But since it needs to read op-code to do the writing, make that >9GHz Z80.

A worthy goal, but 9GHz might be a bit beyond 70's silicon and well into the futuristic optical domain.  I'll get in touch with Intel and SMC and see what they can do. :-DD

I need to know if you can test reading opcode from GPU ram.  It is important as it is worth running read opcodes through a second DDR3 read channel so they have their own separate 16 instruction cache compared to the read and write memory instructions.  This might effect the either the maximum MAGGIE layers or GEO performance if you store OP-code in the DDR3.  It's just a consideration.

Yes, no problem.  I can write a little program and load it into page 1 of GPU RAM and execute it no problems.  Although I can't really see any particular use for it - there's plenty of RAM available elsewhere.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 10, 2021, 11:28:49 am
I need to know if you can test reading opcode from GPU ram.  It is important as it is worth running read opcodes through a second DDR3 read channel so they have their own separate 16 instruction cache compared to the read and write memory instructions.  This might effect the either the maximum MAGGIE layers or GEO performance if you store OP-code in the DDR3.  It's just a consideration.

Yes, no problem.  I can write a little program and load it into page 1 of GPU RAM and execute it no problems.  Although I can't really see any particular use for it - there's plenty of RAM available elsewhere.

Make the Z80 bus generic and support everything.  You never know, you may just use the all the onboard ram as your system memory.  Otherwise loading and executing software from the onboard/SD card flash will be tediously slow.

LOL, you'll have a deca board with nothing but a Z80 mounted on it...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 10, 2021, 12:28:55 pm
Ok, once you checked the V1.10 bus controller and it has passed, here I made your GPU geometry unit run on the DDR3.

Now with more R&W ports on my multiport front end, FMAX has boggled down.  There might be graphic garbage.  It looks like I will need to make my simple high speed stack-able 2:1 multiport front end this week as you will need it for more RW ports if you want any real speed.

*Don't forget you need to copy the font into the DDR3 as it has random junk at power-up.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 12, 2021, 11:32:31 am
Okay, running code from GPU RAM.  Here's the program in the GPU RAM at page 1:

Code: [Select]
DUMP &C100
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C100 3E 55 01 20 00 21 FF C0 77 2B 10 FC C9 00 00 00  >U. .!..w+......
C110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
Ready
DASM &C100,&C
DISASSEMBLING C100h to C10Bh:

C100 3E 4E     LD   A,$55
C102 06 20     LD   B,$20
C104 21 45 00  LD   HL,C1FFH
C107 77        LD   (HL),A
C108 2B        DEC  HL
C109 10 20     DJNZ C107H
C10B C9        RET
             ----------------

It should write 0x55 to C1E0-C1FF.  Here's page 1 after it's run:

Code: [Select]
DUMP &C100
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C100 3E 55 06 20 21 FF C1 77 2B 10 FC C9 00 00 00 00  >U. !..w+.......
C110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1E0 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
C1F0 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU

So that's code executing in page 1 of the GPU RAM and writing to the same page.  Here's a Signal Tap of the first opcode (0x3E) being read:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1295749)

And one of those 0x55s being written to GPU RAM:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1295755)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 12, 2021, 11:40:25 am
Ok, excellent.
We seem to get the wait out ahead in time.

Now, change this parameter:
Code: [Select]
   .Z80_DELAY_WAIT_RI     ( 2       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
And capture the second read opcode as this one should now be read from cache without any 'WAIT' inserted as my DDR3 will now return the data quick enough to not need to.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 12, 2021, 01:26:40 pm
Hmm..  I've added two commands to the start of the previous test code - basically just to disable then enable interrupts, but they're both single-byte opcodes so there's no reading values after each opcode.

First opcode read:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1295806)

Second opcode read:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1295812)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 12, 2021, 02:42:19 pm
As you can see, the 'WAIT' is still being triggered.
Try a value of 3 for both these 2 unless you made the mistake of changing the value in the Z80_Bus_Interface.sv instead of in GPU.sv line 253/(274 on GEO_on_DDR3.zip) where the parameter has been externally set.  It should not be edited on line Z80_Bus_Interface.sv line 24.

Code: [Select]
  .Z80_DELAY_WAIT_RI     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
  .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 13, 2021, 05:45:22 pm
Unusually for me, I'm doing it right - I'm not adjusting the parameters in Z80_Bus_Interface.sv, I'm actually adjusting them in gpu.sv as required. ;)

So it appears that changing these values doesn't make any difference.  As you'll see in the Signal Tap trace below, a WAIT is being inserted in the second opcode read still.

Code: [Select]
   .Z80_DELAY_WAIT_RI     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
   .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Memory cycle.
   .Z80_WAIT_QUICK_OFF    ( 1       ), // 0 (Default) = WAIT is turned off only during a low Z80_CLK.  1 = WAIT is turned off as soon as a read_ready is received.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1296778)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 13, 2021, 06:11:58 pm
It's a bug in the Z80_bus_interface.
I'll fix it tonight.


I don't see any errors.  Are you sure you are editing the correct source code in the correct folder?
Is all your code up to date?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 13, 2021, 09:11:53 pm
Okay, using the latest project you posted on the last page (the one linking the GEO unit into the DDR3), I'm getting a result:

Cache miss opcode read:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1297078)

Two sequential cache hit opcode reads:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1297084)

Graphical corruption is a genuine problem with this build, though - whilst text-tile mode works perfectly, the same can't be said of full-graphics mode:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1297090)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 05:03:29 am
Are you sure you placed a copy of the font in DDR3, or are you blitting random uninitialized data which was already there in the DDR3 since powerup?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 14, 2021, 07:30:59 am
Are you sure you placed a copy of the font in DDR3, or are you blitting random uninitialized data which was already there in the DDR3 since powerup?

 :palm:  Of course, I forgot to copy the font across to DDR3.  Is there an easier way to do this without resorting to copying the raw data from the MIF in the project and transferring that to a ROM bank, so that I can copy it to DDR3 during startup?  That way is probably preferable, actually, as the font can be edited/changed by the user without messing with the GPU, I guess.

EDIT: Don't worry, I'll just copy the font into ROM, think it's the most flexible solution.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 08:07:07 am
Ok, lets see if it works.
In the final GPU, if you want a pre-installed data in the DDR3 after reset, you will need to code it in the HDL to read data from blank flash ram on your DECA board as it has an onboard 64MB QSPI Flash, or you can use the onboard SD-Card slot.  Though, with the onboard SD-Card, you will need to code a filesystem, otherwise it will be nothing more than a rom chip.  You will also want to code a simple RLE encoding scheme for the 64MB flash as 64mb != 512mb, nor do you need to waste all that storage for what will mostly be 0x00.  But now, you could store a 1280x1024 Z80 in 24 bit color instead of that 16 color low res garbage.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 08:21:28 am
Are you sure you placed a copy of the font in DDR3, or are you blitting random uninitialized data which was already there in the DDR3 since powerup?

 :palm:  Of course, I forgot to copy the font across to DDR3.  Is there an easier way to do this without resorting to copying the raw data from the MIF in the project and transferring that to a ROM bank, so that I can copy it to DDR3 during startup?  That way is probably preferable, actually, as the font can be edited/changed by the user without messing with the GPU, I guess.

EDIT: Don't worry, I'll just copy the font into ROM, think it's the most flexible solution.

Rom banks take up ram blocks of identical size.  The rom you are talking about for now needs to be stored in your Z80 OS roms.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 08:38:35 am
Recommendation for new video output modes:

Stick with 1 pll clock rate of 74.25MHz which equals official standard 720p, 1280x720@60Hz.

With that 1 PLL clock setting, you can achieve:
1280x720@60Hz.
1920x1080@30Hz.
1920x540@60Hz. (we can also make this 1920x544@60Hz. so that the Y axis divides evenly into 32 for fonts)
1920x480@60Hz. (with black borders, 1280x480 approximate a 4:3 on a 16:9 screen)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 14, 2021, 08:58:36 am
:palm:  Of course, I forgot to copy the font across to DDR3.  Is there an easier way to do this without resorting to copying the raw data from the MIF in the project and transferring that to a ROM bank, so that I can copy it to DDR3 during startup?  That way is probably preferable, actually, as the font can be edited/changed by the user without messing with the GPU, I guess.

EDIT: Don't worry, I'll just copy the font into ROM, think it's the most flexible solution.

Rom banks take up ram blocks of identical size.  The rom you are talking about for now needs to be stored in your Z80 OS roms.

Yes, that's what I meant.  I've got the font sitting in a 16KB ROM bank on my uCOM.  It's working nicely. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 09:45:30 am
:palm:  Of course, I forgot to copy the font across to DDR3.  Is there an easier way to do this without resorting to copying the raw data from the MIF in the project and transferring that to a ROM bank, so that I can copy it to DDR3 during startup?  That way is probably preferable, actually, as the font can be edited/changed by the user without messing with the GPU, I guess.

EDIT: Don't worry, I'll just copy the font into ROM, think it's the most flexible solution.

Rom banks take up ram blocks of identical size.  The rom you are talking about for now needs to be stored in your Z80 OS roms.

Yes, that's what I meant.  I've got the font sitting in a 16KB ROM bank on my uCOM.  It's working nicely. :-+

So, just to be clear, the geometry unit's pixel writer is working with the DDR3?
You can now move the font to an upper address in the DDR3 and leave all the available FPGA blockram for display, right?

OK, next we need to redo the MAGGIE system completely.
Now we need to change to a 2 clock domain system, the core system clock and the video output clock which runs on a separate PLL.
I also want to multiplex the 'tile' and palette dual port memories' read ports to run at 4x the pixel clock allowing 4 look-ups per pixel allowing 4 dedicated tile layers.  This means with a 74.25MHz pixel clock, we will need to run those memories' read ports at 297MHz.  This is within the DECA's Max10's 300MHz limit however, Lattice ECP5's limit on their fastest unit is 272MHz.  We can operate with a limit of 2 tile layers if you like.  At least this way, 148.5MHz will be slow enough for any FPGA out there.  The second port of those memories will be on the DDR3 & geometry system clock, either 100 or 200MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 14, 2021, 10:00:23 am
So, just to be clear, the geometry unit's pixel writer is working with the DDR3?

Yes, it's working as it did before anyway - I haven't noticed any artefacts or corruption either, drawing filled circles, triangles etc.

You can now move the font to an upper address in the DDR3 and leave all the available FPGA blockram for display, right?

Well yes, I suppose I can.  Hadn't thought of that.  That'll require some changes to the HDL though, which I guess are next on the agenda, right?

OK, next we need to redo the MAGGIE system completely.
Now we need to change to a 2 clock domain system, the core system clock and the video output clock which runs on a separate PLL.
I also want to multiplex the 'tile' and palette dual port memories' read ports to run at 4x the pixel clock allowing 4 look-ups per pixel allowing 4 dedicated tile layers.  This means with a 74.25MHz pixel clock, we will need to run those memories' read ports at 297MHz.  This is within the DECA's Max10's 300MHz limit however, Lattice ECP5's limit on their fastest unit is 272MHz.  We can operate with a limit of 2 tile layers if you like.  At least this way, 148.5MHz will be slow enough for any FPGA out there.  The second port of those memories will be on the DDR3 & geometry system clock, either 100 or 200MHz.

Is that something that we could adjust easily with a parameter in the project, or is it more involved than that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 10:35:39 am
You can now move the font to an upper address in the DDR3 and leave all the available FPGA blockram for display, right?

Well yes, I suppose I can.  Hadn't thought of that.  That'll require some changes to the HDL though, which I guess are next on the agenda, right?
I don't think so.
Have you tried using the Z80 to read and write to higher sections of memory?
Does the Z80_bus_interface have a parameter to block access?
I know you can set the geometry unit to address to it's max address range even though the Z80 bus may have a limit.
It looks like there will need to be upgrades to access the 512mb as that requires 29 address bits.  Sadly 9 short of the current 20 bits.
Quote
OK, next we need to redo the MAGGIE system completely.
Now we need to change to a 2 clock domain system, the core system clock and the video output clock which runs on a separate PLL.
I also want to multiplex the 'tile' and palette dual port memories' read ports to run at 4x the pixel clock allowing 4 look-ups per pixel allowing 4 dedicated tile layers.  This means with a 74.25MHz pixel clock, we will need to run those memories' read ports at 297MHz.  This is within the DECA's Max10's 300MHz limit however, Lattice ECP5's limit on their fastest unit is 272MHz.  We can operate with a limit of 2 tile layers if you like.  At least this way, 148.5MHz will be slow enough for any FPGA out there.  The second port of those memories will be on the DDR3 & geometry system clock, either 100 or 200MHz.

Is that something that we could adjust easily with a parameter in the project, or is it more involved than that?
Nope, maggie needs to be redone.  DDR3 needs to transfer blocks of memory line by line to a bank of dual-port memories to feed the picture output.  Each line, it needs to process an address for each layer and feed DDR3 commands to fill these line buffers.  This is the job of the maggie.  Also, all the registers are too small.  You need 32 bit base ram address and display width settings of 16bit as well as begin and end line positions.  These used to be stored separately for your H&V cursors and maggie address controls.  But now, each maggie layer needs all this info to operate the DDR3 to line mem buffers.  Features and controls will be the same as before, but, everything will land on new addresses with either a 32bit integer, or 16bit integer, or 8 bit integer for the control.  No more funny stacked 8 bit integers with 4 bits for Y scale, and 4 bits Y offset.  Each maggie layer will have 64 bytes of reserved space for it's controls.  This will make your Z80 setting regs a whole lot easier.  Though, 16 layers means 1024bytes of address space.  Also, the tile/font will now be 32bits per character, not 16bit or 8 bit.  You will have 8bit foreground color, 8 bit background color, 2 bit for mirror and flip tile, 14bit for a font with up to 16384 characters.  Now you may include Greek and accent character fonts with math symbols and more complex graphics set.  You will also have tile width and heights of 8,16 and 32.  The only limit will be the 128 kilobytes for tile ram in the DECA and 192 kilobytes for the tile mem in the 16$ Lattice fpga, 384kb in the 34$ Lattice, but access to at least maggie 34 layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 14, 2021, 11:06:58 am
Have you tried using the Z80 to read and write to higher sections of memory?

No, but is there any reason to think it wouldn't work?

Does the Z80_bus_interface have a parameter to block access?

Not as far as I'm aware.

I know you can set the geometry unit to address to it's max address range even though the Z80 bus may have a limit.
It looks like there will need to be upgrades to access the 512mb as that requires 29 address bits.  Sadly 9 short of the current 20 bits.

The Z80 has a hard limit of a 512KB 'window' into the GPU's DDR3 RAM.  As it stands, it can only access the first half megabyte of DDR3 without some form of MMU within the FPGA - probably best controlled via an IO port in Z80_Interface to set which 512KB 'bank' to expose to the Z80.  The Z80 then would use the 32 banks in its 512KB 'window' to access that DDR3 bank.  By setting the GPU's DDR3 bank, the Z80 will be able to access any size of DDR3 memory, albeit in 16KB nibbles of a 512KB chunk at any one time, if that makes sense?

OK, next we need to redo the MAGGIE system completely.
Now we need to change to a 2 clock domain system, the core system clock and the video output clock which runs on a separate PLL.
I also want to multiplex the 'tile' and palette dual port memories' read ports to run at 4x the pixel clock allowing 4 look-ups per pixel allowing 4 dedicated tile layers.  This means with a 74.25MHz pixel clock, we will need to run those memories' read ports at 297MHz.  This is within the DECA's Max10's 300MHz limit however, Lattice ECP5's limit on their fastest unit is 272MHz.  We can operate with a limit of 2 tile layers if you like.  At least this way, 148.5MHz will be slow enough for any FPGA out there.  The second port of those memories will be on the DDR3 & geometry system clock, either 100 or 200MHz.

Is that something that we could adjust easily with a parameter in the project, or is it more involved than that?
Nope, maggie needs to be redone.  DDR3 needs to transfer blocks of memory line by line to a bank of dual-port memories to feed the picture output.  Each line, it needs to process an address for each layer and feed DDR3 commands to fill these line buffers.  This is the job of the maggie.  Also, all the registers are too small.  You need 32 bit base ram address and display width settings of 16bit as well as begin and end line positions.  These used to be stored separately for your H&V cursors and maggie address controls.  But now, each maggie layer needs all this info to operate the DDR3 to line mem buffers.  Features and controls will be the same as before, but, everything will land on new addresses with either a 32bit integer, or 16bit integer, or 8 bit integer for the control.  No more funny stacked 8 bit integers with 4 bits for Y scale, and 4 bits Y offset.  Each maggie layer will have 64 bytes of reserved space for it's controls.  This will make your Z80 setting regs a whole lot easier.  Though, 16 layers means 1024bytes of address space.  Also, the tile/font will now be 32bits per character, not 16bit or 8 bit.  You will have 8bit foreground color, 8 bit background color, 2 bit for mirror and flip tile, 14bit for a front with up to 16384 characters.  Now you may include Greek and accent character fonts with math symbols and more complex graphics set.  You will also have tile width and heights of 8,16 and 32.  The only limit will be the 128 kilobytes for tile ram in the DECA and 192 kilobytes for the tile mem in the 16$ Lattice fpga, 384kb in the 34$ Lattice, but access to at least maggie 34 layers.

I meant once the MAGGIE is redone, would it be possible to set the 'tile and palette dual port memories' clock speed via a parameter to match the target FPGA it's going to be working on?

As for the rest of your reply -  :o :o :o.  Seems some major changes to be done and I'm going to have to go away and read all that at least ten times over to try to understand it all.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 11:22:32 am
I meant once the MAGGIE is redone, would it be possible to set the 'tile and palette dual port memories' clock speed via a parameter to match the target FPGA it's going to be working on?

As for the rest of your reply -  :o :o :o.  Seems some major changes to be done and I'm going to have to go away and read all that at least ten times over to try to understand it all.  ;)
Ok, maybe the better question I should ask is:
Are 2 tile layers + X graphic layers good enough for you?  (X being a parameter based on FPGA resources.)
Or, do you need more than 2 tile layers?
Note that a -8 Altera FPGA can only run it's blockram at 250MHz, so, that's less than the 297MHz requires for a 4:1 mux read running 720p.  Though, we might be able to do some fancy crap to work around this to get 3:1, but, how advanced do you want to go and the cheapest Lattice -6 can only run the core ram at 200MHz. (Not listed, just a guesstimate as only their highest speed 272MHz is in their data sheet.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 14, 2021, 11:34:14 am
Ok, maybe the better question I should ask is:
Are 2 tile layers + X graphic layers good enough for you?  (X being a parameter based on FPGA resources.)
Or, do you need more than 2 tile layers?
Note that a -8 Altera FPGA can only run it's blockram at 250MHz, so, that's less than the 297MHz requires for a 4:1 mux read running 720p.  Though, we might be able to do some fancy crap to work around this to get 3:1, but, how advanced do you want to go and the cheapest Lattice -6 can only run the core ram at 200MHz. (Not listed, just a guesstimate as only their highest speed 272MHz is in their data sheet.)

I think two tile layers should be just fine.  I'm probably misunderstanding the value of tile layers, but afaik there's nothing they can do that a graphics layer can't and the tile layer was borne out of the need to fit an 80x25 character display into the small amount of block RAM we had available before DDR3?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 12:11:42 pm
Ok, maybe the better question I should ask is:
Are 2 tile layers + X graphic layers good enough for you?  (X being a parameter based on FPGA resources.)
Or, do you need more than 2 tile layers?
Note that a -8 Altera FPGA can only run it's blockram at 250MHz, so, that's less than the 297MHz requires for a 4:1 mux read running 720p.  Though, we might be able to do some fancy crap to work around this to get 3:1, but, how advanced do you want to go and the cheapest Lattice -6 can only run the core ram at 200MHz. (Not listed, just a guesstimate as only their highest speed 272MHz is in their data sheet.)

I think two tile layers should be just fine.  I'm probably misunderstanding the value of tile layers, but afaik there's nothing they can do that a graphics layer can't and the tile layer was borne out of the need to fit an 80x25 character display into the small amount of block RAM we had available before DDR3?

The difference is with the tile layers, to get a 256 color foreground/background display, for each line, we need to feed 320 bytes per line (80x4bytes) per line and the tile memory will do all the looking up in that 128kb blockram.  For graphics, that would be 640 bytes per line for 8 bit color.

But, with a blitter software font, not only do you need to display the 640 bytes each line, but graphically there is a new 640 bytes every line instead of a new 640 bytes every 16 lines.  And to do a blitter driven tile set into a normal graphics layer, you need to read from 1 section of memory, then write to another, 16 times for a 8x16 font.  And for every move and screen scroll, that's 32x the memory operations compared to the tile modes.  Regardless of blitter speed, if you are using the blitter to draw and fill in the tile section, that will run 32x faster to fill the screen.  And if you use the blitter to fill sections of the tile memory itself, you can animate 100s of characters/tiles simultaneously on display just by writing a few bytes without any other additional overhead.  With the tiles, you can draw huge tiled repetitive animated backdrops by blitting a few new tiles from upper DDR3 ram into the tile memory once every V sync without the Z80 even noticing anything happening.

If you wanted a 8 bit 256 color font, 8x16, 256 characters, that would be 32 kilobytes of ram.  You can create a 1024 character set with 128kb of ram, or, a 256 character set 32bit color font.  Mixes and matching fonts and color settings is also allowed.  Most likely, we will place 2 palettes at the output of the tile ram so each tile layer may have it's own color palette as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 12:45:16 pm
With the geometry unit reading and writing to the DDR3, and the Z80 not generating errors, we can safely say that my DDR3 controller works with a Z80 and GPU.  We now just need to get the picture to come directly from the DDR3 with the new maggie.  Then think about optimizing the geometry unit to work as fast as possible when drawing on the DDR3 plus update it to render with 16bit coordinates and address 32bits so it may draw within the full 512mb of available ram.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 14, 2021, 01:42:12 pm
With the geometry unit reading and writing to the DDR3, and the Z80 not generating errors, we can safely say that my DDR3 controller works with a Z80 and GPU.  We now just need to get the picture to come directly from the DDR3 with the new maggie.  Then think about optimizing the geometry unit to work as fast as possible when drawing on the DDR3 plus update it to render with 16bit coordinates and address 32bits so it may draw within the full 512mb of available ram.

That'll make a huge difference as it means I won't be restricted by the block RAM size anymore - 640x480x8 here we come! Hopefully. ;)  Okay, cool - what do you want me to do?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 14, 2021, 02:12:00 pm
Ok, step 1:

Make take my 'BrianHG_DDR3_DECA_Show_1080p' project and use it's video output section trimmed down to 8 bit color and add a dummy palette between the 8 bit video output to drive a 32bit color result.  Change the PLL to 74.25MHz and the video settings to 720p.

(You will need to engineer a 32bit .mif file, 8 bit address input, 32 bit data out as your ARGB color.)

I would engineer and play with this as a new 'BrianHG_DDR3_DECA_Show_1080p' project first before committing to the GPU as the compile time is quick.  Note you can change the IO for the RS232 debugger so you may test writing data to the pixels.

Since the screen is 900kb, and you geometry unit can only address 1024kb and the Z80 can only do 512k, begin the screen base address memory at 64kb so that the Z80 can at least upload the font from Z80 into the beginning of memory.

Next, moving onto the GPU...

In your GPU, erase your:
GPU_HW_Control_Regs
data_mux_geo
sync_generator
vid_osd_generator
vid_out_stencil

Now, your output will be hard-wired 1280x720 8 bit color.  Graphics only.  1 layer.  So, you will need to blitter all your text setting the geo source to 1 bit color for the font, and 8 bit color for the output screen just like before.  All your other control regs are now gone.  (You can use the scale setting in the blitter to get a simulated 640x360 clean, or 640x480 with some scaling chunks on the Y axix, or, find a 16x24 font and without scaling, get the best Z80 text you have seen yet.)

In fact, with all the erased modules, it might be easier to just add the 'Z80_bus_interface' and 'geometry_processor', the only 2 modules from the old GPU, and add them into the 'BrianHG_DDR3_DECA_Show_1080p', rename it project as your new GPU project.

Note that the read and write channel numbers for the Z80 and geometry unit should remain the same and my single 1080p maggie channel should be moved onto the next additional DDR3 read channel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 19, 2021, 05:19:20 pm
Okay, literally just had ten minutes to scan your post.  Confused is an understatement, so I'm going to have to take granny steps to make sure I'm not doing it all wrong.  :-\

I've copied your 'BrianHG_DDR3_DECA_Show_1080p' project, renamed it to something similar to our existing project and amended the project top-level files and Quartus meta-project files accordingly.  I've copied across Z80_Interface and geometry_processor files.  I've zipped the project up and attached it for reference.

Make take my 'BrianHG_DDR3_DECA_Show_1080p' project and use it's video output section trimmed down to 8 bit color and add a dummy palette between the 8 bit video output to drive a 32bit color result.  Change the PLL to 74.25MHz and the video settings to 720p.

Which file am I editing for these changes?  Just give me a few more pointers so I know I'm hunting in the right place for these settings. ???

(You will need to engineer a 32bit .mif file, 8 bit address input, 32 bit data out as your ARGB color.)

This is a new palette table?

Since the screen is 900kb, and you geometry unit can only address 1024kb and the Z80 can only do 512k...

... without an internal MMU managed by the Z80_Interface to switch to different 512KB blocks of DDR3.  Once I've gotten my head around how the new memory will be set up etc, shouldn't take long for me to create an MMU controlled by an additional IO port for the host.

Now, your output will be hard-wired 1280x720 8 bit color.  Graphics only.  1 layer.  So, you will need to blitter all your text setting the geo source to 1 bit color for the font, and 8 bit color for the output screen just like before.  All your other control regs are now gone.  (You can use the scale setting in the blitter to get a simulated 640x360 clean, or 640x480 with some scaling chunks on the Y axix, or, find a 16x24 font and without scaling, get the best Z80 text you have seen yet.)

Yeah, I think we're going to have to break this down into simpler steps so I don't royally mess this up.  Sorry.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 19, 2021, 05:55:40 pm
Don't go too far too quick.
Before adding any Z80 bus or geometry unit, first take a look at the existing deca vpg files, it's pll and my bitmap display system.

You want to change the deca video mode from it's dedicated vpg pll settings and and comment in it's 720p settings in it's vpg section.

Then on my pixel address read generator, you also want to change to a 720p resolution with 8 bit color.

You can test uploading an image via rs232 debugger after you match the GPIO for the RXD/TXD to your current PCB.

But again, start with getting a 720p out.

Then we can look at hooking up the z80 and geo units.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 19, 2021, 06:12:30 pm
I dont know anything about Z80 MMUs.  The only experience I ever had with 8 bit systems was the 6502 where we used bank switching.

For now, isn't 512k access enough?

Remember, it is the geometry unit which will access the graphics higher memory, you do not need to give the Z80 full access, only enough for uploading a font.

You will need to explain the earlier mentioned 16k system, what it doe, how it works...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2021, 02:09:41 am
Begin with taking a look at folder vpg_source.

Inside BHG_vpg.v, create a new video mode 720p in the assign section at the bottom.

This wasn't my original code, so you will have to deal with the math.  I've attached a 1080p and 720p standard so you may work out the true 720p numbers.

Next you will need to fix the PLL located in sub-folder 'pll' and edit file pll.v.
I would just change the 'altpll_component.clk0_divide_by = 100,' to 200 making the PLL 74.25 MHz.
Next, check that you are getting a 720p video output.

Next, go to the inputs on my 'BrianHG_display_rmem' initiation and fix them up for a 720p output.

Also inside 'BHG_vga_generator', you will want to make the 'altsyncram   Line_Buffer_DP_ram' buffer address and output 8 bit instead of 32 bit.  Just copy the r/g/b all to the 1 new 8 bit output making a monochrome image.

Get this much working and feed some data into the DDR3 via RS232 debugger and you should see a B&W image.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2021, 04:05:53 pm
Uhh, I'm clearly missing something or doing something wrong, I can't get valid video output at all.  I've got the project set up as you said, then amended GPU_DECA_DDR3_top.sv and BHG_vpg.sv for 720x480 output, but what am I missing?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2021, 04:27:37 pm
You are running the PLL at 148.5MHz.
That's 330Hz progressive at 720x480.
Can your monitor show that?
I know mine cant.
Inside PLL.v you have:
Code: [Select]
altpll_component.clk0_divide_by = 100,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 297,
That's 50MHz divide by 100=0.5Mhz, multiply by 297=148.5MHz.
Try changing the divide by to 50 and the multiply by to 27.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2021, 04:31:40 pm
Also, for my module BrianHG_display_rmem settings, you may use 640x480 and also set the .DISP_bitmap_width to 640.  This way, the bitmap and display res will be compatible with your current 640x480 settings except you will see a little repeat of the bitmap on the right hand side of the screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2021, 05:05:10 pm
Yeah, that's it.  Knew I'd missed something. ::)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1303088)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2021, 05:13:35 pm
Ok, that looks correct.

Next, we can move to 8 bit pixels.

This means changing how 'BHG_vga_generator' addresses the output of the 'Line_Buffer_DP_ram', going from 32bits down to 8 bits.

Then, taking that 8 bits and piping it through a second 256 word x32bit rom/altsyncram with .mif file containing your palette and for now, let's ignore the incurred 2 pixel delay unless you want to go ahead and fix that.  (We will be changing this module anyways into the new MAGGIE & BART, so don't worry about the fine details...)


Next, wire in the Z80bus to the DDR3.

Then wire in the geometry unit to the Z80 bus and DDR3.
Now, you should have your first accelerated 640x480 256 color display working on your Z80.

You may then upgrade your resolution to 1280x720, IE 720p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 20, 2021, 08:27:32 pm
Next, we can move to 8 bit pixels.

This means changing how 'BHG_vga_generator' addresses the output of the 'Line_Buffer_DP_ram', going from 32bits down to 8 bits.

Okay, but it looks like the Line_Buffer_DP_ram instance output is all high (well, data_b is anyway)?   Very confused about how that all works, tbh.

Then, taking that 8 bits and piping it through a second 256 word x32bit rom/altsyncram with .mif file containing your palette and for now, let's ignore the incurred 2 pixel delay unless you want to go ahead and fix that.

So I need to create another altsyncram instance, 256x32 bits in size, with its contents set by a .mif file that I need to generate, with one address and data input (in case I want to change palette values on the fly?) and one data output.  The address input of this second altsyncram instance needs to be the 8-bit output from the Line_Buffer_DP_ram instance, and the palette altsyncram instance's output needs to be a 32-bit value that is fed to... here?

Code: [Select]
CMD_line_mem_wdata
Is that right? :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 20, 2021, 08:55:26 pm
Next, we can move to 8 bit pixels.

This means changing how 'BHG_vga_generator' addresses the output of the 'Line_Buffer_DP_ram', going from 32bits down to 8 bits.

Okay, but it looks like the Line_Buffer_DP_ram instance output is all high (well, data_b is anyway)?   Very confused about how that all works, tbh.

Ok, how it works...

Port A/clock0 is hard wired as a write data located on the DDR3 CMD_CLK domain.
It is 128bits since this is the DDR3 bus width and that is the fastest way to get DDR3 read data into the buffer.
This buffer was designed to be 2 lines of video long.  IE, the DDR3 will fill 1 line in the buffer as the output shows the alternate line in the buffer.
------------------------
Port B/clock1 is hard wired to be 32bits wide and clocked on the VGA pll output clock domain.  On each horizontal line, it will show/draw the opposite line which Port A is working on filling from the DDR3.
Now when reading pixels,  since the read address points to 32bit instead of 128bits, and the data is in the wrong Endian, I'm inverting the bottom 2 bits flipping around the order of every 4 pixels being shown.
Here is what I'm asking you to change, hard wire that port B output to 8 bit and adjust the read pixel address.  Don't forget that this will change the read address width.  IE: .widthad_b, .width_b, &, .numwords_b.

You want 8 bit pixels since 8 bit mode is compatible with the current geometry unit.  IE, you must set the video output mode to 8 bit when writing or blitting graphics.

You also want a palette ram at the output since 256 shades of grey is boring.
Quote

Then, taking that 8 bits and piping it through a second 256 word x32bit rom/altsyncram with .mif file containing your palette and for now, let's ignore the incurred 2 pixel delay unless you want to go ahead and fix that.

So I need to create another altsyncram instance, 256x32 bits in size, with its contents set by a .mif file that I need to generate, with one address and data input (in case I want to change palette values on the fly?) and one data output.  The address input of this second altsyncram instance needs to be the 8-bit output from the Line_Buffer_DP_ram instance, and the palette altsyncram instance's output needs to be a 32-bit value that is fed to... here?

Code: [Select]
CMD_line_mem_wdata
Is that right? :o

No writing to the palette yet.  You just want a default which will give you some color for your text/graphics tests.  Palette writing will come with the new BART system.


Don't worry about the huge wasted dual port memory for 2 lines of 32bit color video at 2048 pixels long for 1080p.  I'm working on a sequential filling as needed tiny 1kb buffer for the MAGGIE instead of this huge 2 line 16kb buffer.  You need 1 of these buffers per maggie layer and 16 layer x16kb would eat up the entire FPGA's blockram.  But the minimum 1kb means 16 maggie layers would eat up 16kb of block ram.  Not to mention having a 1kb palette for every 2 layers eating away another 8kb.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 24, 2021, 06:58:50 pm
Port A/clock0 is hard wired as a write data located on the DDR3 CMD_CLK domain.
It is 128bits since this is the DDR3 bus width and that is the fastest way to get DDR3 read data into the buffer.
This buffer was designed to be 2 lines of video long.  IE, the DDR3 will fill 1 line in the buffer as the output shows the alternate line in the buffer.
------------------------
Port B/clock1 is hard wired to be 32bits wide and clocked on the VGA pll output clock domain.  On each horizontal line, it will show/draw the opposite line which Port A is working on filling from the DDR3.
Now when reading pixels,  since the read address points to 32bit instead of 128bits, and the data is in the wrong Endian, I'm inverting the bottom 2 bits flipping around the order of every 4 pixels being shown.
Here is what I'm asking you to change, hard wire that port B output to 8 bit and adjust the read pixel address.  Don't forget that this will change the read address width.  IE: .widthad_b, .width_b, &, .numwords_b.

You want 8 bit pixels since 8 bit mode is compatible with the current geometry unit.  IE, you must set the video output mode to 8 bit when writing or blitting graphics.

Something like this?

Code: [Select]
altsyncram  Line_Buffer_DP_ram (

   // ********* PORT A *************
   .address_a      ( CMD_line_mem_waddr         ),
   .clock0         ( CMD_CLK                    ),
   .data_a         ( CMD_line_mem_wdata         ),
   .wren_a         ( CMD_line_mem_wena          ),
   .aclr0          (1'b0),
   .addressstall_a (1'b0),
   .byteena_a      (1'b1),
   .clocken0       (1'b1),
   .q_a            (),
   .rden_a         (1'b1),
   
   // ********* PORT B *************
   .address_b      ( ({pixel_line, pixel_x[10:0]}) ^ 12'd3 ),  // Don't forget that Endian swap....
   .clock1         ( clk                              ),
   .q_b            ( {wvga_a, wvga_b, wvga_g, wvga_r} ),
   .aclr1          ( 1'b0 ),
   .addressstall_b ( 1'b0 ),
   .byteena_b      ( 1'b1 ),
   .clocken1       ( 1'b1 ),
   //.data_b         ({32{1'b1}} ),
   .data_b         ( { 8{1'b1} } ),
   .rden_b         ( 1'b1 ),
   .wren_b         ( 1'b0 ),
   
   .clocken2       ( 1'b1 ),
   .clocken3       ( 1'b1 ),
   .eccstatus      (      )
   
);
defparam
   Line_Buffer_DP_ram.address_aclr_b = "NONE",
   Line_Buffer_DP_ram.address_reg_b = "CLOCK1",
   Line_Buffer_DP_ram.clock_enable_input_a = "BYPASS",
   Line_Buffer_DP_ram.clock_enable_input_b = "BYPASS",
   Line_Buffer_DP_ram.clock_enable_output_b = "BYPASS",
   Line_Buffer_DP_ram.init_file = "line_buf_init.mif",
   Line_Buffer_DP_ram.init_file_layout = "PORT_B",
   Line_Buffer_DP_ram.intended_device_family = "MAX 10",
   Line_Buffer_DP_ram.lpm_type = "altsyncram",
   Line_Buffer_DP_ram.numwords_a = 1024,
   //Line_Buffer_DP_ram.numwords_b = 4096,
   Line_Buffer_DP_ram.numwords_b = 16384, // **** THIS HAS BEEN CHANGED FOR 8-BIT
   Line_Buffer_DP_ram.operation_mode = "DUAL_PORT",
   Line_Buffer_DP_ram.outdata_aclr_b = "NONE",
   Line_Buffer_DP_ram.outdata_reg_b = "CLOCK1",
   Line_Buffer_DP_ram.power_up_uninitialized = "FALSE",
   Line_Buffer_DP_ram.widthad_a = 10,
   //Line_Buffer_DP_ram.widthad_b = 12,
   Line_Buffer_DP_ram.widthad_b = 14,     // **** THIS HAS BEEN CHANGED FOR 8-BIT
   Line_Buffer_DP_ram.width_a = 128,
   Line_Buffer_DP_ram.width_b = 8,        // **** THIS HAS BEEN CHANGED FOR 8-BIT
   //Line_Buffer_DP_ram.width_b = 32,
   Line_Buffer_DP_ram.width_byteena_a = 1;

Is that along the right lines, or have my guesses at the correct values completely missed the mark?  The changes to the parameters are based more on educated guesses than true understanding of how they relate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2021, 07:41:39 pm
Correct except for this line:
Code: [Select]
   .address_b      ( ({pixel_line, pixel_x[10:0]}) ^ 12'd3 ),  // Don't forget that Endian swap....
You now need 2 more bits in the read address and remember 8 bit has 16 pixels inside 128 bit, not 4 pixels.

It should look something like this:

Code: [Select]
   .address_b      ( ({pixel_line, 2'b00, pixel_x[10:0]}) ^ 12'd15 ),  // Don't forget that Endian swap....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 24, 2021, 09:43:22 pm
Correct except for this line:
Code: [Select]
   .address_b      ( ({pixel_line, pixel_x[10:0]}) ^ 12'd3 ),  // Don't forget that Endian swap....
You now need 2 more bits in the read address and remember 8 bit has 16 pixels inside 128 bit, not 4 pixels.

It should look something like this:

Code: [Select]
   .address_b      ( ({pixel_line, 2'b00, pixel_x[10:0]}) ^ 12'd15 ),  // Don't forget that Endian swap....

Okay, that makes sense I guess.  :-+

So now I need to create another altsyncram for the palette memory and a .MIF with some palette values?  I'm a little unsure how this will be wired into the existing Line_Buffer_DP_ram instance.  For some reason I'm confused about the Port A/Port B business.  Port A appears to be permanently reading data, Port B permanently writing data?  Or should that be the other way around?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 24, 2021, 09:57:44 pm
Well, this line:

Code: [Select]
.q_b            ( {wvga_a, wvga_b, wvga_g, wvga_r} ),
Is returning the current read as 32 bit data.  The problem is that the data is now only 8 bit.
What you want is a single 8 bit wire placed inside the brackets here.

That 8 bit wire will feed the 8 bit read address of your 32bit palette ram.
That 32bit read data out will then become equivalent to the line above giving you the 32bit palette colored pixels.

The write enable & write address will be disabled.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2021, 07:57:55 am
:palm: Of course.  I'd completely missed the .q_a/b outputs from the syncram.   I was trying to work out how the data was coming out of the syncram and had completely missed those connections.

The palette RAM doesn't need to be dual-port, does it (at least not initially)?  The 8-bit feed from the line buffer will supply the address, the 32-bit data out (.q) will feed these wires below?

Code: [Select]
{wvga_a, wvga_b, wvga_g, wvga_r}
I suppose I'd set it up as DP ram, but leave port B disconnected for the moment?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2021, 08:10:22 am
If you are copying the above 'altsyncram' for the palette, then, port b is the read and port a will be connected to ( 0 ),.

The size is 256x32.
For now, match port a to that as well.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2021, 08:12:49 am
Here's a stab at setting up the palette syncram:

Code: [Select]
// Initiate the 32-bit palette memory.
altsyncram  Palette_DP_ram (

   // ********* PORT A *************
   .clock0         ( clk          ),
   .address_a      ( palette_addr ),
   .data_a         ( { 8{1'b1} }  ),
   .wren_a         ( 1'b0 ),
   .aclr0          ( 1'b0 ),
   .addressstall_a ( 1'b0 ),
   .byteena_a      ( 1'b1 ),
   .clocken0       ( 1'b1 ),
   .q_a            ( {wvga_a, wvga_b, wvga_g, wvga_r} ),
   .rden_a         ( 1'b1 ),
   
   // ********* PORT B *************
   .clock1         (  ),
   .address_b      (  ),
   .data_b         ( { 8{1'b1} } ),
   .wren_b         ( 1'b0 ),
   .aclr1          ( 1'b0 ),
   .addressstall_b ( 1'b0 ),
   .byteena_b      ( 1'b0 ),
   .clocken1       ( 1'b0 ),
   .q_b            (  ),  // output
   .rden_b         ( 1'b0 ),
   
   .clocken2       ( 1'b1 ),
   .clocken3       ( 1'b1 ),
   .eccstatus      (      )
   
);
defparam
   Line_Buffer_DP_ram.address_aclr_b = "NONE",
   Line_Buffer_DP_ram.address_reg_b = "CLOCK1",
   Line_Buffer_DP_ram.clock_enable_input_a = "BYPASS",
   Line_Buffer_DP_ram.clock_enable_input_b = "BYPASS",
   Line_Buffer_DP_ram.clock_enable_output_b = "BYPASS",
   Line_Buffer_DP_ram.init_file = "palette_init.mif",
   Line_Buffer_DP_ram.init_file_layout = "PORT_A",
   Line_Buffer_DP_ram.intended_device_family = "MAX 10",
   Line_Buffer_DP_ram.lpm_type = "altsyncram",
   Line_Buffer_DP_ram.numwords_a = 256,
   Line_Buffer_DP_ram.numwords_b = 256,
   Line_Buffer_DP_ram.operation_mode = "DUAL_PORT",
   Line_Buffer_DP_ram.outdata_aclr_b = "NONE",
   Line_Buffer_DP_ram.outdata_reg_b = "CLOCK1",
   Line_Buffer_DP_ram.power_up_uninitialized = "TRUE",
   Line_Buffer_DP_ram.widthad_a = 8,
   Line_Buffer_DP_ram.widthad_b = 8,
   Line_Buffer_DP_ram.width_a = 32,
   Line_Buffer_DP_ram.width_b = 32,
   Line_Buffer_DP_ram.width_byteena_a = 1;

palette_addr is an 8-bit wire from .q_b in the Line Buffer.  palette_init.mif is an as-yet-non-existent palette table, 256 words long by 32 bits wide.

If you are copying the above 'altsyncram' for the palette, then, port b is the read and port a will be connected to ( 0 ),.

The size is 256x32.
For now, match port a to that as well.

The above just popped up whilst I was writing this post. I'll amend the above syncram setup and post again in a sec.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2021, 08:15:13 am
Attempt 2:

Code: [Select]
// Initiate the 32-bit palette memory.
altsyncram  Palette_DP_ram (

   // ********* PORT A *************
   .clock0         (  ),
   .address_a      (  ),
   .data_a         ( { 8{1'b1} }  ),
   .wren_a         ( 1'b0 ),
   .aclr0          ( 1'b0 ),
   .addressstall_a ( 1'b0 ),
   .byteena_a      ( 1'b0 ),
   .clocken0       ( 1'b0 ),
   .q_a            (  ),
   .rden_a         ( 1'b0 ),
   
   // ********* PORT B *************
   .clock1         ( clk ),
   .address_b      ( palette_addr ),
   .data_b         ( { 8{1'b1} } ),
   .wren_b         ( 1'b0 ),
   .aclr1          ( 1'b0 ),
   .addressstall_b ( 1'b0 ),
   .byteena_b      ( 1'b1 ),
   .clocken1       ( 1'b1 ),
   .q_b            ( {wvga_a, wvga_b, wvga_g, wvga_r} ),  // output
   .rden_b         ( 1'b1 ),
   
   .clocken2       ( 1'b1 ),
   .clocken3       ( 1'b1 ),
   .eccstatus      (      )
   
);
defparam
   Line_Buffer_DP_ram.address_aclr_b = "NONE",
   Line_Buffer_DP_ram.address_reg_b = "CLOCK1",
   Line_Buffer_DP_ram.clock_enable_input_a = "BYPASS",
   Line_Buffer_DP_ram.clock_enable_input_b = "BYPASS",
   Line_Buffer_DP_ram.clock_enable_output_b = "BYPASS",
   Line_Buffer_DP_ram.init_file = "palette_init.mif",
   Line_Buffer_DP_ram.init_file_layout = "PORT_A",
   Line_Buffer_DP_ram.intended_device_family = "MAX 10",
   Line_Buffer_DP_ram.lpm_type = "altsyncram",
   Line_Buffer_DP_ram.numwords_a = 256,
   Line_Buffer_DP_ram.numwords_b = 256,
   Line_Buffer_DP_ram.operation_mode = "DUAL_PORT",
   Line_Buffer_DP_ram.outdata_aclr_b = "NONE",
   Line_Buffer_DP_ram.outdata_reg_b = "CLOCK1",
   Line_Buffer_DP_ram.power_up_uninitialized = "TRUE",
   Line_Buffer_DP_ram.widthad_a = 8,
   Line_Buffer_DP_ram.widthad_b = 8,
   Line_Buffer_DP_ram.width_a = 32,
   Line_Buffer_DP_ram.width_b = 32,
   Line_Buffer_DP_ram.width_byteena_a = 1;

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2021, 08:16:45 am
.data_a/b is 32bit.  It's the address which is 8 bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2021, 08:17:21 am
.data_a/b is 32bit.  It's the address which is 8 bit.

Dang it.  Forgot to update that line.  :o

Code: [Select]
.data_a         ( { 32{1'b1} }  ),
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2021, 08:24:18 am
Ok, make a 256 word, 32 bit .mif with some color and compile and look.

Since the DDR3 is uninitialized random junk, the .mif needs to be full with something otherwise you will see nothing but black.  For now, you can fill it with 0,0,0,0-0,255,255,255.

That can be easily enough done with Quartus generating an auto-increment per address fill in the .mif editor.

Once done, wire in the Z80 bus interface to the DDR3 ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2021, 08:55:14 am
Ok, make a 256 word, 32 bit .mif with some color and compile and look.

Since the DDR3 is uninitialized random junk, the .mif needs to be full with something otherwise you will see nothing but black.  For now, you can fill it with 0,0,0,0-0,255,255,255.

That can be easily enough done with Quartus generating an auto-increment per address fill in the .mif editor.

Yep, got a lovely random snow pattern in various colours (I went for a pseudo-colour palette rather than a greyscale).

Once done, wire in the Z80 bus interface to the DDR3 ram.

Will let you know when this is done.  Should be a straightforward cut 'n' paste from the previous project, in theory at least. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2021, 09:07:04 am
Once done, wire in the Z80 bus interface to the DDR3 ram.

Will let you know when this is done.  Should be a straightforward cut 'n' paste from the previous project, in theory at least. :-/O

Close.  You will be placing the Z80_bus_interface in the GPU_xxxxx_top.sv and wire the read write to a ddr3 read/write port 1.  Move the current show graphics port from 1 to 2.  Configure the DDR3 widths.

Once you see that the Z80 can read/write to the DDR3, next wire the geometry unit into the top and wire it's command port to the Z80 IO port and wire it's R/W to the DDR3 as seen in the previous working project.  I guess the show graphics now on port 2 will move to read port 4.  (The geometry unit uses 1 write port and 2 read ports.  Dont get them backwards as the order optimizes draw speed.)

You can change the base display ram address to give room to store a font and other stuff at the beginning of DDR3 ram.  If you configure the blitter correctly, 8bit color output/proper display raster width and base mem address, and copy over the font to DDR3, you should be able to draw on a 256 colour screen anything you like with the geometry engine.

You can then try moving up to 720p.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 25, 2021, 11:53:28 am
Close.  You will be placing the Z80_bus_interface in the GPU_xxxxx_top.sv and wire the read write to a ddr3 read/write port 1.  Move the current show graphics port from 1 to 2.  Configure the DDR3 widths.

Okay, so I'll need to wire the Z80_Bridge inputs/outputs directly to DECA IO pins, whereas previously they went through the GPU.sv intermediary.

Whilst looking through the HDL and trying to familiarise myself with the changes required, I've noticed there's some differences in parameter values between the current project and the previous working one - like CLK_IN_MULT is 32 in the current project, but it's 40 in the previous (working) version.  I know we changed some of these around because of different screen resolutions and (I think) some issues with talking with the Z80, but do we need to change any of these for the current project?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 25, 2021, 12:22:58 pm
If you feel better just placing in GPU.sv intermediary, the do so except you will want to erase everything I posted above... https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3746599/#msg3746599 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3746599/#msg3746599) ... which is pretty much everything.


Leave the clock divider at 32 as this new code has a separate PLL for the video out and we no longer need to force overclocking the DDR3.

Obviously the DDR3 number of ports and their data widths need to be adjusted.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 26, 2021, 11:42:54 am
Latest version of GPU_DECA_DDR3_top.sv attached.

I'm really struggling with this at the moment.  I'm finding myself staring at a wall of HDL code, really straining to make sense of connections and links I need to make. :palm:  I really found all this much easier with the old diagrams/graphical way of connecting modules up.  Having a long, continuous block of time to spend on it would also make my life much easier, but I have to make do with spare half-hours here and there.

Anyway, enough of me whinging and being defensive about the mistakes I'm no-doubt making, here's where I am so far and my understanding of what needs to be done:

As you'll see from the attached top-level file, I've instantiated the Z80 bridge (lines 481-635) and left the parameter settings untouched.  I've connected up the majority of the ports directly to the DECA's IO pins, leaving unused ports unconnected or still with their old wire names whilst I work out what to do with them (leave them unconnected or create matching wire names with constant values) - this relates almost solely to the legacy IO ports on lines 610-620, but the GEOFF also isn't instantiated yet and there's connections in the bridge that relate to it, so I'll leave those disconnected (although there's wire names there currently).

I've wired up a reset line to the bridge in lines 439-473 - fingers crossed that matches the old system.  I've wired the bridge clock to DDR_CLK_25 (I think that's right). :-/O

I've changed the DDR3 port value to 2 for the BrianHG_display_rmem module (lines 647-677) and BHG_vpg (lines 688-710).

I've changed PORT_R/W_TOTAL by incrementing them by 1.  Likewise, I've adjusted the values in PORT_R/W_DATA_WIDTH and _PRIORITY arrays.

Hope this is right. :-//  No, I haven't tested it yet. :-BROKE

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2021, 11:51:11 am
When interfacing with my DDR3 CMD_xxx lines, everything must be on the CMD_CLK.
Do not play with the things like the 'DDR3_CLK_25' unless you're specifically are doing something special.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 26, 2021, 11:51:58 am
When interfacing with my DDR3 CMD_xxx lines, everything must be on the CMD_CLK.

Oops.  Must have mis-traced the clock line from the bridge upwards in the old project then.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2021, 12:02:09 pm
Everything else looks ok.
Give it a try.
If the Z80 can read/write to DDR3, you should be able to draw pixels direct by the Z80.
1 byte = 1 pixel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2021, 12:08:38 pm
line 681: assign CMD_R_priority_boost[1] = 0; // The boost feature on read channel 1 is not being used.

Add a disable for the priority boost on read port#2 as well.
Same for write port #1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 26, 2021, 01:11:56 pm
Weird things are happening now.  I'm getting the technicolour snow display, no problems there.

Accessing memory is odd, however.   If I dump the first page of GPU memory, I get a page of 0x0F.  I can't write to that page.  If I switch to the second bank (second 16KB of GPU RAM), the first page displays 0x43s.  Writing to any byte in that page changes all the displayed values in that bank, and they persist if I swap banks and read another bank then switch back and read it again.

I can't see any change on the screen with writes to the GPU RAM.  I'll only be able to access a fraction of the screen though until I change the Z80 bridge settings to allow writes to larger RAM spaces.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2021, 06:35:48 pm
Ok, here you go.

Things I've changed:
Temp patch in the VPG to properly support 8 bit.  (Y_POS was inverted and on the wrong line.)
Fixed the .sdc as it was missing half the GPIO ports.
Disabled smart_bank to improve FMAX.
I corrected the palette mem 2 pixel delay.

New file '640x480_raw_8bit_bitmap.zip' has a binary .raw file you can use the rs232-debugger to upload and view.
Note, I made your palette B&W to support the bitmap.


The only thing you missed but could have caught was line 660 in GPU_DECA_DDR3_TOP.sv
Code: [Select]
   .DISP_pixel_bytes    (  3'd4                 ),    // 4=32 bit pixels, 2=16bit pixels, 1=8bit pixels.
You had to change it to a 1.

I thought you were supposed to get 512k access from your Z80.  The display is only 300kb.  So you should be able to clear and draw on this display the slow way...

Make sure the Z80 works correctly with the ram.
Then add the geometry processor.

I have V1.5 of the DDR3 controller coming tomorrow (my time, may be day after for you).
The only change is each port is a read/write port instead of separate read and write ports.
This actually simplifies wiring to the Z80 bus and I will do an example update for you to test then.

I will have to mangle together a new display processor to replace the VPG as you will want switchable modes and multiple layers with a tiny sequential display line cache buffer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 26, 2021, 09:46:11 pm
Note, I made your palette B&W to support the bitmap.

Ah, I had included a greyscale palette in the project (palette_greyscale.mif), but never mind. :)

I thought you were supposed to get 512k access from your Z80.  The display is only 300kb.  So you should be able to clear and draw on this display the slow way...

Yes that's true - the Z80 can access the bottom 512K as 16KB banks.

The Z80_Bus_Interface, however, controls what is read within that 512K.  The MEM_SIZE_BYTES parameter determines a hard limit beyond which the Z80 can't read the GPU RAM - this was to stop the Z80 reading beyond the top of the FPGA's block RAM.  It's currently set to 98,304 bytes.  Any reads beyond this value are ignored and the bridge will return 0xFF for addresses up to the last 16 bytes of the 512K.  The last 16 bytes are the BANK_ID section.  Any reads below that value should return valid DDR3 data.  Obviously that isn't an issue now, so I need to look at that limit and either remove it entirely or disable it.

The three wires at lines 252-254 in Z80_Bus_Interface.sv determine where in the GPU RAM the Z80 is trying to read/write:

mem_in_bank  is HIGH if the Z80 is addressing somewhere in the GPU's 512K window.  It should really be called mem_in_window.
mem_in_range is HIGH if the Z80 is addressing somewhere in the GPU's actual block RAM limits.  This can effectively be replaced with mem_in_bank above, as the DDR3 will always be larger than 512KB.
mem_in_ID      is HIGH if the Z80 is addressing the last 16 bytes of the 512KB window.  These last 16 bytes are the BANK_ID and allow the uCOM to identify that a GPU is available and show it's name/identifier.

Make sure the Z80 works correctly with the ram.

Unfortunately there's no change in behaviour between this latest version and the previous one, aside from a static greyscale snow pattern on the screen.

If I dump a page from a 16KB bank, the initial values seem to be one higher than the bank number.  i.e., if I dump the first page of (or any page within) bank 0x43, the initial values will all be 0x44.  Bank 0x42 is all 0x43 values, etc.  Only bank 0x40 is different (the first 16KB of GPU RAM) with 0x0F values, but probably because that could be the last value written to it as part of the screen setup in the DMI.  It seems the last value written to any bank is the only value displayed in that bank thereafter.

When I get some time (maybe tomorrow), I'll try to get some Signal Tap traces of the read/write timings for you, unless you identify the issue before then. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 26, 2021, 09:56:34 pm
I'm not sure what you have done.
Maybe a bad IO assignment?
Are you using the latest Z80 interface?
I doubt this could be the issue, but, you can try setting the DDR3 to 500MHz so that the Z80bus is running at 125MHz like it used to instead of 100MHz.  (I know with DDR3 v1.5, you could then run it at 200MHz with the DDR3 at 400MHz, but really, needing a 200MHz section to run an 8MHz CPU.)

What does the RS232 debugger tell you?
Did you load the .raw binary fine in the debugger and send it to the DDR3?

Everything seemed to work fine here except for that I don't have a Z80 to test with.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 27, 2021, 07:55:59 am
I'm not sure what you have done.
Maybe a bad IO assignment?
Are you using the latest Z80 interface?
I doubt this could be the issue, but, you can try setting the DDR3 to 500MHz so that the Z80bus is running at 125MHz like it used to instead of 100MHz.  (I know with DDR3 v1.5, you could then run it at 200MHz with the DDR3 at 400MHz, but really, needing a 200MHz section to run an 8MHz CPU.)

I'll double-check the IO assignments later, but they're basically a copy-paste from GPU.sv that fed the Z80_Interface the IOs.

What does the RS232 debugger tell you?
Did you load the .raw binary fine in the debugger and send it to the DDR3?

Didn't have time last night to set up the debugger.  Likewise was unable to get Signal Tap traces.  Will hopefully be able to do both at some point today.

Everything seemed to work fine here except for that I don't have a Z80 to test with.

I'll be sending you a basic system to test on very shortly.  I'm just waiting on a component which should arrive today/tomorrow, then I can assemble and test the latest DECA interface card and get a system on its way to you. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 27, 2021, 09:52:29 pm
Okay, fixed the memory access issue.  I'd not copied some key lines from the GPU.sv file to the new _top file that were setting default directions/enables for the address buffers and command control outputs.

New (working) GPU_DECA_DDR3_top.sv attached.  Lines 438-450 are the fix.

I'm able to clear the screen and read and write values to anywhere in the lower 512KB of DDR3, with the uCOM detecting the GPU thanks to the BANK_ID at the very top of the 512KB.  All looking good so far! :-+

Haven't tested the image via the debugger yet - maybe have time tomorrow for that - but can't see that the debugger should have issues read/writing the DDR3 RAM, unless it's not wired up correctly.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 27, 2021, 10:12:16 pm
Ok, next, wire in the 'geometry_processor   GEOFF' and get the accelerated text working.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 28, 2021, 08:50:04 am
Hit a minor syntax issue with wiring GEOFF up.  Line 700 in the attached GPU_DECA_DDR3_top file - I can't work out how to write that I need the first 20 bits of (PORT_ADDR_SIZE)'(CMD_waddr[2]).  Wherever I put the [19:0] it causes Quartus to throw a wobbly. :-//

Also, while you're looking at it, can you confirm that I've not messed up PORT_R/W_TOTAL and associated DATA_WIDTH and PRIORITY arrays? ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 28, 2021, 12:55:10 pm
Ok, I cleaned everything up.
On the number of write channels, you go 1 extra write channel which wasn't in use.

Also, I had to add and clean up the unused input assignments.

Also, I made an addition to the geometry processor and pixel writer adding a separate output for the read address of the copy pixel channel to help with quartus routing.

You still need to assign a copy of the main pixel write channel's address read channel to it's write address.  See line 714.

System clock 4 is only achieving 80MHz out of the required 100.  Hopefully the system will still work as with my DDR3 V1.5, this FMAX bottleneck in the multiport controller has been solved 3 fold, though, now it's the speed of the ellipse generator which maxes out at ~150MHz though you will be able to run the multiport in v1.5 in half-rate mode at 200MHz with 400MHz ram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 28, 2021, 01:23:41 pm
You still need to assign a copy of the main pixel write channel's address read channel to it's write address.  See line 714.

Bit confused by this - is this something I need to do, or something you've done that you're pointing out I missed?

I've tried variations on:

Code: [Select]
assign CMD_raddr           [3] = CMD_waddr[2] ; // Read address 2 shares write address 2.
With assigning raddr to waddr and vice versa, changing the port numbers, but nothing is compiling.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 28, 2021, 05:04:00 pm
I tried compiling the project I sent you in the last thread.  It works.  It should compile.
This is how I know that the FMAX of clock[4] was 80MHz.
IE: the file 'GPU_DECA_DDR3_DDR3only_with_GEO.zip' was a complete functional compiling project.

Line 714 is there.  I did the assign for you.

You should be rendering text by now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 28, 2021, 09:38:41 pm
I tried compiling the project I sent you in the last thread.  It works.  It should compile.
This is how I know that the FMAX of clock[4] was 80MHz.
IE: the file 'GPU_DECA_DDR3_DDR3only_with_GEO.zip' was a complete functional compiling project.

Line 714 is there.  I did the assign for you.

Ah, well chalk that one up to me misunderstanding what you'd written.  It looked (to me) like you were asking me to add another assign.

You should be rendering text by now.

Unfortunately, no.  The project you posted compiles, but it doesn't work very well.  There's a funny pattern on the screen consisting of vertical bars, fading from white to black with dark horizontal lines every other line.  If I try to view GPU memory - any page or bank - it takes a couple of seconds to display the dump (i.e. it looks like WAIT states are being inserted) and all I'm seeing are 0x7Es, no actual DDR3 RAM contents.  I'm unable to write to GPU RAM. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 28, 2021, 10:12:30 pm
Ok, I see the pattern.
Need to hook up the RS232 debugger and see whats going on.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 28, 2021, 10:21:23 pm
Ok, it looks like the problem is on line 739 of the gpu_deca_DDR3_top.sv.

Code: [Select]
   .PORT_R_DATA_WIDTH   ( PORT_R_DATA_WIDTH[2]  )   // Width of read port.  Always use the 'PORT_CACHE_BITS' for the read port for the most efficient continuous bursts.

You forgot to change the data width to port number 4 where the display is reading memory from.

IE:
Code: [Select]
   .PORT_R_DATA_WIDTH   ( PORT_R_DATA_WIDTH[4]  )   // Width of read port.  Always use the 'PORT_CACHE_BITS' for the read port for the most efficient continuous bursts.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 28, 2021, 10:33:40 pm
 :palm: You also made changes to the Z80 bus interface.

Update the version in the project with your working one here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3774773/#msg3774773 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3774773/#msg3774773)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 29, 2021, 06:38:53 am
:palm: You also made changes to the Z80 bus interface.

That's why I attached it earlier in the post you'd linked.  I should have mentioned that I'd made some adjustments for the RAM size and BANK_ID.

Ok, it looks like the problem is on line 739 of the gpu_deca_DDR3_top.sv.

Code: [Select]
   .PORT_R_DATA_WIDTH   ( PORT_R_DATA_WIDTH[2]  )   // Width of read port.  Always use the 'PORT_CACHE_BITS' for the read port for the most efficient continuous bursts.

You forgot to change the data width to port number 4 where the display is reading memory from.

IE:
Code: [Select]
   .PORT_R_DATA_WIDTH   ( PORT_R_DATA_WIDTH[4]  )   // Width of read port.  Always use the 'PORT_CACHE_BITS' for the read port for the most efficient continuous bursts.

Ah yes, that's sorted it.  :-+

Don't know if GEOFF is supposed to be fully working, but it's not changing RAM at all when I attempt to draw, say, a filled rectangle or anything.  It might be because I haven't updated the graphics driver for the new 8 bpp mode yet, but there should be something written even if it doesn't make sense in the new 8bpp mode?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 29, 2021, 07:51:05 am
Yes, data should write, even if the depth is wrong.
remember, with a monochrome palette, color 1 will be practically invisible.  You need to plot color 255 for white.

Try plotting a pixel at 0x0 and read the DDR3 contents in the Z80 and/or debugger.

Also, change the HSE and VSE inputs to the CMD_CLK versions (lines 682/683):
Code: [Select]
   .hse              ( CMD_vid_xena ), // Horizontal sync signal from VIGEN.
   .vse              ( CMD_vid_yena ), // Vertical   sync signal from VIGEN.

If it stays black, try setting the pixel to white with the Z80 writing mem, the plot the pixel again.  Maybe it will write black.

If you cannot get it to write, then you will need to roll back the:
geometry_processor and pixel_writer
to the one we had when the DDR3 text functioned properly.
It is the one where the 'CMD_raddr[3]' is a copy of '.ram_addr' instead of the new '.ram_addr_C'.  I might have made a mistake in the modifications.

Also make sure the write mask for channel 2 is enabled.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 29, 2021, 09:22:24 am
If all fails, make sure that the working DDR3 geo version is actually writing to the DDR3, not just reading from it.  To do this, draw using the geometry unit and read back using the Z80 making sure there is a change.

You can also try changing the compiler optimization technique from balanced to speed.  Right now, we are overclocking the multiport and it may just be failing to send writes to the DDR3 from port number 2.  You can also try slowing down the DDR3 from 400MHz to 300MHz.  This should make achieving timing much easier.


ALSO:  Are you sure the write port to the geometry unit is working?  Maybe it's not receiving any commands.  Maybe due to the paging or MMU stuff you changes...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 29, 2021, 09:34:35 am
Also move lines 666 through 672 to before the initiation of Z80 bus interface at line 498.  You need to define the wires before you begin to use them, not after.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 29, 2021, 12:18:23 pm
I haven't got the time to put into this that I need today, unfortunately, otherwise I'd be doing Signal Taps and confirming RAM contents with the debugger.  Just by way of a quick update, though:

Yes, data should write, even if the depth is wrong.
remember, with a monochrome palette, color 1 will be practically invisible.  You need to plot color 255 for white.

I can see pixels changing value at the top of the screen where text-tile mode is used by the bootstrap when I first turn on the uCOM, but not a lot happens once I switch to the DMI which uses blitting instead of text-tile mode.  I'm wondering if you might be on to something with this comment:

Also make sure the write mask for channel 2 is enabled.

I don't think I've got a write mask for channel 2 at all.  I can only see references to CMD_wmask[0] in the _top file.  I've got to rush out again. ::)  Hopefully I'll have more time tomorrow or late tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 29, 2021, 10:05:51 pm
Okay, I have no idea what's going on with the write masks it seems.  It appears that a write mask exists for Port 3, as it's set in line 717 of the _top file to 3, which means writes should be possible to the first two bytes (or 16 bits, which is the bit-width of that port).

The write port width array on line 91 appears incorrect, however.  It specifies 8, 8, 16, 32 - so 8-bit-wide ports for the debugger and Z80 bridge, 16-bits wide for GEOFF.  Not sure what the 32 is for - there are only three write ports, so that port isn't used?

Updated _top and bridge files attached - these are my latest versions containing the changes made as as a result of your previous post, so the line numbers above are relevant to these files.  Tomorrow I'll start Signal Tracing and debugging to find out what's going on with the GEOFF writes.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 29, 2021, 11:36:12 pm
Ok, item 1 in geo_pixel_writer.sv, (My bad...)

Comment out line 172, comment in line 171.

Item 2 in _top.sv, lines 664,665:
Change one of those 'CMD_R_priority_boost' into a 'CMD_W_priority_boost'.

Also, to help FMAX, try changing line 711 from:
Code: [Select]
   .ram_mux_busy     ( CMD_W_busy[2] || CMD_R_busy[2] || CMD_R_busy[3] )  // || geo_port_full ), // input from geo_port_full
to
Code: [Select]
   .ram_mux_busy     ( CMD_W_busy[2] )  // input from geo_port_full
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 09:03:15 am
That's working now.  :-+

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311044)

That's the old blitted-text mode (1 bpp) you can see at the top of the screen, showing CP/M and a large white triangle drawn across the screen using GEOFF.

Just need to update the graphics driver for the new 8 bpp mode. :-/O

These are the timings I'm getting from this build:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311050)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 10:23:48 am
Looking good.
Don't forget to move the screen base address away from 0 so that you have room for the Z80 to store fonts.
See line 749 in _top.
Code: [Select]
   .DISP_mem_addr       ( 32'h00000000          ),    // Beginning memory address of bitmap graphic pixel position 0x0.
Don't worry about the FMAX.  My DDR3 V1.5 multiport is now working.  That CLK[4] 71MHz is no longer a problem even with 16 or even more read/write ports.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 10:45:38 am
No worries - have moved the base address back to 1200H where it was before for the moment whilst I'm working on the display driver.  Had to do some workarounds for the previous screen modes that I'm having to backtrack on now - like I was using the same colour for foreground and background previously, whereas I can now use completely separate values for the pen and paper.

Here's a screenshot of progress so far, with a mid-grey background to show the display area of the screen.  I haven't quite got the settings right - since changing the base address, I'm now getting the extra bit of text appearing down the right hand side of the screen.

Also getting individual black pixels against the background that I've noticed and highlighted in the attached image.  Not sure what their source is, to be honest. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 11:08:26 am
That extra bit of text on the right is there because the display area is 720x480 and you have my display address generator set to 640x480.  Change all the 640s to 720, as well make the changes in your Z80 code as well to recognize a 720 pixel wide screen and everything will look good.

As for the pixel dots, maybe try this.  In 'geo_pixel_writer.sv' line 173, change it from:

Code: [Select]
    ram_addr_C[19:0] = pixel_cmd_data[19:0] ; // select the R/W address.
to

Code: [Select]
    ram_addr_C[19:0]   = wr_ena_ladr ? wc_addr[19:0] : pixel_cmd_data[19:0] ; // select the R/W address.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 11:56:48 am
 |O

For some reason I can't fix this Y_INC offset problem since changing to 720x480.  At least I assume it's Y_INC that's the problem, but I've sought out every mention of 640 pixels wide (and 639, where if it cropped up), and replaced them with 720s as appropriate, but I'm getting this on the screen:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311137)

Any ideas what I'm missing?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 12:07:50 pm
That extra bit of text on the right is there because the display area is 720x480 and you have my display address generator set to 640x480.  Change all the 640s to 720, as well make the changes in your Z80 code as well to recognize a 720 pixel wide screen and everything will look good.

As for the pixel dots, maybe try this.  In 'geo_pixel_writer.sv' line 173, change it from:

Code: [Select]
    ram_addr_C[19:0] = pixel_cmd_data[19:0] ; // select the R/W address.
to

Code: [Select]
    ram_addr_C[19:0]   = wr_ena_ladr ? wc_addr[19:0] : pixel_cmd_data[19:0] ; // select the R/W address.

That's got rid of the 'dead' pixels. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 12:34:58 pm
|O

For some reason I can't fix this Y_INC offset problem since changing to 720x480.  At least I assume it's Y_INC that's the problem, but I've sought out every mention of 640 pixels wide (and 639, where if it cropped up), and replaced them with 720s as appropriate, but I'm getting this on the screen:

Any ideas what I'm missing?

Remember, there are no MAGGIE controls anywhere.  The screen is hard wired.
Please show me the settings you used for my 'BrianHG_display_rmem'.

The one and only thing you should have done is change both:
Code: [Select]
   .DISP_bitmap_width   ( 16'd640               ),    // The bitmap width of the graphic in memory.
   .DISP_xsize          ( 14'd640               ),    // The video output X resolution.

To 720.

In your code, the  (see: GEO_tb_Blitter.txt in the geometry test bench)
@SET_PAGET  dest 00a000 640 8
should change to:
@SET_PAGET  dest 00a000 720 8

(assuming you want 00a000  as your display base address)

(See: GEO_tb_command_results.txt  in the geometry test bench after running a 'setup_ModelSim.do' then a 'test_blitter.do')
From
Code: [Select]
Line#  98, SET_PAGET Dest addr(h00a000) width(  640) depth( 8)
           TX CMD > $e00a  =  (224) - ( 10) = (11100000 00001010).
           TX CMD > $a000  =  (160) - (  0) = (10100000 00000000).
           TX CMD > $f000  =  (240) - (  0) = (11110000 00000000).
           TX CMD > $b280  =  (178) - (128) = (10110010 10000000).
           TX CMD > $7e07  =  (126) - (  7) = (01111110 00000111).
           TX CMD > $7107  =  (113) - (  7) = (01110001 00000111).
to:
Code: [Select]
Line#  98, SET_PAGET Dest addr(h00a000) width(  720) depth( 8)
           TX CMD > $e00a  =  (224) - ( 10) = (11100000 00001010).
           TX CMD > $a000  =  (160) - (  0) = (10100000 00000000).
           TX CMD > $f000  =  (240) - (  0) = (11110000 00000000).
           TX CMD > $b2d0  =  (178) - (208) = (10110010 11010000).
           TX CMD > $7e07  =  (126) - (  7) = (01111110 00000111).
           TX CMD > $7107  =  (113) - (  7) = (01110001 00000111).


Also don't forget to change:
@SET_MAX_XY  640 480             Sets the pixel writer coordinate XY limits.
to
@SET_MAX_XY  720 480             Sets the pixel writer coordinate XY limits.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 01:41:20 pm
|O

For some reason I can't fix this Y_INC offset problem since changing to 720x480.  At least I assume it's Y_INC that's the problem, but I've sought out every mention of 640 pixels wide (and 639, where if it cropped up), and replaced them with 720s as appropriate, but I'm getting this on the screen:

Any ideas what I'm missing?

Remember, there are no MAGGIE controls anywhere.  The screen is hard wired.
Please show me the settings you used for my 'BrianHG_display_rmem'.

The one and only thing you should have done is change both:
Code: [Select]
   .DISP_bitmap_width   ( 16'd640               ),    // The bitmap width of the graphic in memory.
   .DISP_xsize          ( 14'd640               ),    // The video output X resolution.

To 720.

Aha! That was it. :-+  I knew it was something silly I'd missed - I had made all the changes in the Z80 code, but had forgotten about it all being hardwired in HDL and having to change the settings in BrianHG_display_rmem.

720x480x8 working nicely (so far - I still have to clean up the scrolling as it's leaving artefacts when the screen scrolls upwards, but that's nothing to do with the HDL). :-+

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311188)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 01:46:45 pm
Don't worry about color.  Just do the basic draw text without transparency and make a palette where you can see the text.
We are changing the pixel writer and address generator and all other regs to support 16bit signed X&Y coordinates plus 32bit addressing for full 4gb access and displays up to 32k x 32k pixels.  Except for reading and copying and tile memory source bitmaps, we will probably be dropping support for anything other than 8bit, 16bit, 32bit displays.  This means you will be able to show and blit/copy 1/2/4/8/16/24/32 bit images, but the target color modes will only be 8/16/32 bit color.  Only the tile memory or direct showing of buffers & tiles will support the 1..32 bit, but pixel/geometric drawing destination color depths with/without blits will be limited to 8/16/32 bit.  This will multiply the draw speed in the DDR3 since we will not need to support reading the existing byte of ram, then modifying the selected bits, then writing the result color as DDR3 writes can only mask out 8 bits at a time, not individual bits.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 01:49:57 pm
You should be able to now to 1080p text and graphics.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 01:56:12 pm
Don't worry about color.  Just do the basic draw text without transparency and make a palette where you can see the text.

Oh I was just playing with the different shades of grey and being able to display multiple 'colours' on the screen at one time. ;)

Your comment re: transparency concerns me though.  I'm running the blitter in mode 3 at the moment to display text in the DMI and CP/M.  Mode 1 (CP & PM off) just displays filled rectangles for each character in the foreground colour:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311197)

(Above shows me changing the blitter to mode 1 and the subsequent result).

We are changing the pixel writer and address generator and all other regs to support 16bit signed X&Y coordinates plus 32bit addressing for full 4gb access and displays up to 32k x 32k pixels.  Except for reading and copying and tile memory source bitmaps, we will probably be dropping support for anything other than 8bit, 16bit, 32bit displays.  This means you will be able to show and blit/copy 1/2/4/8/16/24/32 bit images, but the target color modes will only be 8/16/32 bit color.  Only the tile memory or direct showing of buffers & tiles will support the 1..32 bit, but pixel/geometric drawing destination color depths with/without blits will be limited to 8/16/32 bit.  This will multiply the draw speed in the DDR3 since we will not need to support reading the existing byte of ram, then modifying the selected bits, then writing the result color as DDR3 writes can only mask out 8 bits at a time, not individual bits.

No that's fine - can't see any reason to support <8 bpp to be honest.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 01:56:39 pm
Once everything is confirmed good with the HDL, upload the project so I may convert it over to my DDR3 V1.5.

This will fix FMAX and add a port for the new system REGS and allow you access to write the palette memory as well.

Once working, we will need to make the new MAGGIE with it's new smart regs so you may get back multiple layers.

Then upgrade the pixel writer and geometry unit for all 16&32 bit regs as well.
No more stuffing bytes into compact partial 8 bit arrays to save space as the new arrays will be stored, copied to and from the DDR3 and memory address space has grown from a few 10kb to megabytes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 02:03:08 pm
You should be able to now to 1080p text and graphics.

Right, just so I don't waste too much time scratching my head and making mistakes, what do I need to change to switch to full 1080p?  This is going to involve changes to clock speeds in the video generator etc., or just the three parameters in BHG_display_rmem?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 02:21:05 pm
Ok, on 'BrianHG_display_rmem' lint 737 _top. (change DDR3 read memory display size)


Code: [Select]
   .DISP_bitmap_width   ( 16'd1920               ),    // The bitmap width of the graphic in memory.
   .DISP_xsize          ( 14'd1920               ),    // The video output X resolution.
   .DISP_ysize          ( 14'd1080               ),    // The video output Y resolution.

Next, vpg_source/pll/pll.sv lines 107-109 (Change PLL to output 148.5MHz)
Code: [Select]
altpll_component.clk0_divide_by = 100, // Make this 200 for 74.25MHz.
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 297,

Next, sync generator settings vpg_source/BHG_vpg.v:
disable lines 164-166
enable lines  179-181

don't forget to '@SET_PAGET  dest 00a000 1920 8'
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 02:30:12 pm
 :palm: Your current GEOMETRY address output is only 20 bits long.  Sorry.  You can do 720p's 1280x720 which is 921600 bytes for 8 bit color, but not 1080p which requires 1 more address line because it is 2073600 bytes which requires 21 address lines.  At least once we upgraded this to 32bits, we will never speak of it again.  (Now, never come back to me and say you want a Z80 to access a video card with more than 4 gigabytes of ram on it.  Your life is on the line here.)  Remember, we designed this to work on a 6k gate FPGA.  Every logic cell counted.

Ok, you need to run the PLL at 74.25MHz and add a new mode in the vpg_source/BHG_vpg.v.

I mentioned the math here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3758837/#msg3758837 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3758837/#msg3758837)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 02:48:17 pm
Not sure what's going on here - made the changes you mentioned above, just getting this on-screen now:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311230)

Can read/write RAM fine, but can't seem to clear what's on the screen.  Can't see any screen changes from anything being written to RAM - haven't noticed any major issues with timing in the build report either, other than this in the setup summary:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1311236)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 02:58:57 pm
Sorry, just seen this post - must have missed it when I posted my last.

:palm: Your current GEOMETRY address output is only 20 bits long.  Sorry.  You can do 720p's 1280x720 which is 921600 bytes for 8 bit color, but not 1080p which requires 1 more address line because it is 2073600 bytes which requires 21 address lines.  At least once we upgraded this to 32bits, we will never speak of it again.  (Now, never come back to me and say you want a Z80 to access a video card with more than 4 gigabytes of ram on it.  Your life is on the line here.)  Remember, we designed this to work on a 6k gate FPGA.  Every logic cell counted.

You know, I was more than happy with 640x480 originally. ;)

Ok, you need to run the PLL at 74.25MHz and add a new mode in the vpg_source/BHG_vpg.v.

I mentioned the math here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3758837/#msg3758837 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3758837/#msg3758837)

 :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 03:26:01 pm
OK, I think this is it:

vpg_source/BHG_vpg.v: (we are getting rid of this garbage DECA code.)
Code: [Select]
//1280x720@60, 74.25MHZ (720p)
assign {h_total, h_sync, h_start, h_end} = {12'd1649, 12'd39, 12'd259, 12'd1539};
assign {v_total, v_sync, v_start, v_end} = {12'd749, 12'd4, 12'd24, 12'd696};
assign {v_active_14, v_active_24, v_active_34} = {12'd226, 12'd418, 12'd610};

pll.v:
Code: [Select]
altpll_component.clk0_divide_by = 200, // 100=148.5MHz.
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 297,

BHG_display_rmem:
Code: [Select]
   .DISP_bitmap_width   ( 16'd1280              ),    // The bitmap width of the graphic in memory.
   .DISP_xsize          ( 14'd1280              ),    // The video output X resolution.
   .DISP_ysize          ( 14'd720               ),    // The video output Y resolution.

I've tested it on my end and I get a picture with display buffer underun problems.  It's that even odd 'Y' buffer line selection which will become obsolete soon.

Just stick with 480p until we upgrade the output.

Damn 9 minute compile time...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 03:47:20 pm
OK, I think this is it:

vpg_source/BHG_vpg.v: (we are getting rid of this garbage DECA code.)
Code: [Select]
//1280x720@60, 74.25MHZ (720p)
assign {h_total, h_sync, h_start, h_end} = {12'd1649, 12'd39, 12'd259, 12'd1539};
assign {v_total, v_sync, v_start, v_end} = {12'd749, 12'd4, 12'd24, 12'd696};
assign {v_active_14, v_active_24, v_active_34} = {12'd226, 12'd418, 12'd610};

pll.v:
Code: [Select]
altpll_component.clk0_divide_by = 200, // 100=148.5MHz.
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 297,

BHG_display_rmem:
Code: [Select]
   .DISP_bitmap_width   ( 16'd1280              ),    // The bitmap width of the graphic in memory.
   .DISP_xsize          ( 14'd1280              ),    // The video output X resolution.
   .DISP_ysize          ( 14'd720               ),    // The video output Y resolution.

Saw this post as I was compiling changes my end - pleased to say I'd done everything right apart from a few minor discrepancies in the BHG_vpg.v timings - this is what I arrived at:

Code: [Select]
//1280x720@60 74.250MHZ (720p)
assign {h_total, h_sync, h_start, h_end}       = {12'd1649, 12'd39,  12'd257, 12'd1537} ;
assign {v_total, v_sync, v_start, v_end}       = {12'd749,  12'd4,   12'd23,  12'd743}  ;
assign {v_active_14, v_active_24, v_active_34} = {12'd203,  12'd383, 12'd563}           ;

Got a 720p signal on the TV with those settings, but I'll switch to yours as I'm sure they're more accurate.

Damn 9 minute compile time...

Oh jeez, really? :o  Here I was complaining to myself that the compile time had jumped from just shy of 2 minutes to 2m12.

I got recognisable output my end, probably would have been a lot better if I sorted out the Z80 driver code to set the blitter up properly, but if you think we should stay with 480p for the moment, that's what I'll do. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 30, 2021, 04:04:01 pm
Once everything is good, upload the full project.

I'll do a test switchover to my V1.5 controller tonight.

Basically the same except each CMD_xxx is a read/write port combined instead of a separate read channel and write channel.

Basically a CMD_ena[] with a CMD_write_ena[], read vector[] / write data[] / mask[] inputs, read data[] / vector out[].  All parameters and basic functionality remain the same.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 04:15:47 pm
Once everything is good, upload the full project.

I'll do a test switchover to my V1.5 controller tonight.

Marvellous - thank you. :-+

All is good - latest version of the project attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 30, 2021, 06:58:08 pm
... apart from the issue I raised in this post: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3781079/#msg3781079 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3781079/#msg3781079)

Haven't gotten to the bottom of that one yet. ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 01, 2021, 07:25:34 pm
Demo for V1.5 of my BrianHG_DDR3_Controller here: https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3785711/#msg3785711 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3785711/#msg3785711)

And on my Github page here: https://github.com/BrianHGinc/BrianHG-DDR3-Controller (https://github.com/BrianHGinc/BrianHG-DDR3-Controller)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 02, 2021, 07:07:29 pm
... apart from the issue I raised in this post: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3781079/#msg3781079 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg3781079/#msg3781079)

Haven't gotten to the bottom of that one yet. ???

This is causing me issues now.  I'm running the DMI and CP/M with the blitter text in mode 3 (PM and CP on).  If I change the background colour, there's no change until I clear the screen with GEOFF.  The issue being that the text is getting blitted with no background colour at all.  If I turn off PM on the blitter, I'm just getting foreground-coloured squares when I type anything.

Is there any way I can specify which background colour and which foreground colour to blit the source image as?  I need to be able to colour the background behind the text - blitting the text with a custom background colour seems to be the easiest way to do it, otherwise I'll have to calculate X/Y positions for the character being blitted and get GEOFF to draw a rectangle in the background colour first, then the character in the foreground colour over it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 02, 2021, 08:00:27 pm
Remember, the font is a 1 bit color image.  With transparency on, you can make the 0 or the 1 value transparent by changing the transparent color from 0 to 1 which inverts the transparent color.

Then, when painting, you can choose what color, the '1' opaque color gets painted and XORED with on the screen when transparency is enabled.  Disabling the transparency means that both 0 and 1 are being painted together and the XOR paint color means all you can do is paste 2 adjacent colors in the palette instead of 2 hard selected colors when doing 2 x paste, with transparency on each time at the same coordinates and flipping which part of the font appears to be a '1' and a '0'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2021, 10:09:16 am
Remember, the font is a 1 bit color image.  With transparency on, you can make the 0 or the 1 value transparent by changing the transparent color from 0 to 1 which inverts the transparent color.

Then, when painting, you can choose what color, the '1' opaque color gets painted and XORED with on the screen when transparency is enabled.  Disabling the transparency means that both 0 and 1 are being painted together and the XOR paint color means all you can do is paste 2 adjacent colors in the palette instead of 2 hard selected colors when doing 2 x paste, with transparency on each time at the same coordinates and flipping which part of the font appears to be a '1' and a '0'.

Okay, so this is going to require palette modifications for whatever purpose the software needs.  I'll leave this until we've done the upgrades required to allow palette writing. :-+

In other news, the new interface card works nicely.  Can't say there's any improvement in WAIT release times, but at least now I can measure it!  See image below:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1315106)

In the SignalTap trace above, you're looking at a memory read op that has missed the cache and the Z80 bridge has signalled a WAIT to the Z80 to hang on while the data is retrieved from DDR3 memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on November 04, 2021, 11:39:54 am
nockieboy
Glad the LVC06 is working for you.
Its after the fact but just wanted say you might have needed to adjust the value of the pull-up on the wire-OR lines, interrupt, wait, etc.
Moot point now, its working.

I have to say, following this post everyday is quite a good read.

Best
Ted
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2021, 06:16:32 pm
Remember, the font is a 1 bit color image.  With transparency on, you can make the 0 or the 1 value transparent by changing the transparent color from 0 to 1 which inverts the transparent color.

Then, when painting, you can choose what color, the '1' opaque color gets painted and XORED with on the screen when transparency is enabled.  Disabling the transparency means that both 0 and 1 are being painted together and the XOR paint color means all you can do is paste 2 adjacent colors in the palette instead of 2 hard selected colors when doing 2 x paste, with transparency on each time at the same coordinates and flipping which part of the font appears to be a '1' and a '0'.

Okay, so this is going to require palette modifications for whatever purpose the software needs.  I'll leave this until we've done the upgrades required to allow palette writing. :-+


No, with 2 drawings of the same character with 2 different XOR on the source copy color which changes the transparency color, you can choose any foreground and background color combination you like.

1) Turn on blit with transparency.
2) First draw the character with copy XOR color setting of 1.  Remember, the paste color on the screen you want to show must also need to be XORed with a 1 or it will come out wrong.  This will draw the background color of the text.
3) Next draw the same character again with with copy XOR color setting of 0.  The paste color you choose will be the true actual direct color, no XOR needed.  This will draw the foreground color of the text.

Done.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2021, 11:09:41 pm
nockieboy
Glad the LVC06 is working for you.
Its after the fact but just wanted say you might have needed to adjust the value of the pull-up on the wire-OR lines, interrupt, wait, etc.
Moot point now, its working.

I'm starting to wonder if there isn't some stray capacitance in the circuit that's causing the rise time on the WAIT line to be so slow.  I've already dropped the pullup resistor on the line from 10K (or was it 4K7?) to 1K.  I'll have to go away and learn some more about capacitance and resistance and how both/either affect rise time.

I have to say, following this post everyday is quite a good read.

Thanks Ted, that's much appreciated. :)  I have frequently worried that this forum thread perhaps isn't the best place to conduct ongoing project work as BrianHG and I are doing, but I'm learning all the time from this discussion and I'm hoping that - by extension - other people are learning as well and it'll be a detailed resource for anyone wanting to do something similar in the future.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 04, 2021, 11:15:20 pm
No, with 2 drawings of the same character with 2 different XOR on the source copy color which changes the transparency color, you can choose any foreground and background color combination you like.

1) Turn on blit with transparency.
2) First draw the character with copy XOR color setting of 1.  Remember, the paste color on the screen you want to show must also need to be XORed with a 1 or it will come out wrong.  This will draw the background color of the text.
3) Next draw the same character again with with copy XOR color setting of 0.  The paste color you choose will be the true actual direct color, no XOR needed.  This will draw the foreground color of the text.

I've been stuck in the mental line of thinking that the character should be blitted in one go, so I haven't seen this solution myself until you pointed it out. :-[

So instead of messing with the blitter settings, I can just leave the blitter with Paste Mask (transparency) on and blit each character twice - once for the background, once for the foreground colours?  If I want to use transparent text, I can just miss the first blit, but if I want 'opaque' text, with a coloured background, do the two-blit method you've suggested.  I'll have a closer look at implementing this over the weekend. :-/O

How's the DDR3 update coming along?  I hope it's not causing too much stress!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 04, 2021, 11:50:52 pm
Getting a reliable 200MHz out of the DDR3 multiport is a headache as I need to do Quartus multi-minute compiles to check and I had to re-do a good portion of my multiport code.  It looks like it will take a few more days.  150MHz is now already easy-peasy but, 200MHz is the target to reach for a 400MHz DDR3 system.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 05, 2021, 01:53:27 am
So instead of messing with the blitter settings, I can just leave the blitter with Paste Mask (transparency) on and blit each character twice - once for the background, once for the foreground colours? 
You got it.  No need to change any other regs.  2 consecutive blits with just 2 different transparent & paste color settings.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 05, 2021, 04:54:36 pm
So instead of messing with the blitter settings, I can just leave the blitter with Paste Mask (transparency) on and blit each character twice - once for the background, once for the foreground colours? 
You got it.  No need to change any other regs.  2 consecutive blits with just 2 different transparent & paste color settings.

Okay, done that and tested it - here's the result:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1316366)

Take a look at the header row and address columns - they should be filled with solid colour, but have black lines between (and above/beneath) each character.  I can only guess this is because the font literally doesn't include a blank column at the far right (or left) to space the characters? Is it not wide enough for the blit settings, or am I somehow inserting a 1-pixel gap between each blitted character?  And if I am, what's going to be the easiest way to fill that gap with background colour?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 05, 2021, 05:25:43 pm
If you are using the 'space' character, it should be completely blank.
Are you sure your blit width and height is set to 8x16?

What does the geometry test-bench output when you draw 2x2 characters in the same manner?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 05, 2021, 05:54:27 pm
If you are using the 'space' character, it should be completely blank.
Are you sure your blit width and height is set to 8x16?

Ahh, that was it.  For some reason (probably to do with getting confused over which registers were 0-based), I'd set the blitter width and height to 7x15, which went undetected until now. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2021, 02:57:32 pm
Found some time to work on BBC BASIC in CP/M.  Have started adding drawing commands in - here's a little Mandelbrot the uCOM drew earlier.  It's all greyscale due to the current GPU palette, but is a good test to show that - even in its current state of partial development - the GPU is working.  :-+

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1325327)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 17, 2021, 05:07:01 pm
Found some time to work on BBC BASIC in CP/M.  Have started adding drawing commands in - here's a little Mandelbrot the uCOM drew earlier.  It's all greyscale due to the current GPU palette, but is a good test to show that - even in its current state of partial development - the GPU is working.  :-+

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1325327)
:-+ Nice.....

I'm just about done on my side.  It's been hard finding spare time.  I'm on the last step before sending out a beta DDR3 v1.5.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 17, 2021, 05:45:11 pm
:-+ Nice.....

That was a 480x480 render - took my 8MHz system about 4 hours.  :o  If the aspect ratio isn't 1:1, it ends up clipping some of the image.  That and a full 720x480 render would probably take about 8 hours.  I'd forgotten just how slow these old 8-bit systems were.  ::)

I'm just about done on my side.  It's been hard finding spare time.  I'm on the last step before sending out a beta DDR3 v1.5.

No worries.  Time isn't an issue - it's taken me two weeks to get around to sorting out BBC BASIC so I can do some more testing with the graphics.  Going to try and make a ROM-only version of it too.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2021, 01:18:59 am
  I'd forgotten just how slow these old 8-bit systems were.  ::)
What the longest/slowest calc in the Mandelbrot?
Your gonna have room to place a 32bit integer and floating point math-co-processor in the FPGA to do long-divides within a Z80 instruction cycle.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 18, 2021, 08:52:51 am
What the longest/slowest calc in the Mandelbrot?

Erm.. all the big calculations go off in these loops:

Code: [Select]
  190 FOR I=0 TO 3
  200   FOR J=A(I) TO MAXY/SCALE
  210     FOR K=B(I) TO MAXX/SCALE
  220       CR=XRANGE+K*4/(MAXX/SCALE)
  230       CI=YRANGE+J*3/(MAXX/SCALE)
  240       ZM=0:ZR=0:ZI=0:ZR2=0:ZI2=0
  250       IT=0
  260       REPEAT
  270         Z1=ZR2-ZI2+CR
  280         Z2=2*ZR*ZI+CI
  290         ZR=Z1
  300         ZI=Z2
  310         ZR2=ZR*ZR
  320         ZI2=ZI*ZI
  330         ZM=ZR2+ZI2
  340         IT=IT+1
  350       UNTIL IT=ITERS OR ZM>=4
  360       GCOL COLOFF+(COLS-1-INT(IT/(ITERS/(COLS-1))))
  370       MOVE K,J
  380       PLOT
  390     NEXT K
  400   NEXT J
  410 NEXT I

Lines 360-380 actually deal with setting the graphics pen colour, setting the coordinates of the pixel and plotting the pixel.  SCALE is set to 1, so there's no complicated division going on in lines 200-230, but there could be if SCALE is changed.  The real meat of the calculations is kicking off in lines 260-350, where the program works out the number of times the value can be iterated before it decides it's drifting off to infinity.  ITERS is the iteration limit and is set to 32.  MAXX and MAXY are the dimensions of the image (480 and 480).

So there's some multiplication going on (about 96 times per pixel), but it's all with floating point numbers so an FPU would certainly speed things up a bit.

Your gonna have room to place a 32bit integer and floating point math-co-processor in the FPGA to do long-divides within a Z80 instruction cycle.

 :-+

If I have time I will be expanding the PLOT command today to include various modes, so as well as plotting a pixel it will access the GPU's other drawing functions and allow the user to draw rectangles, triangles and ellipses with ease, and incorporate the MOVE command so I can shorten the loop above by a line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2021, 09:15:38 am
Even if you divide by 1, the Z80 math code may not figure to skip the divide, just that it will take fewer cycles to compute.

'MAXY/SCALE' should be pre-caculated before the loops and stored in a fixed variable when running the routine.

As for implementing the math-co, it is simple easy as all you need to do is use 8 x 8bit write ports, IE 2x 32 bit numbers as your A&B, then feed those into an altera FP add/subtract, fp multiply and divide.  Then feed the 32bit results of each function's output to 3x 4 bit read ports.  Place number a & b into the 8 write ports, and just read the read ports of which function you want to use.

Oh, you will also want to add a 4th function, FP compare which will return 3 bits to another 8 bit port, a>b, a<b, a=b.  Everything should compute before the Z80 can even get to a read except for maybe the 'divide' where after setting the a&b, you may need to 1 nop instruction to add a delay as the divide can still take something like ~100 clocks at 100MHz and if the Z80 can exceed 1 mips going from writing the last port to reading the result, 1 extra nop would definitely clear the hurdle.

The FP module should be something you should be able to create on your own.
Just read and generate the example verilog functions from altera's math IP functions.
I can help you with the wiring to the new Z80 port scheme.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 18, 2021, 09:33:31 am
A floating point divide only takes 15 clock cycles at 100MHz.  There is no way your Z80 can keep up as a single instruction takes 3-4 clocks at 8 MHz, meaning less than 2 mips.

Also, the floating point functions are in the FP_FUNCTIONS inside the IP Basic Functions / Arithmetic.

You can also do trig/log/root functions as well as fixed int to float and float to fixed integer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 19, 2021, 09:22:01 am
A floating point divide only takes 15 clock cycles at 100MHz.  There is no way your Z80 can keep up as a single instruction takes 3-4 clocks at 8 MHz, meaning less than 2 mips.

Also, the floating point functions are in the FP_FUNCTIONS inside the IP Basic Functions / Arithmetic.

You can also do trig/log/root functions as well as fixed int to float and float to fixed integer.

Going to have to go do some reading on FP maths I think.  :o

In other news, I'm noticing some artefacts cropping into the display during 'intensive' GPU activity.  I say 'intensive', it's through BBC BASIC so can't be that intense, but it's a step up from a simple 'draw a full-screen rectangle', if you get my meaning:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1326932)

This image is generated by a simple little program that loops through all the palette colours, 0-255, and gets the GPU to draw a rectangle for each one 720/255 pixels wide and 480 pixels high, so the screen is filled with the palette colours.

As you can see, there's some black pixels slipping through - at first I thought this might be an issue with BBC BASIC trying to pass FP numbers to the GPU, which only takes 24-bit integers, but I'm getting artefacts if I try to display an even number of colours across an even number of pixels, so it looks like read errors in the DDR3 possibly? :-//

The graphics routines are checking for the GPU's input FIFO being free before sending commands.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 19, 2021, 09:43:17 am
A floating point divide only takes 15 clock cycles at 100MHz.  There is no way your Z80 can keep up as a single instruction takes 3-4 clocks at 8 MHz, meaning less than 2 mips.

Also, the floating point functions are in the FP_FUNCTIONS inside the IP Basic Functions / Arithmetic.

You can also do trig/log/root functions as well as fixed int to float and float to fixed integer.

Going to have to go do some reading on FP maths I think.  :o

In other news, I'm noticing some artefacts cropping into the display during 'intensive' GPU activity.  I say 'intensive', it's through BBC BASIC so can't be that intense, but it's a step up from a simple 'draw a full-screen rectangle', if you get my meaning:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1326932)

This image is generated by a simple little program that loops through all the palette colours, 0-255, and gets the GPU to draw a rectangle for each one 720/255 pixels wide and 480 pixels high, so the screen is filled with the palette colours.

As you can see, there's some black pixels slipping through - at first I thought this might be an issue with BBC BASIC trying to pass FP numbers to the GPU, which only takes 24-bit integers, but I'm getting artefacts if I try to display an even number of colours across an even number of pixels, so it looks like read errors in the DDR3 possibly? :-//

The graphics routines are checking for the GPU's input FIFO being free before sending commands.

Hmmm?
The junk is in the middle of the draw.

Are you drawing vertical lines or single pixels?

It the blitter enabled?  I know you are using it for system text and if it gets enabled in the middle of plotting a pixel, you may be drawing a black pixel or rendering a corner of a font at the end of a position as your draw command may have it set to on at some odd intervals.  (This error would only show up if you are drawing single pixels, not lines.)

The color data is only 8 bit, not 24 bit.

The coordinates are only 12bit for signed x and 12 bit signed for y, not 24 bit.

Try a test running your code with integer variables.

For your basic to indeed overflow the pixel drawing, it would need to fill the screen at least 10 times a second if not something like 30fps.

Which version are you using?  We had 1 version which had regular black dots in the past.

What happens if you render the screen twice, or double draw each pixel?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 19, 2021, 09:52:40 am
Hmmm?
The junk is in the middle of the draw.

Are you drawing vertical lines or single pixels?

Rectangles, 720/255 wide and 480 high. (EDIT: Actually, variable width as I'm adjusting the width of the columns as I display increasing colours on the screens up to 255).

It the blitter enabled?  I know you are using it for system text and if it gets enabled in the middle of plotting a pixel, you may be drawing a black pixel or rendering a corner of a font at the end of a position as your draw command may have it set to on at some odd intervals.

Blitter is disabled for all draw commands in BBC BASIC, then re-enabled when the appropriate commands have been sent...  ???  There's no chance that the blitter is being re-enabled before the GPU has completed the current the drawing command, is there?

The color data is only 8 bit, not 24 bit.

The coordinates are only 12bit for signed x and 12 bit signed for y, not 24 bit.

Yeah, I thought I'd got that wrong after I posted.  ;)

Try a test running your code with integer variables.

For your basic to indeed overflow the pixel drawing, it would need to fill the screen at least 10 times a second if not something like 30fps.

Already did before posting previously - same issue.  I've also noticed some colour bleed between the coloured columns - not at all obvious with the greyscale but with the (godawful) colour palette I've inserted at the start, you can see it quite clearly:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1326941)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 19, 2021, 10:02:59 am
Try going into file: "../BrianHG-DDR3-Controller/BrianHG_DDR3/BrianHG_DDR3_COMMANDER.sv"

Lines, 385,386 and lines 436,437 and change:

Code: [Select]
        .words           ( 3                                 ),
        .spare_words     ( 1                                 )                  // The number of spare words before being truly full.

to

Code: [Select]
        .words           ( 4                                 ),
        .spare_words     ( 2                                 )                  // The number of spare words before being truly full.

And see what happens.
If that doesn't work, also try changing line 409 from:

Code: [Select]
        .words             ( (PORT_R_CMD_STACK[x]+1)*8         ),              // Select 4 word or 8 word FIFO.
to:

Code: [Select]
        .words             ( (PORT_R_CMD_STACK[x]+1)*10         ),              // Select 4 word or 8 word FIFO.
This commander section is what is currently being replaced.
Also, the pixel writer will be updated to make better use of the DDR3 ram controller most likely solving what looks like missed pixels after a new-line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 19, 2021, 02:21:58 pm
Hmm.. neither change seems to have any effect.

Could it be the command FIFO, rather than DDR3 read/writes?

Ignore that last sentence.  If it was the FIFO the uCOM wouldn't be sending further drawing commands through to it until it's got space again.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2021, 10:19:19 am
So I've been giving some thought to setting up an SD card interface. :-/O  This is an important step as I intend to replace the existing CompactFlash card with an SD on the graphics card.  The DECA board has a built-in SD card socket, making testing easy.

At this stage I've just been looking up information on how it should all work to get an overview.  My gold-standard outcome would be for the FPGA to store and read files from a standard FAT16/32-formatted SD card and handle translation of files and directory structures between the FAT system and the system CP/M expects to see on the host uCOM.  Depending on how difficult that would be to implement (I have no idea - I'm at the stage where I don't know what I don't know), I could always just copy the existing CF card system of sector-by-sector writing and not worrying about using FAT at all, but it would be great if I could access the SD card from a modern PC too, without faffing around with old/no longer supported CPMtools (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwj9x_vJ27D0AhWn_bsIHWQ8C0UQFnoECAUQAQ&url=http%3A%2F%2Fwww.moria.de%2F~michael%2Fcpmtools%2F&usg=AOvVaw1KgKd2OgFVrSTRgtquudG0) etc.

I'm very early in the design stage at this time.  I have identified an existing project (https://github.com/WangXuan95/FPGA-SDcard-Reader/blob/master/README_en.md) that appears to do what I want, perhaps with a little tweaking necessary, but should be up to the task without being too complex for me to understand.

What I'm trying to decide at the moment is the best way to connect the interface to the FPGA.  The CF card works via IO calls to the card itself - software sets a memory address to read from or write to, calculates the appropriate address on the CF card to read/write as appropriate and it's all handled via IO calls and the Z80 handling the reading and writing.  It's probably going to be a lot easier for me to copy this system and tweak it for the SD card - though it'll be slightly different in that the commands and data will go through the Z80_Bridge and SD interface in the FPGA, rather than direct to the SD card.

I think it'll be easiest if the commands are fed directly to the SD interface (via the Z80_Bridge), with a data buffer in DDR3 RAM or the FPGA's block RAM; the Z80 would write a 512-byte block of data to the FPGA, then use IO commands to signal to the SD interface (via the Z80_Bridge) where the block of data is (if it's not a fixed location) and where it's to be written to.  A status register can tell the Z80 when the write is complete or if there are any errors.  A read would work the same way, with the Z80 requesting data from a sector address (or filename, if I'm using FAT16/32 I guess) and copying the data block from GPU RAM (DDR3/block RAM) when the status register gives it the all-clear.

TL;DR
So really what I'm trying to decide is whether or not to use a read/write buffer in DDR3 and if so, what's the best way to connect the SD interface to it via the BrianHG_DDR3_Controller - do I just expand the PORTS and wire the SD interface to its own DDR3 R/W ports?  The alternative is to stick with a more basic serial stream of data which the Z80 reads from the SD interface and writes to wherever it needs to write it?  The issue with the second method is that I'm not sure the Z80 will keep up with the data from an SD card unless I really slow down the clock on the data transfers, and I don't know how compatible that will be with later SD cards. :-//  Plus it's slower. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 24, 2021, 03:51:43 pm
SD/MicroSD cards support two communication protocols - "legacy" single-line SPI mode (technically it's optional but I'm yet to see a card which doesn't support it), and main SDIO mode (using 1 or 4 bidirectional data lines, command line and a clock). Both transfer data in a chunks of 512 bytes.

Now, handling a filesystem in hardware doesn't sound like a good idea because all filesystems were designed to have software driver handling these. The problem is that there are quite a bit of use-cases, so it might require a lot of hardware to handle all of these, to the point that it will actually be more resource-efficient to include a small specialized softcore dedicated to just that task (and appearing as a fixed hardware to outside world). This has been done in the past, when in IBM PC XT times some of specialized CPUs used in peripherals were actually more powerful than the main CPU in that system.

I also highly recommend implementing support for exFAT filesystem, because finding smaller SD cards in stock is becoming harder by the day. exFAT supports all SD card densities of today and foreseeable future.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2021, 04:43:54 pm
SD/MicroSD cards support two communication protocols - "legacy" single-line SPI mode (technically it's optional but I'm yet to see a card which doesn't support it), and main SDIO mode (using 1 or 4 bidirectional data lines, command line and a clock). Both transfer data in a chunks of 512 bytes.

I'm intending to use a 4-bit SDIO connection - the project I linked in my previous post uses this connection to the SD card and the DECA development board includes a full 4-bit connection to the SD socket on the board.

Now, handling a filesystem in hardware doesn't sound like a good idea because all filesystems were designed to have software driver handling these. The problem is that there are quite a bit of use-cases, so it might require a lot of hardware to handle all of these, to the point that it will actually more resource-efficient to include a small specialized softcore dedicated to just that task (and appearing as a fixed hardware to outside world). This has been done in the past, when in IBM PC XT times some of specialized CPUs used in peripherals were actually more powerful than the main CPU in that system.

I was thinking about including a softcore (this one specifically (http://zipcpu.com/about/zipcpu.html)) to handle the filesystem on the SD card, then I came across the linked project above (https://github.com/WangXuan95/FPGA-SDcard-Reader/blob/master/README_en.md) which seems to support FAT16/32 and up to SDHC v2 cards.  I have a lot of learning to do regarding filesystems though, so your comments regarding exFAT have raised a point I hadn't thought about before now and perhaps including a softcore is more a requirement than an option.

I also highly recommend implementing support for exFAT filesystem, because finding smaller SD cards in stock is becoming harder by the day. exFAT supports all SD card densities of today and foreseeable future.

Okay, you've sold me on exFAT! ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 24, 2021, 05:58:54 pm
I was thinking about including a softcore (this one specifically (http://zipcpu.com/about/zipcpu.html))
That guy is sick with a terminal case of NIH syndrome (had some run-ins with him on other forums where he heavily promotes his stuff), so I would recommend to go with something more established, like RISC-V, as this way you can utilize gcc/binutils toolchain for writing software in C instead of using some custom stuff. You can find some really small cores for RV32I, or you can even implement your own - it's very simple because this instruction set only contains around 40 opcodes.

I came across the linked project above (https://github.com/WangXuan95/FPGA-SDcard-Reader/blob/master/README_en.md) which seems to support FAT16/32 and up to SDHC v2 cards.
Judging by a lot of Chiness on the project's home page, you are probably going to have to dig on your own with little to no docs while integrating it into your project.
FAT16 is obsolete now and I don't think it's even used anywhere these days, so I wouldn't waste my time supporting it. But FAT32 and exFAT are definitely worth supporting, even if there is a clear trend for latter to largely replace the former. That said, since you control what kind of card is to be used, you can go either way, or even limit support to just a single one if you wish.
FAT systems are fairly simple, if you understand how linked lists work then you will feel right at home with it as it's just a bunch of linked lists.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 24, 2021, 06:25:37 pm
Linked to another recent thread... if you want to support FAT, then I suggest just using FatFs. It's become fairly good and it just works. It's written in portable C. http://elm-chan.org/fsw/ff/00index_e.html (http://elm-chan.org/fsw/ff/00index_e.html)

Of course you'll still have to implement the low-level access to SD cards. I have the SD spec (been working on that lately), as far as I've read in it, access in SPI mode is required to be available in all card types except SDUC cards. SDUC cards are those with higher capacity than 2TB - I doubt you'll be using them for a system such as this one, and also given their current price. But be aware that the SPI mode only gives access to a small subset of the SD commands, and while you can absolutely use it to read and write the card and implement a file system, it's pretty inefficient. The end result would be pretty slow (although, compared to typical storage available at the time for 8-bit computers, that'd still be pretty "fast"  ;) ).

As a thought, I find it kinda odd to design a relatively complex and powerful system (graphics controller, storage management) - using subsystems (such as a 32-bit soft core) that are much more powerful than your main CPU. Interesting, certainly, but an odd project in my book.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2021, 07:38:49 pm
I was thinking about including a softcore (this one specifically (http://zipcpu.com/about/zipcpu.html))
That guy is sick with a terminal case of NIH syndrome (had some run-ins with him on other forums where he heavily promotes his stuff), so I would recommend to go with something more established, like RISC-V, as this way you can utilize gcc/binutils toolchain for writing software in C instead of using some custom stuff. You can find some really small cores for RV32I, or you can even implement your own - it's very simple because this instruction set only contains around 40 opcodes.

Well, if nothing else I've learned a new term today - never heard of NIH syndrome before! ;)  Thanks for the heads-up, though.  Will take a look at RISC-V instead then.  Thinking outside the box for a moment, if I'm going to be implementing a RISC softcore in the FPGA, how complicated would it be to incorporate a USB HID controller stack within it as well?  Would that be doable, with my limited expertise and experience, I wonder?

I came across the linked project above (https://github.com/WangXuan95/FPGA-SDcard-Reader/blob/master/README_en.md) which seems to support FAT16/32 and up to SDHC v2 cards.
Judging by a lot of Chiness on the project's home page, you are probably going to have to dig on your own with little to no docs while integrating it into your project.

Oh, you don't speak Mandarin? :-DD  Seriously though, at first glance the project doesn't appear to be too complicated and I should be able to get my head around it - there's a couple of examples showing how to read a file by name and read a sector, so it's just a small step further to write to both as the interface will have to write to the SD card (commands, at least) to read anything from it.  At the moment I see more trouble working out how to get the data from the SD interface to the buffer (i.e. where to place the buffer, how to access it etc).

FAT16 is obsolete now and I don't think it's even used anywhere these days, so I wouldn't waste my time supporting it. But FAT32 and exFAT are definitely worth supporting, even if there is a clear trend for latter to largely replace the former. That said, since you control what kind of card is to be used, you can go either way, or even limit support to just a single one if you wish.
FAT systems are fairly simple, if you understand how linked lists work then you will feel right at home with it as it's just a bunch of linked lists.

FAT32 will go up to 4GB, but like you said previously, those size SD cards are only going to get less and less available as time goes by and technology marches on.  I always have the option of ignoring the FAT16/32/exFAT format altogether and just going to the metal and reading/writing a proprietary format at the sector level like my uCOM does currently on the CF card, but I had no hand in the creation of that system (thanks to Grant Searle and his work there), so at best I'd just be copying and tweaking what he's done there and applying it to the SD card format.  Whether or not that would work is a question I don't have enough knowledge to answer at this point, but in any case, I want to go the exFAT/FAT32 route if at all possible.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 24, 2021, 07:57:04 pm
FAT32 will go up to 4GB,

No, no, ... no. ;D

FAT32 can support partitions up to *2 TB* (with a cluster size of 64 KB.)
The limitation is for file size. Max file size in FAT32 is 4 GB. Not at all the partition size. So unless you're going to write individual files that are larger than 4 GB (which would definitely look odd on an 8-bit system), you may never have to bother.

That said, if you use FatFs as I suggested, the library supports FAT12, 16, 32 and exFAT, so you'd be all covered.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 24, 2021, 08:02:49 pm
Linked to another recent thread... if you want to support FAT, then I suggest just using FatFs. It's become fairly good and it just works. It's written in portable C. http://elm-chan.org/fsw/ff/00index_e.html (http://elm-chan.org/fsw/ff/00index_e.html)

Ah, thanks SiliconWizard, I'll take a look at that later.  The only requirement I have for supporting any of the FAT varieties is that I can access it from Windows 10 with no middle-man software, otherwise I might as well not bother, but FATfs should be okay I guess.

Of course you'll still have to implement the low-level access to SD cards. I have the SD spec (been working on that lately), as far as I've read in it, access in SPI mode is required to be available in all card types except SDUC cards. SDUC cards are those with higher capacity than 2TB - I doubt you'll be using them for a system such as this one, and also given their current price. But be aware that the SPI mode only gives access to a small subset of the SD commands, and while you can absolutely use it to read and write the card and implement a file system, it's pretty inefficient. The end result would be pretty slow (although, compared to typical storage available at the time for 8-bit computers, that'd still be pretty "fast"  ;) ).

I'm not looking to implement an SPI interface to the SD card - I'm going full 4-bit SDIO for the reasons you've identified.

As a thought, I find it kinda odd to design a relatively complex and powerful system (graphics controller, storage management) - using subsystems (such as a 32-bit soft core) that are much more powerful than your main CPU. Interesting, certainly, but an odd project in my book.

Well, you have to remember that this project is a bit of a Frankenstein's monster.  It started out with me learning about electronics whilst building a simple 7-chip Z80 computer on a breadboard.  I've wanted to push my limits constantly since starting the project and, in a great example of feature creep (or project bloat, if you prefer), I now have a stackable, modular Z80 computer made with SMD components on custom PCBs and with up to 4MB of memory running CP/M from a CF card and with a hardware-accelerated GPU providing further IO opportunities (like PS/2, USB HID, HDMI output, etc).  It certainly isn't a well-planned project, just a hobby that I'm following to its conclusion (when the help runs out or I just can't progress any further).

The features I'm adding to the FPGA are for my uCOM, but equally can apply to anyone else wanting to add one of these FPGA GPUs to their DIY system - be it an 8-bit system or something beefier.  I'd certainly like to move on to the Motorola 68000-series when I'm done with this Z80.

FAT32 will go up to 4GB,

No, no, ... no. ;D

FAT32 can support partitions up to *2 TB* (with a cluster size of 64 KB.)

Ah - my misunderstanding there.  Okay, so FAT32 can be used on SD cards up to 2 TB in size?!  That makes the argument for supporting exFAT or FATfs less compelling in my opinion, but only if the complexity of supporting those more modern filesystems is significant, I suppose.

The limitation is for file size. Max file size in FAT32 is 4 GB. Not at all the partition size. So unless you're going to write individual files that are larger than 4 GB (which would definitely look odd on an 8-bit system), you may never have to bother.

That said, if you use FatFs as I suggested, the library supports FAT12, 16, 32 and exFAT, so you'd be all covered.

Indeed - it does weaken the argument for messing around trying to support greater than FAT32.  What I might do is stick to FAT32 initially, then upgrade to FATfs once I know more about what I'm doing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 24, 2021, 08:23:34 pm
From a couple comments you made on FatFs, I'm under the impression you may have misunderstood what it was.
FatFs is a portable library written in C allowing to access FAT partitions. It's not a filesystem in itself. It's just a well tested library that is widely used on embedded systems to support FAT/16/32/exFAT. So instead of implementing FAT access yourself, you can use this nice library. It supports all FAT versions so you can use it with disks formatted in any of them.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on November 24, 2021, 08:55:32 pm
Will take a look at RISC-V instead then.  Thinking outside the box for a moment, if I'm going to be implementing a RISC softcore in the FPGA, how complicated would it be to incorporate a USB HID controller stack within it as well?  Would that be doable, with my limited expertise and experience, I wonder?
Everything is doable with enough effort :) USB stack leans heavily on a software side, but if you are not afraid to dive head-first into USB specs than - sure. You will learn a lot during this, that's for sure. And USB HID is one of the simplest flavors of USB. Hardware-wise you will only need to implement a USB ULPI PHY interface (to external USB PHY) and a DMA engine to transfer data back and forth. You can skim through ECHI specification to give you an idea, but keep in mind that this spec is for fully-featured USB 2.0 host controller implementation used on PCs, so you can likely cut many corners to simplify things.

Oh, you don't speak Mandarin? :-DD  Seriously though, at first glance the project doesn't appear to be too complicated and I should be able to get my head around it - there's a couple of examples showing how to read a file by name and read a sector, so it's just a small step further to write to both as the interface will have to write to the SD card (commands, at least) to read anything from it.  At the moment I see more trouble working out how to get the data from the SD interface to the buffer (i.e. where to place the buffer, how to access it etc).
I'm not saying you shouldn't use it - I'm just warning that it might not be as easy as it sounds. At the end of the day, SDIO is not a very complicated protocol, so I think you should be fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 25, 2021, 10:09:10 pm
Oh, you don't speak Mandarin? :-DD  Seriously though, at first glance the project doesn't appear to be too complicated and I should be able to get my head around it - there's a couple of examples showing how to read a file by name and read a sector, so it's just a small step further to write to both as the interface will have to write to the SD card (commands, at least) to read anything from it.  At the moment I see more trouble working out how to get the data from the SD interface to the buffer (i.e. where to place the buffer, how to access it etc).
I'm not saying you shouldn't use it - I'm just warning that it might not be as easy as it sounds. At the end of the day, SDIO is not a very complicated protocol, so I think you should be fine.

I've had a closer look at the HDL today and there's nothing in the demo code or supplied modules to cater for writing to the SD card, so I'm going to have to modify the state machine to allow for writes as well.  I've also got to add in direction controls for the level converter on the DECA board.  The project I'm using as a template makes no consideration for anything but reading from the SD card, so there's no direction control for the CMD line or DAT0 and DAT1-3 lines.  I'm hoping to have this done by the end of play tomorrow (or maybe over the weekend if I'm too busy tomorrow), but don't foresee any major issues just yet. :-+  (Hoping that's not famous last words...)  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 25, 2021, 11:10:19 pm
The 512byte, or even 1kbyte should be in a single 1kbyte dual ram block.
Once filled, you can copy to and from DDR3 in 128 bit chunks.  This will offer maximum speed.

You can also go direct to and from DDR3, but operating in 8 bit mode means a slower transfer to DDR3.
It is up to you.  The easy part about going to and from DDR3 is that you get the multiport which is shared with everything else and you get 1 less step in complexity.

Note that a single M9K block is 1 kilobyte.  If you define anything smaller, the compiler will still eat the 1kbyte or 9kilobit anyways.  For larger sizes, it will eat chunks in multiples of 2.

All the access to/from the SD card is via 512-byte blocks, so the granularity of 8-bit mode for the DDR read/writes would be unnecessary.  For a read, couldn't I just stack up 16 bytes from the SD card then push them directly into DDR3 in one transaction?  No need to do 8-bit transfers that way, could just write 128 bits with each transaction to the DDR3 for maximum efficiency?

I guess writes to the SD card will need that 16-byte buffer to hold the data from DDR3 whilst it's written.  I need to read up on the writing process before I go too deep in planning it, but I'm guessing there's no issue making the write process wait a few clocks whilst another 16 bytes are retrieved from DDR3 to fill the buffer again?  Or I could make a 32-byte buffer and fill one half while the other is being read?

Ok, before I answer your question, how fast does the SD card read at in megabytes per second?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2021, 12:20:01 am
Look at the attached illustration.  You will need to open it in a normal window and show at 100% size, and scroll to see what is going on...

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1332377)

I assumed that your SD card was capable of reading at 50 Megabytes per second.  The simulation timing is accurate.  Both the upper and lower sims transfer 512 bytes.

Sending 128bit chunks or 8 bit chunks wont make a difference as my controller already stacks the source 8bit read/writes into it's smart cache. It is the overall speed of the SD card which is the bottleneck as seen in my top illustration.

Discuss with asmi & SiliconWizard the ramifications of selecting the 2 possible paths.

Path #1 (top in illustration) allows other commands in-between to change memory rows allowing numerous slow-down and penalties at multiple conjunctures as you will have up to 16 video layers being drawn on the display, a geometry unit drawing things, a Z80 reading and writing data at it's slow pace as we reserved this one case knowing it is a clunker speedwise, and an audio system.

Path #2 crunches everything into a single point smaller in size than a single Z80 read op-code instruction.  Also, when readin & writing the 512bytes from the SD-Card, (because of the M9K structure, you will have up to 4k instead of 512bytes), reading and writing can be done directly into the dual port ram without any individual wait states.

Note that with a 25 megabyte/sec SD card, the top #1 chart would be twice as wide with tiny DDR3 bursts being spaced at twice the distance from each other.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 26, 2021, 12:50:30 am
Just a quick note: getting a sustained 50 MBytes/s read with an SD Card will be challenging and will be doable only with the fastest cards. (And if you add FAT handling on top of that, it's probably going to be all the much harder.) One thing for sure (can say because as I mentioned I'm working with SD cards lately): you'll need to switch the card to 1.8V mode (not all cards support it) and then one of the highest clock rates supported. The fastest you can get in SDIO mode, 4-bit, at 3.3V is 50 MHz - which will give you a max throughput of 25 MB/s minus any overhead. And supporting 1.8V mode is not as trivial - your circuit needs to support powering SD cards at both 3.3V and 1.8V, and be able to switch between them. Makes the hardware more involved. Oh and the initialization phase for an SD card is not trivial either - do not expect implementing all commands and init sequences purely in HDL - that would be pure madness. That part too will need to be done in software. Only the low-level part of the SDIO bus can be handled reasonably in HDL.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2021, 12:59:49 am
LOL, the SD looks so god damn slow compared to the DDR3.  I wont waste my time doubling the width of my above illustration as it already is ridiculous enough but true for a 50mb/sec SD card.

I still think the dual port ram block as a 512 byte or 1024 byte buffer is the best way to go.  We do not want to generate the plethora of activate and precharges with all their associated delays in between due to other access cycles where the SD card routine will need to pause and wait after every 16 bytes which my inner DDR3 cache will accumulate the data, then burst out the response.  Do the transfer in a single shot.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on November 26, 2021, 01:03:51 am
LOL, the SD looks so god damn slow compared to the DDR3.

Definitely.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2021, 08:55:50 am
LOL, the SD looks so god damn slow compared to the DDR3.  I wont waste my time doubling the width of my above illustration as it already is ridiculous enough but true for a 50mb/sec SD card.

I still think the dual port ram block as a 512 byte or 1024 byte buffer is the best way to go.  We do not want to generate the plethora of activate and precharges with all their associated delays in between due to other access cycles where the SD card routine will need to pause and wait after every 16 bytes which my inner DDR3 cache will accumulate the data, then burst out the response.  Do the transfer in a single shot.

Crikey - it's not until I see a visual representation that the difference in clock speeds makes sense.  Okay, no worries, I'll set up a dual-port 1KB (is that enough?) block RAM buffer in the FPGA, then transfer data from that buffer one block (512 bytes) at a time to the DDR3.

Just a quick note: getting a sustained 50 MBytes/s read with an SD Card will be challenging and will be doable only with the fastest cards. (And if you add FAT handling on top of that, it's probably going to be all the much harder.) One thing for sure (can say because as I mentioned I'm working with SD cards lately): you'll need to switch the card to 1.8V mode (not all cards support it) and then one of the highest clock rates supported. The fastest you can get in SDIO mode, 4-bit, at 3.3V is 50 MHz - which will give you a max throughput of 25 MB/s minus any overhead. And supporting 1.8V mode is not as trivial - your circuit needs to support powering SD cards at both 3.3V and 1.8V, and be able to switch between them. Makes the hardware more involved. Oh and the initialization phase for an SD card is not trivial either - do not expect implementing all commands and init sequences purely in HDL - that would be pure madness. That part too will need to be done in software. Only the low-level part of the SDIO bus can be handled reasonably in HDL.

Yeah, I'm happy with 25MB/sec.  I haven't got any justification for all the added complexity trying to squeeze every last drop of speed out of the SD interface - even a 12.5MHz SPI connection would be vastly faster than any 'historically accurate' storage device for the Z80, let alone a 25MHz 4-bit SDIO interface.  The biggest file I have in CP/M currently sits at just over 16KB.


Here's a meta-question, though - should I move this line of discussion regarding setting up an SD interface to another thread?  It IS relevant to this one in that there's discussion around using the DDR3 and it's housed in the same FPGA GPU project, but that's about it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2021, 09:11:35 am
LOL, the SD looks so god damn slow compared to the DDR3.  I wont waste my time doubling the width of my above illustration as it already is ridiculous enough but true for a 50mb/sec SD card.

I still think the dual port ram block as a 512 byte or 1024 byte buffer is the best way to go.  We do not want to generate the plethora of activate and precharges with all their associated delays in between due to other access cycles where the SD card routine will need to pause and wait after every 16 bytes which my inner DDR3 cache will accumulate the data, then burst out the response.  Do the transfer in a single shot.

Crikey - it's not until I see a visual representation that the difference in clock speeds makes sense.  Okay, no worries, I'll set up a dual-port 1KB (is that enough?) block RAM buffer in the FPGA, then transfer data from that buffer one block (512 bytes) at a time to the DDR3.

Use the megafunction tool to test generate a dual port, dual clock ram.  It will tell you how many M9K blocks will be used.  I think no matter what you choose, you may get stuck with 4 as a minimum because of the 128 bit wide side B.  Dual clock just in case as you can always just tie the 2 clocks together.  Dual port with each being a read & write port.  Side A should be 4 or 8 bit for the SD-Card and side B should be 128bit for the DDR3.  I would at least choose 512bytes worth, but if the minimum M9K count is 4, actually choosing a 4kbyte buffer will still use the same amount of M9K blocks.  Only go up to 4K if you can make use of it, for example, transfer 8 consecutive 512 byte blocks, otherwise, there is no plus in doing so.  I don't know much about FAT32.
Quote

Just a quick note: getting a sustained 50 MBytes/s read with an SD Card will be challenging and will be doable only with the fastest cards. (And if you add FAT handling on top of that, it's probably going to be all the much harder.) One thing for sure (can say because as I mentioned I'm working with SD cards lately): you'll need to switch the card to 1.8V mode (not all cards support it) and then one of the highest clock rates supported. The fastest you can get in SDIO mode, 4-bit, at 3.3V is 50 MHz - which will give you a max throughput of 25 MB/s minus any overhead. And supporting 1.8V mode is not as trivial - your circuit needs to support powering SD cards at both 3.3V and 1.8V, and be able to switch between them. Makes the hardware more involved. Oh and the initialization phase for an SD card is not trivial either - do not expect implementing all commands and init sequences purely in HDL - that would be pure madness. That part too will need to be done in software. Only the low-level part of the SDIO bus can be handled reasonably in HDL.

Yeah, I'm happy with 25MB/sec.  I haven't got any justification for all the added complexity trying to squeeze every last drop of speed out of the SD interface - even a 12.5MHz SPI connection would be vastly faster than any 'historically accurate' storage device for the Z80, let alone a 25MHz 4-bit SDIO interface.  The biggest file I have in CP/M currently sits at just over 16KB.

Uninterrupted 25 megabytes a sec will just about give you 24fps with 480p uncompressed digital video.  If you want sound, you'll need a bit more.  Compressed video, well you can pull off 1080p using MJPEG2000.
Quote

Here's a meta-question, though - should I move this line of discussion regarding setting up an SD interface to another thread?  It IS relevant to this one in that there's discussion around using the DDR3 and it's housed in the same FPGA GPU project, but that's about it.

Keep the SD card stuff here.  It should be small compared to the video stuff and it is needed for playing back video from the SD-Card.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2021, 09:42:21 am
" Crikey - "

 :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2021, 12:50:14 pm
Okay, I've had a little time (but not as much as I'd hoped) and have tidied up the source code a little for the SD interface, making it a little more readable at least.

There's some artefacts left in the code from the example source code - artificially driving RD_REQ in SDInterface.sv, for example, as the original example code was set up to perform a read of Sector 0 after reset/powerup, which I'll remove once I start working on the connections to the Z80_Bridge and DDR3_Controller.

There's also no way to write data to the SD card just yet - again, I'll work on this as my understanding of the code and protocol increases.  What I'm trying to work out at the moment, however, is how to control the level translator on the DECA board, which the example code doesn't account for.  The DECA (wisely) has an SN74AVCA406L chip between the FPGA and SD socket, providing static discharge protection and voltage conversion between the FPGA and SD card.  I'll likely use this setup for my SD socket on the GPU card when I can design and build it (much later).

As a result, I have four signals that the example code doesn't cater for:

If you look in SDReader.sv, lines 55 and 57-58 appears to be where the SD_CMD line is switched between input, output and tristate.  I've added line 56 to set the direction of the SD_CMD line through the SN74AVCA406L accordingly (have checked the datasheet and am hoping I've got it the right way around!)

I just want to make sure I'm on the right track and haven't done anything wrong before I go too far with the changes to the code.  Presumably SD_D0_DIR and SD_D123_DIR will follow the same logic and go in the same direction as SD_CMD at any given time and SD_SEL will remain low all the time any read/write is being performed?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 26, 2021, 10:36:58 pm
Use the megafunction tool to test generate a dual port, dual clock ram.  It will tell you how many M9K blocks will be used.  I think no matter what you choose, you may get stuck with 4 as a minimum because of the 128 bit wide side B.  Dual clock just in case as you can always just tie the 2 clocks together.  Dual port with each being a read & write port.  Side A should be 4 or 8 bit for the SD-Card and side B should be 128bit for the DDR3.  I would at least choose 512bytes worth, but if the minimum M9K count is 4, actually choosing a 4kbyte buffer will still use the same amount of M9K blocks.  Only go up to 4K if you can make use of it, for example, transfer 8 consecutive 512 byte blocks, otherwise, there is no plus in doing so.  I don't know much about FAT32.

Here's what I've produced with the megafunction in Quartus.  Hopefully it's not far from the mark.  Takes up 8 M9K blocks, apparently.  If it's okay, I'll tidy it up tomorrow and have a think about how I'm going to connect it to the SDInterface module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 26, 2021, 10:48:35 pm
Use the megafunction tool to test generate a dual port, dual clock ram.  It will tell you how many M9K blocks will be used.  I think no matter what you choose, you may get stuck with 4 as a minimum because of the 128 bit wide side B.  Dual clock just in case as you can always just tie the 2 clocks together.  Dual port with each being a read & write port.  Side A should be 4 or 8 bit for the SD-Card and side B should be 128bit for the DDR3.  I would at least choose 512bytes worth, but if the minimum M9K count is 4, actually choosing a 4kbyte buffer will still use the same amount of M9K blocks.  Only go up to 4K if you can make use of it, for example, transfer 8 consecutive 512 byte blocks, otherwise, there is no plus in doing so.  I don't know much about FAT32.

Here's what I've produced with the megafunction in Quartus.  Hopefully it's not far from the mark.  Takes up 8 M9K blocks, apparently.  If it's okay, I'll tidy it up tomorrow and have a think about how I'm going to connect it to the SDInterface module.

Looks ok.  Only 1 feature is not needed: NEW_DATA_WITH_NBE_READ
Check the megafunction for read during write = new data.  We only require 'Don't Care' or 'old data'.    What's going on here is that you have instructed the compiler to make sure if there is a collision, where you simultaneously write to the same location during a read on the second port at that location, the compiler adds extra logic outside of the M9K block to pass the new data through instantly on the same clock.  We don't need this as that delay is only 2 clock cycles max and we wont be writing to 1 location simultaneously reading the same ram byte of the second port side.  It a waste of gates, albeit a small amount, it still has a cost associated with the feature though I doubt we will ever reach that point are we are running the DP ram at 100MHz, not the top end 300MHz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2021, 07:43:24 am
Here's what I've produced with the megafunction in Quartus.  Hopefully it's not far from the mark.  Takes up 8 M9K blocks, apparently.  If it's okay, I'll tidy it up tomorrow and have a think about how I'm going to connect it to the SDInterface module.

Looks ok.  Only 1 feature is not needed: NEW_DATA_WITH_NBE_READ
Check the megafunction for read during write = new data.  We only require 'Don't Care' or 'old data'.    What's going on here is that you have instructed the compiler to make sure if there is a collision, where you simultaneously write to the same location during a read on the second port at that location, the compiler adds extra logic outside of the M9K block to pass the new data through instantly on the same clock.  We don't need this as that delay is only 2 clock cycles max and we wont be writing to 1 location simultaneously reading the same ram byte of the second port side.  It a waste of gates, albeit a small amount, it still has a cost associated with the feature though I doubt we will ever reach that point are we are running the DP ram at 100MHz, not the top end 300MHz.

Okay, no problem.  Have changed the settings on lines 118 & 119 to:

Code: [Select]
altsyncram_component.read_during_write_mode_port_a = "OLD_DATA",
altsyncram_component.read_during_write_mode_port_b = "OLD_DATA",

Does it need read enables at all?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2021, 07:58:45 am
Actually, read clock enable can be useful when sending data to the DDR3 as a read has a 2 clock delay and we may want to pause the read if the DDR3 is busy.  (I bloody hate that, you wont believe the extent I had to work to deal with the fact that when reading, your response comes in a number of clock cycles later.  Worse, if you want to read a lot fast, you actually are sending in multiple reads as the train of responses come out delayed.)

Everything else is ok.

Remember, if you aren't going to use the enable, you basically are just going to tie that input to a 1'b1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2021, 09:38:48 am
Okay, here's an update on where I am currently.

dual_port_block_cache.sv is - as it says on the tin - the dual port cache for reads/writes to the SD card.  This is instantiated in SDInterface.sv (which I was going to remove, but have now realised it's going to be a key part of the structure) and I've wired up the output from SDReader.sv to it, so that (in theory at least) any data read from the SD card will now be written to the M9K cache.

The cache is 1KB in size, so for the moment I'm intending to separate it into two blocks of 512 bytes - one for reads FROM the SD card, one for writes TO the SD card.  Seems sensible to keep the two separate, especially as block RAM is no longer a scarce resource now we're using DDR3 for everything, but (as always) I'm open to suggestions and advice on whether this is suitable or even necessary.

Take a look at SDInterface.sv.  It contains some comments on how I think the cache is going to work.  I've connected clock_a to CLOCK_50 - seemed sensible to have port A of the cache clocked at the same speed as the data coming from SDReader.sv?  clock_b is connected to CLK, an as-yet-unspecified clock source from the top-level module, but I'm thinking this should be one of the DDR3_CLK clocks.

I'm a little confused about the address width in the dual_port_block_cache.v for some reason (line 56).  It's set up with a 7-bit address bus for port a, which is only 128 bytes?  Have I made a mistake in the setup here, or am I just misunderstanding the values?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2021, 10:35:35 am
I'm a little confused about the address width in the dual_port_block_cache.v for some reason (line 56).  It's set up with a 7-bit address bus for port a, which is only 128 bytes?  Have I made a mistake in the setup here, or am I just misunderstanding the values?

Port A should have a 10bit address if you are reserving 1kbyte and have it set to 8 bit.  Maybe just a typo when using the megafunction.

Port B should have a smaller address as it has fewer words at 128 bit wide.

Double check the M9K usage, they are precious as we need just as many for each maggie layer.  So, only reserve the number of KB which offers the minimum M9K size.

Also, check the erase block size.  I don't know how big it is, but, to edit data within a block, if I remember correctly, you need to read that block, edit the bytes you want to change inside that read buffer, then erase that block, then, write that block with your edited buffer.

For the DDR3 interface, you will use the CMD_CLK.  It is 100MHz.  Check the SD controller, it may be written in a way where you can use the 100MHz and it will divide the output SD clock for you.  Otherwise, you will be stuck with using a PLL or CLK_IN which will generate timing report errors and we will need to fix the .sdc file to fix those.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2021, 02:35:12 pm
Port A should have a 10bit address if you are reserving 1kbyte and have it set to 8 bit.  Maybe just a typo when using the megafunction.
...
Double check the M9K usage, they are precious as we need just as many for each maggie layer.  So, only reserve the number of KB which offers the minimum M9K size.

Yes, was a typo.  I've gone back to the megafunction to work out the M9K usage, and it appears that the 128-bit data bus on port B is ramping up the M9K usage to a minimum of 8 M9K blocks.  Even if I select the minimum RAM size, 16x8 bits, it uses 8 M9K blocks.  I can go right up to 8192x8 bits for the RAM and it still only uses 8 M9K blocks.  So (unless you suggest changing port B's data width) instead of wasting 7.5KB of M9K RAM, I'm setting the cache RAM size to the full 8KB - if we need it later (e.g. for FAT support) then we've got it.

Also, check the erase block size.  I don't know how big it is, but, to edit data within a block, if I remember correctly, you need to read that block, edit the bytes you want to change inside that read buffer, then erase that block, then, write that block with your edited buffer.

I'm assuming you mean the SD card's erase block size?  I can find no mention of erase block size for M9Ks.  It looks like the erase block size can vary from SD card to SD card - primarily based on its capacity and quality of its controller, I would imagine.  A common erase block size seems to be 4KB, although there's no guarantee that would be the case for any particular SD card; this should be a moot point, however, as the SD card's controller should handle block editing/erasure as part of a write of any size to the SD card, along with wear levelling etc.  Why do you ask, could this be an issue?

For the DDR3 interface, you will use the CMD_CLK.  It is 100MHz.  Check the SD controller, it may be written in a way where you can use the 100MHz and it will divide the output SD clock for you.  Otherwise, you will be stuck with using a PLL or CLK_IN which will generate timing report errors and we will need to fix the .sdc file to fix those.

Ah yes, SDReader has a clock divider parameter for just that purpose.  :-+  Okay, both sides of the cache RAM are being clocked at 100MHz from CMD_CLK now.

The project should now read a sector/512 bytes from an SD card and write it to the cache RAM. RD_RDY goes high when the data has been read (and written to the cache RAM as that happens automatically).  Now I just need to write those 512 bytes to DDR3, so I'm going to need....
.. and a little later...
.. is that right?  x and y will be the port numbers... x=3 and y=5?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 27, 2021, 09:51:51 pm
The project should now read a sector/512 bytes from an SD card and write it to the cache RAM. RD_RDY goes high when the data has been read (and written to the cache RAM as that happens automatically).  Now I just need to write those 512 bytes to DDR3, so I'm going to need....
  • wr_ena(x)
  • (PORT_ADDR_SIZE)'(addr(x))
  • PORT_CACHE_BITS)'(wdata(x))
.. and a little later...
  • read_req[y]
  • read_ready[y]
  • (128)'read_data[y]
.. is that right?  x and y will be the port numbers... x=3 and y=5?
For now, this is ok.  With the new V1.5 controller, each single port can read and write just like the DP ram.
Remember, you need to set all the unused CMD_xxx ports to fixed values.

See if you can find a 'micro SD card verilog simulation model' like I have been using Mricon's DDR3 model to test my controller.  This way, you can simulate your interface design with a virtual SD-Card in modelsim first.  Then next, tie that to my Z80 bus simulator wired into my DDR3 controller simulator to give you a full 100% test run before you even stick it into your GPU.  This way, you will know if it's working first.  I have given you a ton of example sim models so you can see how to setup modelsim, but, the Z80 bus will probably be the most useful.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 27, 2021, 11:43:37 pm
See if you can find a 'micro SD card verilog simulation model' like I have been using Mricon's DDR3 model to test my controller.  This way, you can simulate your interface design with a virtual SD-Card in modelsim first.

Failing at this first hurdle here.  I've not found anything yet.  Will keep looking.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2021, 12:01:58 am
Micron might have one in their e.MMC line.  But right now, their website is messed up as I cannot see or select any part numbers including their DDR3 stuff.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 28, 2021, 12:21:59 am
You can google: 'MMC card verilog simulation test model'

Read the comments in this resulting thread : https://www.edaboard.com/threads/sd-card-verilog-behavioral-model.35335/ (https://www.edaboard.com/threads/sd-card-verilog-behavioral-model.35335/)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 28, 2021, 09:25:37 am
You can google: 'MMC card verilog simulation test model'

Read the comments in this resulting thread : https://www.edaboard.com/threads/sd-card-verilog-behavioral-model.35335/ (https://www.edaboard.com/threads/sd-card-verilog-behavioral-model.35335/)

Yeah I found that thread last night; bearing in mind the comments are over 16 years old, I couldn't find anything of use on the Samsung website mentioned - that appears to be a dead end now.  Any information at denali.com is hidden behind a user login wall on the site -  I can't even do a search for relevant information before deciding whether I want to register an account, which I'm reluctant to do when the trail to this site is so cold. :horse:

Take a look at this more recent post https://www.edaboard.com/threads/sd-emmc-card-simulation-model.365970/ (https://www.edaboard.com/threads/sd-emmc-card-simulation-model.365970/) and it appears that denali is a dead-end too.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2021, 03:05:50 pm
Finally, it's here: BrianHG_DDR3 V1.5.
First, the new Z80 bus interface testbench...

Each new port on the DDR3 is a read and write port instead of the separate read ports, then separate write ports.

-PLUS- we now have a DDR3 shadow write TAP port:
// **************************************************************************************
// This Write Data TAP port passes a copy of all the writes going to the DDR3 memory.
// This will allow to 'shadow' selected write addresses to other peripherals
// which may be accessed by all the multiple write ports.
// This port is synchronous to the CMD_CLK.
// **************************************************************************************

This means, any peripherals writing to the DDR3 from any of the multi-ports are ordered and copied out to this port which can be tied to all the GPU control regs and palette rams.  So, blitting / accelerated mem copies from 1 ram location to a GPU control reg will have the same write access as the Z80 originally had.  Multiple prepared palettes, screen settings, or anything anywhere in ram or even on flash card can be GPU hardware written directly into the settings address without the Z80 having to do anything other than set the start & destination address with the number of bytes to be copied.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2021, 04:22:36 pm
Here we go, GPU with my BrianHG_DDR3 controller beta v15.
 (  :scared: All together 11084 lines of code just for the new DDR3...  :scared: )
No more timing violations with 5 ports @ 400MHz, and, there shouldn't be any even with all 16 ports in use (I hope)...

I also noticed that you made changes to the Z80_bus_interface on the last 'GPU_DECA_DDR3_new.zip' compared to my TB posted above.  I hope I got everything right in trying to catch and transfer all the changes, but you still need to verify these 2 settings:

Code: [Select]
   .Z80_DELAY_WAIT_RI     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
   .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Memory cycle.

Check to see the lowest number which properly prevents the 'WAIT' from being asserted during a read cache hit condition.

Also check for the 'filled-box' graphical glitch which happens occasionally on the left most of a new line.

If everything works, you can try connecting your palette ram to the new 'Write Data TAP port'.  You will need to filter the address range for the palette and pass the appropriate write mask bits as the write data width is 128bits with 16 wmask bits.  You will also need to shift the write address.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 29, 2021, 04:31:00 pm
Next I will update my DDR3 github, then if everything is ok with the GPU, I will look at re-doing my Display MEM and make a new VGA/HDMI output section where you can properly change color depth and resolutions plus add multiple layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 29, 2021, 06:22:25 pm
Here we go, GPU with my BrianHG_DDR3 controller beta v15.
 (  :scared: All together 11084 lines of code just for the new DDR3...  :scared: )
No more timing violations with 5 ports @ 400MHz, and, there shouldn't be any even with all 16 ports in use (I hope)...

I also noticed that you made changes to the Z80_bus_interface on the last 'GPU_DECA_DDR3_new.zip' compared to my TB posted above.  I hope I got everything right in trying to catch and transfer all the changes, but you still need to verify these 2 settings:

Code: [Select]
   .Z80_DELAY_WAIT_RI     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Instruction Opcode cycle.
   .Z80_DELAY_WAIT_RM     ( 3       ), // 0 to 7, Number of CMD_CLK cycles to wait for DDR3 read_ready before asserting the WAIT during a Read Memory cycle.

Check to see the lowest number which properly prevents the 'WAIT' from being asserted during a read cache hit condition.

Also check for the 'filled-box' graphical glitch which happens occasionally on the left most of a new line.

Not seeing any glitches at all in the filled boxes now - display output is very clean. :-+

If everything works, you can try connecting your palette ram to the new 'Write Data TAP port'.  You will need to filter the address range for the palette and pass the appropriate write mask bits as the write data width is 128bits with 16 wmask bits.  You will also need to shift the write address.

I've tidied up a couple of bits, added-in some missing connections from the Z80_Bridge and added the SD modules that I'm working on currently.  I've attached the project here so that we've both got the latest version and we don't have to keep amending/altering individual files with new updates.

As far as the palette RAM comment goes - erm.. The palettes sits in the FPGA's block RAM, doesn't it?  I'm going to have to go refresh my memory on how the palette works within the GPU and learn about this Write Data TAP port.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2021, 10:06:37 am
I've tidied up a couple of bits, added-in some missing connections from the Z80_Bridge and added the SD modules that I'm working on currently.  I've attached the project here so that we've both got the latest version and we don't have to keep amending/altering individual files with new updates.

As far as the palette RAM comment goes - erm.. The palettes sits in the FPGA's block RAM, doesn't it?  I'm going to have to go refresh my memory on how the palette works within the GPU and learn about this Write Data TAP port.
What's with all the warnings?

Code: [Select]
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_WAIT" to top-level pin "pre_syn.bp.Z80_BRIDGE_Z80_WAIT". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[7]" to top-level pin "GPIO1_D[11]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[6]" to top-level pin "GPIO1_D[12]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[5]" to top-level pin "GPIO1_D[13]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[4]" to top-level pin "GPIO1_D[14]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[3]" to top-level pin "GPIO1_D[15]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[2]" to top-level pin "GPIO1_D[16]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[1]" to top-level pin "GPIO1_D[17]". Did not propagate pin attribute to the other top-level pins listed below
Warning (12067): Propagated pin attribute from lower-level pin "Z80_Bus_Interface:Z80_BRIDGE|Z80_DATA[0]" to top-level pin "GPIO1_D[18]". Did not propagate pin attribute to the other top-level pins listed below

Info (286031): Timing-Driven Synthesis is running on partition "Top"
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_CMD" driven by bidirectional pin "SD_CMD" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_0_" driven by bidirectional pin "SD_DAT[0]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_1_" driven by bidirectional pin "SD_DAT[1]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_2_" driven by bidirectional pin "SD_DAT[2]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Sidney_SD_DATA_3_" driven by bidirectional pin "SD_DAT[3]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_21_" driven by bidirectional pin "GPIO0_D[14]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_20_" driven by bidirectional pin "GPIO0_D[15]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_19_" driven by bidirectional pin "GPIO0_D[16]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_18_" driven by bidirectional pin "GPIO0_D[17]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_17_" driven by bidirectional pin "GPIO0_D[18]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_16_" driven by bidirectional pin "GPIO0_D[19]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_15_" driven by bidirectional pin "GPIO0_D[20]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_14_" driven by bidirectional pin "GPIO0_D[21]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_13_" driven by bidirectional pin "GPIO0_D[26]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_12_" driven by bidirectional pin "GPIO0_D[27]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_11_" driven by bidirectional pin "GPIO0_D[28]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_10_" driven by bidirectional pin "GPIO0_D[29]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_9_" driven by bidirectional pin "GPIO0_D[30]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_8_" driven by bidirectional pin "GPIO0_D[31]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_7_" driven by bidirectional pin "GPIO0_D[34]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_6_" driven by bidirectional pin "GPIO0_D[35]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_5_" driven by bidirectional pin "GPIO0_D[36]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_4_" driven by bidirectional pin "GPIO0_D[37]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_3_" driven by bidirectional pin "GPIO0_D[38]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_2_" driven by bidirectional pin "GPIO0_D[39]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_1_" driven by bidirectional pin "GPIO0_D[40]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_ADDR_0_" driven by bidirectional pin "GPIO0_D[41]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_WAIT_INn" driven by bidirectional pin "GPIO1_D[0]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_CLK" driven by bidirectional pin "GPIO1_D[3]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_RDn" driven by bidirectional pin "GPIO1_D[4]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_WRn" driven by bidirectional pin "GPIO1_D[5]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_MREQn" driven by bidirectional pin "GPIO1_D[6]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_IORQn" driven by bidirectional pin "GPIO1_D[7]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_M1n" driven by bidirectional pin "GPIO1_D[8]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_7_" driven by bidirectional pin "GPIO1_D[11]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_6_" driven by bidirectional pin "GPIO1_D[12]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_5_" driven by bidirectional pin "GPIO1_D[13]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_4_" driven by bidirectional pin "GPIO1_D[14]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_3_" driven by bidirectional pin "GPIO1_D[15]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_2_" driven by bidirectional pin "GPIO1_D[16]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_1_" driven by bidirectional pin "GPIO1_D[17]" cannot be tri-stated
Warning (14632): Output pin "pre_syn.bp.Z80_BRIDGE_Z80_DATA_0_" driven by bidirectional pin "GPIO1_D[18]" cannot be tri-stated
Critical Warning (18061): Ignored Power-Up Level option on the following registers
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[1] will power up to Low
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[2] will power up to High
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[7] will power up to High
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[1] will power up to Low
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[2] will power up to High
Critical Warning (18010): Register SDInterface:Sidney|SDReader:SDReader_inst|clkdiv[7] will power up to High


What did you do?
The GPU I sent you doesn't have all of these...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 30, 2021, 10:56:57 am
I added in the extra pins for Z80_INTACKn, Z80_INT_INn, Z80_WAIT_INn to the Z80_Bus_Interface.sv (they're mostly unused, except Z80_WAIT_INn which can be used by SignalTap to see when the WAIT line goes low).  These are additional lines available to the GPU with the latest uCOM/DECA interface card version and are all inputs that can be ignored.

The SD card modules can be removed/ignored - there's going to be warnings generated by them as they're in the middle of development and may be incomplete or just plain wrong.

I have no idea why all the '...cannot be tri-stated' warnings are there.  I've not done anything with the other Z80 bus lines - at least afaik.  There's always the possibility I've made a typo or silly mistake somewhere, but it builds and works. :-//

EDIT:  I also grouped all the CMD_xxxx assigns together.  I've compiled the design with the additional signals above commented-out, in case they were causing the error, but no change.  It's the SD card modules - I've removed them and it compiles fine, with very limited warnings.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2021, 11:13:52 am
You might need to go back a version, then, add the new stuff 1 by 1 looking to see when the error arises.


Anyways, to help you see what the 'TAP_xxx' port does, take a look at my attached BrianHG_DDR3_v15 block diagram:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1336175)

Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

I guess 1 parameter A will contain the total number of 'reset' presets you wish to enter and the second parameter will be an array with '{{address hex,data value hex},{address hex,data value hex},{address hex,data value hex},...}.

It may be useful to have the defaults at 16bit instead of 8 bit for convenience since all our presets will be 16bit or 32bit quantities.

Your gonna need a fancy write into the array since the source data is 128bit, but you want an 8bit output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 30, 2021, 11:19:48 am
You might need to go back a version, then, add the new stuff 1 by 1 looking to see when the error arises.

It's the SD module - comment out lines 770-837 in GPU_DECA_DDR3_top.sv and all the warnings go away.  I'm going to take a break from the SD side for a while, I think. ::)

Anyways, to help you see what the 'TAP_xxx' port does, take a look at my attached BrianHG_DDR3_v15 block diagram:

Thanks for this.  I'll go away and focus on this for a while instead! ;D

Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

You mean like the GPU_HW_Control_Regs?

I guess 1 parameter A will contain the total number of 'reset' presets you wish to enter and the second parameter will be an array with '{{address hex,data value hex},{address hex,data value hex},{address hex,data value hex},...}.

It may be useful to have the defaults at 16bit instead of 8 bit for convenience since all our presets will be 16bit or 32bit quantities.

Your gonna need a fancy write into the array since the source data is 128bit, but you want an 8bit output.

Righto, leave it with me. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2021, 11:27:25 am
Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

You mean like the GPU_HW_Control_Regs?

You got it exactly  :-+

Once we have the new 'GPU_HW_REGS[7..0][0..16383]', with a reset powerup settings, we can feed selected bytes into anything, like my display_rmem controls.  Then you could change resolution, move screen buffer addresses and scroll offset from the Z80 as the first test.

Also, you can connect your palette port_b's write enable directly to the TAP_xxx with an address range selector anded with the write enable & byte enable for the 4 byte wide data so that the Z80 can write and read a new color palette.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 30, 2021, 08:09:43 pm
Next, start by making a module which is a reg-port, like the old one, except make it with a 16 kilobyte output port.
You will need to have a reset input where you can add an arbitrary number of reset parameters.

I guess 1 parameter A will contain the total number of 'reset' presets you wish to enter and the second parameter will be an array with '{{address hex,data value hex},{address hex,data value hex},{address hex,data value hex},...}.

It may be useful to have the defaults at 16bit instead of 8 bit for convenience since all our presets will be 16bit or 32bit quantities.

Something like this?

Code: [Select]
parameter HW_REGS_SIZE = 14    ; // 2^14 = 16384 bytes
parameter int RST_PARAM_SIZE = 8     ;
parameter int BASE_WRITE_ADDRESS = 20'h0 ;

parameter RESET_VALUES[RST_PARAM_SIZE] = '{
{8'h01, 8'h10}, {8'h03, 8'h10}, {8'h04, 8'h02}, {8'h05, 8'h8F},
{8'h06, 8'h01}, {8'h07, 8'hEF}, {8'h09, 8'h8C}, {8'h0B, 8'h86},
};

I've used 8-bit values, but will convert to 16-bit if I'm on the right path and you can answer this question; are we setting these 16-bit values in big-endian or little-endian format?  I could just use e.g. {16'h01, 16'h10} as a value if endianness matches up, I guess?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2021, 10:49:26 pm
Ok, so far, so good.
Now for the reset values, the issue here is that the FPGA doesn't have 16kb of registers (that would be a 160k reg/gate fpga).  What we are doing is selectively using reg at our convenience from that 16kb, not every one.  This also means we do not and need not assign 16kb of reset values.  The fewer resets we assign, the better.  So, for the default/reset RESET_VALUES, we want the '1:RST_PARAM_SIZE' for the number of entries, and inside the reset values, we want to define the 14'hxxxx address and the 8'hxx data so that in your verilog if(reset), you perform a for loop from 1 to RST_PARAM_SIZE, and read in that loop read the 14'hxxxx address and assign the HW_REGS[14'hxxxx] <= 8'hxx.

This will allow you to selective indvidualy define reset values as specific points...

reset values will most likely look like:
parameter bit [23:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......

Where the contents will be 24'haaaadd, ....
[aaaa] being a 16 bit address and [dd] being 8 bit data.

Then in the for loop, you can select 14 of the upper 16 bits for the address pointer and use the lower 8 bits for the reset data.  Or you can go straight to [31:0] and assign 16 bit data presets which will be easier since the majority of our presets will be 16bits long.


Inside the for loop, you should apply 8bits at a time and make an option to swap endian just in case.

Also, remember that in the main write data loop, the TAP_ data is 128bit with byte enables for the 16 bytes in the 128bit.  Make a parameter on-top to select the bus TAP width of 128 bits and and the TAP address does go down to the 'byte', but the lower address bits are always equal to 0'.  And when you store the data coming in, remember you wand an endian parameter option there too.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 30, 2021, 11:02:38 pm
I have yet to use it packed bits like this, but this should also be possible:

parameter bit [13:0][7:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......
or
parameter bit [13:0][15:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......

Just stick with the previous one unless you prove it's usefullness.

Also, for the HW_REGS module, make it a stand alone module and test in modelsim by initiating it inside:
Z80_Interface_TB_v15 / Z80_Bus_Interface_to_DDR3_tb.sv . (around line 580...)

Update the 'setup_z80_to_DDR3.do' and 'run_z80_to_DDR3.do' to include the new HW_REGS.sv source.
In the 'setup_z80_to_DDR3.do', add the HW_REGS to the waveform display.

Modify the 'Z80_cmd_stimulus.txt' to test that write memory works and that read memory has no effect.
Also remember that you can test the reset in the 'Z80_cmd_stimulus.txt' as well.

Don't forget to use my parameter names for the TAP widths.
And make the HW_REG size in memory adjustable as for testing, maybe 256/1024 bytes total will be enough.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2021, 11:37:08 am
Ok, so far, so good.
Now for the reset values, the issue here is that the FPGA doesn't have 16kb of registers (that would be a 160k reg/gate fpga).  What we are doing is selectively using reg at our convenience from that 16kb, not every one.  This also means we do not and need not assign 16kb of reset values.  The fewer resets we assign, the better.  So, for the default/reset RESET_VALUES, we want the '1:RST_PARAM_SIZE' for the number of entries, and inside the reset values, we want to define the 14'hxxxx address and the 8'hxx data so that in your verilog if(reset), you perform a for loop from 1 to RST_PARAM_SIZE, and read in that loop read the 14'hxxxx address and assign the HW_REGS[14'hxxxx] <= 8'hxx.

This will allow you to selective indvidualy define reset values as specific points...

reset values will most likely look like:
parameter bit [23:0] RESET_VALUES[1:RST_PARAM_SIZE] = '{......

Where the contents will be 24'haaaadd, ....
[aaaa] being a 16 bit address and [dd] being 8 bit data.

Then in the for loop, you can select 14 of the upper 16 bits for the address pointer and use the lower 8 bits for the reset data.  Or you can go straight to [31:0] and assign 16 bit data presets which will be easier since the majority of our presets will be 16bits long.


Inside the for loop, you should apply 8bits at a time and make an option to swap endian just in case.

Okay, this is where I am with the HW_REGS module right now:

Code: [Select]
module HW_REGS (

        input                               RESET,
        input                               CLK,
        input                               WE,
        input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
        input         [PORT_CACHE_BITS-1:0] DATA_IN,
        input       [PORT_CACHE_BITS/8-1:0] WMASK,
        output  reg                 [  7:0] HW_REGS[0:(2**HW_REGS_SIZE-1)],
        output  reg                 [  7:0] DATA_OUT

);

parameter int           PORT_ADDR_SIZE                  = 19       ; // This parameter is passed by the top module
parameter int           PORT_CACHE_BITS                 = 128      ; // This parameter is passed by the top module
parameter               ENDIANNESS                      = "LITTLE" ; // Specify endianness of the reset values
parameter               HW_REGS_SIZE                    = 14       ; // 2^14 = 16384 bytes
parameter int           RST_PARAM_SIZE                  = 2        ; // Number of default values
parameter int           BASE_WRITE_ADDRESS              = 20'h0    ; // Where the HW_REGS are held in RAM
parameter bit   [31:0]  RESET_VALUES[1:RST_PARAM_SIZE]  = '{
    {16'h00, 16'h10}, {16'h02, 16'h10}
};

wire enable   = ( ADDR_IN[PORT_ADDR_SIZE-1:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[PORT_ADDR_SIZE-1:HW_REGS_SIZE] ) ;   // upper x-bits of ADDR_IN should equal BASE_WRITE_ADDRESS for a successful read or write
wire valid_wr = WE && enable ;

integer i;
always @( posedge CLK ) begin
   
    if ( RESET ) begin
        // reset registers to initial values
        for (i = 0; i < RST_PARAM_SIZE; i = i + 1) begin
            if (ENDIANNESS == "LITTLE") begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][ 7:0] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][15:8] ;
            end else begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][15:8] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][ 7:0] ;
            end
        end
    end
    else
    begin
        if (valid_wr) begin
            // apply written value to addressed register
            //HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] <= DATA_IN ;
        end
    end
   
    if (enable) begin
        //data_out <= HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] ;
    end else begin
        data_out <= 0 ;
    end
   
end

endmodule

The commented-out lines in (valid_wr) and (enable) are relics from the old GPU_HW_REGS module, which I'll be replacing with something more advanced to extract the data required from the 128-bit DATA_IN bus later.

Also, remember that in the main write data loop, the TAP_ data is 128bit with byte enables for the 16 bytes in the 128bit.  Make a parameter on-top to select the bus TAP width of 128 bits and and the TAP address does go down to the 'byte', but the lower address bits are always equal to 0'.  And when you store the data coming in, remember you wand an endian parameter option there too.

I need to look at the content of TAP_WMASK and each high bit will correspond to a valid byte in DATA_IN.  Are valid bytes always the lowest sequential ones, or will there ever be non-written bytes between the write bytes?  Will these valid bytes always follow the {16'address,16'data} format I'm using for the RESET_VALUES?


EDIT:  Thinking about my last questions, I guess the bytes will always be sequential as the DDR3_Controller will stack them up in the FIFO - and the format will follow whatever format the bytes have been written to RAM in, so that's down to the host software.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2021, 11:55:26 am
This is what I've just thrown together based on my understanding of TAP_WDATA and TAP_WMASK:

Code: [Select]
    begin
        if (valid_wr) begin
            // apply written value to addressed register
            //HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] <= DATA_IN ;
            for(i = 0; i < PORT_CACHE_BITS/8; i = i + 1) begin
                if (WMASK[i:i]) begin
                    if (ENDIANNESS == "LITTLE") begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+7:i*32]    ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+15:i*32+8] ;
                    end else begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+15:i*32+8] ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+7:i*32]    ;
                    end
                end
            end
        end
    end

Is this along the right lines for writing to the HW_REGS?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2021, 11:57:02 am
The mask is like a write enable for every 16 bytes in the case of the data bus being 128 bit.  If the data bus was 256 bit, then there would be 32 bytes.

Note that Modelsim prefers the parameters placed before the IO ports, otherwise the parameter width settings will not be ready yet for the width settings in the IO ports.  Take a look at any of my latest .sv code...

You can get rid of the if (enable) data out section, after writing a value, if the Z80 does a read, it will get the contents from the DDR3.

Your reset looks OK.
For your valid_wr, you will need to make a 2 layer loop, the outer one which incs (PORT_CACHE_BITS/8) as the inner will inc 1 at a time from 0 to (PORT_CACHE_BITS/8-1), using a second write enable for the WMASK[innerloopcounter] while adding the 2 loop counters together to generate the write address.  Don't forget to select the correct part of WDATA by using WDATA[innerloopcounter*8+:8]

No endian option for the valid_wr section.  If you did want to, it would be weird as the source data is 128 bits, not 32 or 16.

And, dont forget to simulate it...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2021, 12:04:49 pm
This is what I've just thrown together based on my understanding of TAP_WDATA and TAP_WMASK:

Code: [Select]
    begin
        if (valid_wr) begin
            // apply written value to addressed register
            //HW_REGS[ADDR_IN[HW_REGS_SIZE-1:0]] <= DATA_IN ;
            for(i = 0; i < PORT_CACHE_BITS/8; i = i + 1) begin
                if (WMASK[i:i]) begin
                    if (ENDIANNESS == "LITTLE") begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+7:i*32]    ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+15:i*32+8] ;
                    end else begin
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b0}] <= DATA_IN[i*32+15:i*32+8] ;
                        HW_REGS['{DATA_IN[i*32+29:i*32+17], 1'b1}] <= DATA_IN[i*32+7:i*32]    ;
                    end
                end
            end
        end
    end

Is this along the right lines for writing to the HW_REGS?
Ok, close, bu no endianess here.
Also try this line instead:
Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
It seems smaller than your example.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2021, 12:15:17 pm
Ok, close, bu no endianess here.
Also try this line instead:
Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Yes, if we're not worried about endianness it simplifies the logic a little - and I was confusing the format of RESET_VALUES with DATA_IN, overcomplicating the logic massively. |O

It seems smaller than your example.
I get that a lot. :-DD

Okay, will try simulating later this afternoon if there's nothing else I need to do with it?

Full code here:
Code: [Select]
module HW_REGS (

        input                               RESET,
        input                               CLK,
        input                               WE,
        input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
        input         [PORT_CACHE_BITS-1:0] DATA_IN,
        input       [PORT_CACHE_BITS/8-1:0] WMASK,
        output  reg                 [  7:0] HW_REGS[0:(2**HW_REGS_SIZE-1)],
        output  reg                 [  7:0] DATA_OUT

);

parameter int           PORT_ADDR_SIZE                  = 19       ; // This parameter is passed by the top module
parameter int           PORT_CACHE_BITS                 = 128      ; // This parameter is passed by the top module
parameter               ENDIANNESS                      = "LITTLE" ; // Specify endianness of the reset values
parameter               HW_REGS_SIZE                    = 14       ; // 2^14 = 16384 bytes
parameter int           RST_PARAM_SIZE                  = 2        ; // Number of default values
parameter int           BASE_WRITE_ADDRESS              = 20'h0    ; // Where the HW_REGS are held in RAM
parameter bit   [31:0]  RESET_VALUES[1:RST_PARAM_SIZE]  = '{
    {16'h00, 16'h10}, {16'h02, 16'h10}
};

wire enable   = ( ADDR_IN[PORT_ADDR_SIZE-1:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[PORT_ADDR_SIZE-1:HW_REGS_SIZE] ) ;   // upper x-bits of ADDR_IN should equal BASE_WRITE_ADDRESS for a successful read or write
wire valid_wr = WE && enable ;

integer i;
always @( posedge CLK ) begin
   
    if ( RESET ) begin
        // reset registers to initial values
        for (i = 0; i < RST_PARAM_SIZE; i = i + 1) begin
            if (ENDIANNESS == "LITTLE") begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][ 7:0] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][15:8] ;
            end else begin
                HW_REGS['{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][15:8] ;
                HW_REGS['{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][ 7:0] ;
            end
        end
    end
    else
    begin
        for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && WMASK[i]) HW_REGS[(ADDR_IN | i)] <= DATA_IN[i*8+:8] ;
    end
   
end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2021, 12:20:29 pm
You want the reverse endian, here you go:

Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i ^ ENDIAN]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Just make ENDIAN = 1 for 16 bit reverse endian, or make it 3 for 32 bit reverse endian.  Happy?  Only 7 more characters.

Dont forget to move the parameters to the top of the code for Modelsim compatibility and next put the code into my Z80_bus_interface_to_DDR3 and simulate.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2021, 02:36:27 pm
You want the reverse endian, here you go:

Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i ^ ENDIAN]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Just make ENDIAN = 1 for 16 bit reverse endian, or make it 3 for 32 bit reverse endian.  Happy?  Only 7 more characters.

Dont forget to move the parameters to the top of the code for Modelsim compatibility and next put the code into my Z80_bus_interface_to_DDR3 and simulate.

What about reads from HW_REGS?  Is there any need for DATA_OUT?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 01, 2021, 07:44:38 pm
You want the reverse endian, here you go:

Code: [Select]
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && mask[i ^ ENDIAN]) HW_REGS[(ADDR_IN[HW_REGS_SIZE-1:0] | i)] <= DATA_IN[i*8+:8] ;
Just make ENDIAN = 1 for 16 bit reverse endian, or make it 3 for 32 bit reverse endian.  Happy?  Only 7 more characters.

Dont forget to move the parameters to the top of the code for Modelsim compatibility and next put the code into my Z80_bus_interface_to_DDR3 and simulate.

What about reads from HW_REGS?  Is there any need for DATA_OUT?


You can get rid of the if (enable) data out section, after writing a value, if the Z80 does a read, it will get the contents from the DDR3.


Remember, with the 'TAP_xxxx' port, you are tapping writes to the DDR3 meaning the you see the written data, but the DDR3 also gets a copy of the same data at the same address.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 01, 2021, 11:11:44 pm
Remember, with the 'TAP_xxxx' port, you are tapping writes to the DDR3 meaning the you see the written data, but the DDR3 also gets a copy of the same data at the same address.

D'oh.  I'd forgotten that.  Okay, well I've got ModelSim 20.1 running, have tried to run the simulation and am getting this error:

Code: [Select]
** Error: (vsim-3033) Instantiation of 'HW_Regs' failed. The design unit was not found.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_to_DDR3_tb File: Z80_Bus_Interface_to_DDR3_tb.sv Line: 627
#         Searched libraries:
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/altera
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/220model
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/sgate
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/altera_mf
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/altera_lnsim
#             D:/FPGA/ModelSim_20-1/modelsim_ase/altera/verilog/cycloneive
#             D:/FPGA/Projects/GPU/test/Z80_Interface_TB_v15/work
# Loading work.Z80_Bus_Interface
# Error loading design
# Error: Error loading design
#        Pausing macro execution
# MACRO ./setup_z80_to_DDR3.do PAUSED at line 20

I'll take a closer look tomorrow, but I've probably missed something really basic.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2021, 05:31:42 am
Update the 'setup_z80_to_DDR3.do' and 'run_z80_to_DDR3.do' to include the new HW_REGS.sv source.
In the 'setup_z80_to_DDR3.do', add the HW_REGS to the waveform display.
In both of your xxxxxx.do files, you did not add the:
vlog -sv -work work {HW_Regs.sv}

Like this:
Code: [Select]
vlog -sv -work work {BrianHG_DDR3/altera_gpio_lite.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_GEN_tCK.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_PLL.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_FIFOs.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_CMD_SEQUENCER.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_IO_PORT_ALTERA.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_PHY_SEQ.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_COMMANDER_v15.sv}
vlog -sv -work work {BrianHG_DDR3/BrianHG_DDR3_CONTROLLER_v15_top.sv}
vlog -sv -work work {HW_Regs.sv}
vlog -sv -work work {Z80_Bus_Interface.sv}
vlog -sv -work work {Z80_Bus_Interface_to_DDR3_tb.sv}

Look at the third to last line...
Don't forget to add the line to both the setup and run...

You have other bugs too, but, you can figure them out
You will also want to add the 'HW_REGS' output to the waveform display in the 'setup_xxxx.do'.

Let's see how many bugs you can find and patch.

Also, if I were you, change the HW_REGS size in your sim to a total of 64 instead of 16k.  If you have the HW_REGS displayed on your waveform and it has 16k entries, every recompile will take a dumb amount of time just for clearing out the waveform display's contents, then replacing it as it's height will at least be 16384 rows tall.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2021, 09:41:01 am
OK, after testing, have you figured out why the endian option is a bad thing?
Do you have a better solution to cover all possibilities?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2021, 10:20:49 am
OK, after testing, have you figured out why the endian option is a bad thing?
Do you have a better solution to cover all possibilities?

Not yet, I still can't get the simulation to run.  I've fixed the assignment syntax errors - the error I'm getting now is this one:

# Z80_Bus_Interface_to_DDR3_tb.sdramddr3_0.file_io_open: at time                    0 WARNING: no +model_data option specified, using /tmp.
# ** Warning: (vsim-3533) [FOFIW] - Failed to open file "/tmp/Z80_Bus_Interface_to_DDR3_tb.sdramddr3_0.open_bank_file.0" for writing.
# No such file or directory. (errno = ENOENT)    : BrianHG_DDR3/ddr3.v(633)
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_to_DDR3_tb/sdramddr3_0
# Z80_Bus_Interface_to_DDR3_tb.sdramddr3_0.open_bank_file: at time 0 ERROR: failed to open /tmp/Z80_Bus_Interface_to_DDR3_tb.sdramddr3_0.open_bank_file.0.
# ** Note: $finish    : BrianHG_DDR3/ddr3.v(637)
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_to_DDR3_tb/sdramddr3_0

The simulation 'finishes' at this point.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2021, 10:22:45 am
How is that possible?
It's working fine on my side....
What did you do?
If I don't let you do this, you will always rely on me...
I even told you the 1 line to add to the 'setup_z80_to_DDR3.do' and 'run_z80_to_DDR3.do'.
Everything else you had except for the '   ' {  ' error once removed, it should have worked after typing:
do setup_z80_to_DDR3.do


To be safe, close modelsim, delete the 'work' directory and delete modelsim.ini, and delete vlog.opt and delete vsim.wlf to flush everything blank.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2021, 10:26:10 am
No idea. :o  I added HW_Regs.sv to the TB folder, updated setup.do to include HW_Regs.sv... I've attached the TB folder for info.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2021, 10:27:52 am
How is that possible?
It's working fine on my side....
What did you do?
If I don't let you do this, you will always rely on me...
I even told you the 1 line to add to the 'setup_z80_to_DDR3.do' and 'run_z80_to_DDR3.do'.
Everything else you had except for the '   ' {  ' error once removed, it should have worked after typing:
do setup_z80_to_DDR3.do


To be safe, close modelsim, delete the 'work' directory and delete modelsim.ini, and delete vlog.opt and delete vsim.wlf to flush everything blank.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2021, 10:35:15 am
before sending out any Modelsim .zip, please delete TB_v15.code-workspace and delete the 'work' directory and delete modelsim.ini, and delete vlog.opt and delete vsim.wlf to flush everything blank.  You just want a clean tiny project.

And what you sent me, (though I did the deleting first) seems to run completely fine.

Do you have the project in a folder where modelsim has write privileges?
What about the C:\tmp folder for the DDR3 bank files?
(If it is the C:\tmp write privileges, then I know you never ran a single DDR3 testbench of mine.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2021, 11:13:13 am
before sending out any Modelsim .zip, please delete TB_v15.code-workspace and delete the 'work' directory and delete modelsim.ini, and delete vlog.opt and delete vsim.wlf to flush everything blank.  You just want a clean tiny project.

And what you sent me, (though I did the deleting first) seems to run completely fine.

Do you have the project in a folder where modelsim has write privileges?
What about the C:\tmp folder for the DDR3 bank files?
(If it is the C:\tmp write privileges, then I know you never ran a single DDR3 testbench of mine.)

Yeah, sorry about that, the DDR3 testbench always ran fine on the old one - then I realised I'd forgotten to update tmp_model_dir value in ddr3.v (with a Windoze-compatible path) in the new TB. ::)

Got meetings now - might get a chance to review the simulation later this afternoon.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 02, 2021, 03:58:50 pm
Okay, this is interesting.  According to the test bench (see screenshot below), the TAP port doesn't go live with data for quite a while after reset, presumably because it's waiting for more data to hit the DDR3 control buffer before writing to the memory to reduce writing?

In any case, as you can see in the screenshot, the simulation is writing to memory address 0x00000002 with data 0xAA.   This should be interpreted as HW_Reg[2], but it looks like TAP_ADDR is wrong?  It's showing an address of 0x00000000, but that should be 0x00000002?  The data and write mask appear correct, however the HW_Regs are not updating correctly either.  Instead of them changing to "10 00 AA 00 55 00 xx xx xx xx xx xx xx xx xx xx", they change to "10 00 10 00 55 00 xx xx xx xx xx xx 00 xx xx xx".

Is this to do with the endian issue you've alluded to or some other problem?  Either way, TAP_ADDR is wrong and the wrong data is being written to the wrong HW_Reg.  All in all, not a good start for me! ;)

[attach=1]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 02, 2021, 08:48:40 pm
Why didn't you simplify your sim display to Z80 bus / HW_REGS only and click on the ' + ' on the HW_REGS, zoom out, so you can see what's going on like I did?

SEE:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1338053)

Also, why do you have 16regs only, I said to use 64 so you can at least go above 1 single 128bit wide WDATA all at address 16'h0000.

And again, why did you choose such poor test write data which wouldn't give you a clue to the actual problem, why not try these Z80 writes (inside Z80_cmd_stimulus.txt) to see what is going on:
Code: [Select]
@LOG_FILE Z80_cmd_stimulus_log.txt
@RESET

@CMD WM 0000 aa     Write to memory address
@CMD WM 0001 11     Write to memory address
@CMD WM 0002 22     Write to memory address
@CMD WM 0003 33     Write to memory address
@CMD WM 0004 44     Write to memory address
@CMD WM 0005 55     Write to memory address
@CMD WM 0006 66     Write to memory address
@CMD WM 0007 77     Write to memory address
@CMD WM 0010 10     Write to memory address
@CMD WM 0020 20     Write to memory address
@CMD WM 0030 30     Write to memory address
@CMD WM 0040 40     Write to memory address
@CMD WM 0050 50     Write to memory address
@CMD WM 1110 BB     Write to memory address
@CMD WM 2210 CC     Write to memory address
@CMD WM 3310 DD     Write to memory address

Now do not look at this line, see if you can figure out the problem by yourself first:
for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1) if (valid_wr && WMASK[i ^ ENDIAN]) HW_REGS[( ADDR_IN[HW_REGS_SIZE-1:0] | (i^(PORT_CACHE_BITS/8-1)) )] <= DATA_IN[i*8+:8] ;

Next, work out why the 'ENDIAN' only messes up then entire HW_REG system, why you need to get rid of it and why making new IO port with the same output reg renamed to 8bit and these new assigned output wires would help provide a better solution:
Code: [Select]
)(

        input                               RESET,
        input                               CLK,
        input                               WE,
        input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
        input         [PORT_CACHE_BITS-1:0] DATA_IN,
        input       [PORT_CACHE_BITS/8-1:0] WMASK,
        output  reg                 [  7:0] HW_REGS_8bit[0:(2**HW_REGS_SIZE-1)]
        output  wire                [ 15:0] HW_REGS_16bit[0:(2**HW_REGS_SIZE-1)]
        output  wire                [ 31:0] HW_REGS_32bit[0:(2**HW_REGS_SIZE-1)]

);

You may also do the 'reset' values in the same way for defaults which are 8bit, 16bit, or 32bit.

(BTW: I do not have a "D:\tmp" drive.  Also, isn't there a way to define the tmp folrder in the code instead of modifying Micron's ddr3.v source code + make that folder in the same folder as the work directory...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 03, 2021, 02:00:05 pm
 :phew:
Here is the GPU project with the final BrianHG_DDR3_Controller_v15 release.
Consider all the files updated, including the .sdc file.
Let me know if it works properly.

The new complete BrianHG_DDR3_Controller v1.50 here:
https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415)
And here:
https://github.com/BrianHGinc/BrianHG-DDR3-Controller (https://github.com/BrianHGinc/BrianHG-DDR3-Controller)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 06, 2021, 09:59:57 am
Well nockieboy, is my final release DDR3 v1.5 working fine?
Did you tune the Z80 read cache / WAIT output timing?
Did you solve the new HW_REGS code issue?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 06, 2021, 07:51:18 pm
Had a busy weekend, unfortunately.  Have just had time to compile the new project and quickly try it out with the BBCBASIC tests - getting no artefacts in the graphics so far. :-+

Did you tune the Z80 read cache / WAIT output timing?
Did you solve the new HW_REGS code issue?

Nope.  Will maybe get some time later this week, depends how things go.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 08, 2021, 10:14:04 pm
Did you tune the Z80 read cache / WAIT output timing?

From what I can tell from SignalTap, it looks like the default settings are working fine.  Not seeing any unnecessary WAITs being inserted when a cache-hit is achieved and no bad reads as a result of a cache miss and no WAIT.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2021, 10:51:04 am
Did you solve the new HW_REGS code issue?

Looks like it was writing each 16-bit value to the wrong address - i.e. for the first write (0xAA), it should have been writing to address 0, it was writing to 15-(the required address).  I don't know why it would do that and I'm struggling to get my head around what's going on with [i^ENDIAN] and OR-ing values together etc. :o

(BTW: I do not have a "D:\tmp" drive.  Also, isn't there a way to define the tmp folrder in the code instead of modifying Micron's ddr3.v source code + make that folder in the same folder as the work directory...)

Fixed this - although it still required an alteration to Micron's ddr3.v source code.  Changed the path from "D:\tmp" to just ".\tmp" - it now uses a folder called 'tmp' in the project directory.  Can find no reference to a command that allows me to change the tmp directory path outside of the source code, and frankly don't have the time to hunt it down when I have a working solution that (hopefully) won't cause issues at anyone else's end either.

Am I going along the right path with the changes I've made in the attached files?  Haven't sorted out the resets for the 16 and 32-bit regs, plus it all seems a bit wasteful in terms of gates duplicating all that data, but I'm sure there's probably a much simpler way of doing it all that you've got.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2021, 11:05:34 am
Did you solve the new HW_REGS code issue?

Looks like it was writing each 16-bit value to the wrong address - i.e. for the first write (0xAA), it should have been writing to address 0, it was writing to 15-(the required address).  I don't know why it would do that and I'm struggling to get my head around what's going on with [i^ENDIAN] and OR-ing values together etc. :o

(BTW: I do not have a "D:\tmp" drive.  Also, isn't there a way to define the tmp folrder in the code instead of modifying Micron's ddr3.v source code + make that folder in the same folder as the work directory...)

Fixed this - although it still required an alteration to Micron's ddr3.v source code.  Changed the path from "D:\tmp" to just ".\tmp" - it now uses a folder called 'tmp' in the project directory.  Can find no reference to a command that allows me to change the tmp directory path outside of the source code, and frankly don't have the time to hunt it down when I have a working solution that (hopefully) won't cause issues at anyone else's end either.

Am I going along the right path with the changes I've made in the attached files?  Haven't sorted out the resets for the 16 and 32-bit regs, plus it all seems a bit wasteful in terms of gates duplicating all that data, but I'm sure there's probably a much simpler way of doing it all that you've got.

Next, work out why the 'ENDIAN' only messes up then entire HW_REG system, why you need to get rid of it and why making new IO port with the same output reg renamed to 8bit and these new assigned output wires would help provide a better solution:
Code: [Select]
)(

        input                               RESET,
        input                               CLK,
        input                               WE,
        input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
        input         [PORT_CACHE_BITS-1:0] DATA_IN,
        input       [PORT_CACHE_BITS/8-1:0] WMASK,
        output  reg                 [  7:0] HW_REGS_8bit[0:(2**HW_REGS_SIZE-1)]
        output  wire                [ 15:0] HW_REGS_16bit[0:(2**HW_REGS_SIZE-1)]
        output  wire                [ 31:0] HW_REGS_32bit[0:(2**HW_REGS_SIZE-1)]

);

I said assigned wires, not new regs.

IE:
for loop
assign HW_REGS_16bit[ i ] = {HW_REGS_8bit[ i+0 ],HW_REGS_8bit[ i+1 ]};

similar for the 32bit assigns.

Swap the +0 and +1 depending on the endian setting.

Unused regs are "PRUNED" from the design automatically, otherwise, your original 160kbits of regs would excede the DECA's available 50kbit logic cells.

I have a feeling you will soon need to look at my tiny code in the 2 point size.
It is kind of obvious if the address you are writing to is going into the wrong memory location that you need to correct the write address.  Well, at least you have seen that much with my chosen test 'write data'.  Look at the pattern of where each write goes to into the HW_REGS regardless of the data which is being written.  Look at the write address in the SIM and where the write data ends up.  Maybe this hint will help.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2021, 02:16:21 pm
I said assigned wires, not new regs.

Darn it, missed that minor detail. ::)

IE:
for loop
assign HW_REGS_16bit[ i ] = {HW_REGS_8bit[ i+0 ],HW_REGS_8bit[ i+1 ]};

similar for the 32bit assigns.

Swap the +0 and +1 depending on the endian setting.

This might seem a silly question, but where should I put these assigns?  For some reason I've got it into my head that you can't (or shouldn't) put assigns in an always block?  Do I need a separate comb block for this assign loop?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2021, 02:42:07 pm
The address needs to be inverted..

Okay, had to go look at the tiny code you'd posted.  There was no way I was going to work out how to invert the address like that. :o

My question still stands re: where to put the assigns, though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2021, 06:56:19 pm
The assigns do not go inside the always_ff block.

Though, you can make an 'always_comb' block and just use a simple '16bit={8bit,8bit}' if you like.  IE: the 'assign' header is not needed inside an always_comb block.
 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2021, 07:17:06 pm
There was no way I was going to work out how to invert the address like that. :o
That isn't the only way.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 10, 2021, 11:07:44 pm
I'm missing something or doing something wrong here with the assigns.  According to ModelSim, the 16bit and 32bit HW_Regs are constantly hi-z and their values never change?

Code: [Select]
assign HW_Regs_16bit = enable ? { HW_REGS__8bit[( ADDR_IN[HW_REGS_SIZE-1:0] )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 1 )] } : 16'b0 ;
assign HW_Regs_32bit = enable ? { HW_REGS__8bit[( ADDR_IN[HW_REGS_SIZE-1:0] )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 1 )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 2 )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 3 )] } : 32'b0 ;

Both outputs should only show a value if enable is high.  Is that preferable to just outputting a value no matter what?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 10, 2021, 11:57:46 pm
I'm missing something or doing something wrong here with the assigns.  According to ModelSim, the 16bit and 32bit HW_Regs are constantly hi-z and their values never change?

Code: [Select]
assign HW_Regs_16bit = enable ? { HW_REGS__8bit[( ADDR_IN[HW_REGS_SIZE-1:0] )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 1 )] } : 16'b0 ;
assign HW_Regs_32bit = enable ? { HW_REGS__8bit[( ADDR_IN[HW_REGS_SIZE-1:0] )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 1 )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 2 )], HW_REGS__8bit[(( ADDR_IN[HW_REGS_SIZE-1:0] ) + 3 )] } : 32'b0 ;

Both outputs should only show a value if enable is high.  Is that preferable to just outputting a value no matter what?

IE:
for loop
assign HW_REGS_16bit[ i ] = {HW_REGS_8bit[ i+0 ],HW_REGS_8bit[ i+1 ]};

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 11, 2021, 11:12:53 am
Hello?  Did you get it working??

You can also try:

Code: [Select]
always_comb begin
for (i = big_endian ; i < (total_size-1) ; i ++ ) HW_REGS_16bit[ i ] = {HW_REGS_8bit[ i+little_endian ],HW_REGS_8bit[ i+big_endian ]};
end
Im sure I might have flipped around an endian or 2...
You will probably need to change the output wire to output logic for this to work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2021, 07:58:29 am
For simplicity - and unless you really think we need it, I'm dropping endianness concerns for the moment.  Here's what I've done so far:

Code: [Select]
integer x ;
always_comb begin
    for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 2)  begin
        HW_REGS_16bit[x] = { HW_REGS__8bit[x+0], HW_REGS__8bit[x+1] } ;
    end
    for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 4)  begin
        HW_REGS_32bit[x] = { HW_REGS__8bit[x+0], HW_REGS__8bit[x+1], HW_REGS__8bit[x+2], HW_REGS__8bit[x+3] } ;
    end
end

integer i ;
always @( posedge CLK ) begin
   
    if ( RESET ) begin
        // reset registers to initial values
        for (i = 0; i < RST_PARAM_SIZE; i = i + 1) begin
            HW_REGS__8bit[{RESET_VALUES[i][29:17], 1'b0}] <= RESET_VALUES[i][ 7:0] ;
            HW_REGS__8bit[{RESET_VALUES[i][29:17], 1'b1}] <= RESET_VALUES[i][15:8] ;
        end
    end
    else
    begin
        for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1)  begin
            if (valid_wr && WMASK[i]) begin
                HW_REGS__8bit[( ADDR_IN[HW_REGS_SIZE-1:0] | (i^(PORT_CACHE_BITS/8-1)) )] <= DATA_IN[i*8+:8] ;
            end
        end
    end
   
end

I've also had to change the 16-bit and 32-bit HW_REGS outputs to logic instead of wires as you said.  I guess these are being treated as regs now?

Seems there's a problem with the index value for 16- and 32-bit values, however:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1347446)

So I changed the comb slightly to index the 16- and 32-bit values better:

Code: [Select]
integer x;
always_comb begin
    for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 2)  begin
        HW_REGS_16bit[x/2] = { HW_REGS__8bit[x+0], HW_REGS__8bit[x+1] } ;
    end
    for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 4)  begin
        HW_REGS_32bit[x/4] = { HW_REGS__8bit[x+0], HW_REGS__8bit[x+1], HW_REGS__8bit[x+2], HW_REGS__8bit[x+3] } ;
    end
end

But it seems no values are being updated in these two HW_REGS outputs in addresses >0x0F?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1347452)

As you can see, values up to 0x0F are reflected in the 16- and 32-bit outputs, but writes to HW_REGS after that to 0x14, 0x15 etc. are not updated.  Not sure why this is happening?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2021, 08:17:18 am
What happens when you write a 16bit number to address 005 vs 006 in a Z80.
Shouldn't you want the option to read a 16bit number in the odd addresses?

Code: [Select]
integer x ;
always_comb begin
    for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 2)  begin
        HW_REGS_16bit[x] = { HW_REGS__8bit[x+0], HW_REGS__8bit[x+1] } ;
    end
    for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 4)  begin
        HW_REGS_32bit[x] = { HW_REGS__8bit[x+0], HW_REGS__8bit[x+1], HW_REGS__8bit[x+2], HW_REGS__8bit[x+3] } ;
    end
end


 :palm:
for (x = 0; x < PORT_CACHE_BITS/8 - 1; x = x + 2)  begin
No...
This:
for (x = 0; x < (HW_REGS_SIZE**2) - 1; x = x + 1)  begin
You want all the HW regs.

And what's wrong with the endian?

Code: [Select]
parameter string ENDIAN = "Big Endian",   // Enter "B****" for Big Endian, anything else for Little Endian.

......

localparam endian_h16 = (ENDIAN[0] == "B") ? 1 : 0 ;
localparam endian_l16 = (ENDIAN[0] == "B") ? 0 : 1 ;
localparam endian_h32 = (ENDIAN[0] == "B") ? 3 : 0 ;
localparam endian_m32 = (ENDIAN[0] == "B") ? 2 : 1 ;
localparam endian_n32 = (ENDIAN[0] == "B") ? 1 : 2 ;
localparam endian_l32 = (ENDIAN[0] == "B") ? 0 : 3 ;

.......

for (x = 0; x < [color=red](HW_REGS_SIZE**2)[/color] - 3; x = x + 1)  begin // The -3 means the final 3 bytes cannot be used as wide words as they would exceed the HW_REGS_8bit final address.
HW_REGS_16bit[x] = { HW_REGS_8bit[x+endian_h16], HW_REGS_8bit[x+endian_l16] } ;
HW_REGS_32bit[x] = { HW_REGS_8bit[x+endian_h32], HW_REGS_8bit[x+endian_m32], HW_REGS_8bit[x+endian_n32], HW_REGS_8bit[x+endian_l32] } ;
end

Need I say more?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2021, 09:27:24 am
BTW, I still do not like your reset values system.
Remember, we want to specify the same Z80 address and data if it were a Z80 equivalent write.

If you do not want to complicate things on the reset, then just make it a defined byte/byte reset.

I would personally make 3 sets of input reset parameters, one for 8 bit values, one for 16bit values and one for 32bit values.  The 3 input parameters each would have their own counter for the number of presets and you can use the same 2&4 Endian localparams I created in the previous post to define how a 16bit or 32bit reset default ends up sorted into the 8bit regs.

The only thing left is an optional 'strobe' output for each 8bit address.  This will allow you to move the GPU geometry Z80 output ports to a Z80 write memory address.  (There are some weird caveats here when using this feature without the Z80 doing the writing, but we can work out a few work arounds.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2021, 11:00:06 am
 |O A little typo above.  I just had the closing brackets in the wrong place:

Code: [Select]
localparam endian_h16 = (ENDIAN[0] == "B") ? 1 : 0 ;
localparam endian_l16 = (ENDIAN[0] == "B") ? 0 : 1 ;
localparam endian_h32 = (ENDIAN[0] == "B") ? 3 : 0 ;
localparam endian_m32 = (ENDIAN[0] == "B") ? 2 : 1 ;
localparam endian_n32 = (ENDIAN[0] == "B") ? 1 : 2 ;
localparam endian_l32 = (ENDIAN[0] == "B") ? 0 : 3 ;

My earlier example would probably still function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2021, 07:17:42 pm
Okay, so the changes to the 16- and 32-bit registers results in this:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1347896)

Looking okay?

BTW, I still do not like your reset values system.
Remember, we want to specify the same Z80 address and data if it were a Z80 equivalent write.

... so instead of using zero-based addresses for the default byte values, you want full address values as if the Z80 were writing these values?  At the moment, the HW_Regs__8bit array starts at 0x0000 as BASE_WRITE_ADDRESS is 20'h0, but we're not doing any processing of the incoming address so when we change BASE_WRITE_ADDRESS, we're going to jump outside of the HW_Regs__8bit array very quickly?

Is this needed, then?

Code: [Select]
HW_REGS__8bit[( (ADDR_IN[HW_REGS_SIZE-1:0] - BASE_WRITE_ADDRESS) | (i^(PORT_CACHE_BITS/8-1)) )] <= DATA_IN[i*8+:8] ;


I can then do this with the reset lines:

Code: [Select]
HW_REGS__8bit[{(RESET_VALUES[i][29:17] - BASE_WRITE_ADDRESS), 1'b0}] <= RESET_VALUES[i][ 7:0] ;
HW_REGS__8bit[{(RESET_VALUES[i][29:17] - BASE_WRITE_ADDRESS), 1'b1}] <= RESET_VALUES[i][15:8] ;


... and then the default RESET_VALUES can be specified with literal addresses for the HW registers being set to default values, instead of zero-based addresses.  Is this what you meant?

I would personally make 3 sets of input reset parameters, one for 8 bit values, one for 16bit values and one for 32bit values.  The 3 input parameters each would have their own counter for the number of presets and you can use the same 2&4 Endian localparams I created in the previous post to define how a 16bit or 32bit reset default ends up sorted into the 8bit regs.

Something like this?

Code: [Select]
module HW_Regs #(

    parameter string      ENDIAN                           = "Big" , // Enter "B****" for Big Endian, anything else for Little Endian.
    parameter int         PORT_ADDR_SIZE                   = 19    , // This parameter is passed by the top module
    parameter int         PORT_CACHE_BITS                  = 128   , // This parameter is passed by the top module
    parameter             HW_REGS_SIZE                     = 14    , // 2^14 = 16384 bytes
    parameter int         DEFAULT_PARAMS                   = 16    , // Indicate which set of RESET_VALUES to use; 8, 16 or 32 bit ones
    parameter int         RST_8_PARAM_SIZE                 = 4     , // Number of default values
    parameter int         RST16_PARAM_SIZE                 = 2     , // Number of default values
    parameter int         RST32_PARAM_SIZE                 = 1     , // Number of default values
    parameter int         BASE_WRITE_ADDRESS               = 20'h0 , // Where the HW_REGS are held in RAM
    parameter bit [23:0]  RESET_VALUES_8[1:RST_8_PARAM_SIZE] = '{
            {16'h00, 8'h10}, {16'h01, 8'h00}, {16'h02, 8'h10}, {16'h03, 8'h00}
    },
    parameter bit [31:0]  RESET_VALUES16[1:RST16_PARAM_SIZE] = '{
            {16'h00, 16'h0010}, {16'h02, 16'h0010}
    },
    parameter bit [47:0]  RESET_VALUES32[1:RST32_PARAM_SIZE] = '{
            {16'h00, 32'h00100010}
    }

)(

    input                               RESET,
    input                               CLK,
    input                               WE,
    input          [PORT_ADDR_SIZE-1:0] ADDR_IN,
    input         [PORT_CACHE_BITS-1:0] DATA_IN,
    input       [PORT_CACHE_BITS/8-1:0] WMASK,
    output  reg                 [  7:0] HW_REGS__8bit[0:(2**HW_REGS_SIZE-1)],
    output  logic               [ 15:0] HW_REGS_16bit[0:(2**HW_REGS_SIZE-1)],
    output  logic               [ 31:0] HW_REGS_32bit[0:(2**HW_REGS_SIZE-1)]

);

localparam endian_h16 = (ENDIAN[0] == "B") ? 1 : 0 ;
localparam endian_l16 = (ENDIAN[0] == "B") ? 0 : 1 ;

localparam endian_h32 = (ENDIAN[0] == "B") ? 3 : 0 ;
localparam endian_m32 = (ENDIAN[0] == "B") ? 2 : 1 ;
localparam endian_n32 = (ENDIAN[0] == "B") ? 1 : 2 ;
localparam endian_l32 = (ENDIAN[0] == "B") ? 0 : 3 ;

wire enable   = ( ADDR_IN[PORT_ADDR_SIZE-1:HW_REGS_SIZE] == BASE_WRITE_ADDRESS[PORT_ADDR_SIZE-1:HW_REGS_SIZE] ) ;   // upper x-bits of ADDR_IN should equal BASE_WRITE_ADDRESS for a successful read or write
wire valid_wr = WE && enable ;

integer x;
always_comb begin
    for (x = 0; x < (HW_REGS_SIZE**2) - 3; x = x + 1)  begin
        HW_REGS_16bit[x] = { HW_REGS__8bit[x+endian_h16], HW_REGS__8bit[x+endian_l16] } ;
        HW_REGS_32bit[x] = { HW_REGS__8bit[x+endian_h32], HW_REGS__8bit[x+endian_m32], HW_REGS__8bit[x+endian_n32], HW_REGS__8bit[x+endian_l32] } ;
    end
end

integer i ;
always @( posedge CLK ) begin
   
    if ( RESET ) begin
        // reset registers to initial values
        if (DEFAULT_PARAMS == 8) begin
            for (i = 0; i < RST_8_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[(RESET_VALUES_8[i][21:8])] <= RESET_VALUES_8[i][ 7:0] ;
            end
        end else if (DEFAULT_PARAMS == 16) begin
            for (i = 0; i < RST16_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[{RESET_VALUES16[i][29:17], endian_h16}] <= RESET_VALUES16[i][ 7:0] ;
                HW_REGS__8bit[{RESET_VALUES16[i][29:17], endian_l16}] <= RESET_VALUES16[i][15:8] ;
            end
        end else if (DEFAULT_PARAMS == 32) begin
            for (i = 0; i < RST32_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_h32}] <= RESET_VALUES32[i][ 7: 0] ;
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_m32}] <= RESET_VALUES32[i][15: 8] ;
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_n32}] <= RESET_VALUES32[i][23:16] ;
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_l32}] <= RESET_VALUES32[i][31:24] ;
            end
        end
    end
    else
    begin
        for (i = 0; i < PORT_CACHE_BITS/8; i = i + 1)  begin
            if (valid_wr && WMASK[i]) begin
                HW_REGS__8bit[( ADDR_IN[HW_REGS_SIZE-1:0] | (i^(PORT_CACHE_BITS/8-1)) )] <= DATA_IN[i*8+:8] ;
            end
        end
    end
   
end

endmodule


I'm not sure that the part marked in red below is working as I'm intending it to:

HW_REGS__8bit[{RESET_VALUES16[29:17], endian_h16}] <= RESET_VALUES16[ 7:0] ;

I'm trying to set the last bit of the HW_REGS__8bit 'address' to 1 or 0, dependent on the endianness selected.  endian_h16 is set up as a a localparam with no type specified, so I guess SystemVerilog will treat it as a though it's a 32-bit integer? Am I going to have to be more specific in how I use that value?  Something like endian_h16[0] instead?

The only thing left is an optional 'strobe' output for each 8bit address.  This will allow you to move the GPU geometry Z80 output ports to a Z80 write memory address.  (There are some weird caveats here when using this feature without the Z80 doing the writing, but we can work out a few work arounds.)

Run this one past me again, I'm not getting the implications? :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 12, 2021, 07:19:04 pm
|O A little typo above.  I just had the closing brackets in the wrong place:

Code: [Select]
localparam endian_h16 = (ENDIAN[0] == "B") ? 1 : 0 ;
localparam endian_l16 = (ENDIAN[0] == "B") ? 0 : 1 ;
localparam endian_h32 = (ENDIAN[0] == "B") ? 3 : 0 ;
localparam endian_m32 = (ENDIAN[0] == "B") ? 2 : 1 ;
localparam endian_n32 = (ENDIAN[0] == "B") ? 1 : 2 ;
localparam endian_l32 = (ENDIAN[0] == "B") ? 0 : 3 ;

My earlier example would probably still function.

No matter, I must have copied that code after you edited it as I had no issues with it. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2021, 11:33:28 pm
How about changing :
Code: [Select]
            for (i = 0; i < RST16_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[RESET_VALUES16[i][29:16]+ endian_l16] <= RESET_VALUES16[i][ 7:0] ;
                HW_REGS__8bit[RESET_VALUES16[i][29:16]+ endian_h16] <= RESET_VALUES16[i][15:8] ;
            end
        end else if (DEFAULT_PARAMS == 32) begin
            for (i = 0; i < RST32_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_h32}] <= RESET_VALUES32[i][ 7: 0] ;
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_m32}] <= RESET_VALUES32[i][15: 8] ;
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_n32}] <= RESET_VALUES32[i][23:16] ;
                HW_REGS__8bit[{RESET_VALUES32[i][45:34], endian_l32}] <= RESET_VALUES32[i][31:24] ;
            end

to:

Code: [Select]
if (RST_8_PARAM_SIZE != 0) begin
            for (i = 1; i <= RST_8_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[(RESET_VALUES_8[i][21:8])] <= RESET_VALUES_8[i][ 7:0] ;
            end
end

if (RST16_PARAM_SIZE != 0) begin
            for (i = 1; i <= RST16_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[RESET_VALUES16[i][29:16]+ endian_l16] <= RESET_VALUES16[i][ 7:0] ;
                HW_REGS__8bit[RESET_VALUES16[i][29:16]+ endian_h16] <= RESET_VALUES16[i][15:8] ;
            end
end

if (RST32_PARAM_SIZE != 0) begin
            for (i = 1; i <= RST32_PARAM_SIZE; i = i + 1) begin
                HW_REGS__8bit[RESET_VALUES32[i][45:32]+ endian_h32] <= RESET_VALUES32[i][ 7: 0] ;
                HW_REGS__8bit[RESET_VALUES32[i][45:32]+ endian_m32] <= RESET_VALUES32[i][15: 8] ;
                HW_REGS__8bit[RESET_VALUES32[i][45:32]+ endian_n32] <= RESET_VALUES32[i][23:16] ;
                HW_REGS__8bit[RESET_VALUES32[i][45:32]+ endian_l32] <= RESET_VALUES32[i][31:24] ;
            end
end

No "else"s as we will have a few 8, 16 and 32 bit reset values.
Also, keep the + endian so any address we enter here will match the Z80 writes.

Quote
I'm not sure that the part marked in red below is working as I'm intending it to:

HW_REGS__8bit[{RESET_VALUES16[29:17], endian_h16}] <= RESET_VALUES16[ 7:0] ;

This is because the 'endian_h16' is seen as an integer of unknown bits, up to 32.  there are 2 ways to fix this, 1:
Code: [Select]
localparam bit       endian_h16 = (ENDIAN[0] == "B") ? 1 : 0 ;
localparam bit       endian_l16 = (ENDIAN[0] == "B") ? 0 : 1 ;
localparam bit [1:0] endian_h32 = (ENDIAN[0] == "B") ? 3 : 0 ;
localparam bit [1:0] endian_m32 = (ENDIAN[0] == "B") ? 2 : 1 ;
localparam bit [1:0] endian_n32 = (ENDIAN[0] == "B") ? 1 : 2 ;
localparam bit [1:0] endian_l32 = (ENDIAN[0] == "B") ? 0 : 3 ;

2:
HW_REGS__8bit[{RESET_VALUES16[29:17], (1)'(endian_h16)}] <= RESET_VALUES16[ 7:0] ;

Telling the compiler to trim endian_h16 down to 1 bit.
Whenever you use the braces { }, the compiler needs to know how many bits to stuff together.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 12, 2021, 11:42:57 pm
Also:
Code: [Select]
parameter int         BASE_WRITE_ADDRESS               = 20'h0 , // Where the HW_REGS are held in RAM
Should be:

Code: [Select]
parameter int         BASE_WRITE_ADDRESS               = 32'h0 , // Where the HW_REGS are held in RAM
Remember, the 'ram' address exceeds your puny Z80 address and you may assign these controls outside the Z80's range if you wish, then once the Z80 sets everything within it's range, you may DMA copy that to where these address may be held.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 13, 2021, 03:38:46 pm
Okay, made those changes.  Latest file attached.  Now, can you expand on this next bit a little?  I'm not sure I understand the implications:

The only thing left is an optional 'strobe' output for each 8bit address.  This will allow you to move the GPU geometry Z80 output ports to a Z80 write memory address.  (There are some weird caveats here when using this feature without the Z80 doing the writing, but we can work out a few work arounds.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2021, 03:51:05 pm
Okay, made those changes.  Latest file attached.  Now, can you expand on this next bit a little?  I'm not sure I understand the implications:

The only thing left is an optional 'strobe' output for each 8bit address.  This will allow you to move the GPU geometry Z80 output ports to a Z80 write memory address.  (There are some weird caveats here when using this feature without the Z80 doing the writing, but we can work out a few work arounds.)

Remember when writing to the Geometry unit's FIFO using a port output?
You have 2 bytes for the 16 bit word, correct?
Now, how does the FIFO know that the 16bit word is ready to be accepted?

The issue stems if you have a piece of logic or function, tied to the HW_REGS, which needs to know you are sending a new data.  Imagine I want to send five 8'h00 then five 8'hFF to my serial port transmitter connected to HW_REGS address 15.  How will it know that five and five identical bytes are being sent.  This case is different than for example having my serial baud rate selector tied to HW_REGS address 16 & 17 which will be whatever it will be at any time once the Z80 writes to it.  The baud rate will just control a count-down period in the serial transmitter, but, address 15 may need to transmit hundreds of 8'h00.  How will it know how many writes were made to address 15?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 13, 2021, 04:08:56 pm
You only want the strobe for the 8 bit address, so, something like this should simplify things:

output logic [(2**HW_REGS_SIZE-1):0] HW_REGS_strobe = 0, // default to '0'

inside a reset:
HW_REGS_strobe <= 0 ;


For now, scrap it as I think of a good way to write out the 1 clock bit set inside the strobe.  It's going to be something simple stupid when I code it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2021, 07:06:16 am
Ok Nockieboy, I need test files for my new multi-layer window video generator system, all in raw binary format.  Note that if you need or want anything different, now is the time to speak up...


Tiles/Fonts: (Supports separate 4/8/16/32 widths and heights, 1/2/4/8/16a/16b/32 bpp, up to 16k characters with mirror and flip per character.)

1bpp 8x16, 256 character VGA Font  (I already have this one.)
1bpp 8x8, 256 character VGA Font.
1bpp 16x32, up to 256 character Font.
1bpp 32x32, up to 256 character Font.
2bpp 16x32, up to 256 character Font.  (4 color.)
4bpp 8x16, up to 256 character Font.  (16 color.)
4bpp 16x32, up to 256 character Font.  (16 color.)
8bpp 8x16, up to 256 character Font.  (256 color.)
16bpp 8x16, up to 256, 16 is enough, character Font.  (4x4x4x4 ABGR 4096 true color font with with 16 translucency levels.)
16bpp 8x16, up to 256, 16 is enough, character Font.  (5x6x5 BGR 65536 true color font.)
32bpp 8x16, 16 is enough, character Font.  (8x8x8x8 ABGR 16.7M true color font with with 256 translucency levels.)


Palette ->  Supports 256 entries per layer at 32 bit, in ABGR format: (Yes, make a real palette as it needs to be used for the multicolored sample fonts and images.)

8 bit Alpha translucency - 0 = completely transparent to the layer below, 255= completely opaque.
8 bit Blue intensity.
8 bit Green intensity.
8 bit Red intensity.


Graphics: Supports 1/2/4/8/16a/16b/32 bpp, with window dimensions up to 65535x65535.
(All the horizontal size needs to round down to 32bits, IE 4 bytes)

~2048x1536  1bpp monochrome image.
~1024x768  2bpp 4 color mage.    (Make it work with your provided palette)
~1024x768  4bpp 16 color image.    (Make it work with your provided palette)
~1024x768  8bpp 256 color image.  (Make it work with your provided palette)
~512x512  16bpp stored in 4x4x4x4 ABGR 4096 true color mode.  (I suggest first making the 32bpp version, then computing this 16bpp version.)
~512x512  16bpp stored in 5x6x5 BGR 65536 true color mode.
~512x512  32bpp stored in 8x8x8x8 ABGR 16.7M true color mode with with 256 translucency levels.


     For the 32bpp, use a paint software to render a foreground with a soft stencil so that it may be overlayed on top of one of the other images you sent with smooth edges.

     I'm around half way done with the new display system and I need to fill the DDR3 with graphics to test.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2021, 09:32:19 am
Ok Nockieboy, I need test files for my new multi-layer window video generator system, all in raw binary format.  Note that if you need or want anything different, now is the time to speak up...

Can't think of anything, you've covered all the bases and far more than I'd ever have thought of. :-+

Here's a monochrome test image in 2048x1536x1, RAW format.  Let me know if this is suitable - I'm no expert with a paint program, so I need to know I'm saving in the right format etc.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2021, 09:47:44 am
Since it is not a picture of anything, I cannot tell.
However, the final binary file size should be:

1bpp -> 2048*1536/8 = 393216 bytes
2bpp -> 2048*1536/4 = 786432 bytes
4bpp -> 2048*1536/2 = 1572864 bytes
8bpp -> 2048*1536/1 = 3145728 bytes
16bpp -> 2048*1536*2 = 6291456 bytes
32bpp -> 2048*1536*4 = 12582912 bytes


a 1bpp is stored in single bits per pixel:
byte 1      byte 2    byte 3.....
0101010101010100101010....
24 Individual pixels on the screen from left to right, not 3 pixels, or 1 pixel.

*** I need actual pictures, not patterns which may be misinterpreted as a bug or may hide a bug.
*** Also, it is good to have a 1 pixel wide border surrounding the screen

You will need to find or generate your own converter.  Or make the image in the GPU and copy the raw binary screen data to a file.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2021, 10:48:40 am
This isn't going to be quick and I'm short on time this week.  I've got a lovely picture, right size, 1-pixel border, 1 bpp.  Gimp won't save it any smaller than 3MB a RAW/data file. :palm:

I'm going to have to dig out that really old copy of Photoshop I've got buried somewhere on the old PC.

Also, regarding the palette creation, is there a particular app or web resource I can use to create what you're after?  Gimp allows custom palettes, but the one I'm using is RGB.  I don't have time to write a Python script to translate it, especially if there's already options out there in the correct format, or offering the ability to convert between formats.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2021, 11:00:47 am
 :palm: Well, I'm writing a new multi-layer window system from scratch supporting many functions which will be compatible with both my DDR3 system and then new TAP_xxx port which is looking to be around 3k lines of code.  As for getting a picture and font out which is 8/32 bit, you might find a paint program to do that, but, for 16bit 4444 and 565 BGR mode, plus 4/2/1 bit modes, you will have to find tools for 8bit which store the image this way.  Especially for the fonts.  Though, the current VGA font is already in 1 bit mode, so, you are lucky there, but what about the larger X&Y sizes?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 15, 2021, 08:33:24 pm
:-/O  Could you test this image for me please?  It is 2048x1536x1 with a solid single-pixel border all around the edge - it's an image of a parrot in flight.  Hopefully. ???

You'll have to change the attached file's .txt extension to something appropriate like .bin as the good old forum security won't allow me to upload the file with a .bin extension.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 15, 2021, 11:27:18 pm
You do realize you could have zipped the file, right?

Anyways, are you asking me to make a program to convert the .bin back to a .bmp.  Remember, when I show it on hardware, I might end coding my display hardware to correct for any mistakes in the file you provided me to show it correctly even if the data is in error.

A hint you may use is if you make a 1 bit binary to regular 24bit .bmp picture, if you load our VGA font and say it is 1 bit 8 pixels wide, your resulting .bmp should be a vertical tall entirely displayed font.

Also, I don't remember, but, I believe that my GPU test-bench should be able to load and blit convert it onto a 8bit image, though, I do not remember the maximum X/Y screen coordinates.  You might need to re-do it with a res of something like 800x600.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2021, 01:21:50 am
Ok, I've patched the 'GPU_GEO_tb.sv' to support 2048x1536, though, the frame buffer maxes out at 1 megabyte due to the rest of the geometry unit.  So, if any file you generate is over 1mb, it will be corrupted.  You will just need to lower the image resolution.

I provided the edited the 'GEO_tb_Blitter.txt' to process 3 files so you can see how to make the .bmp's.

You provided image above has the bit orientation backwards, take a look.
I also provided & saved the original VGA 1bit font's and saved it as a .BMP, and as you can see, the letters are forwards.  Though, this bug may not be on you as the bit orientation issue isn't a universal standard, it is just the way all the old 8-bit computers ran their 1bit color video modes.  IE: Atari 8bit / Amiga / Commodore 64 / Old school VGA, and many others packed each byte the other way around.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1350635)

Perhaps, I might add a display control which will allow you to select the 'bit-orientation'.
Note that you can only process 1/2/4/8 bit images.  The BMP saver will not support 16/32 bit images.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2021, 11:03:13 am
Hi Nockieboy, please approve the new tile layer modes and features:

Code: [Select]
// **********************************************************************************
// Tile selection when using different 'CMD_vid_bpp' modes, 8/16a/32/16b bpp modes.
// * On a tile layer, bpp will actually mean bpc -> Bits Per Character Tile.
// ----------------------------------------------------------------------------------
// FGC  = Foreground color.  Adds this FGC value to any tile pixels whose color data is != 0.
// BGC  = Background color.  Replace tile pixels whose color data = 0 with this BGC value.
// MIR  = Mirror the tile.
// FLIP = Vertically flip the tile.
// ----------------------------------------------------------------------------------
//
//'CMD_vid_bpp' mode:
//
// 8   bpp -> Each byte = 1 character, 0 through 255, no color, mirror or flip functions.
//
//             BGC,  FGC,  Char 0-255.   *** BGC & FGC are multiplied by 16 in this mode.
// 16a bpp -> {4'h0, 4'h0, 8'h00 }                       = 16 bits / 256 possible tiles.
//
//             FLIP, MIR,  Char 0-16383.
// 16b bpp -> {1'b0, 1'b0, 14'h0000 }                    = 16 bits / 16384 possible tiles.
//
//              BGC,   FGC,  FLIP, MIR,  Char 0-16383.
// 32  bpp -> {8'h00, 8'h00, 1'b0, 1'b0, 14'h0000 }      = 32 bits / 16384 possible tiles.
//
//
// Remember, the contents inside a tile set's 'CMD_vid_tile_bpp' can be 1/2/4/8/16a/32/16b bpp.
// The tile set can only be as large as the reserved fixed available FPGA blockram.
// It is possible to have multiple tile layers when using the 'SDI_LAYERS' feature
// where each layer may share or have different tile sets so long as there is enough
// room in the single reserved FPGA blockram.
//
// **********************************************************************************

Note that your GPU will be using 2 for 'SDI_LAYERS' when running 720p60, 1080p30 modes.
If you stick to 480p, you can bump that up to 4 or maybe even 8 layers.  Because of FMAX routing on the MAX10 fpga, the 'SDI_LAYERS' can only be set to 1 for 1080p60.  (2 for 1080p60, 4 for 1080p30 would be pushing timings into the red, but most likely functional...) The Lattice EPC5 series may allow doubling all the SDI_LAYER figures as their core ram in some scenarios will clear the required 300MHz.

Also note that multiple window modules may run in parallel, in tile or graphics mode.  So, running 4 graphics plus 1 tile unit in 480p at 4xSDI_LAYERS means your total layer count will be 4x4 graphics = 16 graphics layers and 4 tile layers for a total of 20 layers.  The FPGA blockram exclusively holds the tile sets and individual palettes for each layer or combined palette within each module to save on blockram.

The text data and graphics data for each layer are all stored on DDR3 with a limit of 65535x65535 pixel window size.  IE, on a tile layer, with a 16x16 pixel tile set, you can open a window displaying 1048576x1048576 pixels, but do to a lack of DDR3 ram, your limit would be more like 16384x16384, a window display of 262144x262144 pixels.

Is this enough for your Z80?
How about a 68000?
Maybe a 68040, or even 68060 as they are only 75Mhz...  I think my DDR3 could handle it with graphics and sound.  Especially if we were to design a pcb with 32 or 64 bit DDR3 instead of 16bit.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2021, 01:04:57 pm
**** I need to know the 'BYTE' order your Z80 os uses to store 16bit numbers.

A) With a 16bit int stored at address 0, address 0 = low 8 bits, and address 1 = high 8 bits.

or

B) With a 16bit int stored at address 0, address 0 = high 8 bits, and address 1 = low 8 bits.

So far, I designed the tile system to operate in B) BigEndian.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2021, 03:45:20 pm
You do realize you could have zipped the file, right?

|O  Uh, just chalk that up to me doing two jobs and three things at once at the moment.  :(

Anyways, are you asking me to make a program to convert the .bin back to a .bmp.  Remember, when I show it on hardware, I might end coding my display hardware to correct for any mistakes in the file you provided me to show it correctly even if the data is in error.

Oh jeez no, you've got more than enough on!  I was just bouncing off walls yesterday trying to get lots of stuff done and was worried I was unable to do something as basic as create a bitmap.  ::)  Fortunately, the image you've produced is exactly what I expected for it to be working properly - yes, the bit order is reversed but I did that accidentally on purpose.  Should be able to fix that with the next images I produce now I know the default order the bits are being spat out by the software I'm using.

Perhaps, I might add a display control which will allow you to select the 'bit-orientation'.

This shouldn't be necessary now I know the bit order of the conversion software I'm using.

**** I need to know the 'BYTE' order your Z80 os uses to store 16bit numbers.

A) With a 16bit int stored at address 0, address 0 = low 8 bits, and address 1 = high 8 bits.

or

B) With a 16bit int stored at address 0, address 0 = high 8 bits, and address 1 = low 8 bits.

So far, I designed the tile system to operate in B) BigEndian.

The Z80 is a little-endian system.  So A is the order it would store a 16-bit int.  Always LSB, then MSB.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2021, 04:23:48 pm
**** I need to know the 'BYTE' order your Z80 os uses to store 16bit numbers.

A) With a 16bit int stored at address 0, address 0 = low 8 bits, and address 1 = high 8 bits.

or

B) With a 16bit int stored at address 0, address 0 = high 8 bits, and address 1 = low 8 bits.

So far, I designed the tile system to operate in B) BigEndian.

The Z80 is a little-endian system.  So A is the order it would store a 16-bit int.  Always LSB, then MSB.

Ok, this produces a weird issue with the tile/font addressing when storing the 'text/tile' data.
Since I have modes which can address 16k characters, not just the old fashioned limited 256 where 1 byte = 1 character, and this is in the DDR3, I will need to add an ENDIAN swap option for the line buffer tile mode.  Otherwise, when you address the extended character set, you will always need to swap bytes in the Z80.

This is not a problem with the HW_REGs controls since for those, we have 16 & 32 bit outputs where 1 parameter will change the entire GPU control system's address order, however, this does not change the order of the large ints stored in the DDR3 where the display characters are stored.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2021, 05:15:01 pm
Hi Nockieboy, please approve the new tile layer modes and features:

Code: [Select]
// **********************************************************************************
// Tile selection when using different 'CMD_vid_bpp' modes, 8/16a/32/16b bpp modes.
// * On a tile layer, bpp will actually mean bpc -> Bits Per Character Tile.
// ----------------------------------------------------------------------------------
// FGC  = Foreground color.  Adds this FGC value to any tile pixels whose color data is != 0.
// BGC  = Background color.  Replace tile pixels whose color data = 0 with this BGC value.
// MIR  = Mirror the tile.
// FLIP = Vertically flip the tile.
// ----------------------------------------------------------------------------------
//
//'CMD_vid_bpp' mode:
//
// 8   bpp -> Each byte = 1 character, 0 through 255, no color, mirror or flip functions.
//
//             BGC,  FGC,  Char 0-255.   *** BGC & FGC are multiplied by 16 in this mode.
// 16a bpp -> {4'h0, 4'h0, 8'h00 }                       = 16 bits / 256 possible tiles.
//
//             FLIP, MIR,  Char 0-16383.
// 16b bpp -> {1'b0, 1'b0, 14'h0000 }                    = 16 bits / 16384 possible tiles.
//
//              BGC,   FGC,  FLIP, MIR,  Char 0-16383.
// 32  bpp -> {8'h00, 8'h00, 1'b0, 1'b0, 14'h0000 }      = 32 bits / 16384 possible tiles.
//
//
// Remember, the contents inside a tile set's 'CMD_vid_tile_bpp' can be 1/2/4/8/16a/32/16b bpp.
// The tile set can only be as large as the reserved fixed available FPGA blockram.
// It is possible to have multiple tile layers when using the 'SDI_LAYERS' feature
// where each layer may share or have different tile sets so long as there is enough
// room in the single reserved FPGA blockram.
//
// **********************************************************************************

Note that your GPU will be using 2 for 'SDI_LAYERS' when running 720p60, 1080p30 modes.
If you stick to 480p, you can bump that up to 4 or maybe even 8 layers.  Because of FMAX routing on the MAX10 fpga, the 'SDI_LAYERS' can only be set to 1 for 1080p60.  (2 for 1080p60, 4 for 1080p30 would be pushing timings into the red, but most likely functional...) The Lattice EPC5 series may allow doubling all the SDI_LAYER figures as their core ram in some scenarios will clear the required 300MHz.

Also note that multiple window modules may run in parallel, in tile or graphics mode.  So, running 4 graphics plus 1 tile unit in 480p at 4xSDI_LAYERS means your total layer count will be 4x4 graphics = 16 graphics layers and 4 tile layers for a total of 20 layers.  The FPGA blockram exclusively holds the tile sets and individual palettes for each layer or combined palette within each module to save on blockram.

The text data and graphics data for each layer are all stored on DDR3 with a limit of 65535x65535 pixel window size.  IE, on a tile layer, with a 16x16 pixel tile set, you can open a window displaying 1048576x1048576 pixels, but do to a lack of DDR3 ram, your limit would be more like 16384x16384, a window display of 262144x262144 pixels.

Is this enough for your Z80?
How about a 68000?
Maybe a 68040, or even 68060 as they are only 75Mhz...  I think my DDR3 could handle it with graphics and sound.  Especially if we were to design a pcb with 32 or 64 bit DDR3 instead of 16bit.

:o Looks good. :-+  Yes, should hopefully be enough for the Z80. ;)  Just have one question - is tile mode necessary if we're going for a full DDR3 implementation?  I've gone from tiled to full-graphics mode thanks to the increased space in the DDR3.   Are there benefits to using a tiled mode instead of blitting the text characters in a full graphics mode?  Have I got the wrong idea and am I missing something blatantly obvious?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 16, 2021, 05:41:35 pm
Hi Nockieboy, please approve the new tile layer modes and features:

Code: [Select]
// **********************************************************************************
// Tile selection when using different 'CMD_vid_bpp' modes, 8/16a/32/16b bpp modes.
// * On a tile layer, bpp will actually mean bpc -> Bits Per Character Tile.
// ----------------------------------------------------------------------------------
// FGC  = Foreground color.  Adds this FGC value to any tile pixels whose color data is != 0.
// BGC  = Background color.  Replace tile pixels whose color data = 0 with this BGC value.
// MIR  = Mirror the tile.
// FLIP = Vertically flip the tile.
// ----------------------------------------------------------------------------------
//
//'CMD_vid_bpp' mode:
//
// 8   bpp -> Each byte = 1 character, 0 through 255, no color, mirror or flip functions.
//
//             BGC,  FGC,  Char 0-255.   *** BGC & FGC are multiplied by 16 in this mode.
// 16a bpp -> {4'h0, 4'h0, 8'h00 }                       = 16 bits / 256 possible tiles.
//
//             FLIP, MIR,  Char 0-16383.
// 16b bpp -> {1'b0, 1'b0, 14'h0000 }                    = 16 bits / 16384 possible tiles.
//
//              BGC,   FGC,  FLIP, MIR,  Char 0-16383.
// 32  bpp -> {8'h00, 8'h00, 1'b0, 1'b0, 14'h0000 }      = 32 bits / 16384 possible tiles.
//
//
// Remember, the contents inside a tile set's 'CMD_vid_tile_bpp' can be 1/2/4/8/16a/32/16b bpp.
// The tile set can only be as large as the reserved fixed available FPGA blockram.
// It is possible to have multiple tile layers when using the 'SDI_LAYERS' feature
// where each layer may share or have different tile sets so long as there is enough
// room in the single reserved FPGA blockram.
//
// **********************************************************************************

Note that your GPU will be using 2 for 'SDI_LAYERS' when running 720p60, 1080p30 modes.
If you stick to 480p, you can bump that up to 4 or maybe even 8 layers.  Because of FMAX routing on the MAX10 fpga, the 'SDI_LAYERS' can only be set to 1 for 1080p60.  (2 for 1080p60, 4 for 1080p30 would be pushing timings into the red, but most likely functional...) The Lattice EPC5 series may allow doubling all the SDI_LAYER figures as their core ram in some scenarios will clear the required 300MHz.

Also note that multiple window modules may run in parallel, in tile or graphics mode.  So, running 4 graphics plus 1 tile unit in 480p at 4xSDI_LAYERS means your total layer count will be 4x4 graphics = 16 graphics layers and 4 tile layers for a total of 20 layers.  The FPGA blockram exclusively holds the tile sets and individual palettes for each layer or combined palette within each module to save on blockram.

The text data and graphics data for each layer are all stored on DDR3 with a limit of 65535x65535 pixel window size.  IE, on a tile layer, with a 16x16 pixel tile set, you can open a window displaying 1048576x1048576 pixels, but do to a lack of DDR3 ram, your limit would be more like 16384x16384, a window display of 262144x262144 pixels.

Is this enough for your Z80?
How about a 68000?
Maybe a 68040, or even 68060 as they are only 75Mhz...  I think my DDR3 could handle it with graphics and sound.  Especially if we were to design a pcb with 32 or 64 bit DDR3 instead of 16bit.

:o Looks good. :-+  Yes, should hopefully be enough for the Z80. ;)  Just have one question - is tile mode necessary if we're going for a full DDR3 implementation?  I've gone from tiled to full-graphics mode thanks to the increased space in the DDR3.   Are there benefits to using a tiled mode instead of blitting the text characters in a full graphics mode?  Have I got the wrong idea and am I missing something blatantly obvious?

Well, every 4 bytes can equal an 8x8 or 16x16 256 color character.  That's editing 4 bytes to change 64 or 256 bytes of pixels on the screen.  Now if you fill the screen with a repetitive pattern or tiles, and now edit/paint new contents in those tiles.  Only drawing into 4 or 8 16x16 tiles will completely fill the screen with the animated graphics instead of re-drawing a megabytes of blits to repaint that full-screen sized animated backdrop.

And again, super huge X/Y scrolling levels can be constructed with a fraction the storage if they are painted in tiles.

What else do you want me to say.  Imagine how many Super Nintendo and Amiga games were made, but blow up the memory content and available colors & palettes many fold.

Each open 1080p 256/65536 color screens eats a lot of DDR3 bandwidth just to maintain the picture, 16.7m color screen even more.  A tile/text layer typically uses 1/16th the DDR3 bandwidth and 1/16th the memory for the same colors and screen size making it 16x faster fill/erase, load & blit data to and from.

Even with accelerated graphics, this is not a NVIDIA RTX card and not a 64bit 5GHz cpu...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 16, 2021, 06:04:07 pm
So far, I designed the tile system to operate in B) BigEndian.
Pretty much all modern systems are little endian, and even those which can be configured either way (like some ARM CPUs) are typically ran in little endian mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 16, 2021, 06:26:07 pm
Each open 1080p 256/65536 color screens eats a lot of DDR3 bandwidth just to maintain the picture, 16.7m color screen even more.  A tile/text layer typically uses 1/16th the DDR3 bandwidth and 1/16th the memory for the same colors and screen size making it 16x faster fill/erase, load & blit data to and from.
Most modern cards actually support floating point colors, meaning each of R, G and B color will take 4 bytes - this is often used for post-processing like tone mapping. Also they often trade speed for memory efficiency, so for example for FullHD resolution(1920x1080) they actually use lines which are 2048 pixel long, as this makes the address math easier and allow for course alignment - remember than most video cards have very wide memory bus (256 bit is pretty usual, but there are wider buses out there), so they read/write in big chunks. Also just about all of them now even in integer RGB mode use 32bit pixels - again to make processing them easier. Modern video memory has a very large access latency, so they need to have a very regular access patterns because they have to know well in advance what data will they require - in order for it to be fetched in time for the processing cores to work on. Another way they deal with such large latency is through cycle-level parallelism, when processing cores send a request to memory (for example for texture fetch), and then switch to some other task while that request is being executed, and switch back once request is completed and data has arrived. The reason it works is that there are literally millions of pixels in a single frame, so at any point in time you will have pixels which have the data ready for processing, and so those cores can be occupied pretty much all the time without any stalls. There is a dedicated hardware on a video chip which controls all of that scheduling so that processing cores are utilized as much as possible to the point that each clock cycle they can end up processing different pixel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 16, 2021, 06:52:00 pm
:o Looks good. :-+  Yes, should hopefully be enough for the Z80. ;)  Just have one question - is tile mode necessary if we're going for a full DDR3 implementation?  I've gone from tiled to full-graphics mode thanks to the increased space in the DDR3.   Are there benefits to using a tiled mode instead of blitting the text characters in a full graphics mode?  Have I got the wrong idea and am I missing something blatantly obvious?

Well, every 4 bytes can equal an 8x8 or 16x16 256 color character.  That's editing 4 bytes to change 64 or 256 bytes of pixels on the screen.  Now if you fill the screen with a repetitive pattern or tiles, and now edit/paint new contents in those tiles.  Only drawing into 4 or 8 16x16 tiles will completely fill the screen with the animated graphics instead of re-drawing a megabytes of blits to repaint that full-screen sized animated backdrop.

And again, super huge X/Y scrolling levels can be constructed with a fraction the storage if they are painted in tiles.

What else do you want me to say.  Imagine how many Super Nintendo and Amiga games were made, but blow up the memory content and available colors & palettes many fold.

Each open 1080p 256/65536 color screens eats a lot of DDR3 bandwidth just to maintain the picture, 16.7m color screen even more.  A tile/text layer typically uses 1/16th the DDR3 bandwidth and 1/16th the memory for the same colors and screen size making it 16x faster fill/erase, load & blit data to and from.

Ah okay, I'm with you.  I was just thinking of text when I though of tile mode - clearly I was missing the whole tiled-graphics display possibilities. ::)

Even with accelerated graphics, this is not a NVIDIA RTX card and not a 64bit 5GHz cpu...

I wonder how long it'll be before we (hobbyists) have access to that level of power?  I mean, the (low-end) FPGA's we're talking about and using provide us with power and versatility unheard of back in the 80's, even on dedicated hardware.

Most modern cards actually support floating point colors, meaning each of R, G and B color will take 4 bytes - this is often used for post-processing like tone mapping. Also they often trade speed for memory efficiency, so for example for FullHD resolution(1920x1080) they actually use lines which are 2048 pixel long, as this makes the address math easier and allow for course alignment - remember than most video cards have very wide memory bus (256 bit is pretty usual, but there are wider buses out there), so they read/write in big chunks. Also just about all of them now even in integer RGB mode use 32bit pixels - again to make processing them easier. Modern video memory has a very large access latency, so they need to have a very regular access patterns because they have to know well in advance what data will they require - in order for it to be fetched in time for the processing cores to work on. Another way they deal with such large latency is through cycle-level parallelism, when processing cores send a request to memory (for example for texture fetch), and then switch to some other task while that request is being executed, and switch back once request is completed and data has arrived. The reason it works is that there are literally millions of pixels in a single frame, so at any point in time you will have pixels which have the data ready for processing, and so those cores can be occupied pretty much all the time without any stalls. There is a dedicated hardware on a video chip which controls all of that scheduling so that processing cores are utilized as much as possible to the point that each clock cycle they can end up processing different pixel.

And I thought what BrianHG was doing with the DDR3 was complicated.  My question is, is the access latency literally "very large", or does it just appear that way because the GPU is running at such high clock speeds that it's hitting the physical limits of DDR memory cell capacitor charge/discharge times?  Would be cool if they could come up with a quicker memory technology.  Isn't SRAM faster, but a lot more expensive, or did I imagine that?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on December 16, 2021, 11:09:49 pm
I wonder how long it'll be before we (hobbyists) have access to that level of power?  I mean, the (low-end) FPGA's we're talking about and using provide us with power and versatility unheard of back in the 80's, even on dedicated hardware.
5 GHz will probably be out of reach for a long time - considering that even the very best FPGAs out there can barely cross 1 GHz line, but 300-500 MHz for a general logic is very achievable with Xilinx Ultrascale+ devices. These new Artix US+ devices which are supposed to come out soon will also be built on the same fabric, but can be somewhat accessible to hobbyists, even if on a pricey side ($200 per chip). So while certainly not Arduino-level cheap, they are still a lot cheaper than existing devices from that family, which I think starts at like 1500$ per device.

And I thought what BrianHG was doing with the DDR3 was complicated. 
It's not very complicated, because all shader units are usually grouped into "warps", and all shader units within a warp execute in lock-step, meaning each and every shader unit executes the same operation. You can think of SU as a specialized ALU capable of performing all typical math operations. Then you can have two FIFOs, which are filled by the scheduling unit - one for "ready" commands - which have all data ready for their execution, and another one for waiting for memory (since memory operations are pipelined, they complete in the same order they were issued). So if you encounter a memory access operation, you just send a request into the memory subsystem and place command into the "waiting" FIFO, and once it completes, you put it back into the "ready" FIFO. This is of course very simplified, but I hope you get an idea.

My question is, is the access latency literally "very large", or does it just appear that way because the GPU is running at such high clock speeds that it's hitting the physical limits of DDR memory cell capacitor charge/discharge times?  Would be cool if they could come up with a quicker memory technology.  Isn't SRAM faster, but a lot more expensive, or did I imagine that?
DRAM speed in not a problem - interface speed is. This is why NVidia had to partner with Micron to engineer PAM4 interface for GDDR6X memory, which essentially transmits two bit per edge instead of one (by having 4 different signal levels as opposed to just two for typical NRZ-type digital interface), effectively doubling available bandwidth. The downside is that this interface is much more susceptible to the noise (because receiver now need to distinguish between 4 signal levels as opposed to just two), which is why they integrated error correction right at the interconnect level.

As for SRAM - it's faster (BRAM blocks inside FPGA are essentially SRAM, and so are all caches inside a CPU and GPU), but it takes a lot of die space, and it consumes a lot of power - compared to DRAM. You can just look up how much a 32 MB SRAM module costs, and compare it to DDR3 for example - you will see like close to two orders of magnitude difference. SRAM (in form of QDR-X) is still used in some specialized applications where DDRx latency is just unbearable - like network switching equipment, and even there it's mostly used as an extension of on-chip RAM - like additional cache level. Incidentally, I had a single design where I connected a small 1MByte SRAM chip to FPGA and used it as a cache for much larger DDR3 memory, because while it can't match DDR3 bandwidth, it's capable of completing an access in just single cycle, and since it doesn't need a refresh, this access time was guaranteed all the time. It was just a simple 10 ns SDR chip, but there are chip out there which can work at significantly higher frequencies, the problem is they cost a lot of money - we're talking 100's of dollars per chip.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 17, 2021, 02:10:34 am
And I thought what BrianHG was doing with the DDR3 was complicated. 
It's not very complicated, because all shader units are usually grouped into "warps", and each warp performs in lock-step, meaning each and every shader unit executes the same operation. You can think of SU as a specialized ALU capable of performing all typical math operations. Then you can have two FIFOs, which are filled by the scheduling unit - one for "ready" commands -  ....

Yes even my little multiplayer DDR3 window reader and multiple parallel window outputs I'm making now already has the beginnings of such built in parallel-ism, both using parallel modules for pure speed and serial sequential channels in each module where as much speed isn't needed, allowing me to use each of the same rendering pipes for multiple layers cutting logic resources by a number of fold.  (Now when I say rendering, this is nothing more than a schedule ahead line cache read, with a playback system which manages color mixing overlays of said channels which tells the read scheduler the status of the playback display buffers.)

The tricky 2 sided mess is making code which bottom end fabric FPGAs will still achieve a good FMAX even as you add channels, and, generate code where the compiler may automatically trim/prune logic effectively based on which features the user enables as well as whether a number of functions as hard-wired or under real-time software control without needing to go to the top-end dedicated HDL compilers separate of the FPGA vendor's development studios.

The other issue is the tiny 1.7megabit core FPGA ram.  1.7megabyte for this project would have been a luxury and I could code things much simpler, but, being a project designed to fit even on a smaller 6$ lattice 25kgate, 900kbit core ram FPGA, I went through the effort of making something which can still function on a few 10k of blockram instead of requiring a few 100k of blockram.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: voltsandjolts on December 17, 2021, 09:33:08 am
LVGL (https://lvgl.io/) is a nice open source graphics library for adding a GUI to your embedded system.
It doesn't currently support 8-bitters, but then they didn't expect an 8-bitter to have a GPU :o
It might be worth considering LVGL requirements when designing new GPU functionality to ease creation of an LVGL backend (https://github.com/lvgl/lvgl/tree/master/src/draw) for your custom GPU.
Just a thought.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on December 17, 2021, 05:46:27 pm
LVGL (https://lvgl.io/) is a nice open source graphics library for adding a GUI to your embedded system.
It doesn't currently support 8-bitters, but then they didn't expect an 8-bitter to have a GPU :o
It might be worth considering LVGL requirements when designing new GPU functionality to ease creation of an LVGL backend (https://github.com/lvgl/lvgl/tree/master/src/draw) for your custom GPU.
Just a thought.

Not a bad idea indeed, although here, as you yourself said, this is a bit beyond what was meant for an 8-bit system.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 18, 2021, 04:28:02 pm
I've managed to put together some simple test images for the 1-8 bpp images you requested.  I have no idea where to start or how to do the 512x512 images you're requesting.  There's a 512x512 image with transparency in the zip, but I have no idea if it's ABGR or anything else. :-//

I'll make a start on the fonts as soon as I have some more time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 18, 2021, 11:49:33 pm
Cute, the Mandalorian, 32bit instead of 24bit, with an Alpha translucency layer, in .png.
Ok, for the palette, Why isn't color 0 black?
I figure they are in order.
Also, not a single transparent color, usually #0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2021, 12:33:41 am
 :palm: Ohhh, Adobe Photoshop Elements, Ohhh Paint Shop Pro 5, you both screw up, but in different ways and one is more use full than the other.

Ok Nockieboy, your 512x512.png Mandiloarian has a proper true Alpha blend channel recognized by both Adobe Photoshop and Paint-Shop-Pro 5, though PSP5 doesn't show it as nice unless you have an additional layer or stencil enabled below it.

If I save the image in non-compressed Truvision TARGA .tga in Photoshop, I had a choice of 16/24/32.
Saving it as 24 bit gave me a file just above 786432 bytes as expected.
Saving it as 32 bit gave me a file just above 1048576 bytes as expected.

If I save the image in non-compressed Truvision TARGA .tga in PaintShopPro5, I had a choice of 8/16/24.
Saving it as 24 bit gave me a file just above 1048576 bytes, not as expected.

Ok, I took the 2 just above 1048576 bytes files from both paint tools and hex-edited them both to remove the header and footer making both files exactly 1048576 bytes.  From what I can tell, the image in the file is vertically flipped, I don't like that, but, it seems to be a trend with a number of picture formats on the PC.

Look at the 2 files in the attached .zip in once of your hex editor of choice and remembering the image is upside-down, you tell me what is the difference.  (Hint, make sure you hex editor rows are viewed in rows which fit a multiple of 4 bytes...)

Files:
512x512x32.Adobe.tga.bin
512x512x32.paintshoppro5.tga.bin
(I removed the useless file as the next post has a good one.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 19, 2021, 01:28:40 am
Ok, same photo, saved by photoshop in .tif uncompressed, including transparency layer.

This time the photo is right side up.
However, the header was a doozy, fairly large filled with tons of garbage text.

On the plus side, this is the only format which did not loose anything at all or interpret the transparent pixels to another background color in the process of saving.

The order appears to be RGBA.

So, in my window system, place this .bin on a layer above another with the alpha enabled, you will get that smooth shaded transition embedded in the outline of the Mandalorian so he will appear floating above the below image without any visible harsh cut-out edge.

Keep this .bin as it is a good test reference image for playing with an image with a true smooth transitioned alpha-blend edge.

Know that PSP5 seems to loose the transparency when loading the .png and saving to .tif, or corrupt the transparent area with color values it deems to be it's set default background color.

I've attached the save method to make the .tif in Adobe Photoshop Elements 9 which I trimmed in a hex-editor to make the attached raw 512x512x32 .bin file.  With these settings, though there is a cram of header BS, it should be easier to decode in software as uncompressed .tif is not too complicated and you get the RGBA as a 32bit integer for each pixel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 21, 2021, 10:37:04 am
Ok, progress so far on my new BrianHG_DDR3 video generator system:

Module 1: BrianHG_GFX_Sync_Gen.sv and testbench.
Done.
Provide a pixel clock with CLK_DIVIDE_IN, H&V total, display res, front porch width & sync width and it generates all the synchronization signals to generate a video output.
CLK_DIVIDE_IN can be 0,1,2,3,4,5,6,7 to both divide the source clock by 1,2,3,4,5,6,7,8 and also used by the output video line generator to support from 1 through 8 layers sequentially interleaved / multiplexed.

Module 2: BrianHG_GFX_Video_Line_Buffer.sv and testbench.
Beta functional.
Takes input from a single BrianHG_DDR3 read port with multiplex addressing to allow multiple parallel modules running from one single DDR3 read port, and a set write address range for tile memory and palette memory compatible with my BrianHG_DDR3 TAP_xxxx port, and generates a line of video output with the capability of up to 8 sequential layers according to the sync generator's CLK_DIVIDE_IN setting.  All inputs run on the system CMD_CLK while the video output stream runs on the video output clock synchronized to the BrianHG_Sync_Gen.sv.

Module 3: BrianHG_GFX_Window_DDR3_Reader.sv and testbench:
Just beginning to work on.
Takes in the user graphics settings and sends commands to a DDR3 read port to fill the BrianHG_Video_Line_Buffer's memory in sync with that module's feedback outputs: horizontal reset, vertical enable and line buffer FIFO position status.
It will be configurable to support both up to 16 parallel BrianHG_Video_Line_Buffer.sv modules with up to 8 Sequential layers within each module allowing addressing up to 128 layers total.  (I don't think the DECA has enough blockram/gates to do all 128 layers, but, the 35$ 85kgate 4megabit Lattice LFE5U-85 can do it with ease.)

Module 4: BrianHG_GFX_Window_Layer_Mixer.sv
Will work on after module 3.
Coalesces and superimpose/mix all the video layers streamed out of the BrianHG_Video_Line_Buffer modules, using the 'Alpha' channel to set the layer-to-layer translucency when generating the single video output.  Also contains the individual layer-layer hardware accelerated pixel collision detector status.


Once #4 is done, it is just a wiring into the GPU and assigning the video window setting controls to your chosen HW_REGS settings.  Then program away.  Though, I will have a GPU setup ready when module #3 is done, except it will only support 1 layer, but every video mode and feature should function for testing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 24, 2021, 11:41:25 am
Module 3: BrianHG_GFX_Window_DDR3_Reader.sv update:

Finished all the IO, definitions and testbench setup.  Next onto the formulai and testing in my DDR3 1080p example.

Here are your new window controls with description exposed to the Z80:
Code: [Select]
input        [2:0]                  CMD_win_bpp            [0:LAYERS-1], // Bits per pixel.  For 1,2,4,8,16a,32,16b bpp, use 0,1,2,3,4,5,6.  *16a bpp = 4444 RGBA, 16b bpp = 565 RGB.
input        [31:0]                 CMD_win_base_addr      [0:LAYERS-1], // The beginning memory address for the window.
input        [HC_BITS-1:0]          CMD_win_bitmap_width   [0:LAYERS-1], // The full width of the bitmap stored in memory.  If tile mode is enabled, then the number of tiles wide.
input        [HC_BITS-1:0]          CMD_win_bitmap_x_pos   [0:LAYERS-1], // The beginning X pixel position inside the bitmap in memory.
input        [VC_BITS-1:0]          CMD_win_bitmap_y_pos   [0:LAYERS-1], // The beginning Y line position inside the bitmap in memory.

input        [HC_BITS-1:0]          CMD_win_x_offset       [0:LAYERS-1], // The onscreen X position of the window.
input        [VC_BITS-1:0]          CMD_win_y_offset       [0:LAYERS-1], // The onscreen Y position of the window.
input        [HC_BITS-1:0]          CMD_win_x_size         [0:LAYERS-1], // The onscreen display width of the window.      *** Using 0 will disable the window.
input        [VC_BITS-1:0]          CMD_win_y_size         [0:LAYERS-1], // The onscreen display height of the window.     *** Using 0 will disable the window.

input        [3:0]                  CMD_win_scale_width    [0:LAYERS-1], // Pixel horizontal zoom width.  For 1x,2x,3x thru 16x, use 0,1,2 thru 15.
input        [3:0]                  CMD_win_scale_height   [0:LAYERS-1], // Pixel vertical zoom height.   For 1x,2x,3x thru 16x, use 0,1,2 thru 15.
input        [3:0]                  CMD_win_scale_h_begin  [0:LAYERS-1], // Begin display part-way into a zoomed pixel for sub-pixel accurate scrolling.
input        [3:0]                  CMD_win_scale_v_begin  [0:LAYERS-1], // Begin display part-way into a zoomed pixel for sub-pixel accurate scrolling.

input        [7:0]                  CMD_win_alpha_override [0:LAYERS-1], // When 0, the layer translucency will be determined by the graphic data.
                                                                         // Any figure from +1 to +127 will progressive force all the graphics opaque.
                                                                         // Any figure from -1 to -128 will progressive force all the graphics transparent.

input                               CMD_win_tile_enable    [0:LAYERS-1], // Enable Tile mode enable.  *** Display will be corrupt if the BrianHG_GFX_Video_Line_Buffer
                                                                         //                               module's ENABLE_TILE_MODE parameter isn't turned on.

input        [2:0]                  CMD_win_tile_bpp       [0:LAYERS-1], // Defines the tile bits per pixel.  For 1,2,4,8,16a,32,16b bpp, use 0,1,2,3,4,5,6.  *16a bpp = 4444 RGBA, 16b bpp = 565 RGB.
input        [15:0]                 CMD_win_tile_base      [0:LAYERS-1], // Defines the beginning tile 16 bit base address (multiplied by) X 16 bytes for a maximum of 1 megabytes addressable tile set.
input        [1:0]                  CMD_win_tile_width     [0:LAYERS-1], // Defines the width of the tile.  0,1,2,3 = 4,8,16,32
input        [1:0]                  CMD_win_tile_height    [0:LAYERS-1], // Defines the height of the tile. 0,1,2,3 = 4,8,16,32

HC_BITS and VC_BITS are set to 16 meaning a maximum horizontal and vertical resolution of 65536 pixels or tiles.
LAYERS is a parameter which allows you to set the maximum available window layers.
All the above inputs are wired to incrementing addresses from the new HW_REGS module.
The tile/font and palette memory are also addressed as regular DDR3 memory as they are wired through the new TAP_xxx port.

It looks like you will need 32 bytes worth of controls per window.
We should double it just for spare future expansion.

So, once we configure a base offset for the HW_REGS, each progressive window layer will has the same controls, but beginning at +64 bytes above the previous window's beginning address.

Except for CMD_win_scale_h_begin & CMD_win_scale_v_begin inputs (which you probably not want to use unless it is something special), this new window module does all the cruddy math work internally when addressing sub-pixel positions with regards to tile/font and the input CMD_win_bitmap_x/y_pos settings so you just enter the coordinate you want and my window HDL will automatically work out the sub-pixel addressing within each tile or bitmap below 32bit for you.

When choosing a base address and bitmap width, it is still recommended that you pad the address and size to every 32 bytes to make the most of the new BrianHG_DDR3_Memory_Copy_Manager.sv coming in the new year which will copy memory from A->B with functions which can be used for general memory copying with advanced functions for graphics, sound mixing/blending/processing where 128/256bit mode is the fastest, but to use the 128/256 bit mode, your source and destination memory pointers will need to be located on 128/256bit boundaries.  Otherwise, 64bit mode is half speed, 32bit mode is half that, 16 bit mode is half that, and 8 bit mode is half that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 25, 2021, 04:07:58 pm
Merry X-Mas everyone, Happy Holidays!

Module 3: BrianHG_GFX_Window_DDR3_Reader.sv update:

All the window metrics/coordinates and addressing appear simulate properly.

Next:
A) Stream out the DDR3 read requests from the generated addresses.
B) Wire into my existing show_1080p demo project and test.
C) Wire into Nockieboy's GPU.

D) Work on module 4: BrianHG_GFX_Window_Layer_Mixer.sv so we may see more than 1 window layer.

I have passed 2K lines of code for this Video Windows Generator and expect ~1k mode before I finish.
It is already as complicated as my DDR3 controller from over a decade ago.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 27, 2021, 07:38:55 pm
Got the first picture with HW_REGS controls.
Got a bunch of debugging to do.

I need those font files...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 28, 2021, 10:14:19 pm
@Nockieboy, the font tool you need: http://www.codehead.co.uk/cbfg/ (http://www.codehead.co.uk/cbfg/)

Though you only get 128/64kb using the HW accelerated tile/font system, with a max of 32x32 pixels, (maybe I should extend that to 64x64 as 1bpp/2bpp fonts still are just within 128k, using the blitter for text give you access to all DDR3 memory to draw text.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 29, 2021, 02:04:24 am
I've managed to put together some simple test images for the 1-8 bpp images you requested.  I have no idea where to start or how to do the 512x512 images you're requesting.  There's a 512x512 image with transparency in the zip, but I have no idea if it's ABGR or anything else. :-//

I'll make a start on the fonts as soon as I have some more time.

Test Image report:
1024x768x2.bin   - I seem to be getting a line of garbage at the top of the display and a width of 1028 pixels, not 1024 pixels.

1024x768x4.bin   - This one seems fine, 16 shades of grey.  However, with 16 shades, did you really need to dither is so hard?  Or, is there some sort of color palette I need to see it right?

1024x768x8.bin   - Best looking one yet.  Still heavily dithered.  I'm guessing I need a special palette to see it in color.

2048x1536x1.bin  - Looks good.

Only the '1024x768x2.bin' is out of spec.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 31, 2021, 07:49:55 pm
Ok, the my BrianHG_GFX_VGA_Window_System is 90% functional.  Only the final layer alpha channel mixer is missing as I am now just averaging windows for testing, but they are all there with all their features.

I paused here because the ravage DDR3 memory access done by the BrianHG_GFX_VGA_Window_System with multiple windows simultaneously open, each deliberately configured with an odd number of row pixels and to eat up over 90% of the available bandwidth causes that one DDR3 read port in use by the graphics system to randomly freeze.  It's time to look at debugging my multiport section of my controller before I finish my last alpha-blend window layer mixing module of my window system.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 03, 2022, 07:27:25 pm
Okay, I'm back - sorry for the radio silence over the holiday, it's been a bit hectic and for some reason I wasn't getting notifications of posts to the forum.  I've got a very busy couple of days coming up, but I'll try to get up to speed with developments as quickly as I can and get those fonts sorted ASAP.

Happy New Year!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 04, 2022, 02:49:44 pm
Tiles/Fonts: (Supports separate 4/8/16/32 widths and heights, 1/2/4/8/16a/16b/32 bpp, up to 16k characters with mirror and flip per character.)

1bpp 8x16, 256 character VGA Font  (I already have this one.)
1bpp 8x8, 256 character VGA Font.
1bpp 16x32, up to 256 character Font.
1bpp 32x32, up to 256 character Font.
2bpp 16x32, up to 256 character Font.  (4 color.)
4bpp 8x16, up to 256 character Font.  (16 color.)
4bpp 16x32, up to 256 character Font.  (16 color.)
8bpp 8x16, up to 256 character Font.  (256 color.)

See attached fonts.zip for the above font requests.  I've produced several bitmap (.BMP) source files for each tile size (filenames are Font_XxX.bmp) and from those source files I've produced font bitmaps with the requested number of bit planes.  Hopefully they're in the correct format you want and all is okay with them.  They're all greyscale, so despite the differing bpp, they should all be only 2 colours.

16bpp 8x16, up to 256, 16 is enough, character Font.  (4x4x4x4 ABGR 4096 true color font with with 16 translucency levels.)
16bpp 8x16, up to 256, 16 is enough, character Font.  (5x6x5 BGR 65536 true color font.)
32bpp 8x16, 16 is enough, character Font.  (8x8x8x8 ABGR 16.7M true color font with with 256 translucency levels.)

I have no idea where to start or how to produce a colour bitmap font mapped to a particular palette type. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 04, 2022, 05:49:22 pm
Big update coming tonight.
Be ready for tomorrow morning your time.

The documentation alone will be hell as my VGA system is has controls up the wazoo.  (Yes, spellcheck says 'wazoo' is a real word to my surprise.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 05, 2022, 04:10:46 am
 :phew: Ok, here we go, the first beta of the GPU project with my new:

     BrianHG_GFX_VGA_Window_System.sv

 :scared: Another maddening 4596 lines of code so far.... WTF was I thinking...

Anyways, right now, the number of window PDI_LAYERS can only be set to 1 while the number of SDI_LAYERS windows is 4.  The layer swapping / priority sorting logic isn't functional and there is no pixel collision detect function.

You will need to read the attached documentation to do anything.

To avoid a bug with my DDR3 Controller, for now, the ram is clocked at 300MHz half-rate mode instead of 400MHz quarter rate mode.  It's shouldn't affect anything on your side as with a 4 window layer limit, you arent getting close to the DDR3 limits no matter what you do.

I've also attached a 4layer.bin file which you may use the RS232 debugger to send to your GPU with a test setup having all 4 layers turned on.

These are your current project setup parameters:
(The attached .txt file tells you what they do and how to use the graphics system.)

Code: [Select]
parameter string     ENDIAN                  = "Little",            // Endian for 8bit addressing access.
parameter bit [3:0]  PDI_LAYERS              = 1,                   // Number of parallel window layers.
parameter bit [3:0]  SDI_LAYERS              = 4,                   // Number of sequential window layers.
parameter bit        ENABLE_TILE_MODE  [0:7] = '{1,0,0,0,0,0,0,0},  // Enable tile mode for each PDI_LAYER from 0 to 7.
                                                                    // TILES are available to all SDI_LAYERS of an enabled PDI_LAYER.
                                                                    // Each tile enabled PDI_LAYER will use it's own dedicated FPGA blockram.
parameter bit        SKIP_TILE_DELAY         = 0,                   // Skip horizontal compensation delay due to disabled tile mode features.  Only necessary for multiple PDI_LAYERS with mixed tile enable options.

parameter bit        ENABLE_PALETTE    [0:7] = '{1,1,1,1,1,1,1,1},  // Enable a palette blockram for each PDI_LAYER from 0 to 7.
                                                                    // Each palette enabled PDI_LAYER will use it's own dedicated FPGA blockram.
parameter bit        SKIP_PALETTE_DELAY      = 0,                   // Skip horizontal compensation delay due to disabled palette.  Only necessary for multiple PDI_LAYERS with mixed palette enable options.


parameter int        HWREG_BASE_ADDRESS      = 32'h00000100,     // The first address where the HW REG controls are located for window layer 0.  The first 256 bytes are reserved for general purpose use.
                                                                 // Each window uses 32 bytes for their controls, IE assuming 32 windows, we need 1024 bytes worth of address space.
parameter int        HWREG_BASE_ADDR_LSWAP   = 32'h000000F0,     // The first address where the 16 byte control to swap the SDI & PDI layer order.

parameter int        PAL_BASE_ADDR           = 32'h00001000,     // Assuming 32 layers where each palette is 1024 bytes, we will use 32768 bytes for the palette.
parameter int        TILE_BYTES              = 65536,            // Number of bytes reserved for the TILE/FONT memory.  We will use 64k, IE it is possible to make a 16x16x8bpp 256 character font.
parameter int        TILE_BASE_ADDR          = 32'h00004000,     //

Good luck and make sure you can get everything to work.
I will be adding PDI_LAYERS support in the next few days multiplying you available windows up to 8 fold.
Then I'll fix my DDR3 controller.
The add a hardware window-to-window pixel collision detector.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 07, 2022, 04:13:17 pm
Well?
Do I finish what I started?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 07, 2022, 06:15:32 pm
Well?
Do I finish what I started?

Unfortunately I've had next to no time to spend on anything other than work this week. :-\  Hopefully this weekend.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 07, 2022, 11:28:49 pm
Before I hit the sack for the night, I've built the project and uploaded it to the DECA.  Getting a rock-solid 1080p@60Hz output with random memory contents on the screen, but signs of life as a band at the top is cleared and pixels are being written to the screen when I type, albeit not making any sense.  Looks like I will need to re-write the graphics driver for the new system, or at the very least study the instructions you've provided and see how to set up the screen as before. :-/O

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 08, 2022, 12:29:27 am
Yes, read the instructions.

I believe you should first switch to 720x480 mode.
Also, read the new storage positions for the multiple palettes and font memory as well as every control register which is now different.

Remember, even drawing to the screen using the geometry unit, if that unit writes to an address containing the palette, font, or screen controls, they will all be affected as if your Z80 did the writing of the data.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 10, 2022, 09:59:30 am
Okay, I'm making progress with getting the display set up for the uCOM and understanding the notes you've provided.

I have a 480p 60Hz screen mode working using the 'special 480p' mode 7.  The graphics driver is currently unchanged, which is the next thing I need to tweak as it still thinks that the start of the video buffer is at 1200H and the tile data starts at 0200H, which overwrites the palette data at 1000H, making some text black, but I've got this on screen so far:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1375418)

As you can see, GEOFF is working too.  I'll run some more tests once I've tweaked the graphics drivers (especially the CP/M one).

Here's my current settings:
Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C100 00 00 12 00 83 7F 02 D0 00 00 00 00 00 00 00 00
C110 02 D0 01 E0 00 00 00 40 00 00 00 00 00 00 00 74

This translates to:

HWREG_BASE_ADDRESS+00 = 0x00001200 (32-bit) Window[0] base address
HWREG_BASE_ADDRESS+04 = 0x83 (8-bit value) Screen bpp (3 bpp and enabled) <- arrived at this value by trial and error
HWREG_BASE_ADDRESS+05 = 0x7F (8-bit signed value) 100% opacity
HWREG_BASE_ADDRESS+06 = 0x02D0 (16-bit) Bitmap width (720)
HWREG_BASE_ADDRESS+10 = 0x02D0 (16-bit) Window width (720)
HWREG_BASE_ADDRESS+12 = 0x01E0 (16-bit) Window height (480)
HWREG_BASE_ADDRESS+16 = 0x4000 (16-bit) Tile/font base address <- this doesn't appear to be important?
HWREG_BASE_ADDRESS+1F = 0x74 (8-bit) Video mode (480p, CLOCK_DIVIDER 5)

Going to get the drivers updated before I do too much more so that the palette isn't getting corrupted.

One question I have on your HDL notes - the Altera string bug.  This isn't preventing us from loading tile data into the FPGA's setup, is it?

Also, the font base address of 4000H doesn't seem to do anything - if I set it to 0x0000H, nothing changes.  I think this is because my GPU driver ignores this setting as it loads a font in at 200H and sets the blit parameters itself at startup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 10, 2022, 11:13:56 am
Okay, I'm making progress with getting the display set up for the uCOM and understanding the notes you've provided.

I have a 480p 60Hz screen mode working using the 'special 480p' mode 7.  The graphics driver is currently unchanged, which is the next thing I need to tweak as it still thinks that the start of the video buffer is at 1200H and the tile data starts at 0200H, which overwrites the palette data at 1000H, making some text black, but I've got this on screen so far:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1375418)

As you can see, GEOFF is working too.  I'll run some more tests once I've tweaked the graphics drivers (especially the CP/M one).

Here's my current settings:
Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C100 00 00 12 00 83 7F 02 D0 00 00 00 00 00 00 00 00
C110 02 D0 01 E0 00 00 00 40 00 12 00 00 00 00 00 74

This translates to:

HWREG_BASE_ADDRESS+00 = 0x00001200 (32-bit) Window[0] base address
HWREG_BASE_ADDRESS+04 = 0x83 (8-bit value) Screen bpp (3 bpp and enabled) <- arrived at this value by trial and error
Ok, yes the high bit enables the window layer.  As for the 3, as seen in my notes:

// Bits per pixel.  For 1,2,4,8,16a,32,16b bpp, use 0,1,2,3,4,5,6.  *16a bpp = 4444 RGBA, 16b bpp = 565 RGB.

IE:
0 = 1 bpp 2 color mode.
1 = 2 bpp 4 color mode.
2 = 4 bpp 16 color mode.
3 = 8 bpp 256 color mode.  Also the lowest mode required for tile text mode.
4 = 16a bpp 4096 color mode with 16 translucency levels, IE: 4444 RGBA mode.
5 = 32 bpp 16.7m color mode with 256 translucency levels, IE: 8888 RGBA mode.
6 = 16b bpp 65536 color mode, where color 0 is 100% translucent and all other color values are 100% opaque, IE: 565 RGB mode.

Quote
HWREG_BASE_ADDRESS+05 = 0x7F (8-bit signed value) 100% opacity
HWREG_BASE_ADDRESS+06 = 0x02D0 (16-bit) Bitmap width (720)
HWREG_BASE_ADDRESS+10 = 0x02D0 (16-bit) Window width (720)
HWREG_BASE_ADDRESS+12 = 0x01E0 (16-bit) Window height (480)
HWREG_BASE_ADDRESS+16 = 0x4000 (16-bit) Tile/font base address <- this doesn't appear to be important?


Step 1, first you need the 'CMD_win_bpp', HWREG_BASE_ADDRESS+0x04 video mode enabled to at least 8bpp or higher as we need at least 8 bit data to access a character.  The 16a&b bpp and 32bpp gives you access to colored characters, 1024 of them and H&V mirror/flip per character.

Step 2, 'CMD_win_tile_enable', HWREG_BASE_ADDRESS+0x18 needs to be at least 0x80 to turn the tile mode, '0' meaning the tile set is 1 bpp 2 color mode just like the IBM VGA font.
Quote

HWREG_BASE_ADDRESS+1F = 0x74 (8-bit) Video mode (480p, CLOCK_DIVIDER 5)

Going to get the drivers updated before I do too much more so that the palette isn't getting corrupted.

One question I have on your HDL notes - the Altera string bug.  This isn't preventing us from loading tile data into the FPGA's setup, is it?

Also, the font base address of 4000H doesn't seem to do anything - if I set it to 0x0000H, nothing changes.  I think this is because my GPU driver ignores this setting as it loads a font in at 200H and sets the blit parameters itself at startup.

The tile font base address will not do anything for a few reasons.

1. The 'CMD_win_tile_enable', HWREG_BASE_ADDRESS+0x18 needs to be at least set to 0x80 to turn on the tiles for that window layer as well as setting the CMD_win_tile_width & CMD_win_tile_height.

2. Note that even if the 'TILE_BASE_ADDR' parameter is set to 0x00004000, this is just the address you use the Z80 to write and read the tile's bitmap pattern data.  This address points to 0x0000 when setting the 'CMD_win_tile_base' @ HWREG_BASE_ADDRESS+0x16.  Placing a 0x0001 in this address tells the tile processor that the first character 0x00 will be moved from 0x000000, IE 0x00004000 accessed by the Z80, to 0x000010, IE addressed by the Z80 at 0x00004010.  This is a 16 byte step per 1 16 bit 'CMD_win_tile_base' value allowing you to address a 1mb offset.  Basically, since the VGA font is 16 bytes per character, adding a 0x00001 into the 'CMD_win_tile_base' would shift all the characters you see on the screen by 1.  (IE printing a 'B' would show a 'C'.)

As for the 'TILE_MIF_FILE' and 'PAL_MIF_FILE', it is just that Altera will no accept the parameter string.  I have hard wired the 2 parameters to 'VGA_FONT_8x16_mono32.mif' and 'VGA_PALETTE_RGBA32.mif' inside the source code and you will find the source .mif files inside the 'BrianHG_DDR3_GFX_source_v16' source code folder.  If you will be editing these, be sure to keep backups as receiving new updates from me may overwrite your changes.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 10, 2022, 10:18:22 pm
The tile font base address will not do anything for a few reasons.

Ah yes, for some reason I was thinking that tile mode was being used when I wrote my last post. ;)

As for the 'TILE_MIF_FILE' and 'PAL_MIF_FILE', it is just that Altera will no accept the parameter string.  I have hard wired the 2 parameters to 'VGA_FONT_8x16_mono32.mif' and 'VGA_PALETTE_RGBA32.mif' inside the source code and you will find the source .mif files inside the 'BrianHG_DDR3_GFX_source_v16' source code folder.  If you will be editing these, be sure to keep backups as receiving new updates from me may overwrite your changes.

The uCOM is overwriting the TILE_MIF_FILE with its own font anyway (or should be - have yet to see if it's working properly with the new memory locations for tiles etc).

One thing I've noticed so far is that changing the opacity almost makes the blitted text look bold.  Interesting side effect, I suppose.

I just have to get scrolling working again - I've made a lot of changes to the code to allow scrolling to work with any screen mode,  now I need to spend some time finishing it off tomorrow; then it looks like the uCOM will be as functional (well, more so given all the extra functions the GPU has now) than previous versions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 10, 2022, 10:55:45 pm
Quote
One thing I've noticed so far is that changing the opacity almost makes the blitted text look bold.  Interesting side effect, I suppose.

Could it be a background color difference?
Remember, the palette's contents counts and there are translucency levels for each palette color.  Forcing the 'opacity' to 100% will forcefully ignore the values in the palette.
Could it be a foreground color difference?

Please upload an example RS232-debugger capture of the memory.  IE save it as a .bin file.

Also remember, layer 0 is the top.  Layer 3 is the bottom.  So, if you want a HW text/tile layer on top, you will need to move your current GFX bitmap based layer down a level or more and configure the text window above.

Also, with the alpha adjust set to 0, transparent colors will take on the 'BGC' rgb color settings seen here:
Code: [Select]
CMD_BGC_RGB[23:16] = hw_reg8[HWREG_BASE_ADDRESS+16'h001A]     ; // Global system 24 bit color background color for where no active window exists,
CMD_BGC_RGB[15: 8] = hw_reg8[HWREG_BASE_ADDRESS+16'h001B]     ; // or any pixels where all the layers are transparent all the way through the bottom layer.
CMD_BGC_RGB[ 7: 0] = hw_reg8[HWREG_BASE_ADDRESS+16'h001C]     ; //
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 11, 2022, 08:27:47 am
Quote
One thing I've noticed so far is that changing the opacity almost makes the blitted text look bold.  Interesting side effect, I suppose.

Could it be a background color difference?
Remember, the palette's contents counts and there are translucency levels for each palette color.  Forcing the 'opacity' to 100% will forcefully ignore the values in the palette.
Could it be a foreground color difference?
...
Also remember, layer 0 is the top.  Layer 3 is the bottom.  So, if you want a HW text/tile layer on top, you will need to move your current GFX bitmap based layer down a level or more and configure the text window above.

I'm using a full graphics mode with 'manually'-blitted fonts like previously in layer 0, just mentioned this as an interesting side-effect more than a bug or anything.  I was adjusting the 'alpha adjust' value at HWREG_BASE_ADDRESS+5 when I noticed this effect - hadn't changed any individual transparency values in the palette.

As soon as I sort out scrolling, I'll look into this in more detail if you want and get you a debugger-capture etc, but I don't think it's a bug as I'm not using multiple layers (yet).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 11, 2022, 11:25:47 am
If you are using only 1 layer, anything transparent or semi-transparent still needs to go somewhere.  This is the BGC register.   Also, I want to see what you are seeing.  'bold' is weird as that might mean a horizontal pixel shift when my HDL internally runs it's pixel mixer which is how the SDI-layer mixing works.  I want to see if I have a bug, or what you see is just an illusion.  The debug capture will provide me a frozen picture of your screen.  Well, at least 1mb worth...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 11, 2022, 02:22:49 pm
Okay, a couple of images for you.  The first is normal settings:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1376357)

The second is with alpha (HW_REGS +5) set to 0x20 (you can just about make out a dark vertical line separating the 0's between each pair):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1376363)

And this third one is with alpha set to 0 (no separating line between each pair of zeros at all - can't even see it with my own eyes, this isn't a trick of the camera):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1376369)

The blurring effect appears to reach a maximum at 0x00, then dies off as I set the alpha from 0xFF towards 0x80, probably because it's becoming transparent and mixing with the black background as its transparency increases.  At 0x80, there's no text visible at all due to (I presume) 100% transparency.

I'll see if I can get the RS232 debugger set up later for the memory dump.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 11, 2022, 05:20:17 pm
The question is:  Is there a different translucent white in between the 0's dots stored in ram due to the geometry pixel writer screwing up, or is it my new pixel mixer screwing up generating/inserting that translucent white?

You would need to read the DDR3 pixel values of the screen to tell.

It looks like a bug on my side.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 11, 2022, 10:13:30 pm
@nockieboy, if hooking up the RS232 debugger is such a problem, why not write a Z80 program to write a 1 megabyte file of the GPU ram into a .bin file and upload that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 12, 2022, 10:14:14 am
Uh, sorry for the lack of consistency, but I've been messing with the palette trying to work out why it's a bit messed up at switch-on.  The end result is that now I'm only seeing the blurring of characters when I do a memory dump and it can be seen on the column and row headers.

1MB debug memory dump attached, along with a picture of the screen so you can see what's in the video memory at the time the dump was taken. ???

Previously, the palette contents were corrupted (I'm still searching for the cause) with odd values - most of the palette entries had some form of transparency.  The palette is still corrupted now, but appears partially erased to zero with only a few colours alpha set to 0xFF.  I'll have this sorted soon, but for the moment it has affected the test results in that previously ALL the characters on the screen showed this blurring effect, whereas now it's only the column and row headers.

(The memory dump in the screenshot is of the start of palette RAM anyway, showing the existing palette entries in use on the screen).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 12, 2022, 05:12:15 pm
For future reference: All you had to do in the RS232 debugger was hit 's' and choose a file name.

Ok, I got your image.

The bold letters are colors 0x03 and 0x09 while the thin letters are 0x03 and 0x00.

In the palette, you have colors:
0x00 = 0x000000FF    = Black, 100% opaque.
0x03 = 0x602020FF    = Burgundy, 100% opaque.
0x09 = 0x00000000    = 100% transparent. (Also black if forced to 100% opaque through the CMD_win_alpha_adj control.)

Ok, this is a bug with my mixer code.  When you have a transparent pixel, it is using the color value from the previous pixel.

The reason for this is that we have the SDI Layers set to 4, IE 0,1,2,3,0,1,2,3.  But the clock divider is set to 0x4, a sequential divider of 5 meaning you are trying to address 0,1,2,3,4,0,1,2,3,4.  Now this supposed to work, but my SDI mixer relies on blending previous pixels sequentially in a pipe and since I forgot to code for 'blank' layers when you have a divider set larger than the available set SDI_LAYERS parameter, it is using the last known processed pixel as that missing data for the '4' position, meaning the last shown pixel making this smear effect with transparent pixels.

Forcing the top layer 100% opaque masks out the bug, but now you are stuck with 1 layer.

The other fix is to change the video mode @0x011F from 0x74 to 0x73.  You will now have 75Hz 480p, but now my processor will only see layers 0,1,2,3,0,1,2,3 where there is no empty 4 slot for garbage to creep in.

I'll patch my code to properly mute out those empty slots so you may use any divider regardless of the SDI_LAYERS parameter setting.  For now, to get the right picture, just use the 75Hz 480p mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 12, 2022, 05:34:53 pm
Ok, fixed.
Just replace the attached .sv file with the one in your 'BrianHG_DDR3_GFX_source_v16' folder.


Ok, I know this note is meaningless, but, what the hell...

Line 475 went from:
Code: [Select]
    lb_lena[1]  <= win_line_ena[lb_phase[0]] ;to:
Code: [Select]
    lb_lena[1]  <= win_line_ena[lb_phase[0]] && (lb_phase[0]<SDI_LAYERS) ; // Make sure to mute out video line when the lb_phase is outside the available SDI layers

My 'lb_lena' just stands for Line Buffer output Enable, the 'lb_phase' stands for line buffer phase divider position, the 'win_line_ena' goes high when an active window layer pixels are to be drawn, and we know what the SDI_LAYERS is.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 12, 2022, 07:46:44 pm
Yep, that works nicely. :-+

There doesn't seem to be a noticeable difference between alpha values of 0x00 and 0x7F, with the text maintaining (what appears to be) full brightness down to 0x00, but transparency increases noticeably from 0xFF down to 0x80.  Is that as expected?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 12, 2022, 08:13:49 pm
Yep, that works nicely. :-+

There doesn't seem to be a noticeable difference between alpha values of 0x00 and 0x7F, with the text maintaining (what appears to be) full brightness down to 0x00, but transparency increases noticeably from 0xFF down to 0x80.  Is that as expected?
Yes.  You are making layer 0 progressively transparent as you go from 0 to -128.  (Alpha adjust is a SIGNED 8 bit number.)
Try changing color 9 in your palette, but keep it transparent then play with the adjust and then see what happens.

Then, create a custom BGC settings and then see what happens with the alpha adj.

Also, shrink you output window to 640 pixels wide and see the results.

Try loading in the 32bit color 512x512 alpha image into video memory and open it on another window to see what happens.
Swap around the top and bottom layer with that image to see what happens.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 11:51:13 am
Well?
Did my above tutorial help you understand the mechanics of the layers and alpha settings?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 13, 2022, 12:20:40 pm
Yes, thank you.  Haven't had a lot of time and what I have had I've spent working on my graphics driver to get it to a state where I can change screen modes on the go.

Quick question based on a random idea that just popped into my head - if I was to set window[0] to a smaller size than the display dimensions and centre it, say with a 40-pixel border around the left/right/top/bottom and filling it with an opaque non-system-default background colour, would changing the system-default-background colour allow me to have a coloured border?  I guess I could change the colour randomly during data transfers to emulate the old 80's 'stripy coloured border' you used to get when loading from tape, etc...?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 12:25:14 pm
Follow my instructions above and you will see... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 13, 2022, 05:17:16 pm
I seem to be struggling to get a window set up smaller than the display size. |O

Could you possibly give me an example so I know what settings I should be changing and where?

I've tried just changing the width of the window at the moment:

HWREG+0000H - Base address for layer 0 - haven't changed this.
HWREG+0004H - Screen BPP - kept this the same
HWREG+0005H - Alpha - kept the same at 0x7F
HWREG+0006H - Bitmap Width - This is just the byte width of the layer, right? Should be the same as layer width in 8bpp?
HWREG+0008H - Bitmap X offset - Set to zero. Not sure what this does?
HWREG+000AH - Bitmap Y offset - as above.
HWREG+000CH - Window X pos - should offset the window across the screen.
HWREG+000EH - Window Y pos - should offset the window down the screen.
HWREG+0010H - Window width - set to some figure less than screen width.
HWREG+0012H - Window height - as above.
HWREG+0016H - Tile/font base address - unchanged.
HWREG+001FH - Video mode - unchanged.

I'm getting some odd behaviour when I reduce the window width, and I just want to know that I'm setting it up properly before I start combing my code for bugs.  If I set the window width to >0280 but <02D0 (720 px, the full-width value), the left edge of the screen is repeated on the right.  Anything less than 0280 for window width causes screen corruption or no text to be visible at all.  I'm probably misunderstanding a setting somewhere, or getting the Endianness of a value the wrong way around, but I just want to confirm that I'm at least trying to do the right thing. ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 05:45:04 pm
I seem to be struggling to get a window set up smaller than the display size. |O

Could you possibly give me an example so I know what settings I should be changing and where?

I've tried just changing the width of the window at the moment:

HWREG+0000H - Base address for layer 0 - haven't changed this.
HWREG+0004H - Screen BPP - kept this the same
HWREG+0005H - Alpha - kept the same at 0x7F
HWREG+0006H - Bitmap Width - This is just the byte width of the layer, right? Should be the same as layer width in 8bpp?
HWREG+0008H - Bitmap X offset - Set to zero. Not sure what this does?
HWREG+000AH - Bitmap Y offset - as above.
HWREG+000CH - Window X pos - should offset the window across the screen.
HWREG+000EH - Window Y pos - should offset the window down the screen.
HWREG+0010H - Window width - set to some figure less than screen width.
HWREG+0012H - Window height - as above.
HWREG+0016H - Tile/font base address - unchanged.
HWREG+001FH - Video mode - unchanged.

I'm getting some odd behaviour when I reduce the window width, and I just want to know that I'm setting it up properly before I start combing my code for bugs.  If I set the window width to >0280 but <02D0 (720 px, the full-width value), the left edge of the screen is repeated on the right.  Anything less than 0280 for window width causes screen corruption or no text to be visible at all.  I'm probably misunderstanding a setting somewhere, or getting the Endianness of a value the wrong way around, but I just want to confirm that I'm at least trying to do the right thing. ::)

How in heavens name it is difficult to just shrink these 2:
HWREG+0010H - Window width - set to some figure less than screen width.
HWREG+0012H - Window height - as above.
These need to fit within the screen width / height as well as be less than or equal to the bitmap width/height.  Otherwise you will see extra junk.  THEY ARE NOT ENDING COORDINATES, THEY ARE WIDTH AND HEIGHT.  0,0 means no window. 1,1 means a window 1 pixel wide by 1 pixel tall.  40,40 means a window 40 pixels wide by 40 pixels tall, regardless of the window's beginning screen offset X&Y coordinates.

HWREG+0006H - Bitmap Width - This is just the byte width of the layer, right? Should be the same as layer width in 8bpp?
No, this is the number of pixels wide your bitmap is in memory.  If the bitmap has 720 pixels, then you make this 720.  If the bitmap is 640 pixels wide, then make this 640.  If the bitmap is 22450 pixels wide, then you make this 22450.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 05:52:02 pm
HWREG+0008H - Bitmap X offset - Set to zero. Not sure what this does?
HWREG+000AH - Bitmap Y offset - as above.

If you have a bitmap in ram that is 18000x20000 and you want to show the center, or top left, or bottom right of that bitmap on the screen which is only 720x480, how to you expect to set that display position?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 05:59:01 pm
Like my debugger where I only need to click on a value and hold down the +/- keys on the numpad to scroll the 16 bit contents, you need to make yourself a window playing utility on your Z80 to you may play with the values in a controllable smooth animated fashion so you may see of the window system reacts and operates.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 06:07:52 pm
The only byte controls are the HWREG+0000H - Base address for layer 0 and tile base address.
Every single other control deals with quantity of pixels.
It no longer matters what you have chosen for pixel bpp depth.  My new window system internally works out where to look in ram to retrieve / address the correct memory to draw the image.  You just place in the coordinates / width and height sizes.

Even when using tile mode, the bitmap offset will figure out partial scrolling inside each tile to begin the display when you set the bitmap offset.  Your Z80 no longer needs to do any math.  It just needs to concern itself with a 16bit X&Y coordinate.

This is no longer a piece of code designed to squish into a small portion of a 6k logic gate FPGA.  It is now designed to eat up ~8k logic gates just to operate the windows all on it's own besides the additional requirements for layer mixing and huge tile-ram, then everything else for geometry and DDR3 processing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 13, 2022, 07:23:04 pm
Thank you - I just needed to know I was on the right track, and indeed I was - it was an Endianness issue.  Have a nice 20-pixel border all around the screen now. :-+

If I'm not too busy tomorrow, I'll get a 'BORDER' command created so I can change the border colour easily in the DMI and try out some colourful borders when I paste data in via the serial console. :-/O

Increasing transparency on layer 0 produces a nice 'fade to red' (or whatever the global background colour is set to) effect.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1378678)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 13, 2022, 11:09:02 pm
Hun?  Didn't I ensure it was set to 'Little Endian'?

You can also try using 720p or 1080p with a H&V 'zoom/scale' setting for the window if you want sharper text.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 07:31:05 am
Hun?  Didn't I ensure it was set to 'Little Endian'?

That could be another issue then.  As you can see from the screenshot showing the HW_REGS with the red border in my previous post, all the 16-bit registers (and the 32-bit one) are Big Endian. ???

You can also try using 720p or 1080p with a H&V 'zoom/scale' setting for the window if you want sharper text.

I'm working my way up to 720p and 1080p modes next.  Just making my graphics driver 'multi-mode', then I'll give this a try! :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 07:57:40 am
Hun?  Didn't I ensure it was set to 'Little Endian'?

That could be another issue then.  As you can see from the screenshot showing the HW_REGS with the red border in my previous post, all the 16-bit registers (and the 32-bit one) are Big Endian. ???

That would be a bug in the HW_REGS module, 32bit output assignment.
But, are you sure?
All the 16bit window regs have the MSB to the left (even addr ending in 0) and the LSB to the right (+1 addr).
This is the same with that window address reg, the MSB is on the left (even 0 addr)  and the LSB is on the right (+3 addr)...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 11:19:59 am
Hun?  Didn't I ensure it was set to 'Little Endian'?

That could be another issue then.  As you can see from the screenshot showing the HW_REGS with the red border in my previous post, all the 16-bit registers (and the 32-bit one) are Big Endian. ???

That would be a bug in the HW_REGS module, 32bit output assignment.
But, are you sure?
All the 16bit window regs have the MSB to the left (even addr ending in 0) and the LSB to the right (+1 addr).
This is the same with that window address reg, the MSB is on the left (even 0 addr)  and the LSB is on the right (+3 addr)...

Yes, they're all Big Endian.  Up until your recent post reminding me of the endianness option, I'd just worked around the issue.

Code: [Select]
                ADDR  ADDR+1
Big Endian    = MSB,  LSB
Little Endian = LSB,  MSB

Code: [Select]
line 26 parameter string     ENDIAN                  = "Little",            // Endian for 8bit addressing access.
As you can see, ENDIAN is set to "Little" in the GPU_DECA_DDR3_top.sv file.  I can't test the "Big" setting just now, but I'm wondering if you've got them the wrong way around, maybe?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 12:32:22 pm
It sounds like all the endianess is all backwards.
Try swapping to 'Big' in the 'xxx_top' file.

If this fixes the problem, there are 2 places in the code to fix.  1 in the HW_REGS source and 1 in my line buffer.

Also, now my RS232 debugger's '+/-' key to inc/dec 16bit values will be f'ed up.

In HW_REGS.sv, lines 46 to 51, all the "B"s should change into "L"s.

and in 'BrianHG_GFX_Video_Line_Buffer.sv.', line 631,,,  Wait, I think I got that one right.  You will find out when writing 16bit text in tile mode.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 04:45:50 pm
Just in case... Update the attached file.
The endianess is now correct.

Now I need to fix my RS232 debugger....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 05:58:06 pm
I'll get that tested shortly - will need to remove some register-swapping code in my graphics driver too now; that'll be like pulling at a loose thread, but it'll make the code more streamlined. :-+

Compile time is just under 4 minutes now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 06:09:49 pm
Now I'm confused.  Did you just change the ENDIAN value to "Big" in that file to test whether that is the issue?  The HWREGS in memory are now in Little Endian format.

I've reversed the byte order on lines 46-51 in HW_Regs.sv, so the ENDIAN setting now matches the byte order of the HW_REGS values.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 06:14:49 pm
Now I'm confused.  Did you just change the ENDIAN value to "Big" in that file to test whether that is the issue?  The HWREGS in memory are now in Little Endian format.

I've reversed the byte order on lines 46-51 in HW_Regs.sv, so the ENDIAN setting now matches the byte order of the HW_REGS values.
Now I'm confused.  Did you just un-do the change I made which fixed the endian issue?
Yes, yes you did.
I reversed the ENDIAN's direction by changing the "B" to an "L" and you flipped the numbers around putting everything back to what it would be if you had the "B" in the 'IF'...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 06:17:37 pm
Now I'm confused.  Did you just un-do the change I made which fixed the endian issue?

 :-DD

Yes, probably.

EDIT: Working fine with ENDIAN set to 'Little'. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 06:20:38 pm
Here is the new RS232 debugger.
You can now swap endians so that editing with the +/- key will show and change the right memory cells in 16 bit.

Also, the endian swap will also affect the Quartus Save .mif file for 16bit and the new save Quartus 32bit .mif file.  This is usefull when generating a palette and tile .mif files which are 32bit .mif.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 06:21:27 pm
Now I'm confused.  Did you just un-do the change I made which fixed the endian issue?

 :-DD

Yes, probably.
Destroy your linked file so no one downloads it by mistake.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 06:36:26 pm
All done, working perfectly now.  Tidying up the GPU driver's init code nicely too without having to swap byte-order for the HWREGS. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 14, 2022, 06:54:07 pm
EDIT: Working fine with ENDIAN set to 'Little'. :-+
Just so you know, that 'ENDIAN' = "Little" parameter is set at the top of your 'GPU_DECA_DDR3_top.sv' on line 26.  Not inside the 'HW_Regs.sv' source file line 14 which is nothing more than a default value if it is not set elsewhere.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 06:58:47 pm
EDIT: Working fine with ENDIAN set to 'Little'. :-+
Just so you know, that 'ENDIAN' = "Little" parameter is set at the top of your 'GPU_DECA_DDR3_top.sv' on line 26.  Not inside the 'HW_Regs.sv' source file line 14 which is nothing more than a default value if it is not set elsewhere.

Yeah, I know that, but it's been a long day. ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 14, 2022, 08:13:17 pm
1080p @ 60Hz with a 680x440 window scaled to 2x size. :-+

I can now swap between 480p, 720p and 1080p with a single command in the DMI.  Have some work to do with getting the driver to recognise window width when it comes to text blitting, but that won't take long.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 16, 2022, 10:06:02 am
Took longer than expected this morning, but here's a flashy border linked to the serial interface:

https://www.youtube.com/watch?v=a2htNSu0rh0 (https://www.youtube.com/watch?v=a2htNSu0rh0)

Just have a couple of bugs in changing screen modes, but hopefully will get them sorted early this week. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 16, 2022, 04:41:20 pm
You are lucky I didn't decide to latch all the window controls once every V-sync.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 16, 2022, 10:12:38 pm
You are lucky I didn't decide to latch all the window controls once every V-sync.

I sure am. ;D

What's next on the list? :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 16, 2022, 10:26:37 pm
Next you are getting 16-32 layers, a set or regs which will allow yo to swap layer priority, IE which layer is on top of any other layer, and a new block diagram documenting/illustrating my VGA system.

You will need to show me mastery of my system.

IE: Did you get the color tile/text mode working yet?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 16, 2022, 10:30:27 pm
Haven't tried tile mode yet - will need to write a (or re-write the) driver in a CP/M test program for this.  This will take a little time and I'm not blessed with big blocks of spare time at the moment like I was last year.  I'm going to get the issues I'm experiencing with mode-changing in the DMI sorted, then I'll make a start on a tile mode demo/test program in CP/M. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 17, 2022, 08:56:58 am
I've been trying to sort his one bug for the last couple of days and I thought I had it yesterday, but it's back again today. :palm:

Under what circumstances would the GPU blit font tiles with the background bits transparent, despite alpha being 0x7F?

I've got the HWREGS alpha adjust set to 0x7F.  In fact, here's a dump of the HWREGS:

Code: [Select]
     ​+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
C100 00 50 00 00 83 7F A8 02 00 00 00 00 14 00 14 00  .P..............
C110 A8 02 B8 01 00 00 00 00 00 00 00 00 00 00 00 74  ...............t
C120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C180 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
C1F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

Text is appearing okay, until I backspace and try to overwrite text where it becomes obvious the text is being blitted with background pixels (entry 0 on the palette below) being treated as if they're transparent, so a mess is created as the characters are overdrawn.

Any text blitted with a different colour background selected, like the column and row headers in the screen dumps, appear with a transparent black background.

If I change the background colour, there is no change with the next line of text I write (the background colour is still being treated as transparent) - until I do a CLS, which uses GEOFF to clear the screen to background colour, when the background obviously becomes the colour I've selected.

The worst thing is, it seems to come and go.  I removed the routine that copies the font data from ROM to the GPU when the DMI starts up and the problem cleared up yesterday - so I thought I'd fixed it, although I didn't understand the issue.  Today, with no further code changes, the problem is back again.

Here's the palette:

Code: [Select]
     +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
D000 00 00 00 FF 80 00 00 FF FF 00 00 FF 00 00 80 FF  ................
D010 FF 9D 00 FF 80 00 80 FF FE 99 99 FF 00 00 FF FF  ................
D020 A1 42 FF FF 00 40 00 FF C0 C0 C0 FF 6C 6C 6C FF  .B...@......lll.
D030 80 80 00 FF 00 80 80 FF E0 B0 FF FF 00 FF 00 FF  ................
D040 7A 87 FE FF 9F 62 00 FF 67 40 00 FF 00 5B 67 FF  z....b..g@...[g.
D050 FF FF 00 FF FF FF FF FF 52 9E 6B BF C2 DC D5 3F  ........R.k....?
D060 08 DB 56 C0 46 5E 98 F5 44 64 FA D1 A3 50 7E 59  ..V.F^..Dd...P~Y
D070 52 4B EC B4 FF DC FD 6E A5 7C 1D 3A BE 7C 30 59  RK.....n.|.:.|0Y
D080 97 DF 9E F3 3C 5F 2E 97 5F 19 95 7E AE EE 63 2B  ....<_.._..~..c+
D090 7F 11 7F C9 CD 59 F5 F1 4D 32 95 3D 18 FF 9F 3D  .....Y..M2.=...=
D0A0 49 27 B1 B6 6B 53 C5 53 DE DB FC 7B EC FC 70 57  I'..kS.S...{..pW
D0B0 E4 B7 88 06 7E EF CC FE 96 3E 6E C9 24 5B 05 03  ....~....>n.$[..
D0C0 FA 6B C7 5D 76 DF E5 17 84 5F 67 77 7C 01 A0 2A  .k.]v...._gw|..*
D0D0 FE 72 D4 2E 3B 49 75 AE 23 F8 33 34 5A 69 64 57  .r..;Iu.#.34ZidW
D0E0 D1 DB FE 92 6B CD C4 C1 9F 0B 5E 46 EE F5 CB A6  ....k.....^F....
D0F0 CD BA 39 2A DD 79 9F 14 2E FD 06 7F CD E5 4D DB  ..9*.y........M.

Is there anything else other than blitter mode (which blits text in mode 3 - i.e. activated with PM enabled) or the alpha adjust value that could cause this?  Neither the blitter mode, text blitting code or alpha adjust have been touched since this problem started, went away again and started again this morning... |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 17, 2022, 09:26:48 am
     Blitting does not look at the palette.  That blitter's 'transparent' color only has to do with the blitter settings in the geometry settings.  In fact, the blitter can only choose to paint or omit the painting of a pixel based on the source pixel data and the chosen 'xor' reference stencil out color.  Have your tried turning off the blitter's transparency stencil so it plots every pixel when painting the background color?  You should be looking at the screen picture buffer data, not the palette.

     The alpha and transparency in the palette entries only affects how the onscreen picture color data is presented between the current window layer all the previous layers below it.  It has nothing to do with drawing pixels on the screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 19, 2022, 01:01:09 am
Well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 19, 2022, 08:34:41 am
Funnily enough I've just sat down to spend some time on this issue - I haven't had a chance to look into it up til now. ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 19, 2022, 09:08:09 am
Fixed it. :-/O  It was a 'minor' tweak to the DMI setup code I'd made at some point last week, causing the text transparency flag to not be reset at bootup, so it had a random value which caused the inconsistent nature of the bug.  :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2022, 07:07:33 am
 :phew: Ok, here we go, 16 layers...

GPU_DECA_DDR3_version_16_Jan_20_2021.zip = 16 layers.

Parameters...
PDI_LAYERS     = 4
SDI_LAYERS     = 4

This means that the layers 0 through 15 =
PDI layer 0 -> SDI 0,1,2,3 = Layer 0,1,2,3
PDI layer 1 -> SDI 0,1,2,3 = Layer 4,5,6,7
PDI layer 2 -> SDI 0,1,2,3 = Layer 8,9,10,11
PDI layer 3 -> SDI 0,1,2,3 = Layer 12,13,14,15.

Note that to save on blockram resources, the TILE/FONT mode & memory is only available for PDI_LAYER 0.  This means the tile/font mode is only functional on layers 0,1,2&3.  The available ram for the font is set to 65536 bytes.  This means a 256 character 16x16 pixel font with 8bpp, IE 256 colors per pixel font is possible.

Remember, the 'CLK_DIVIDER' must be at least =3 to have all SDI layers 0,1,2,&3 functional.

IE, if the 'CLK_DIVIDER' = 1, (needed for 720p@60hz, or 1080p@30hz) then only SDI layers 0&1 will function meaning only layers 0,1,4,5,8,9,12,&13 are functional.  That's 8 functional window layers.

IE, if the 'CLK_DIVIDER' = 0, (needed for 1080p@60hz) then only SDI layer 0 will function meaning only layers 0,4,8,12 are functional.  That's 4 functional window layers.

Do not forget to disable any unused layers as they will still eat DDR3 bandwidth, especially in 1080p@60hz as that mode eats a ton of DDR3 bandwidth.  Even if the SDI layer arent functional, my controller will still try to do the DDR3 reading for those unseen SDI layers, but at full speed wasting bandwidth and potentially corrupting the display's line buffer.

The new layer swapping controls are at address 0x00F0 through 0x00FF.  These controls allows you to quick swap which layers sit on top of each other allowing you to move which window appears in front of one another.  This means you can also move a tile enabled layer in the 0,1,2,&3 to a different position in the window stack.  Documentation is coming.

Note that by default, layer 15 is the bottom window layer, layer 0 is the top window layer.  Only the BGC color setting is below layer 15 and it cannot be swapped anywhere above like all other windows 0 through 15.

You may take a look at the Debugger_test_bin_files.zip file and load the 14 layer bobafet example,and play with the swap controls in the RS232 debugger to see how you can swap which window sits in front of another.

Things left to do:
1. Fix a bug in my DDR3 controller to allow bug free support for 'Quarter Rate' mode to allow 400MHz DDR3 support fixing the current red timing report.
2. Have Nockieboy do something interesting with all 16 layers.
3. Add a hardware pixel collision detector between window layers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 20, 2022, 07:50:27 am
Ooops, found a bug in the 'BrianHG_GFX_Layer_mixer.sv' when swapping SDI_LAYERS.  It can potentially kill the video.  Please download this patch and update the file in your 'BrianHG_DDR3_GFX_source_v16' folder.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 20, 2022, 09:18:19 am
No major issues that I can detect so far. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 21, 2022, 04:44:57 pm
Ok, show me something good...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 24, 2022, 03:22:22 pm
Okay, nothing interesting to show yet - I haven't had much time to sit and write a demo for the new tile/layer capabilities, but I'll have something soon(-ish).

In the meantime, I've been trying to fix a problem with changing modes.  I have three modes - the default (Mode 0) 720x480 which works fine.  Mode 1 is 1280x720 and Mode 2 is 1920x1080.  Switching to either Mode 1 or Mode 2 causes graphical problems on the screen.  The video mode is updating correctly, the HW_REGs are being updated according to the current mode, but what I'm seeing on the screen doesn't correlate.  Here's an image of Mode 1 - it should be a clear screen with a yellow vertical line running down the right edge.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1390508)

Instead, the area of the screen being cleared appears to be only 720x480.  The DMI uses GEOFF to clear the screen and the screen width and height are recalculated during mode changes.  I've dumped the HW_REGs values in the screenshot so you can see how the screen is being set up.  If I try to draw lines, circles, triangles etc with GEOFF, they aren't drawn outside of the 720x480 limits.  Before I pull too many hairs out, this isn't an issue with GEOFF is it?

Oh, before you point out the obvious, the line is drawn at the limits of what is visible - I've tried drawing from 1279,0 to 1279,720 and nothing shows up.  It looks like GEOFF really doesn't want to go outside 720x480.

The very bottom of the 'screen' also seems to be offset to the right slightly and at the top of the real screen, as you can see with the yellow line fragment.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 24, 2022, 05:49:26 pm
What is the @SET_MAX_XY limiter set to in the GEOFF?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 24, 2022, 06:59:22 pm
What is the @SET_MAX_XY limiter set to in the GEOFF?

Ah yes, thanks - that was it.  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 24, 2022, 10:15:35 pm
What is the @SET_MAX_XY limiter set to in the GEOFF?

Ah yes, thanks - that was it.  :-+
Remember, if you are using the GPU ram for CPU code or even GPU instructions as well, without any type of limiter for the geometry unit, carelessly drawing a line or rectangle somewhere will erase your code.  In under a second, you can erase you entire entire Z80 4mb.  (More like 3 seconds to erase all 512mb if you ever get around to re-doing the pixel-writer and optimize it for 128bit access.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 24, 2022, 10:19:15 pm
Remember, if you are using the GPU ram for CPU code or even GPU instructions as well, without any type of limiter for the geometry unit, carelessly drawing a line or rectangle somewhere will erase your code.  In under a second, you can erase you entire entire Z80 4mb.  (More like 3 seconds to erase all 512mb if you ever get around to re-doing the pixel-writer and optimize it for 128bit access.)

Yes of course - with a little tweaking and careful design, I could have the entire Z80's memory space in the GPU.  Does the pixel-writer need re-writing then to be more DDR3-optimised?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 24, 2022, 10:43:14 pm
Remember, if you are using the GPU ram for CPU code or even GPU instructions as well, without any type of limiter for the geometry unit, carelessly drawing a line or rectangle somewhere will erase your code.  In under a second, you can erase you entire entire Z80 4mb.  (More like 3 seconds to erase all 512mb if you ever get around to re-doing the pixel-writer and optimize it for 128bit access.)

Yes of course - with a little tweaking and careful design, I could have the entire Z80's memory space in the GPU.  Does the pixel-writer need re-writing then to be more DDR3-optimised?
It's more like the pixel writer need to be changed into a generic blitter copy function, with a few mask and mix functions.  It needs to be designed smart so that it can perform multiple tasks during this copy.

I'm thinking the controls will look like this:
------------------------------------------------------------------
copy length (set the number of cycles the copy should run)

copy source data A bits width   (8,16,32,64,128)
copy beginning source address A
copy source address A inc/dec step size per copy cycle.

copy source data B bits width   (8,16,32,64,128)
copy beginning source address B
copy source address B inc/dec step size per copy cycle.

copy A-B function, only use source A or B/add AB/subtract AB/mult AB/divide AB/float or int/ XOR/and/or/ mask in and mask out levels.

copy destination Y data bits width   (8,16,32,64,128)
copy beginning destination Y address
copy destination address inc/dec step size size per copy cycle.
--------------------------------------------------------

With the above, you should have enough to do graphics, blending, sound stereo/mono stream processing as well as volume control and channel mixing at different depths as well as resampling/pitch bending including generic math-co processing, FFT, multidimensional transformations, vector array scaling and a bunch of other things the Z80 has no business of attempting at such a scale.


You would then need to modify the geometry unit's pixel address generator to prepare the list of commands to feed this new generic memory processor to write the pixels, but now you can also drive this section directly by the Z80 to perform other functions.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 24, 2022, 10:52:36 pm
The next step after the above new memory co-processing engine, we will need to make a sequencer, IE something akin to a simple MCU with only something like 20 assembly instructions which reads commands from DDR3 and feeds controls to the memory co-processor engine as well as the geometry unit's command inputs separate of the Z80's control.  Software for this little MCU will run everything including the SD card, audio, com ports.  Basically it will be a super-stupid PIC32 like micro-controller running code off of the DDR3 giving you your complex interface picture/sound/IO function without needing the Z80 to do anything.

(LOL, running at 100MHz, it may be fast enough to emulate a Z80 as well...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 24, 2022, 11:25:37 pm
The next step after the above new memory co-processing engine, we will need to make a sequencer, IE something akin to a simple MCU with only something like 20 assembly instructions which reads commands from DDR3 and feeds controls to the memory co-processor engine as well as the geometry unit's command inputs separate of the Z80's control.  Software for this little MCU will run everything including the SD card, audio, com ports.  Basically it will be a super-stupid PIC32 like micro-controller running code off of the DDR3 giving you your complex interface picture/sound/IO function without needing the Z80 to do anything.

(LOL, running at 100MHz, it may be fast enough to emulate a Z80 as well...)

Holy moly.  :popcorn:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1390940)

Sound, SD card, com ports? And here I am thinking that the graphics part of this project was 150% of what I thought it could achieve...  :clap:

I've been thinking about messing with a softcore processor for some time.  Building one would be mind-blowing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2022, 11:21:56 am
What is the @SET_MAX_XY limiter set to in the GEOFF?

Ah yes, thanks - that was it.  :-+

I spoke too soon.  Now I've been able to test a little further, I've found that setting the MAX_XY limiter has sorted out the X-axis limitations in Modes 1 & 2, but the blitter's Y-axis is still not taking up the full height of the screen:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1391606)

As you can see above, switching to Mode 1 sets the screen to 1280x720 and GEOFF is used to clear the screen, which now accounts for the full 1280 pixels across, but not the the full height.  From looking at the GPU's video RAM using the RS232 debugger, it appears that GEOFF stops clearing the screen when it reaches 0x85000, an oddly round number.  This equates to about 1008 pixels across by 421 pixels down the screen.

Drawing a circle at the bottom edge shows something going on, but I'm not sure how to interpret what I'm seeing.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1391612)

This is highly likely to be an issue with my code rather than the HDL, but I've checked and double-checked the code setting MAX_XY when the blitter is set up.  Could there be anything else causing this?

Also, unrelated question, but what is the best way to turn off the scalers?  You've mentioned setting up- and down-scaling to 4,096 and setting the scalers with command 0903, but it's also possible to just send command 0900 to turn the scalers off... Are these equivalent or are there catches to the second method? :-//

EDIT:  And yes Star Wars fans, I realise that the second screenshot just needs the addition of Luke Skywalker gazing off into the distant binary sunset. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2022, 11:41:56 am
Another thought - is there any uniqueness with the byte- or bit-order that data is passed to the MAX_XY limiter?

Here's Mode 2 (1920x1080p) with a single circle drawn at 1500,200 with diameter 400,400:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1391618)

Again, 0x85000 is the hard-limit for GEOFF to clear the RAM, with random data from that point onwards.  MAX_XY is set to the window dimensions - so MAX_X will be 1880, MAX_Y will be 1040 as there's a 20-pixel border around layer 0 in all modes.

Is there a setting I'm missing somewhere that is stopping GEOFF writing to RAM beyond 0x85000?  What's going wrong with the circle being draw on opposite edges of the screen?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 25, 2022, 12:00:22 pm
What is the @SET_MAX_XY limiter set to in the GEOFF?

Ah yes, thanks - that was it.  :-+

I spoke too soon.  Now I've been able to test a little further, I've found that setting the MAX_XY limiter has sorted out the X-axis limitations in Modes 1 & 2, but the blitter's Y-axis is still not taking up the full height of the screen:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1391606)

As you can see above, switching to Mode 1 sets the screen to 1280x720 and GEOFF is used to clear the screen, which now accounts for the full 1280 pixels across, but not the the full height.  From looking at the GPU's video RAM using the RS232 debugger, it appears that GEOFF stops clearing the screen when it reaches 0x85000, an oddly round number.  This equates to about 1008 pixels across by 421 pixels down the screen.

Drawing a circle at the bottom edge shows something going on, but I'm not sure how to interpret what I'm seeing.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1391612)

This is highly likely to be an issue with my code rather than the HDL, but I've checked and double-checked the code setting MAX_XY when the blitter is set up.  Could there be anything else causing this?

Also, unrelated question, but what is the best way to turn off the scalers?  You've mentioned setting up- and down-scaling to 4,096 and setting the scalers with command 0903, but it's also possible to just send command 0900 to turn the scalers off... Are these equivalent or are there catches to the second method? :-//

EDIT:  And yes Star Wars fans, I realise that the second screenshot just needs the addition of Luke Skywalker gazing off into the distant binary sunset. ;)

Ok, 1280x720x8bpp = 921600 bytes.  Your current pixel_address_generator.sv and 'geo_pixel_writer.sv' have only 20 address bits meaning that they can only address 2^20=1048576 bytes.  So, if your screen base address begins at 126976 bytes, you can just make it to drawing 1 full screen.  If your screen base address is higher than 126976, then anything you draw would wrap around to the bottom address 0 and up.

Looks like these need patching.  Might as well push them up to 32bit while we are at it.

The 'geometry_xy_plotter.sv' has 12bit X&Y coordinate outputs.  Since we are using signed coordinates, this means you should max out at 2048x2048.

Try a 4bpp, 16 color video mode to see if you can use the full screen.  This should give you the full height with nothing else changed.  I know my window system has no problem with huge resolutions as it can handle the 4096x4096x32bpp mode used in my ellipse generator demo.

I'll look at your old geo address & pixel writer code tonight.

As for the scaler @900 & 903, remind me what you are talking about?
I assume it's this:
Code: [Select]
[at]BLIT SCALE <usX> <usY> <dsX> <dsY>     > Sets blitter scale, us=upsample   float X/Y zooms up the SRCE image copy input   1.000000 to 4095.00000. (12 bit granularity)
                                                                 ds=downsample float X/Y shrinks  the DEST image paste output 1.000000 to 0.000245.   (12 bit granularity)
You need to set all 4 to 1.0000000 to have no scaling of the blitter image.
At reset power-up, all 4 settings are already at 1.000000.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2022, 12:48:31 pm
Ok, 1280x720x8bpp = 921600 bytes.  Your current pixel_address_generator.sv and 'geo_pixel_writer.sv' have only 20 address bits meaning that they can only address 2^20=1048576 bytes.  So, if your screen base address begins at 126976 bytes, you can just make it to drawing 1 full screen.  If your screen base address is higher than 126976, then anything you draw would wrap around to the bottom address 0 and up.

Looks like these need patching.  Might as well push them up to 32bit while we are at it.

The 'geometry_xy_plotter.sv' has 12bit X&Y coordinate outputs.  Since we are using signed coordinates, this means you should max out at 2048x2048.

Try a 4bpp, 16 color video mode to see if you can use the full screen.  This should give you the full height with nothing else changed.  I know my window system has no problem with huge resolutions as it can handle the 4096x4096x32bpp mode used in my ellipse generator demo.

I'll look at your old geo address & pixel writer code tonight.

As for the scaler @900 & 903, remind me what you are talking about?
I assume it's this:
Code: [Select]
[at]BLIT SCALE <usX> <usY> <dsX> <dsY>     > Sets blitter scale, us=upsample   float X/Y zooms up the SRCE image copy input   1.000000 to 4095.00000. (12 bit granularity)
                                                                 ds=downsample float X/Y shrinks  the DEST image paste output 1.000000 to 0.000245.   (12 bit granularity)
You need to set all 4 to 1.0000000 to have no scaling of the blitter image.
At reset power-up, all 4 settings are already at 1.000000.

Well, removing the start memory offset (0x5000), GEOFF is crapping out at 0x80000, or 512KB - that would equate to a 19-bit address range, so it looks like you're onto something there. :-+

I've just tried adding another mode for 1280x720x4, but it's doing the same thing - doesn't seem to have made much difference, but yet again it could be something I've missed in my rush to test the extra mode:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1391642)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 25, 2022, 10:11:59 pm
As for the scaler @900 & 903, remind me what you are talking about?
I assume it's this:
Code: [Select]
[at]BLIT SCALE <usX> <usY> <dsX> <dsY>     > Sets blitter scale, us=upsample   float X/Y zooms up the SRCE image copy input   1.000000 to 4095.00000. (12 bit granularity)
                                                                 ds=downsample float X/Y shrinks  the DEST image paste output 1.000000 to 0.000245.   (12 bit granularity)
You need to set all 4 to 1.0000000 to have no scaling of the blitter image.
At reset power-up, all 4 settings are already at 1.000000.

Yes, that's it.  I assume then that the reason just using 900 is working is because the 4 settings start out at 1.0 and don't get changed.  I'll stick with the first method then (setting all to 4,096 and command 903). :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 05:03:37 am
Ok, here we go.

I had to change 2 things:

1) The specified geometry 24 bit base address is now multiplied by 256 bytes.  IE, left shifted by 8 when pointing to the base address of a DDR3 memory address.  This is both for the source and destination bitmaps.  So, placing a 1 in the 24bit address means a location of 256 in the DDR3 memory and 256 in my window generator's base address.  This means you can now address 4gb, or all of the 512mb on the DECA's DDR3 ram chip except each bitmap must begin on a 256 byte boundary.

2) I changed one of the old 2 word command FIFOs to a new one used in my DDR3 controller as it performed better.  However, I could not do a full test as I do not have a Z80 system.  I hope the geometry unit still functions.

Let me know if this works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 10:24:33 am
Ok, here we go.

I had to change 2 things:

1) The specified geometry 24 bit base address is now multiplied by 256 bytes.  IE, left shifted by 8 when pointing to the base address of a DDR3 memory address.  This is both for the source and destination bitmaps.  So, placing a 1 in the 24bit address means a location of 256 in the DDR3 memory and 256 in my window generator's base address.  This means you can now address 4gb, or all of the 512mb on the DECA's DDR3 ram chip except each bitmap must begin on a 256 byte boundary.

2) I changed one of the old 2 word command FIFOs to a new one used in my DDR3 controller as it performed better.  However, I could not do a full test as I do not have a Z80 system.  I hope the geometry unit still functions.

Let me know if this works.

Something's up with GEOFF.  CLS isn't working properly - it's just creating vertical lines every even pixel, by the look of it.  The image below shows the DMI's usual welcome screen, which has been cleared with a GEOFF CLS and a memory dump has been performed of the HW_REGs, then I've used GEOFF to draw a filled yellow circle.  There's garbage across the top that doesn't seem to be affected by GEOFF and the blitter isn't placing text right at the top of the window and you can see the remnants of the welcome text from before the CLS, which hasn't been cleared by GEOFF properly.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1392425)

As you can see, the blitter is set up correctly with the start address >>8 and it's blitting text just fine. I've bit-shifted the screen memory start address >>8, but there's garbage at the top of the window.

Am I missing some obvious setting that I need to >>8 with the issue at the top of the screen, or is that related to the GEOFF issue?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 10:43:00 am
Ok, it looks like I had to clear the LSB of the address going out of the pixel address generator.  Try this update.

If this doesn't fix it, then I'll try going back to the old 2 word FIFO.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 11:08:58 am
Why did you shift the address in my VGA window system?
You are supposed to shift the intended address you are sending to the GEOFF.
I think you are addressing really impossibly high memory address this way.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 11:13:22 am
Why did you shift the address in my VGA window system?
You are supposed to shift the intended address you are sending to the GEOFF.
I think you are addressing really impossibly high memory address this way.

I'm a little confused.  I thought I had to shift ALL addresses?  I should only be shifting the ones going to the blitter and GEOFF?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 11:15:36 am
And yes, that update worked - I still have that crap at the top of the screen, but this is likely an addressing issue I guess. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 11:19:25 am
It's the geoff which has the 24bit limit, but we need 32 bit addressing.

Does my VGA system not already have 32bits for the screen address?

This is the reason I multiplied the geoff base address by 256.  So you may access all the DDR3 ram.

My VGA system already has 32bit addressing.  So I did not need to multiply the value by anything.

Also, the display address you choose needs to be divided by 256 before being sent to the geoff since the geoff only has a 24bit register.  So, any base address which will not evenly divide into 256 will be messed up.  Unless you want to give me a new assignments to allow 32bits in that geoff and how you will be setting them as it is currently hard wired for 24bit.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 11:26:30 am
Okay, modes are working properly now and I can draw to the very bottom-right edge of the screen, whatever the mode, so GEOFF is able to access the extra memory required. :-+

I just have a bug to sort with text scrolling now - obviously missed setting an address that needs to be >>8 somewhere. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 11:44:18 am
Obviously I'm setting addresses for the blitter when scrolling the screen up one tile height that require more accuracy than an 8-bit limit will allow.  I'll need to go down to at least 4-bits to get scrolling to work, even less than that for smaller tile work on a game screen, for example.  Is this an issue or is the blitter working to a 24/32-bit address resolution?

EDIT:
Actually that can't be the issue, as text is getting blitted to the screen fine with 8/16-pixel increments, so setting the blitter to copy the bottom section of the screen (minus one font row) up 16 pixels shouldn't be affected by the recent changes to address mechanism?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 11:52:42 am
What are you talking about?
The scrolling should be the same source base address as the display output base base address of the screen display.
It's just the selection of starting X&Y coordinates which are different for the blit & the paste coordinates which are different.

If you were using a screen base pointer to scroll the screen, then once again, you have went about doing something so completely backwards, I just do not know what to say.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 12:04:13 pm
The blitter doesn't take pixel locations, it only takes memory addresses? ???

I've got a command for Blitter Copy Source Pointer and Blitter Copy Destination Pointer amongst others - neither take pixel locations, they're both memory pointers?  In fact, I only have memory pointers as a way of referencing the screen with the GPU at all???

EDIT:  Just to clarify, the draw commands use pixel locations - but I'm not aware of any blitter commands that do.

EDIT2: Oh hang on...  I've just been reviewing the GPU manual.  I guess I could set the blitter's copy width & (height - tile height) using 74, turn the blitter on then draw a single pixel at 0,0 to copy the screen and paste it there...  |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 12:16:15 pm
The blitter doesn't take pixel locations, it only takes memory addresses? ???

I've got a command for Blitter Copy Source Pointer and Blitter Copy Destination Pointer amongst others - neither take pixel locations, they're both memory pointers?  In fact, I only have memory pointers as a way of referencing the screen with the GPU at all???
The blitter is the source address and since you are blitting from the display screen to the display screen, the 2 addresses should match.

Remember, you have the:
Code: [Select]
SET_PAGET <src/dest> <base_address_hex> <width> <depth>    > Sets PAGET's (pixel address generator) source/dest   memory address, image width, color depth in bits/pixel = (1/2/4/8/16).

For the source and destination address, display width and depth.

Say for example, address 200, width 720, 8 bits for both source and destination.

Now, set:
Code: [Select]
BLIT POS   <px> <py> <width> <height>  > Sets the source image top left pixel position (px,py) and the copy (width,height) in pixels.
Use 0,16,720,480 so you end up selecting a blit beginning 16 lines down all the way to 496, but 0-720 across.
You can also use 0,16,720,464 if you will be black-box fill drawing in the bottom line to clear the bottom line unless your screen is truly 720-496 where the extra 16 lines have already been cleared to a black.

Next:
Code: [Select]
DRAW PIXEL <X>   <Y>   <c>                                          > Draws a dot at coordinates [XY], c=color(0..255)
Use 0,0,0.

This will take the screen beginning 16 lines down and paste it beginning at 0,0, in otherwords, moving the screen 16 lines up.

Don't forget:
Code: [Select]
BLIT CONFIG  <ena>  <mask> <h-centp> <mirror> <v-centp> <flip> <r90>  <r45>To turn off the mask, turn off the h-centerp, turn off the v-centerp, and turn off everything except the <ena>.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 12:23:44 pm
Without my above instructions, how have you been blitting the text up until now?
It must be a killer to work out the beginning base address for each letter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 26, 2022, 02:28:49 pm
Without my above instructions, how have you been blitting the text up until now?
It must be a killer to work out the beginning base address for each letter.

Here's how I've been doing the scroll:

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 26, 2022, 05:01:31 pm
Well, I hope you now understand that this was a round about way to do it.
Otherwise, how did you expect to do horizontal scrolling?
Even the original base address did not allow for 'ODD' address values meaning you could not set a horizontal pixel offset of 1 or 3 pixels in 8 bit mode, let alone 1 or 2 or 3... pixels in 4 bpp or 2bpp or 1 bpp  video modes.

I mean, if you wanted to scroll the screen to the left by 1 pixel on a 1bpp screen mode.  How would you do that if the base address for the first 8-16 pixels are all identical?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 28, 2022, 02:56:55 am
Quote
Hi,

I still can't get scrolling to work again since the recent changes.  I am obviously missing something very obvious, but I gave up in frustration yesterday and thought a clear head would help this morning, but it hasn't. |O

Scrolling is currently overwriting the HW_REGs, no matter what address format I use to set the destination and source pointers (i.e. normal or >>8, I've tried both).  What am I doing wrong?

Here's a breakdown of the current scroll routine (values for 720x480x8 mode):

* Check FIFO isn't full before proceeding
* Clear X[0-3] and Y[0-3] registers
* Turn off blitter features with command 0001
* Set Y[3] to 0
* Set X[3] to 0x50
* Command 7B00 sets source address to Y[3]X[3] (0x000050), or address of start of screen space >>8 (it should be 0x5000 normally)
* Command 7C00 sets destination address to the same as above using Y[3]X[3] without setting/changing their values
* Y[3] set to 0
* X[3] set to 680 - width of Window[0] (this is screen width 720 minus 40 pixels for the borders)
* Command 7207 sets destination raster width to X[3], with low byte set to bpp for the screen mode
* Set Y[3] to tile height (height of font - 16 pixels)
* Set X[3] to 0
* Command 7700 sets source image offset to 0,16 (to skip top row of window)
* Set Y[3] to window height minus tile height (this will be 440-16) - MINUS 1 for 0-based register(?)
* Set X[3] to window width 680 - MINUS 1 for 0-based register(?)
* Command 7500 sets blitter copy width & height to above values to copy the window, minus one text row
* Command 0100 blits source to destination (the offset portion of the screen to the top at 0,0)
* Clear the bottom row (this isn't the issue at the moment so I won't detail this section)

What am I doing wrong?  Is this still overcomplicated?  :-//

Ok, I simulated a screen text CR/LF in the 'GPU_GEOMETRY_Testbench' and the saved test bitmaps seem to look fine.

I've attached the latest testbench as it now has the new 4GB addressable space source code.  However, I set modelsim to cap the screen memory to 16 megabytes, otherwise it will crash badly.

Enter modelsim and change to the testbench directory.
In the transcript, type:
Code: [Select]
do setup.do
do test_blitter.do
Wait 10 seconds for the sim to complete.

Read the 'GEO_tb_Blitter.txt' to see the commands I sent.
(CR/LF begins at line 145 which sets the blitter to match the destination output screen specs.)
(Lines 146,147,148 are optional if they have already been set accordingly.)
(Lines 150,151 perform the CR/LF.)
Read the 'GEO_tb_command_results.txt' to see what was actually being sent to the GEOFF.

Look at:
GEO_print_before_crlf_blit.bmp
GEO_print_after_crlf_blit.bmp
GEO_print_after_clear_boxfill.bmp

To see what's happening to the display after the commands are being sent.

If you like, you can change all the coordinates and screen sizes in the 'GEO_tb_Blitter.txt' to match your screen and pixel sizes as well as screen address and see what happens after typing 'do test_blitter.do' once again in the transcript.  Note that higher resolutions means a longer simulation time for the CR/LF as the sim needs to simulate all the hardware to copy all those pixels in simulated memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 28, 2022, 05:08:43 am
Here is a GEOFF patch for the GPU.  All the files in the .zip belong in the GPU's 'SV' folder.  The patch just makes the new 4gb DDR3 addressing change match the source files in the above Modelsim simulation.  There should be no change in functionality.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 28, 2022, 12:52:54 pm
 :phew: Ok, here is the new 2 page block diagram 'BrianHG_GFX_VGA_Window_System.pdf' and 'BrianHG_GFX_VGA_Window_System.txt' documentation for developers.

Details here... (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3972380/#msg3972380)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 28, 2022, 03:08:00 pm
Ok, I simulated a screen text CR/LF in the 'GPU_GEOMETRY_Testbench' and the saved test bitmaps seem to look fine.

I've attached the latest testbench as it now has the new 4GB addressable space source code.  However, I set modelsim to cap the screen memory to 16 megabytes, otherwise it will crash badly.

Enter modelsim and change to the testbench directory.
In the transcript, type:
Code: [Select]
do setup.do
do test_blitter.do
Wait 10 seconds for the sim to complete.

Read the 'GEO_tb_Blitter.txt' to see the commands I sent.
(CR/LF begins at line 145 which sets the blitter to match the destination output screen specs.)
(Lines 146,147,148 are optional if they have already been set accordingly.)
(Lines 150,151 perform the CR/LF.)
Read the 'GEO_tb_command_results.txt' to see what was actually being sent to the GEOFF.

Look at:
GEO_print_before_crlf_blit.bmp
GEO_print_after_crlf_blit.bmp
GEO_print_after_clear_boxfill.bmp

To see what's happening to the display after the commands are being sent.

If you like, you can change all the coordinates and screen sizes in the 'GEO_tb_Blitter.txt' to match your screen and pixel sizes as well as screen address and see what happens after typing 'do test_blitter.do' once again in the transcript.  Note that higher resolutions means a longer simulation time for the CR/LF as the sim needs to simulate all the hardware to copy all those pixels in simulated memory.

Perfect.  Got it working now.  I seem to recall you mentioning something about the order in which certain registers are set for the blitter, though I might be making that up - my memory is terrible thanks to an accident involving a mountain bike, my head and some tree roots years ago.  There didn't seem to be a lot wrong with the commands I was sending other than the order in a couple of cases, but once I'd sorted that and got single-line scrolling working, I needed to look at mass output (typing HELP, for example, produces about 3 screens worth of text in Mode 0) and it does look as though I was flooding the GPU's command FIFO as well; adding an extra FIFO status check has cleared up some random graphical issues with repeated scrolling.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 28, 2022, 07:02:19 pm
Perfect.  Got it working now.
:-+
Quote
  I seem to recall you mentioning something about the order in which certain registers are set for the blitter, though I might be making that up - my memory is terrible thanks to an accident involving a mountain bike, my head and some tree roots years ago.  There didn't seem to be a lot wrong with the commands I was sending other than the order in a couple of cases, but once I'd sorted that and got single-line scrolling working, I needed to look at mass output (typing HELP, for example, produces about 3 screens worth of text in Mode 0)
  ??? Is mode 0 640x480, or 1920x1080?  If the latter, then my god, how big is your documentation?
Quote
and it does look as though I was flooding the GPU's command FIFO as well; adding an extra FIFO status check has cleared up some random graphical issues with repeated scrolling.
Yes, in super-hires, blitting a full screen CR/LF with the current old-fashioned pixel-writer driving the DDR3 command bus, it will take around 1/60th of a second, maybe 1/30th of a second for 1080p.

2 ways around this:

A. Use a tile font text mode and still use the blitter and box fill, but blitt and fill (actually now only a line) to the screen data which will be a 16/32bit word of ascii data for every 8x16 pixels on display.

Approx calculation:
For 32bit character mode = 8:(32/(8*16))= or  1:32, or 32 times faster.
(32 bit blits probably wont work as we never expected to go that far with the 8 bit GPU, but you can cheat this one with 16bit or 8 bit blits setting the screen width to 2x or 4x the character width when driving the GEOFF.)
For 16bit character mode = 8:(16/(8*16))= or  1:64, or 64 times faster. (16 bit blits should work, I hope.)

B. Make the new memory co-processing engine which can move ~750 megabytes a second, and clear/write/set around 1500 megabytes a second.  Probably at least 15x the current speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 28, 2022, 07:58:34 pm
Quote
  I seem to recall you mentioning something about the order in which certain registers are set for the blitter, though I might be making that up - my memory is terrible thanks to an accident involving a mountain bike, my head and some tree roots years ago.  There didn't seem to be a lot wrong with the commands I was sending other than the order in a couple of cases, but once I'd sorted that and got single-line scrolling working, I needed to look at mass output (typing HELP, for example, produces about 3 screens worth of text in Mode 0)
  ??? Is mode 0 640x480, or 1920x1080?  If the latter, then my god, how big is your documentation?

Mode 0 = 720x480, Mode 1 = 1280x720, Mode 2 = 1920x1080.  All modes use a window with a 20-pixel border around its edges, so take 40 pixels off those dimensions for the actual display area.

It is three pages in Mode 0.  Less than 16KB as it fits in a ROM bank. ;)

Quote
and it does look as though I was flooding the GPU's command FIFO as well; adding an extra FIFO status check has cleared up some random graphical issues with repeated scrolling.
Yes, in super-hires, blitting a full screen CR/LF with the current old-fashioned pixel-writer driving the DDR3 command bus, it will take around 1/60th of a second, maybe 1/30th of a second for 1080p.

Scrolling in 1080p is noticeably slower.

2 ways around this:

A. Use a tile font text mode and still use the blitter and box fill, but blitt and fill (actually now only a line) to the screen data which will be a 16/32bit word of ascii data for every 8x16 pixels on display.

Approx calculation:
For 32bit character mode = 8:(32/(8*16))= or  1:32, or 32 times faster.
(32 bit blits probably wont work as we never expected to go that far with the 8 bit GPU, but you can cheat this one with 16bit or 8 bit blits setting the screen width to 2x or 4x the character width when driving the GEOFF.)
For 16bit character mode = 8:(16/(8*16))= or  1:64, or 64 times faster. (16 bit blits should work, I hope.)

B. Make the new memory co-processing engine which can move ~750 megabytes a second, and clear/write/set around 1500 megabytes a second.  Probably at least 15x the current speed.

B is looking like a far more interesting route. :-+  I don't really want to go back down the tile font text mode route again as I can easily do text and graphics on the screen currently, but yes I know that text mode is fast.  I'm going to get around to writing a tile mode demo soon though, as it'll be useful for countless applications in gaming etc.

Still have a remaining bug to squash in mode-switching.  I'm still sounding this one out at the moment, but it appears to happen if the GEOFF draws a shape in a higher-resolution mode, outside the bounds of a lower resolution mode, then I switch to that lower resolution mode.  It shouldn't make any difference to anything, but it causes screen corruption on switching to a lower mode and causes the GPU and or whole system to lock up after a few characters are typed into the console.  Like I said, I'm still exploring this issue at the moment so I can't clearly define the conditions that cause it (though what I've described above it pretty much it), and it's most likely to be an issue with my code, but at the moment I can't see an obvious cause for it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 28, 2022, 08:14:16 pm
B is looking like a far more interesting route. :-+  I don't really want to go back down the tile font text mode route again as I can easily do text and graphics on the screen currently,
??? You cannot place 1 text window above or below a graphics window?

This way when CR/LF scrolling, you may separately decide to scroll or not scroll the graphics image in tandem as well.  Well, I guess you can still do this with 2 graphics layers, but, the picture data cannot be separated with the text data if they are on the same layer.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 28, 2022, 11:08:57 pm
B is looking like a far more interesting route. :-+  I don't really want to go back down the tile font text mode route again as I can easily do text and graphics on the screen currently,
??? You cannot place 1 text window above or below a graphics window?

Well I suppose I could - perhaps I'm a little too fixated on duplicating the display of my old 8-bit computer.  I'm also trying to shake the mindset that I'm short on video memory space.  When the opportunity to shave 10-20 bytes off of some critical code is a big thing, it's hard for me to switch to the mindset that I've got megabytes of DDR3 RAM sitting around doing nothing.

This way when CR/LF scrolling, you may separately decide to scroll or not scroll the graphics image in tandem as well.  Well, I guess you can still do this with 2 graphics layers, but, the picture data cannot be separated with the text data if they are on the same layer.

Indeed, the possibilities are endless; but whilst a text layer and a graphics layer would be trivial for the GPU and DDR3 RAM, the driver for both would take up a significant portion of my system's limited available resources.  My DMI has to fit within a 16KB ROM bank - that includes the GPU driver as well, and I'm down to my last 1KB space for testing and development, and that's with some features turned off to make room for the GPU driver.  I'll probably develop the tile system for CP/M as that gives me a little more room to manoeuvre.

Hopefully not getting too far ahead regarding the co-processor, but I've started reading about CPU design in case it helps me understand what's going on later.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 28, 2022, 11:21:33 pm
Well, with 'OPTION B' memory processor for manipulating pixels and such, each instruction will either be 64bits, or 128bits.  So, we are going to eat through those tiny 16kb banks in a flash just to store a set of instructions / functions you wish to access.

Though, the multi-coordinate drawing functions like a quadrilateral will still exceede 128bit as you will have 8x16bit coordinates, then you still need a 32bit color and which display address it belongs to.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 29, 2022, 03:00:03 am
Ok, I'm now working on a weird overflow bug in my DDR3 controller when you really load it beyond 95% bandwidth.  It will occasionally glitch out on the read channel, then, recover a frame later.

It's another annoying once in a blue moon bug to track down.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2022, 08:04:11 am
Well, with 'OPTION B' memory processor for manipulating pixels and such, each instruction will either be 64bits, or 128bits.  So, we are going to eat through those tiny 16kb banks in a flash just to store a set of instructions / functions you wish to access.

Though, the multi-coordinate drawing functions like a quadrilateral will still exceede 128bit as you will have 8x16bit coordinates, then you still need a 32bit color and which display address it belongs to.

Naïve question; do the instructions have to be so many bits wide?

The 16KB bank issue relates solely to my DMI test/development environment on the uCOM, which I use because it's quick to develop for, get into and update with changes.  If I'm using CP/M, the program can (in theory) be any size, but without bank swapping or magical waving of hands, I have about 46KB to play with.  I could take over the entire system with a game and have the full 64KB to play with. With bank swapping and careful programming, I have megabytes to play with (albeit in 16KB chunks).

Ok, I'm now working on a weird overflow bug in my DDR3 controller when you really load it beyond 95% bandwidth.  It will occasionally glitch out on the read channel, then, recover a frame later.

It's another annoying once in a blue moon bug to track down.

That's all I seem to have been doing recently.  I feel your pain.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on January 29, 2022, 10:53:16 am
Isn't this project too *complex* to be a-single-person hobby?
Really I am lost here, too many things, too many pages for my little free time.

Guys, you have my moral support  :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 29, 2022, 09:29:00 pm
Well, with 'OPTION B' memory processor for manipulating pixels and such, each instruction will either be 64bits, or 128bits.  So, we are going to eat through those tiny 16kb banks in a flash just to store a set of instructions / functions you wish to access.

Though, the multi-coordinate drawing functions like a quadrilateral will still exceede 128bit as you will have 8x16bit coordinates, then you still need a 32bit color and which display address it belongs to.

Naïve question; do the instructions have to be so many bits wide?

Hun?  Count the coordinates.  A quadrilateral has 4 pairs of XY coordinates.  Each XY coordinate has 16bits for the X and 16 bits for the Y coordinate.  That's 32bits * 4 pairs = 128bits.  Each quad is 128bits not counting the 32 bit color, filled or not filled.  Now, we haven't yet decided how this will be stored in DDR3 ram as your current old design relies on the Z80 to copy this data to the GEOFF port and it is still the old-school 12bit X&Y coordinate system which cannot support large windows bigger than the display resolution.  Remember, you want to switchover from having the Z80 sending everything to the GEOFF is 16bit chunks to a system where you have a per-compiled string of commands stored in the DDR3 as microcode and has the Z80 just tell the new microcode system to run the code @DDR3 address and let the GPU do all the graphics work on it's own.  (This means a lot of home make assembly programming to engineer all you graphics routines.)

The Current DDR3 is optimized to read and write 128bit chunks at a time and does exponentially better as you enlarge that read or write by multiples of 128bit.  If you ever upgrade the PCB to a 256bit DDR3 system, then 256bit becomes the optimum burst chunk size.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 29, 2022, 09:33:36 pm
Isn't this project too *complex* to be a-single-person hobby?
Really I am lost here, too many things, too many pages for my little free time.

Guys, you have my moral support  :-+
I'm sure Noickieboy has done his share.  Because of the DDR3 and new Window system, plus my earlier contributions, I have contributed over 25K lines of HDL code not counting some of the extras like the RS232 hex editor and debugger.   But, yes, properly doing such a project should have required a team of around 8-12 people beginning with a 25kgate FPGA from day one instead of the extra effort involved in squeezing so much into a 6k gate FPGA at the beginning.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on January 29, 2022, 11:18:08 pm
Well, with 'OPTION B' memory processor for manipulating pixels and such, each instruction will either be 64bits, or 128bits.  So, we are going to eat through those tiny 16kb banks in a flash just to store a set of instructions / functions you wish to access.

Though, the multi-coordinate drawing functions like a quadrilateral will still exceede 128bit as you will have 8x16bit coordinates, then you still need a 32bit color and which display address it belongs to.

Naïve question; do the instructions have to be so many bits wide?

Hun?  Count the coordinates.  A quadrilateral has 4 pairs of XY coordinates.  Each XY coordinate has 16bits for the X and 16 bits for the Y coordinate.  That's 32bits * 4 pairs = 128bits.  Each quad is 128bits not counting the 32 bit color, filled or not filled.  Now, we haven't yet decided how this will be stored in DDR3 ram as your current old design relies on the Z80 to copy this data to the GEOFF port and it is still the old-school 12bit X&Y coordinate system which cannot support large windows bigger than the display resolution.  Remember, you want to switchover from having the Z80 sending everything to the GEOFF is 16bit chunks to a system where you have a per-compiled string of commands stored in the DDR3 as microcode and has the Z80 just tell the new microcode system to run the code @DDR3 address and let the GPU do all the graphics work on it's own.  (This means a lot of home make assembly programming to engineer all you graphics routines.)

The Current DDR3 is optimized to read and write 128bit chunks at a time and does exponentially better as you enlarge that read or write by multiples of 128bit.  If you ever upgrade the PCB to a 256bit DDR3 system, then 256bit becomes the optimum burst chunk size.

Ah, I misunderstood and thought you just meant the instruction itself, not the data that goes with it.  Remind me - we're aiming for a memory implementation, aren't we?  Where the data and some instructions are written to GPU memory and the GPU gets on with it?

Isn't this project too *complex* to be a-single-person hobby?
Really I am lost here, too many things, too many pages for my little free time.

Guys, you have my moral support  :-+
I'm sure Noickieboy has done his share.  Because of the DDR3 and new Window system, plus my earlier contributions, I have contributed over 25K lines of HDL code not counting some of the extras like the RS232 hex editor and debugger.   But, yes, properly doing such a project should have required a team of around 8-12 people beginning with a 25kgate FPGA from day one instead of the extra effort involved in squeezing so much into a 6k gate FPGA at the beginning.

This most definitely started out as a single-person hobby.  I designed and built the uCOM myself, then decided I'd try to wrap my head around building some sort of video output - hence this thread.  What happened thereafter is well documented here in the starting pages, but basically BrianHG has lent his considerable knowledge and skill with FPGAs and taught me a heck of a lot about them in the process.  I'd never really heard of FPGAs before starting this thread and we started with a 6kgate FPGA because it was cheap and in a package that I felt my soldering skills could stretch to (a QFP-144) - but as BrianHG points out, if we could have gone straight to a 25kgate BGA package, it would have skipped a significant diversion at the start, but I feel starting simple and building from there makes it easier for people (who have the time and willpower) to follow.  ;)

The GPU project has pretty-much outgrown the uCOM project that birthed it - you'd have a hard time arguing that the development and technology going into the GPU has any place being hosted by an 8-bit system - but at the same time the GPU can be used with ANY home-built system (be it 8-, 16- or more bits).

I am, now more than ever, along for the ride as what BrianHG is doing is well beyond my capabilities and even understanding for the most part. I provide some hardware corroboration that the GPU is working as intended with a host system and offer feedback on the design and features where appropriate, but this a public project intended to help anyone out who wants to do more than just print text to the screen.  And I'm really enjoying it as I'm learning about things and doing stuff that I couldn't even have dreamed of when I was a kid.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 29, 2022, 11:31:24 pm
Ah, I misunderstood and thought you just meant the instruction itself, not the data that goes with it.  Remind me - we're aiming for a memory implementation, aren't we?  Where the data and some instructions are written to GPU memory and the GPU gets on with it?

The data and instructions will be the same thing.  IE: A single bitstream of data can draw objects as well as perform other GPU instructions besides GEOFF functions and generate a drawing.  The complexity of the support structure managing a lot of this will be up to you to develop.  If done right, most geometric objects should be akin to a file just being copied to DDR3 and you setting a pointer to execute that drawing, one of many as well as a master routine table calling each drawing in a list.  Within that drawing, I would recommend setting up some system default register pointers which the drawing can call, like screen base address and resolution, window drawing limits and scale/rotate coordinates.  (Scale and rotate, including floating point support here is assuming you want to add such modules to the GEOFF, but we are a long way off from that.)

Ok, lets see something interesting with what you got now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 01, 2022, 04:33:37 pm
Here's a little something.  It's really simple, doesn't using tiling but it does show parallax scrolling over 4 layers (5 if you include the normal text layer in the background):

https://www.youtube.com/watch?v=lCyPvUgumaI (https://www.youtube.com/watch?v=lCyPvUgumaI)

Took some messing around with the PDI/SDI swap settings - I think a little more info on how they work would be handy.  If I get more time in the future, I'll make a start on something a little more technically impressive in tile mode.

The CP/M program is less than 130 lines of assembly and took me about ten minutes.  Converting and setting the images up in the GPU RAM and tweaking the PDI/SDI layers took a couple of hours.  :-[
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 01, 2022, 08:46:46 pm
Here's a little something.  It's really simple, doesn't using tiling but it does show parallax scrolling over 4 layers (5 if you include the normal text layer in the background):
Nice.  :-+
Quote
Took some messing around with the PDI/SDI swap settings - I think a little more info on how they work would be handy.  If I get more time in the future, I'll make a start on something a little more technically impressive in tile mode.
I know it may be a little confusing.  There is a technical limitation due to the method in which the SDI video layers come out in a sequential manner compared to the PDI Layers.  I tried to code it as simple as possible.  I recommend opening up all the layers with a screen size big white fat 0 through 15 text with black outline on each layer and play with the settings to see what happens.  As you can see on my page 2 of my .pdf documents, the bitwise 'XOR' means first for each PDI sequence, you can swap layers 0/1, 2/3, or 0&1, 2&3, or reverse the 4 layers.  Same goes for 4/5/6/7, 8/9/10/11, 12/13/14/15.  Then, once those layers have been optionally swapped around, you have the vertical equivalent swap.  If I were to do it any other way, like assigning 1 layer to a target layer, you would need a full byte per layer, meaning 64 control bytes to address 64 SDI layer swapping plus another 64 bytes to address the 64 PDI layer swapping with a ton of routing inside the FPGA.

This means if you are making a game where the character can move vertically in front and behind a few parallax scrolling layers, you will just have to strategically space the parallax layer numbers so that the players end up on the second or third location when it comes to the vertical PDI swap variable allowing you to move your player vertically among the parallax background layers without having to change those layer swap variables.
Quote
The CP/M program is less than 130 lines of assembly and took me about ten minutes.  Converting and setting the images up in the GPU RAM and tweaking the PDI/SDI layers took a couple of hours.  :-[
Well, scrolling 4 windows means nothing more than incrementing 4 'CMD_win_bitmap_x_pos' 16 bit integers at a different pace for each window.  This can even be done in basic with around 10 lines of code.  As for the graphics, yes, converting and dealing with the palettes and making use of the transparency is a massive chore especially if you haven't engineered any tools for the job.  Well, if you made the graphics in photoshop using translucency and save those images as 32bit .tiff uncompressed, like that madilorian 512x512x32bit image you uploaded awhile back, all you would have to do is strip out the .tiff header, open your 4 windows as 32 bit layers in the GPU with the correct bitmap width setting and copy in the raw data to the correct beginning address.  No palettes, just perfect 32bit true color with transparency data.

Looking at the graphic data having dithering patterns for the background, I'm assuming you took these images from somewhere else?  Otherwise, you have a new 256 color palette per window layer, or even 16.7m colors per layer, dithering should have not been needed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 01, 2022, 09:29:29 pm
As for the graphics, yes, converting and dealing with the palettes and making use of the transparency is a massive chore especially if you haven't engineered any tools for the job.

Thanks - another idea for a tool I can make; something that will open a binary file and allow me to change values throughout the file, so I can reassign pixels to custom palette entries. :-+ :-/O

EDIT: Or I could just not re-invent the wheel and use Find/Replace in my hex editor of choice. ::)

On the subject of palettes, how can I make a particular Layer use a particular palette?  With five layers, each referenced its own palette when I would have preferred to point them all to the same palette.

Looking at the graphic data having dithering patterns for the background, I'm assuming you took these images from somewhere else?  Otherwise, you have a new 256 color palette per window layer, or even 16.7m colors per layer, dithering should have not been needed.

Yes, for familiarity and ease I just downloaded some Creative Commons assets from here: https://ansimuz.itch.io/mountain-dusk-parallax-background (https://ansimuz.itch.io/mountain-dusk-parallax-background)

I did think about using some 32-bit images with transparency, but I wanted to keep the sizes small and use something more era-appropriate for a test run. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 01, 2022, 09:47:45 pm
The only way I can get the graphics into the GPU currently is via the RS232_debugger.  I can't access the actual graphics in the GPU's DDR3 RAM from the uCom if I wanted to - the first layer starts at the very end of GPU RAM that the uCOM can access within its 512KB window.

As a minor side project, I'm going to start on an MMU for the uCOM's memory interface to the GPU's DDR3.  I'm just starting to think about it and could do it one of two ways that I can see at the moment:
Option 1 seems the most sensible way to do it.  This would involve some minor additional code in Bridgette (the Z80 interface) to add some additional address lanes to its DDR3 pathway and control the upper bits with an additional IO port value.  Is there an easier/better way to do this?  Can you see any issues that I am unaware of or haven't thought of yet?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 01, 2022, 09:52:37 pm
On the subject of palettes, how can I make a particular Layer use a particular palette?  With five layers, each referenced its own palette when I would have preferred to point them all to the same palette.
I'm sorry, but it is hard wired.
If I were to share palettes, every PDI layer channel would still have it's own palette.
You will have to wait for the memory copy function, store 1 master palette in DDR3 and send the command to copy that reference palette into all the destination palettes once a V-Sync or so.
Actually you can already do this using the blitter.
Store your palette anywhere in DDR3 so long as it's base address begins on a 128byte boundary.

When copying, you are basically blitting a single 1024x1 pixel 8 bit bitmap to the destination base address, coordinates 0x0 to fill layer 1 palette.  Paste a blit pixel again into 0x1 to fill the palette for layer 1, paste a blit pixel again into 0x2 to fill palette for layer 2.  To fill the palettes of all layers, just draw a vertical blit line from 0x0 to 0x15.  You can also blit from palette to palette just by defining the blit source image at address of palette 0, 8bit, 1024 pixel width and draw a line from 0x1 to 0x15.  You can also blit portion of a palette by defining the X coordinates in your copy.

You can also stack the palette vertically by making the blit source 4 8bit pixels wide and using every 1 Y coordinate for the color index #.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 01, 2022, 09:56:28 pm
The only way I can get the graphics into the GPU currently is via the RS232_debugger.  I can't access the actual graphics in the GPU's DDR3 RAM from the uCom if I wanted to - the first layer starts at the very end of GPU RAM that the uCOM can access within its 512KB window.

As a minor side project, I'm going to start on an MMU for the uCOM's memory interface to the GPU's DDR3.  I'm just starting to think about it and could do it one of two ways that I can see at the moment:
  • I could page 512KB banks of DDR3 into the uCOM's memory window. Maybe the easiest way to do this would be to control which 512KB bank of DDR3 is visible to the uCOM via another IO port, which would give the uCOM access to 256x512KB banks - enough to access 128MB of DDR3 if I use only one additional IO port.
  • The other way would be to keep the lowest 16KB of DDR3 (the HW_REGS and palettes) always visible to the uCOM, and instead of IO, use a memory location/s in that first 16KB to control which 496KB chunk is available in the rest of the 512KB window.  That sounds complicated, but would give access to unlimited memory.
Option 1 seems the most sensible way to do it.  This would involve some minor additional code in Bridgette (the Z80 interface) to add some additional address lanes to its DDR3 pathway and control the upper bits with an additional IO port value.  Is there an easier/better way to do this?  Can you see any issues that I am unaware of or haven't thought of yet?
Go for #1.  The lane addition is easy enough as they are already wired there, just that those addresses are assigned to a value of 0 when addressing the DDR3.  As for the patched GEOFF and my Window system, all 32bits are wired, so they already have full 512mb access and can go to up to 4gb.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 01, 2022, 09:57:08 pm
On the subject of palettes, how can I make a particular Layer use a particular palette?  With five layers, each referenced its own palette when I would have preferred to point them all to the same palette.
I'm sorry, but it is hard wired.

Pff, don't apologise - it's not an issue. ;D  I just had it in my head for some reason that we could do that - I'd even checked the HW_REGS table to see if there was a palette memory location for each layer. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 08, 2022, 08:48:26 am
Ok, it's been a week.  Anything new to see?  Any new bugs found?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 09, 2022, 10:26:36 am
Hi, no - nothing new to see yet.  As usual, work is getting in the way of 'less important' time sinks, like hobbies.  Hopefully might be able to set aside some time this weekend or next week.

Did you manage to sort that overflow bug with the DDR3 controller?  I haven't noticed any bugs or issues.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 09, 2022, 11:20:43 pm
Hi, no - nothing new to see yet.  As usual, work is getting in the way of 'less important' time sinks, like hobbies.  Hopefully might be able to set aside some time this weekend or next week.

Did you manage to sort that overflow bug with the DDR3 controller?  I haven't noticed any bugs or issues.
I've been waiting on you to do more with the video controller.  I need to know if it is ready to finalize.
I doubt you can overload the DDR3 with your current apps.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 15, 2022, 05:43:57 am

Ok, it's been a week.  Anything new to see?  Any new bugs found?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 15, 2022, 07:55:30 am
No, spare time is like gold dust for me currently. :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 16, 2022, 03:23:53 pm
Okay, I found a half hour this morning to get something done today and that something was... *drumroll*  An MMU for the GPU RAM. ;)

It's not much, but the Z80 can now access up to 4GB of DDR3 RAM via the 512KB 'window' into the GPU RAM.  Two IO ports control which 512KB block of DDR3 RAM is accessible in the 512KB window.  The host controls bits 18:0, with one IO register adding a full 8 bits to the address; the other adds 5 bits, allowing the host to access the full 32-bit address width of the DDR3.

I was able to streamline the HDL a little in BRIDGETTE as well, removing the mem_in_range wire etc.

I didn't have time to look into the new IO system you've created unfortunately, settling for a quick hit rather than trying to work the changes into a new system and all the bug-hunting complications that may create.  It seems simple enough, but I have to ask the question - why?  How is it better to have a 256-bit strobe bus (and 256*8 data bus) that (presumably) goes off to another module dedicated to handling the IO functions?  As far as I can tell, the only benefit is to keep BRIDGETTE as platform-agnostic as possible, so long as it uses a Z80 all anyone would need to do is edit the IO module?  I realise Quartus will prune the 2,304 wires down to the minimum required, depending on the number of IO ports in use, but still, to me it seems a little obtuse. :-\

Anyhoo, I'm sure there's a compelling argument that I haven't thought of. :)

The Z80 can now access the entire GPU RAM, so I'm not limited to the first 512KB like previously.  Can focus on writing the tile demo when I get a chance now.

Latest project files attached.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 17, 2022, 06:13:37 pm
Ok, when will we see this?
https://youtu.be/rAd6MlU5yiY?t=387

You have all the layers, color, and memory you need.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 17, 2022, 09:47:39 pm
Ok, when will we see this?
https://youtu.be/rAd6MlU5yiY?t=387 (https://youtu.be/rAd6MlU5yiY?t=387)

You have all the layers, color, and memory you need.

:-DD  :o  I was watching that video for far too long... became engrossed in nostalgia before I remembered what you'd written.  You're expecting what?! :scared:

You DO realise I'm not a professional programmer, right?  Everything I've learned about Z80 assembly is self-taught or from z80-Heaven (http://z80-heaven.wikidot.com). :o  Give me some time though, I'll see what I can do. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 17, 2022, 11:03:47 pm
Well, this was done on a Commodore 64 with the only requirement being a 256k ram expansion:
https://youtu.be/_Cg8r-VmeMk?t=0

However, for Rayman, if you were to get a file copy from the assets, almost all of them will be directly compatible with my video buffer.  Just a lot of smart look-up tables for the animation cells and some clever physics engine written in assembly should squeeze out a good 60fps as there are around at most 8 enemies onscreen.  (IE: A Sony PS1 emulator running the game or CD/roms from the other 2 systems it was available on)

A guess improving/adding a programmable smarter memory copy module for my DDR3 controller would mean the Z80 would need be spitting out around 50 sets of coordinates with animation cell ID each frame to replicate the Rayman game.  Something which looks possible for a 8MHz Z80.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 18, 2022, 02:40:42 pm
Well, this was done on a Commodore 64 with the only requirement being a 256k ram expansion:
https://youtu.be/_Cg8r-VmeMk?t=0

That's very impressive.

Quick question - I should probably know the answer, but can't seem to find it.  How do I change the foreground/background colour of a 1bpp font tile in Tile Mode?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 18, 2022, 11:06:26 pm
Read here (beginning at line 362 in the manual):
Code: [Select]
******************************************************************************************************
******************************************************************************************************
******************************************************************************************************
******************************************************************************************************
*** Understanding the TILE/FONT enabled PDI layer.
******************************************************************************************************
******************************************************************************************************
******************************************************************************************************
******************************************************************************************************

The font/tile layer utilized on-chip FPGA blockram to hold it's tiles/fonts.

**********************************************************************************
Tile selection when using different 'CMD_vid_bpp' modes, 8/16a/32/16b bpp modes.
* On a tile layer, bpp will actually mean bpc -> Bits Per Character Tile.
----------------------------------------------------------------------------------
FGC  = Foreground color.  Adds this FGC value to any tile pixels whose color data is != 0.
BGC  = Background color.  Replace tile pixels whose color data = 0 with this BGC value.
MIR  = Mirror the tile.
FLIP = Vertically flip the tile.
----------------------------------------------------------------------------------

CMD_vid_bpp' mode:

8   bpp -> Each byte = 1 character, 0 through 255, no color, mirror or flip functions.

            BGC,  FGC,  Char 0-255.   *** BGC & FGC are multiplied by 16 in this mode.
16a bpp -> {4'hx, 4'hx, 8'hxx}                           = 16 bits / 256 possible tiles.

            FLIP, MIR,  FGC,  Char 0-1023. *** FGC is multiplied by 16 in this mode.
16b bpp -> {1'bx, 1'bx, 4'hx, 10'hxxx}                   = 16 bits / 1024 possible tiles.

             BGC,   FGC,  FLIP, MIR,  N/A,  Char 0-1023.
32  bpp -> {8'hxx, 8'hxx, 1'bx, 1'bx, 4'h0, 10'hxxx}     = 32 bits / 1024 possible tiles.

Instead of 8bit for the CMD_vid_bpp' mode screen data, use 16bit or 32bit where 1 of the bytes is still the letter, the other bytes contain the color and features.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 21, 2022, 12:14:46 pm
I think I'm a little confused about how to address different tile sets. ::)

Here's what I'm trying to do whilst I learn how to use different layers:

1) I've got 3 layers - top Layer 0 is text, middle Layer 1 is anything I want to appear above Layer 2, which is the bottom layer and displays a map.
2) Layers 1 & 2 need to use a different tile set to Layer 0, which displays the standard font.  Layers 1 & 2 will display an 8bpp graphical tileset, which I'm loading (randomly) at 7000h, out of the way of the screen memory for the three layers.

It appears, from tweaking the HWREGs settings for the layers using the RS232_debugger, that the 16-bit Tile/Font Base Address register is actually only a 12-bit register, as the value set doesn't seem to care what the MSN (top 4 bits) are set to, but then reading the HDL notes in BrianHG_GFX_VGA_Window_System.sv, I'm reminded that the tiles are stored in block RAM, not DDR3 RAM, so where should I be loading the additional tile set? :scared:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2022, 02:47:14 am
Arrrg... Ok....

Code: [Select]
module GPU_DECA_DDR3_top #(

// ****************  GPU controls.
parameter int        GPU_MEM                 = 524288,           // Defines total video RAM, including 1KB palette

parameter string     ENDIAN                  = "Little",            // Endian for 8bit addressing access.
parameter bit [3:0]  PDI_LAYERS              = 4,                   // Number of parallel window layers.
parameter bit [3:0]  SDI_LAYERS              = 4,                   // Number of sequential window layers.
parameter bit        ENABLE_TILE_MODE  [0:7] = '{1,0,0,0,0,0,0,0},  // Enable tile mode for each PDI_LAYER from 0 to 7.
                                                                    // TILES are available to all SDI_LAYERS of an enabled PDI_LAYER.
                                                                    // Each tile enabled PDI_LAYER will use it's own dedicated FPGA blockram.
parameter bit        SKIP_TILE_DELAY         = 0,                   // Skip horizontal compensation delay due to disabled tile mode features.  Only necessary for multiple PDI_LAYERS with mixed tile enable options.

parameter bit        ENABLE_PALETTE    [0:7] = '{1,1,1,1,1,1,1,1},  // Enable a palette blockram for each PDI_LAYER from 0 to 7.
                                                                    // Each palette enabled PDI_LAYER will use it's own dedicated FPGA blockram.
parameter bit        SKIP_PALETTE_DELAY      = 0,                   // Skip horizontal compensation delay due to disabled palette.  Only necessary for multiple PDI_LAYERS with mixed palette enable options.


parameter int        HWREG_BASE_ADDRESS      = 32'h00000100,     // The first address where the HW REG controls are located for window layer 0.  The first 256 bytes are reserved for general purpose use.
                                                                 // Each window uses 32 bytes for their controls, IE assuming 32 windows, we need 1024 bytes worth of address space.
parameter int        HWREG_BASE_ADDR_LSWAP   = 32'h000000F0,     // The first address where the 16 byte control to swap the SDI & PDI layer order.

parameter int        PAL_BASE_ADDR           = 32'h00001000,     // Assuming 32 layers where each palette is 1024 bytes, we will use 32768 bytes for the palette.
parameter int        TILE_BYTES              = 65536,            // Number of bytes reserved for the TILE/FONT memory.  We will use 64k, IE it is possible to make a 16x16x8bpp 256 character font.
parameter int        TILE_BASE_ADDR          = 32'h00004000,     //

These lines:

Code: [Select]
parameter bit [3:0]  PDI_LAYERS              = 4,                   // Number of parallel window layers.
parameter bit [3:0]  SDI_LAYERS              = 4,                   // Number of sequential window layers.
parameter bit        ENABLE_TILE_MODE  [0:7] = '{1,0,0,0,0,0,0,0},  // Enable tile mode for each PDI_LAYER from 0 to 7.

Means that the tile mode will only function on layers 0,1,2,3.

These lines:

Code: [Select]
parameter int        TILE_BYTES              = 65536,            // Number of bytes reserved for the TILE/FONT memory.  We will use 64k, IE it is possible to make a 16x16x8bpp 256 character font.
parameter int        TILE_BASE_ADDR          = 32'h00004000,     //

Means that when the Z80 or any other peripheral writes to memory address 32'h00004000 through 32'h00013FFF, you will be writing into the tile block memory memory address 20'h00000 through 20'h0FFFF.

This is hard wired and cannot be changed once compiled.

So, writing a font beginning at address 32'h00004000 means it's tile blockram address begins at 20'h00000.
Or, writing a font beginning at address 32'h00005000 means it's tile blockram address begins at 20'h01000.

Now, when setting the 16 bit register 'CMD_win_tile_base' address, it sets the first character '0' pointing into the 'tile blockram address', not DDR3 address.  Remember, the value you set will be multiplied by 16 so that you may address more than 65536 bytes for the tile blockram memory.  Now, since in the parameters you have a set limit of 65536 bytes, this means that setting a value above 4095, (65536/16-1), the tile memory blockram read address will loop around back to 0 as the line display buffer has no check for error addresses above the set parameter 'TILE_BYTES' size.

I hope this helps.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 22, 2022, 09:39:30 am
Means that when the Z80 or any other peripheral writes to memory address 32'h00004000 through 32'h00013FFF, you will be writing into the tile block memory memory address 20'h00000 through 20'h0FFFF.

Probably a stupid question, but does this mean that all of the screen memory I've been using so far has been in block RAM, as I've had the screen memory start at 0x5000...?

Ah, thinking about it, all the work is handled by GEOFF in graphics modes.  The only direct writes to memory by the host are when writing the font/tile set data in the first place, and this will go to block RAM where it should be.  Still, handy to know that I can't write to the screen directly (without using the blitter or GEOFF) below 0x13FFF.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2022, 09:46:48 am
Yes, the GEOFF can write into the tile memory.
You can use the blitter to quickly move/edit/animate not just the picture data, but the tile's contents as well.
Yes, you were probably wasting some of the limited available tile memory space.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 22, 2022, 11:15:58 am
|O  Okay, I'm struggling with this for some reason.

Here's what I'm trying to do:

1) Set up Tile Mode, with Layer 0 displaying normal text.
2) Set up Layer 1 and Layer 2 to display 16x16 graphics tiles (which I'm loading-in with the rs232_debugger for the moment)

The setup works, displaying normal text on all three layers.  What I can't get to work is making Layers 1 & 2 display a different tile set (i.e. the 16x16 graphics tiles).

Here's the HW_REGs setup code:

Code: [Select]
VMtabl: ; Layer 0 - TEXT
DB 00h,0D0h,00h,00h,83h,00h,TPR,00h,00h,00h,00h,00h,20h,00h,20h,00h
DB 90h,02h,0A0h,01h,00h,00h,00h,00h,80h,12h,00h,00h,00h,00h,00h,74h
; Layer 1 - ACTORS
DB 00h,0D9h,00h,00h,83h,00h,TPR,00h,00h,00h,00h,00h,20h,00h,20h,00h
DB 90h,02h,0A0h,01h,00h,00h,00h,00h,80h,12h,00h,00h,00h,00h,00h,00h
; Layer 2 - BACKGROUND
DB 00h,0E2h,00h,00h,83h,00h,TPR,00h,00h,00h,00h,00h,20h,00h,20h,00h
DB 90h,02h,0A0h,01h,00h,00h,00h,00h,80h,12h,00h,00h,00h,00h,00h,00h

I've updated the setup to move the screen memory location up to 0xD000 onwards, to avoid writing into the tile memory in the GPU's block RAM.  The above setup works, displaying ASCII characters appropriately on all three layers.

So, the next step is to load up and test the graphics.  I tweak the above setup code to make Layer 1 & 2 display 16x16 tiles from a different location in the GPU's block RAM (hopefully!):

Code: [Select]
VMtabl: ; Layer 0 - TEXT
DB 00h,0D0h,00h,00h,83h,00h,TPR,00h,00h,00h,00h,00h,20h,00h,20h,00h
DB 90h,02h,0A0h,01h,00h,00h,00h,00h,80h,12h,00h,00h,00h,00h,00h,74h
; Layer 1 - ACTORS
DB 00h,0D9h,00h,00h,83h,00h,29h,00h,00h,00h,00h,00h,20h,00h,20h,00h
DB 90h,02h,0A0h,01h,00h,00h,00h,01h,80h,22h,00h,00h,00h,00h,00h,00h
; Layer 2 - BACKGROUND
DB 00h,0E2h,00h,00h,83h,00h,29h,00h,00h,00h,00h,00h,20h,00h,20h,00h
DB 90h,02h,0A0h,01h,00h,00h,00h,01h,80h,22h,00h,00h,00h,00h,00h,00h

Then I try to load the tile set into the GPU RAM using the rs232_debugger.  The tile set is a 64x64 image, stripped to raw binary, 4,096 bytes long.  I load this at address 20,480 (0x5000), which should be 0x1000 in the block RAM and above the existing font tile set.  With the above HW_REGs settings, I should see something?  Unfortunately, the screen just goes blank and I have to quit my test program, which resets the HW_REGs, then I get a normal (graphics-based) display back again.  When I load the test program again, I can only see Layer 0 text, messing with the tile_base_addr setting in the debugger I can't seem to find any graphics.

Is there anything obvious I'm doing wrong?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2022, 11:38:29 am
Hmmm, ok.

TPR?  I assume that's your raster/character width, IE number of characters across the screen.

Everything looks OK.

Are you sure you actually placed actual tile data into the right address?
The only real change between layers is the tile base address and the 16x16 pixel tile mode.
And, if the text on all 3 layers worked, it's only that the tiles you chose to print may be blank or never filled with any data.  This is all I can think is happening.

You have a tile address of $0100 x 16= 4096, or you need to place this tile data into DDR3 ram at $5000.
Remember, the data at $5000-to-$501F is char(0) if you are using a 1 bit, 16x16 pixel font.  $5020 begins char(1).  The 1 bit font data at 16x16pixels means 2 bytes per line.

Try filling the display mem with char(0) and just poke around $5000.  You should be filling the entire screen with pixels as you modify the font's char(0) bitmap.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2022, 03:43:41 pm
Did you remember to set the palette for layers 1 & 2?  If you did not, the RS232 debugger may have cleared them.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 22, 2022, 03:59:39 pm
Ah, I'm making progress.  I had an errant piece of code that was clearing the wrong part of memory since I'd moved the layer addresses further up into DDR3 RAM, and I worked out I was putting the tiles together in the wrong format - I'd just created a 4x4 tilesheet, then realised as I was looking at the garbled mess on the screen that they should be a 1x16 layout instead. ::)

Exactly what does the rs232_debugger do when you load in a binary at an address?  It looks like it reloads memory from 0000 all the way up, rather than just loading in the specific area of memory affected by the binary?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2022, 04:09:24 pm
Exactly what does the rs232_debugger do when you load in a binary at an address?  It looks like it reloads memory from 0000 all the way up, rather than just loading in the specific area of memory affected by the binary?

The debugger tends to always re-read the 1mb buffer.

If you load a binary to a specific address, it will place the file into it's 1mb buffer at the specified location, then re-transmit the entire 1mb buffer.

When starting up the debugger, it will read in the 1mb buffer from the DDR3.

When scrolling through the display, it continuously re-reads that current 256byte block in real time, updating the internal 1mb buffer.

Remember, the debugger has a 1mb limit to the first 1mb.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 22, 2022, 05:55:29 pm
The debugger tends to always re-read the 1mb buffer.

If you load a binary to a specific address, it will place the file into it's 1mb buffer at the specified location, then re-transmit the entire 1mb buffer.

When starting up the debugger, it will read in the 1mb buffer from the DDR3.

When scrolling through the display, it continuously re-reads that current 256byte block in real time, updating the internal 1mb buffer.

Aha!  That's what's been going on.  I've been experiencing some very strange behaviour whilst testing the tile set, with the screen looking perfect when the binary load starts, but half the screen disappearing as the load continues.  The debugger hadn't buffered the changes made by the test program when I loaded it, so when I then loaded the binary image with the tile set in, it reset a load of stuff that the test program had set up (Layer 1 and 2's screen map, essentially) and corrupted the screen.  After reading your last post, I went back and scrolled through the screen memory in the debugger before loading the tile set in, and it works. :-+

I just need to spend a little time sorting the palettes out now. :-/O

Is there any chance the debugger could be modified to ONLY load the memory area specified in the load instruction, or would that cause too many issues?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 22, 2022, 06:01:36 pm

Is there any chance the debugger could be modified to ONLY load the memory area specified in the load instruction, or would that cause too many issues?
Before you do the 'Load', just do a re-read / update of the 1mb DDR3 memory buffer.
Just hit the letter ' r '.
This will first read all the DDR3 buffer.
Then load binary and the portion you load will be the only portion changed...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 24, 2022, 03:30:53 am
So?  Do the tile modes/layers work?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 24, 2022, 10:15:14 am
So?  Do the tile modes/layers work?

Yes, they appear to so far.  Progress is slow due to the much-mentioned work pressures currently, along with a slight diversion to write a tileset tool that does exactly what I need (i.e. makes it much easier and quicker to realign palette indices in the image and displays the actual memory locations for each palette entry used, imports the image's palette and converts it for the GPU etc).

Layer 2 is displaying the map nicely.  Once I've finished off the Tile Set Editor, I'll pop it up on github and crack on with the next steps in the tile demo's development.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1423666)

EDIT: This 'game' has been sat on CP/M for a year or two in development limbo, I've just modified it to use tile layers and graphics instead of the old ASCII art I initially set it up to use.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 24, 2022, 12:49:27 pm
 :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: SiliconWizard on February 24, 2022, 06:06:51 pm
Great project guys!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 26, 2022, 11:32:45 am
The Tile Set Editor is now up on github (https://github.com/nockieboy/TileSet_Editor).

It's not pretty, but it gets the job done in terms of turning an 8-bit indexed PNG image into a raw binary file and separate pixel table that can be uploaded via the rs232_debugger to the GPU.  Saves messing around with ImageMagick and endless checking and copying palette values directly into memory. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 27, 2022, 06:18:58 am
    Great.  What's the next step?

    I thought that your tile editor would have been done on the Z80.

    Are you having a file system compatibility and transfer problem?

    Remember, if the Z80 cant cope with .png, using uncompressed .tiff is nothing more than stripping out the header, copying the palette info and picture data directly to the DDR3 and setting my window parameters accordingly, for both working with using font/tiles and showing full pictures up to 32bit color.

    You know you can try to add the SD-Card reader.  You can tie the read and write directly to my DDR3 controller anyway you like.  The SD-Card is so slow, it just isn't worth the effort to make a super fancy cached controller as the tiny 16/32 byte cache buffer built inside my DDR3 controller should be enough for 90% of anything you can imagine.  Only a real-time MJPEG video playback codec may be the one case where a complete high speed 4kb block cache will be beneficial.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 27, 2022, 10:36:10 am
    Great.  What's the next step?

I think I was going to tackle something a little more taxing, like the videos you linked previously.

    I thought that your tile editor would have been done on the Z80.

Yeah, no. ;)  Thanks to modern IDEs, I was able to create TSE in a few hours work.  Doing something similar on the Z80 would take significantly longer, and I've felt a little pressured recently to get results out of the door, so to speak.


    Are you having a file system compatibility and transfer problem?

    Remember, if the Z80 cant cope with .png, using uncompressed .tiff is nothing more than stripping out the header, copying the palette info and picture data directly to the DDR3 and setting my window parameters accordingly, for both working with using font/tiles and showing full pictures up to 32bit color.

My focus has been PC dev tools as that's where all the development has been done so far, so I haven't really looked into this idea much at all yet.  If I can get an SD card interface up and running, then I'll move it up the list as transferring files to the Z80 will become much easier.

    You know you can try to add the SD-Card reader.  You can tie the read and write directly to my DDR3 controller anyway you like.  The SD-Card is so slow, it just isn't worth the effort to make a super fancy cached controller as the tiny 16/32 byte cache buffer built inside my DDR3 controller should be enough for 90% of anything you can imagine.  Only a real-time MJPEG video playback codec may be the one case where a complete high speed 4kb block cache will be beneficial.

I've been wanting to make a start on this for ages now, especially since moving to the DECA (and its working SD card socket!)  The issue is, I'm not sure really where to start.  It's an unfortunate combination of two areas of knowledge I'm really deficient in - storage and storage.  I know that's technically only one area, but I thought it was worth mentioning twice.

My simplistic understanding of it is that basically data is serialised and written to/read from the interface a block at a time - the only working example is the CF card interface that I use currently with my uCOM (I didn't write that).  On top of that, there's also considerations about formatting, file/folder structure etc.  The CF card interface I'm using uses an old CP/M format - I'm able to read the contents on the PC using some old cpmtools (http://www.moria.de/~michael/cpmtools/) drivers that read the old format.

Now what I'd like to do - and I have no idea if it's even possible - is have CP/M think it's accessing a floppy disk as usual (i.e. use the existing CF driver, with maybe a couple of tweaks), but in reality use a FAT32-formatted SD card and be able to drop it into a PC and have Windows read the card without any additional drivers.  The problem is, I have no idea what would be required of the FPGA interface and host driver to do that.  I've been putting off disappearing from the forum for a month or two to go read up on all this in favour of quick hits to show progress, but with the GPU now able to shift graphics about like a JCB in a sandpit, I really need a better method of file storage and transfer for the uCOM.  Looking at existing SD card interfaces on OpenCores, for example, doesn't fill me with confidence when I have to also learn about Wishbone interfaces and loads of other stuff I don't really need.

I need to stop procrastinating and bite the bullet on this task. ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 04, 2022, 10:39:47 am
    Great.  What's the next step?

I think I was going to tackle something a little more taxing, like the videos you linked previously.

Really.  :-+ A multilayer 2D platformer game engine isn't too difficult with my video system, but, it's all the graphics and sound assets.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: rstofer on March 04, 2022, 07:33:44 pm
Now what I'd like to do - and I have no idea if it's even possible - is have CP/M think it's accessing a floppy disk as usual (i.e. use the existing CF driver, with maybe a couple of tweaks), but in reality use a FAT32-formatted SD card and be able to drop it into a PC and have Windows read the card without any additional drivers.  The problem is, I have no idea what would be required of the FPGA interface and host driver to do that.  I've been putting off disappearing from the forum for a month or two to go read up on all this in favour of quick hits to show progress, but with the GPU now able to shift graphics about like a JCB in a sandpit, I really need a better method of file storage and transfer for the uCOM.  Looking at existing SD card interfaces on OpenCores, for example, doesn't fill me with confidence when I have to also learn about Wishbone interfaces and loads of other stuff I don't really need.

I need to stop procrastinating and bite the bullet on this task. ::)

A Compact Flash implementation on an FPGA is dead simple because it is a parallel interface.  In fact, it is an ATA protocol just like an HDD.    At least in terms of reading and writing sectors. 

The IBM 1130 had 321 word sectors (642 bytes) which I mapped into adjacent 512 byte sectors.  The rest was trivial.

However, I didn't have to create a file system or have any ability to work with it on a PC.  The 1130 had its own file system and I was just implementing the underlying hardware.

If I couldn't come up with some other way to do things, I would use the Linux 'dd' command to read and write the CF.  Turning the raw image into a recognizable file system (FAT32) would be done in code somehow.

CP/M is the file system, all the BIOS does is read and write sectors.  You could easily map an entire CP/M drive into a named file if you could deal with the allocation table in FPGA code.  I might use a small core and some assembly language to do this mapping.  It seems rather complex to do it in hardware but maybe not.  You can use 512 byte sectors in CP/M, the code for packing and unpacking is easily obtained and was written by Digital Research.  I haven't thought about it in years.  Maybe it came with CP/M 2.2

https://en.wikipedia.org/wiki/Parallel_ATA#Compact_Flash_interface
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 04, 2022, 10:30:55 pm
A Compact Flash implementation on an FPGA is dead simple because it is a parallel interface.  In fact, it is an ATA protocol just like an HDD.    At least in terms of reading and writing sectors. 

The IBM 1130 had 321 word sectors (642 bytes) which I mapped into adjacent 512 byte sectors.  The rest was trivial.

However, I didn't have to create a file system or have any ability to work with it on a PC.  The 1130 had its own file system and I was just implementing the underlying hardware.

Yes, my uCOM currently uses a CF card interface I built based on Grant Searle's original designs (his CP/M design, specifically (http://searle.wales)), with a few extra features like bus buffering etc, so I have a working BIOS with the low-level routines (including blocking/de-blocking) to operate the CF card with no problems, but not having to write them myself or watching how they came together I have very little true understanding of the basics of the CP/M format - I don't know what I don't know, if you know what I mean, so I don't know what's possible and what isn't - hence the question regarding whether or not it's possible to 'convert' CP/M files into FAT32/Windows files (and back) on the fly between the host and SD card, and why I'm now hitting the books hard to learn more about the subject.

If I couldn't come up with some other way to do things, I would use the Linux 'dd' command to read and write the CF.  Turning the raw image into a recognizable file system (FAT32) would be done in code somehow.

Tools exist already for Linux and Windows (cpmtools (http://www.moria.de/~michael/cpmtools/)) that do this - I can take the CF card out of the uCOM, plug it into my PC and read/write the CP/M drives and files (almost) like a native Windows drive.  If I could remove cpmtools from the equation, however, it removes another potential point of failure in the system (at some point, cpmtools will probably disappear or stop being compatible with the latest OSes, etc).

CP/M is the file system, all the BIOS does is read and write sectors.  You could easily map an entire CP/M drive into a named file if you could deal with the allocation table in FPGA code.  I might use a small core and some assembly language to do this mapping.  It seems rather complex to do it in hardware but maybe not.  You can use 512 byte sectors in CP/M, the code for packing and unpacking is easily obtained and was written by Digital Research.  I haven't thought about it in years.  Maybe it came with CP/M 2.2

Yes, I've been reading about CP/M's file system earlier today (The Programmer's CP/M Handbook by Andy Johnson-Laird) and it's clear that the way the file system works is embedded deeply into BDOS and the BIOS, so it's not looking likely that what I want to do is possible without some major refactoring of CP/M's source code - a rabbit hole I certainly don't have the time or experience to dive down.

Anyway, I'm massively jumping the gun by worrying about what I can and can't achieve with the SD card's format - I've first got to get an interface up and running that allows the host to read and write SD card data at all.  I'm considering using this project on OpenCores (https://opencores.org/projects/sdcard_mass_storage_controller) to establish an SD interface in the FPGA.  I know nothing about the Wishbone interface, so that's something else for me to learn about, but I don't think I actually need it and might be able to remove that part from the project, as the Z80_Bridge module in the FPGA should be able to handle the data and command flow between host and SD interface without a Wishbone bus.

Once I get some form of data read/write access to the SD card for the host, I can then start thinking about DMA into a DDR3 buffer and working out what's required to get CP/M working.  Right now, though, I'm researching the basic concepts. :phew:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: rstofer on March 05, 2022, 12:01:50 am
My first FPGA project after the all-important 'blinky' was to use the Opencores T80 core (Z80 workalike) to bring up CP/M.  This was on a Spartan 2 (great 5V FPGA) with a compact flash.  It was pretty trivial after I properly terminated the INT input.  Lot of head scratching before I tumbled to unending recursive interrupts.

The next time I used a compact flash was on a Z80Eclaim! project.  CP/M at 50 MHz really screams!

Finally, I used the compact flash on my IBM1130 project.  There is a disk image build routine that lays out all of the IBM code files in the proper sequence and 'dd' copies the image to the CF.

This is the guide I use for creating the various BIOSs beginning back  in '79 or so.

http://bitsavers.trailing-edge.com/pdf/digitalResearch/cpm/2.2/CPM_2.2_Alteration_Guide_1979.pdf (http://bitsavers.trailing-edge.com/pdf/digitalResearch/cpm/2.2/CPM_2.2_Alteration_Guide_1979.pdf)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 05, 2022, 08:52:09 am
My first FPGA project after the all-important 'blinky' was to use the Opencores T80 core (Z80 workalike) to bring up CP/M.  This was on a Spartan 2 (great 5V FPGA) with a compact flash.  It was pretty trivial after I properly terminated the INT input.  Lot of head scratching before I tumbled to unending recursive interrupts.

The next time I used a compact flash was on a Z80Eclaim! project.  CP/M at 50 MHz really screams!

I can see myself doing away with the uCOM stack entirely at some point and moving to a softcore Z80 CPU, but that's for when I get bored of the hardware side of the development. ;)

Finally, I used the compact flash on my IBM1130 project.  There is a disk image build routine that lays out all of the IBM code files in the proper sequence and 'dd' copies the image to the CF.

This is the guide I use for creating the various BIOSs beginning back  in '79 or so.

http://bitsavers.trailing-edge.com/pdf/digitalResearch/cpm/2.2/CPM_2.2_Alteration_Guide_1979.pdf (http://bitsavers.trailing-edge.com/pdf/digitalResearch/cpm/2.2/CPM_2.2_Alteration_Guide_1979.pdf)

Thanks for that link - you seem to have found the one CP/M book I missed when I did my research trawl at the start of this project several years ago!  Will give that a read too. :-+

Just thinking out loud, but presumably it'd be possible to re-write the BDOS to intercept disk I/O at the file level, instead of the sector level in the BIOS, and just have CP/M work with filenames which would translate directly to an SD card interface that does the same, but handles the low-level interfacing with the SD card (and cut out the BIOS middle-man)?  Obviously it wouldn't be CP/M anymore at that point, but only in the strictest sense of the name.  This would be a brittle system, though - likely to fail terribly if a program somewhere accesses the drive at a lower level than the BDOS, but I'm not aware of anything that does? (Other than maybe formatting programs?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: voltsandjolts on March 07, 2022, 10:58:46 am
Sorry, slight OT, but I thought this was quite cool...if you were making games for your system...
https://www.theguardian.com/games/2022/mar/07/duck-hunt-light-gun (https://www.theguardian.com/games/2022/mar/07/duck-hunt-light-gun)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 07, 2022, 11:18:41 am
Sorry, slight OT, but I thought this was quite cool...if you were making games for your system...
https://www.theguardian.com/games/2022/mar/07/duck-hunt-light-gun (https://www.theguardian.com/games/2022/mar/07/duck-hunt-light-gun)

Interesting idea.  I've missed the old CRT-enabled light guns - didn't think the Wii version was that bad, but there's clearly room for improvement/optimisation over that particular method of getting a gun to work with a modern display.

As for making games for my system - heh... yes, I suppose if there more than 48 hours in a day I'd have time to make significant progress, but at the moment it's almost strictly one-thing-at-a-time and the pressing need for an SD card interface is at the top of the list. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 07, 2022, 02:14:35 pm
I think I need a little guidance or at least an opinion on which direction I should take with this SD card interface.  I've been looking very closely at this OpenCores project (https://opencores.org/projects/sdcard_mass_storage_controller) that provides a fully-functioning SD card interface (project files attached).

The issue is that it uses a Wishbone interface which, to my inexperienced eye at least, appears to be an unnecessary complication.  I figured it would be simplest to directly interface the SD interface logic with the Z80_Bridge, but I'm not convinced I'm up to the task of removing the Wishbone interface HDL and stripping the SD interface down to the barebones required to interface to the Z80_Bridge.  It also looks like it's going to need some additional tri-state control of a couple of the connections from sd_controller_top to the SD card on the DECA board (the DECA has SD_DAT [3:0], but sd_controller_top has separate sd_dat_dat_i [3:0] and sd_dat_out_o [3:0] buses).

In fact I'm not 100% sure that this particular interface will do what I want it to do - which is (initially, at least) to allow sector-level R/W access to the SD card.  From there I can move on to look at more advanced features of this interface - it looks like it may allow higher-level access to the card at the filename/directory level.

Anyway, I've added the SD interface files to the GPU project and made a very early start on adding the interface to the GPU_DECA_DDR3_top file (i.e. it's not connected yet).  I've attached the updated GPU_DECA_DDR3_top and SD interface files below for info.  Would it be easier to connect the Z80_Bridge via Wishbone or surgically remove it from the SD interface and replace it with a specific set of connections/buses?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 17, 2022, 03:30:32 pm
Here's an interesting FPGA I just found on Mouser - https://www.mouser.co.uk/ProductDetail/Microchip-Technology/A3P250-FG256I (https://www.mouser.co.uk/ProductDetail/Microchip-Technology/A3P250-FG256I).

Seems to use flash instead of SRAM to hold the FPGA's gate setup, so it's instant-on and doesn't require an external EEPROM to hold the FPGA's design.  Not sure how it compares with the likes of Altera and Xilinx, but it seems to be lacking in the block RAM department.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: woofy on March 17, 2022, 04:00:39 pm
Hopefully a working link
https://www.mouser.co.uk/ProductDetail/Microchip-Technology/A3P250-FG256I?qs=sGAEpiMZZMsopV7UX9wSFD7ZLTigxKjg (https://www.mouser.co.uk/ProductDetail/Microchip-Technology/A3P250-FG256I?qs=sGAEpiMZZMsopV7UX9wSFD7ZLTigxKjg)

Just had a quick look.
Only 1 PLL, 36k bits RAM, 6144 tiles which can EITHER be LUT or D-flipflop, and the LUT is only 3 input anyway.
Unless I missed something - for GBP23, not overly impressive.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 17, 2022, 04:31:14 pm
Just had a quick look.
Only 1 PLL, 36k bits RAM, 6144 tiles which can EITHER be LUT or D-flipflop, and the LUT is only 3 input anyway.
Unless I missed something - for GBP23, not overly impressive.

Ah, that's where having an experienced eye look at the datasheet is handy. ;)  I was hunting for something else and noticed the A3P250 - was mildly impressed with the use of flash rather than SRAM (at least I assume that's what it is) to hold the configuration in the FPGA, but I'm easily impressed it seems. ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 18, 2022, 08:40:39 am
Think I found an error in the GPU_DECA_DDR3_top pin assignments - which would have originated from the original file we got the assignments from. ???

In the MicroSD Card assignments section (lines 364-317 in GPU_DECA_DDR3_top.sv), line 368 specifically, looks like this:

Code: [Select]
inout    SD_D123_DIR
Unless anyone can tell me otherwise, it should be an output, not a bi-directional port, as it controls the direction of the SN74AVCA406L voltage-translation transceiver between the FPGA and the SD card socket, and that pin is just an input on the 406L.

I don't know if that would make any difference to anyone's attempts to use the SD socket on the DECA, but I thought it was worth mentioning. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 18, 2022, 09:30:13 am
|O  I've finally had some time to work on this again, and this is where I'm at.  I've got the SD socket connected up to this OpenCores SD host controller IP (https://opencores.org/projects/sdcard_mass_storage_controller) that I'm hoping to use.

As yet I haven't touched the Wishbone interface, I'll worry about that when I can the GPU project to compile with the SD host controller module in it, which - at the moment - it is not.  There's been a succession of errors which I've corrected on the way through, but I've reached one that has stumped me.

Compilation halts with this error:

Error (10818): Can't infer register for "new_bw" at sd_bd.v(132) because it does not hold its value outside the clock edge
Error (10822): HDL error at sd_bd.v(132): couldn't implement registers for assignments on this clock edge
Error (12152): Can't elaborate user hierarchy "sd_controller_top:SID|sd_bd:rx_bd"


Offending code segment:

Code: [Select]
// Main side read/write 
always @(posedge clk or posedge rst ) begin

  new_bw <= 0 ;
 
  if ( rst ) begin

    m_wr_pnt  <= 0 ;
    write_cnt <= 0 ;
    new_bw    <= 0 ;
    read_cnt  <= 0 ;
   
  end
  else if ( we_m ) begin

    if ( free_bd > 0 ) begin

      write_cnt <= write_cnt + 1 ;
      m_wr_pnt  <= m_wr_pnt  + 1 ;

      if (!write_cnt[1]) begin // First write indicate source buffer addr (2x16)

        bd_mem[m_wr_pnt] <= dat_in_m     ;             

      end
      else begin               // Second write indicate SD card block addr (2x16)

        bd_mem[m_wr_pnt] <= dat_in_m     ;
        new_bw           <= write_cnt[0] ;      //Second 16 bytes writen, complete BD

      end

    end

  end
   
end

I've done some research elsewhere online and all of the related problems people have had (I may have missed an exception somewhere) related to VHDL implementations, which isn't helping me much, but I think the issue is to do with the always block triggering on clk or rst, but the if (we_m) is causing issues as it isn't triggered by a clock edge, but that shouldn't matter as we're just testing its value on a trigger edge, like we do loads of times in other modules....? :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 18, 2022, 02:58:14 pm
In the line 'always @(posedge clk or posedge rst ) begin', try removing the 'or posedge rst'.  Quartus hates that when you try multiple assignments to a logic.

Also, in addition, maybe disable line 4 if the top line doesn't work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 18, 2022, 08:21:35 pm
In the line 'always @(posedge clk or posedge rst ) begin', try removing the 'or posedge rst'.  Quartus hates that when you try multiple assignments to a logic.

Also, in addition, maybe disable line 4 if the top line doesn't work.

Thanks BrianHG, that fixes that issue.  Even fixing some more errors after this last one, it seems I'm not out of the woods yet. |O

Now getting these errors that I'm not sure how to fix:

Error (10170): Verilog HDL syntax error at sd_data_master.v(118) near text: ")";  expecting an operand. Check for and fix any syntax errors that appear immediately before or at the specified keyword. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.
Error (10170): Verilog HDL syntax error at sd_data_master.v(121) near text: "else";  expecting "end". Check for and fix any syntax errors that appear immediately before or at the specified keyword. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.
Error (10170): Verilog HDL syntax error at sd_data_master.v(121) near text: ")";  expecting an operand. Check for and fix any syntax errors that appear immediately before or at the specified keyword. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.
Error (10170): Verilog HDL syntax error at sd_data_master.v(124) near text: "else";  expecting "end". Check for and fix any syntax errors that appear immediately before or at the specified keyword. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.
Error (10170): Verilog HDL syntax error at sd_data_master.v(325) near text: ")";  expecting an operand. Check for and fix any syntax errors that appear immediately before or at the specified keyword. The Intel FPGA Knowledge Database contains many articles with specific details on how to resolve this error. Visit the Knowledge Database at https://www.altera.com/support/support-resources/knowledge-base/search.html (https://www.altera.com/support/support-resources/knowledge-base/search.html) and search for this specific error message number.
Error (10112): Ignored design unit "sd_data_master" at sd_data_master.v(3) due to previous errors
Error: Quartus Prime Analysis & Synthesis was unsuccessful. 6 errors, 6 warnings
   Error: Peak virtual memory: 4745 megabytes
   Error: Processing ended: Fri Mar 18 20:15:16 2022
   Error: Elapsed time: 00:00:05
   Error: Total CPU time (on all processors): 00:00:12
Error (293001): Quartus Prime Full Compilation was unsuccessful. 8 errors, 6 warnings

I can't see a typo in the lines referred to, but the sensitivity list for the always block the code is within is pretty long:

Code: [Select]
always @ (state or resend_try_cnt or tx_full or free_tx_bd or free_rx_bd or bd_cnt or send_done or rec_done or rec_failed or trans_done or trans_failed)
begin : FSM_COMBO
 next_state  = 0;   
case(state) 
 
  IDLE: begin
   if (free_tx_bd !=`BD_EMPTY)begin   <--- LINE 118
      next_state = GET_TX_BD;
   end
   else if (free_rx_bd !=`BD_EMPTY) begin  <-- LINE 121
      next_state = GET_RX_BD;
   end 
   else begin                        <--- LINE 124
      next_state = IDLE;
   end
  end

There I was thinking I'd be spending most of my time picking the Wishbone interface apart, instead I can't even get the darn project to compile. ::)  At this rate, I think I'll be switching to the far simpler SPI version of the SD card interface and just make do with the 'poor' transfer rates - they'll be more authentic, I suppose. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 22, 2022, 09:12:30 am
I've found an updated repo using the same SD controller code but heavily modified so that it actually compiles, which is a start and means I can focus on wiring it all up.

Have a question, though.  The SD interface needs access to the DDR3 RAM as I'd like to be able to use a buffer in DDR3 RAM to read from/write to, that the host can access as well.   Can I just increase PORT_TOTAL to 6 and wire the SD DMA to the new port, or are there any concerns/considerations if I up the total ports accessing the DDR3_controller to 6?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 22, 2022, 09:41:53 am
I've found an updated repo using the same SD controller code but heavily modified so that it actually compiles, which is a start and means I can focus on wiring it all up.

Have a question, though.  The SD interface needs access to the DDR3 RAM as I'd like to be able to use a buffer in DDR3 RAM to read from/write to, that the host can access as well.   Can I just increase PORT_TOTAL to 6 and wire the SD DMA to the new port, or are there any concerns/considerations if I up the total ports accessing the DDR3_controller to 6?
No problem, direct connection to the DDR3 with an additional port #/total is allowed.
No fifo buffer needed, the SD card is too slow anyways, so long as you can pause the SD card reader's reads and writes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 22, 2022, 10:13:14 am
I've found an updated repo using the same SD controller code but heavily modified so that it actually compiles, which is a start and means I can focus on wiring it all up.

Have a question, though.  The SD interface needs access to the DDR3 RAM as I'd like to be able to use a buffer in DDR3 RAM to read from/write to, that the host can access as well.   Can I just increase PORT_TOTAL to 6 and wire the SD DMA to the new port, or are there any concerns/considerations if I up the total ports accessing the DDR3_controller to 6?
No problem, direct connection to the DDR3 with an additional port #/total is allowed.
No fifo buffer needed, the SD card is too slow anyways, so long as you can pause the SD card reader's reads and writes.

Ah great. :-+  I'm working on an interface that will sit between the SD's Wishbone interface and the DDR3 controller at the moment.  At first glance it appears all that's needed is some wires to connect different signals together, but I'm sure it won't be that simple once I drill down into it.

I'm not confident in my ability or knowledge enough to strip out the Wishbone interface from the SD project I'm using, so I thought it might be simpler to just work with it instead.  We'll see. :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 22, 2022, 02:53:14 pm
I've just finished the DDR3_Controller to Wishbone interface - I don't suppose you'd mind casting your eye over it when you can to point out any obvious mistakes I've made? :)

I put this together based on the READ/WRITE cycle diagrams on pages 47-50 of the Wishbone B3 specification document here (https://cdn.opencores.org/downloads/wbspec_b3.pdf).  Note that the interface isn't intended to support block read/writes, as it seems the Wishbone bus coming out of the SD interface doesn't require them (there's no LOCK_O signal in that interface).

The interface is clocked by CMD_CLK, which is also used to clock the SD interface / Wishbone bus.  I've still got to have to have a closer look at the sel_i signals - I don't suppose it's likely that they work the same way or mean the same thing as CMD_write_mask.

Zip attached has the new interface module and the current GPU_DECA_DDR3_top module, so you can see how the DDR3_wb_interface module is connected up.

EDIT:  Just fixed a typo on line 92 - STB_O instead of STB_I, and removed line 62 which zeroed DAT_O, which wasn't required.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 23, 2022, 03:41:14 pm
Ok, I'll take a look tonight.
Remember, you can always signal-tap your new port 6 with the wishbone interface.
I do no know anything about wishbone, so I hep it wont be too difficult.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 23, 2022, 04:08:07 pm
I don't think Wishbone is all that complicated, to be honest - I was able to work out how to interface it without help, so it must be pretty simple. ;)  I've yet to test it, though - and yes, I'll be making significant use of SignalTap.

I've spent my free time today designing and writing the Wishbone Master interface in the Z80_bridge module.  Haven't had a lot of time, but I'm just testing the I/O system I'm intending to use to get commands and values to the SD interface - will probably have it finished tomorrow, then I can start testing the whole setup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 23, 2022, 04:28:18 pm
Hmm.. bit stumped by this one:

Code: [Select]
reg [31:0] SD_ARGUMENT = 32'b0 ; // Value to RD/WR SD interface's 32-bit ARGUMENT register
reg [1:0]  ARG_PTR     = 2'b0  ; // 2-bit pointer to current byte in 32-bit SD_ARGUMENT
...
assign  READ_PORT_DATA[SD_ARGS]    = SD_ARGUMENT[((ARG_PTR+1)*8)-1:ARG_PTR*8] ;

So, the above code is a line from the Z80_Bridge module. SD_ARGS is an I/O port parameter (integer 245 to be exact).  SD_ARGUMENT is a register that holds a 32-bit value.  I want to return an 8-bit segment of that 32-bit value, depending on the value of ARG_PTR (which itself is a 2-bit register).  Depending on ARG_PTR's value, reading the SD_ARGS I/O port should return either the top MSB, top LSB, bottom MSB or bottom LSB of SD_ARGUMENT.

Compiling the above code results in this error:

Error (10734): Verilog HDL error at Z80_Bus_Interface.sv(213): ARG_PTR is not a constant

I suspect this is because I'm trying to assign a variable value to a wire and I'll probably need some more steps to switch between the four bytes in SD_ARGUMENT before assigning them to READ_PORT_DATA[SD_ARGS]??

EDIT:

Also, what am I doing wrong here?  This is a simple I/O port that can be read/written to, that modifies (or reads) the 2-bit ARG_PTR register mentioned above.

Code: [Select]
assign  ARG_PTR[1:0]     = WRITE_PORT_DATA  [SD_ARG_PTR][1:0] ;
...
assign  READ_PORT_DATA[SD_ARG_PTR] = '{ 6'b0, ARG_PTR[1:0] }      ;

I'm reading a zero value from it, which I guess is right as it should start at zero, but I'm unable to write a new value to it (or read the new value back - just getting zero back).

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 24, 2022, 06:07:18 pm
Ok, I finally have time.
You will need to send me the project.  I tried to add your previous .zip source and obviously, things are missing.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 24, 2022, 07:21:45 pm
Ok, I finally have time.
You will need to send me the project.  I tried to add your previous .zip source and obviously, things are missing.

Yes, I was just asking for a brief glance at the module I'd written, hence I posted it and the Z80_Bridge in isolation, but things have moved on since then and I have a working (well, it compiles) interface between the Z80_Bridge and SD interface.

Z80_Bridge is modified to remove legacy PS2 ports and now has a developing Wishbone interface state machine at the bottom that I only got working and started looking at the SignalTap traces for this afternoon, so there's more work to be done with it to get it to a workable state communicating properly with the SD interface.

I seem to have broken the GPU MMU feature somehow, so I'll be looking into that.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on March 24, 2022, 07:31:09 pm
 :-+ Great to see that you are coding HDL...

As frustrating as bugs are, I'm sure you'll get it working...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 30, 2022, 08:29:45 am
Just a quick update - I have the Wishbone interface working fine at the moment.  I'm currently testing the SD card interface itself from the host and trying to get an SD card initialised in 1-bit mode.  Once that's done and I can get a block read to execute, I'll be testing the Wishbone interface to the DDR3. :-/O

Does anyone have any experience with SD 1-bit and 4-bit initialisation?  It seems there's literally tons of information on how to set up an SPI interface to the SD card, but very little at all about the faster methods.

EDIT: That said, I've moved away from existing examples and now I'm using the Part1_Physical_Layer_Simplified_Specification_Ver8.00 document, so it's just a matter of time before I decode the flow charts and get it running.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on March 30, 2022, 12:15:18 pm
Hi Jonathan,

Not to detract from the current focus.
 
Sometime in the near future I plan to work with my DECA board on an unrelated project and it would be nice to have the same Z80 bus to level shifters, to DECA FPGA connections as this GPU project. It would save a ton of "wire up" time if I want to give the GPU a try.

Is there an updated, current, schematic on your GIT that I could follow?

I know time is hard to come by so no hurry.

Great job to all on the GPU project BTW!

Best / Ted   
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on March 30, 2022, 01:33:58 pm
Just a quick update - I have the Wishbone interface working fine at the moment.  I'm currently testing the SD card interface itself from the host and trying to get an SD card initialised in 1-bit mode.  Once that's done and I can get a block read to execute, I'll be testing the Wishbone interface to the DDR3. :-/O

Does anyone have any experience with SD 1-bit and 4-bit initialisation?  It seems there's literally tons of information on how to set up an SPI interface to the SD card, but very little at all about the faster methods.

EDIT: That said, I've moved away from existing examples and now I'm using the Part1_Physical_Layer_Simplified_Specification_Ver8.00 document, so it's just a matter of time before I decode the flow charts and get it running.

Take a look here https://github.com/pecostm32/FNIRSI_1013D_Firmware/blob/main/fnirsi_1013d_startup_from_sd_card/bl_sd_card_interface.c (https://github.com/pecostm32/FNIRSI_1013D_Firmware/blob/main/fnirsi_1013d_startup_from_sd_card/bl_sd_card_interface.c)

It is C code for working with a SD card on the F1C100s.

I went through the same path to get SD cards working on the FNIRSI 1013D, so might save you some time. In the folder with the scope source there is also the FatFs code I used to get it working.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on March 30, 2022, 02:39:12 pm
Hi Jonathan,

Not to detract from the current focus.
 
Sometime in the near future I plan to work with my DECA board on an unrelated project and it would be nice to have the same Z80 bus to level shifters, to DECA FPGA connections as this GPU project. It would save a ton of "wire up" time if I want to give the GPU a try.

Is there an updated, current, schematic on your GIT that I could follow?

I know time is hard to come by so no hurry.

Great job to all on the GPU project BTW!

Best / Ted

Hi Ted,

Nothing on the github repo in relation to the DECA interface, unfortunately.  I designed my DECA-uCOM interface card on EasyEDA - if you use that (or want to try learning it, it's easier than KiCAD) then I can probably work out how to share that project with you, but in the meantime here's the schematic PDF - hope it helps.  If you have any questions, you know how to get hold of me. ;D

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: Ted/KC9LKE on March 31, 2022, 11:39:53 am

Schematic form is perfect

Thanks!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 07, 2022, 01:36:16 pm
SD interface progress update - I seem to have actually worked out how to initialise an SD card. :phew:  Special thanks to @pcprogrammer and his link to the FNIRSI_1013D firmware repo link. :-+

I get the feeling this should be a lot easier than it is, but I'm working in SD-mode instead of SPI and using an OpenCore project that adds an extra layer of variables between the software and the SD card.

I'm now expanding the HDL in Bridgette to allow reads from the Wishbone interface, so I can allow the host Z80 to get data directly from the interface and SD card registers.  Up until now I've been using SignalTap to see what's going on with the SD interface's registers. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 07, 2022, 05:21:40 pm
@BrianHG - have made some progress on reading SD interface registers via the Wishbone interface today, but am having to read the IO ports twice because the SD interface isn't responding with the register value in time for the Z80 before it reads the IO port value.

How do I need to go about adding WAIT states to IO port reads? (current Bridgette attached).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 07, 2022, 05:26:20 pm
I'll look at it tonight...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 07, 2022, 09:15:13 pm
I'll look at it tonight...

Thank you.  Here's a SignalTap trace showing some of the timings.  The 32-bit register, wb_DATA_IN, is where the requested register value is loaded into on a successful read over the Wishbone interface.  This can then be read by the host via two I/O ports, one to read the data a byte at a time and the other as a pointer to the byte in the wb_DATA_IN word.

A read is performed by setting the address of the desired register using I/O port 242, then reading I/O port 240 to get the byte pointed to by port 249.  The SD interface and Wishbone bus are fast enough that the register value is retrieved and wb_DATA_IN should be set within the Z80's I/O cycle, ready for it to be read, but there's a full Z80 clock cycle delay between the I/O cycle starting (z80_op_read_port going HIGH in the trace) and the Wishbone read request (wb_RQ_READ) going HIGH.  Maybe there's room to speed this up and not have to insert any WAIT states?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1457776)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 04:35:49 am
Ok, our problem here is the current Z80 code delivers you a read port pulse, simultaneously latching the read data on that exact pulse where it is obvious the data isn't yet ready.

What you want is not a delay due to interrupt, but a delivery of the read port port address when the command is received, which is actually already available on the first Z80 clock, and have the return data sampled before it is actually needed to be send to the z80 on clock position number 3.  The wishbone interface appears to be way faster than the Z80, so this actually isn't a problem.  We just need to capture the read data later at the right time.  See your code on lines 486,487, and 494 which does the same as line 486.

However, we want to fix this properly and include the potential for a super fast Z80 in case we ever go to a Z80 FPGA core which can operate in the 100MHz region.

Step #1, take the above Z80 code and stuff it into my Z80 bridge interface Modelsim simulator and let's perform the Z80 code port read/write and see the waveform.  Provide the new Z80 bridge simulator here so we can modify the code to make the bridge provide with a read in advance and then wait before line 487/488 are driven.

Helping you here will ensure in the future you know how to either use the Z80 bridge properly, or how to properly modify it to your liking.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 07:16:05 am
The latest testbench version for the Z80 interface I have is v15.  It might take me some work to upgrade it to the current v16 GPU setup, but I'll see what I can do. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 07:19:56 am
The latest testbench version for the Z80 interface I have is v15.  It might take me some work to upgrade it to the current v16 GPU setup, but I'll see what I can do. :-/O
Funny, the Z80 bridge testbench has nothing but the Z80 bridge in it plus the _tb file.
You do not need the DDR3 or SD card HDL.  Just the Z80 bridge so you may do development work on the code for the ports.
How can that possibly take so long?
There is no GPU.
There is no DDR3.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 07:46:53 am
The latest testbench version for the Z80 interface I have is v15.  It might take me some work to upgrade it to the current v16 GPU setup, but I'll see what I can do. :-/O
Funny, the Z80 bridge testbench has nothing but the Z80 bridge in it plus the _tb file.
You do not need the DDR3 or SD card HDL.  Just the Z80 bridge so you may do development work on the code for the ports.
How can that possibly take so long?
There is no GPU.
There is no DDR3.

I guess because I'm not familiar with the _tb version of the Z80 bridge.  When I wrote that last message, I'd just run the new Z80_bridge and v15 Z80_bridge_tb through a file comparison and saw the number of changes needed to be made. :scared:  Maybe it won't take so long, but I've got to add in the Wishbone ports and I'm not that confident messing with ModelSim yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 08:16:51 am
Just copy over the Z80 bridge.v file.
All you wan it the bare bone Z80 bridge I made for you.
No wishbone.
No ddr3 version.
No gpu version.

You can simulate the wishbone response.
And just add the nets to the waveform.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 08:39:36 am
Just copy over the Z80 bridge.v file.
All you wan it the bare bone Z80 bridge I made for you.
No wishbone.
No ddr3 version.
No gpu version.

You can simulate the wishbone response.
And just add the nets to the waveform.

Ah, okay, that makes life easier.  I was thinking I'd have to tweak the Z80_Bus_Interface_tb.sv file to include all the changes in the Z80_Bus_Interface.sv file. :o

Running 'do setup_z80.do' throws errors in the always_comb section of the new Bridgette, like this one:

# ** Error: Z80_Bus_Interface.sv(251): (vlog-2110) Illegal reference to net "READ_PORT_DATA".

Uncommenting line 286 in Z80_Bus_Interface_tb.sv doesn't stop the errors. :-//

EDIT: Have also modified READ_PORT_END and upped it from 249 to 251 to account for the additional IO ports in use.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 08:54:24 am
 :palm: I said not to use the enhanced overblown DDR3 test version.
All you want is the version with 6 files for the entire z80 tb.

there should be 2 .do files,
a z80_xxx.sv and z80_xxx_tb.sv files
and an ascii .txt script file to send simulated Z80 buss commands.

All we want to do is play with the read port function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 08:58:36 am
Ok, lets work with what you provided.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 09:04:19 am
:palm: I said not to use the enhanced overblown DDR3 test version.
All you want is the version with 6 files for the entire z80 tb.

there should be 2 .do files,
a z80_xxx.sv and z80_xxx_tb.sv files
and an ascii .txt script file to send simulated Z80 buss commands.

All we want to do is play with the read port function.

Oops, sorry.  I guess that'll be 'Z80_Interface_TB' in the test folder then.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 09:07:48 am
Ok, you need to change lines 188 through 215 to this:
Code: [Select]
// ***************************************************************************************************

// until the legacy ports are removed, this needs to be a wire outside the IO ports.
logic    [7:0] READ_PORT_DATA    [0:255] ; // The array [port_number] will be sent to the Z80 during a port read so long as the read port

// TODO:
// 1) Wishbone Master SD interface
// 2) Interrupt handling for keyboard data
//
// *******************************************************************************************************
//
// ********************** Settings and IO ports for features *********************************************
//
// *******************************************************************************************************
//
//reg        PS2_prev   = 1'b0        ;
//reg [12:0] port_dly    = 13'b0 ; // Port delay pipeline delays data output on an IO port read
reg [7:0]  GPU_MMU_LO  = 8'b0   ; // Lower 8-bits of the upper 12-bits of the DDR3 address bus
reg [7:0]  GPU_MMU_HI  = 8'b0   ; // Upper 4-bits of the upper 12-bits of the DDR3 address bus
wire  [7:0]  SD_ADDRESS  = 8'b0   ; // SD register being addressed
wire  [31:0] SD_COMMAND  = 32'b0  ; // Value to RD/WR SD interface's 32-bit COMMAND register
reg [31:0] SD_ARGUMENT = 32'b0  ; // Value to RD/WR SD interface's 32-bit ARGUMENT register
reg [7:0]  ARG_PTR     = 8'b0   ; // 2-bit pointer to current byte in 32-bit SD_ARGUMENT
reg [2:0]  wb_STATE    = 3'b000 ; // Wishbone transceiver state machine register
reg        wb_RQ_SEND  = 1'b0   ; // Wishbone write request flag
reg        wb_RQ_READ  = 1'b0   ; // Wishbone read request flag
reg        wb_DAT_RDY  = 1'b0   ; // Data ready flag
reg [31:0] wb_DATA_IN  = 32'b0  ; // Data latch for incoming Wishbone data

Line 191 was most important as it must be logic, not a simple wire if you are using it inside an 'always_comb'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 09:26:24 am
Okay, it's still not running (throwing an error loading design and pausing on line 10 of setup_z80.do), but there's only suppressible errors in the log, all relating to legacy IO ports that are no longer in the latest Bridgette (PS2 and sound ports):

# ** Error (suppressible): (vsim-3584) Z80_Bus_Interface_tb.sv(222): Module parameter 'IO_DATA' not found for override.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb File: Z80_Bus_Interface_tb.sv
# ** Error (suppressible): (vsim-3584) Z80_Bus_Interface_tb.sv(222): Module parameter 'IO_STAT' not found for override.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb File: Z80_Bus_Interface_tb.sv
# ** Error (suppressible): (vsim-3584) Z80_Bus_Interface_tb.sv(222): Module parameter 'SND_DUR' not found for override.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb File: Z80_Bus_Interface_tb.sv
# ** Error (suppressible): (vsim-3584) Z80_Bus_Interface_tb.sv(222): Module parameter 'SND_OUT' not found for override.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb File: Z80_Bus_Interface_tb.sv
# ** Error (suppressible): (vsim-3584) Z80_Bus_Interface_tb.sv(222): Module parameter 'SND_TON' not found for override.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb File: Z80_Bus_Interface_tb.sv
# Error loading design

I've updated the _tb file include the updated IO port addresses and names and removed the legacy ports listed above.  ModelSim is now complaining about missing connections for ports:

# Loading work.Z80_Bus_Interface
# ** Warning: (vsim-2685) [TFMPC] - Too few port connections for 'Z80_BRIDGE'.  Expected 48, found 41.
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb/Z80_BRIDGE File: Z80_Bus_Interface_tb.sv Line: 225
# ** Error: (vsim-3063) Port 'READ_PORT_DATA' not found in the connected module (30th connection).
#    Time: 0 ps  Iteration: 0  Instance: /Z80_Bus_Interface_tb/Z80_BRIDGE File: Z80_Bus_Interface_tb.sv Line: 225
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_adr_o'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_dat_o'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_dat_i'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_sel_o'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_we_o'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_cyc_o'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_stb_o'.
# ** Warning: (vsim-3722) Z80_Bus_Interface_tb.sv(225): [TFMPC] - Missing connection for port 'm_wb_ack_i'.
# Error loading design

I'll start adding these ports if that's the right way to go...?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 09:29:26 am
Line 191 was most important as it must be logic, not a simple wire if you are using it inside an 'always_comb'.

Ah okay, I've updated Bridgette accordingly.  I guess Quartus was correcting this mistake itself during compilation as it's never thrown an error regarding this line, but ModelSim isn't so happy about it?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 09:29:59 am
None of this would have been an issue if you placed the SD card stuff externally to the Z80 bridge, as it's own module in the GPU top hierarchy.

This way, we could have concentrated on the one tiny issue with the read-port function.

Line 191 was most important as it must be logic, not a simple wire if you are using it inside an 'always_comb'.

Ah okay, I've updated Bridgette accordingly.  I guess Quartus was correcting this mistake itself during compilation as it's never thrown an error regarding this line, but ModelSim isn't so happy about it?
Quartus was a little more forgiving with it's implementation of SystemVerilog.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 09:33:11 am
Remember, we just wanted to fix the Z80 bridge.
Now, because you placed the SD card stuff in there, we will have a nightmare of a time getting this to simulate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 09:50:50 am
Remember, we just wanted to fix the Z80 bridge.
Now, because you placed the SD card stuff in there, we will have a nightmare of a time getting this to simulate.

It seemed like the logical thing to do at the time. :-\  What's going to be easier?  Trying to get it to simulate as-is, or I go back and remove the Wishbone stuff from Bridgette?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 09:57:43 am
All the signals your WB uses are located in the 4 port arrays:

Code: [Select]
   output logic [255:0] WRITE_PORT_STROBE          = 0 , // The bit   [port_number] in this 256 bit bus will pulse when the Z80 writes to that port number.
   output logic   [7:0] WRITE_PORT_DATA   [0:255]      , // The array [port_number] will hold the last written data to that port number.
   output logic [255:0] READ_PORT_STROBE           = 0 , // The bit   [port_number] in this 256 bit bus will pulse when the Z80 reads from that port number.

// Until the legacy ports are moved out, this port needs to be a wire inside this module exclusively.
//   input  wire    [7:0] READ_PORT_DATA    [0:255]      , // The array [port_number] will be sent to the Z80 during a port read so long as the read port
                                                         // number is within parameter READ_PORT_BEGIN and READ_PORT_END.

However, I guess for now you can add dummy signals for the WB IO ports.
In the _tb.sv files, just add the ports and tie the inputs to '0'.
This should be enough to get the sim to run.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 10:24:49 am
Okay, that runs.  I've just created the extra WB ports and put a wire name in them, not connected to anything else.  Hopefully that's the right thing to do...?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1458103)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 10:40:38 am
ok, edit the 'Z80_cmd_stimulus.txt' and make it only read the 1 port replicating the bug.
And I'll be able to help fix the issue later tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 11:52:04 am
Latest testbench folder included.  Have updated the stimulus list to just write an address to SD_ADDR and then read from SD_DATA.  Here's the output:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1458142)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 06:37:19 pm
1 note when making the modelsim .zip files: you do not need the sub-folders...

Ok, take update the new setup file and the waveforms I listed.

Here is a snapshot:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1458460)

You will see I am now showing the read and write ports with their strobes which should be driving your wishbone interface.

The problem with the read strobe is that is appears at the same time we expect the read data to be valid.
This is no good if you wish to process something first before returning a read.

An example fix, this can still work if you execute your WB command when you do the write port setting the function so the results are ready by the time you perform the read.  This might solve your current problem.

However, working with your current control scheme, we can change the read port function a little.  Take a look at the position of the yellow cursor.  It is at that point we know that a read command has been sent and what the address is.  If we were to modify the Z80 bridge to send the strobe at that point and wait for an acknowledge before latching the result, maybe this might be a route to take.

What do you think?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 09:57:58 pm
The problem with the read strobe is that is appears at the same time we expect the read data to be valid.
This is no good if you wish to process something first before returning a read.

An example fix, this can still work if you execute your WB command when you do the write port setting the function so the results are ready by the time you perform the read.  This might solve your current problem.

Interesting idea.  The only issue (if I understand your suggestion correctly) is that the bridge doesn't know if it's going to be a read or a write op when the address is written (the host writes to the SD interface's registers as well as reading them). I'm assuming you mean fire off a WB read request when the address is first written, instead of waiting for the IO read to send the read request via WB?

However, working with your current control scheme, we can change the read port function a little.  Take a look at the position of the yellow cursor.  It is at that point we know that a read command has been sent and what the address is.  If we were to modify the Z80 bridge to send the strobe at that point and wait for an acknowledge before latching the result, maybe this might be a route to take.

What do you think?

I think this should work. :-+  My only concern is that of completeness.  It will work for slightly delayed IO reads, but what about if/when a slower IO device is used?  Will the bridge be able to insert WAITs as required whilst it waits for the device's read ack?  That feature isn't needed for this particular case, though, I'm just thinking out loud. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 10:07:55 pm
Ok, step 1: Change the  parameter READ_PORT_CLK_POS to:

Code: [Select]
// Z80 bus timing settings.
   parameter bit [3:0]  READ_PORT_CLK_sPOS    = 0,     // Number of Z80_CLK cycles before the bus interface before the read strobe pulse outputs.
   parameter bit [3:0]  READ_PORT_CLK_aPOS    = 2,     // Number of Z80_CLK cycles before the bus interface read port data is returned.

Next break the read port into 2 parts:
Code: [Select]
            // ************************************************************
            // *** Read port
            // *** This will trigger once on the transition of Z80_CLK
            // *** position READ_PORT_CLK_sPOS.
            // ************************************************************
            end else if (z80_op_read_port && (Z80_CK_POS==READ_PORT_CLK_sPOS ) && zclk ) begin
       
                if (port_in_range) begin    // Only respond to a port read request if the read port is in range.

                    READ_PORT_STROBE[Z80_addr_r[7:0]] <= 1        ; // Generate the access strobe signal on the requested port number.

                end
       
            // ************************************************************
            // *** Read port
            // *** This will trigger once on the transition of Z80_CLK
            // *** position READ_PORT_CLK_aPOS, the acknowledge position for the read port.
            // ************************************************************
            end else if (z80_op_read_port && (Z80_CK_POS==READ_PORT_CLK_aPOS ) && zclk ) begin
       
                if (port_in_range) begin    // Only respond to a port read request if the read port is in range.

                    READ_PORT_ACK[Z80_addr_r[7:0]] <= 1        ; // Generate the acknowledge for debugging purposes.
                    Z80_fpga_data_out                 <= READ_PORT_DATA[Z80_addr_r[7:0]]; // send data to read port.
                    Z80_fpga_data_oe                  <= 1'b1     ; // set the FPGA Z80_data bidirectional IO port to output.
                    Z80_245data_dir                   <= data_out ; // Set the 245 to send data from the Z80 to the FPGA.
                    Z80_245_oe                        <= 1'b0     ; // Enable 245 OE.

                end

And further down, don't forget the:
Code: [Select]
                READ_PORT_ACK     <= 0 ; // Make sure that the generated strobes are only active for 1 clock.

Now, please get rid of that silly ' wb_RQ_READ <= 1'b1 ; // initiate a Wishbone RD' and properly assign it to the correct read strobe address.

Add the new ACK reg to the setup_Z80.do script file so you can see whats going on and upload the update.

What these additions wont do is supply a 'wait' state to the z80, but, you should see what is going on in the new waveform with the separate strobe and ack.

Once sim-ed, then tested on hardware, we will look at the signal-tap, then add the 'wait' capability.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 11:11:52 pm
Made those changes, plus a couple more to get the simulation to run.  Had to edit setup_z80.do to add the sPOS and aPOS values as READ_PORT_CLK_POS was no longer in use.  Had to tweak Z80_Bus_Interface_tb.sv to update the CLK_POS parameter to sPOS and aPOS.  Made the alterations to Z80_Bus_Interface.sv as suggested in your post.

Here's the new simulation result:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1458640)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 08, 2022, 11:30:02 pm
Good.  I'm deliberately leaving out the little things.

Now, your WB will see the first READ_PORT_STROBE[ x ].
As long as the matching READ_PORT_DATA[ x ] has the correct value before the READ_PORT_ACK[ x ] pulses, the Z80 will see the correct data.

Ok, proceed to the GPU hardware and test / signal-tap.

If everything is ok, then we will generate an optional 'wait' for the Z80 which will hold until you feed an acknowledge input.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 08, 2022, 11:32:01 pm
Have just done a quick hardware test and it seems to be working perfectly based on my tests on the host.  I can read the SD interface registers and have access to the full 32-bit register. :-+

I don't have time to set up SignalTap tonight (it's late here and I need sleep), but will get on it tomorrow when I have time.

Thanks! ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 09, 2022, 08:26:55 am
Okay, SignalTap of a read to port 240 (reading SD interface register for the SD clock divider):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1458904)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 16, 2022, 04:36:09 am
Ok, it's been a week.  Anything new to see?  Any new bugs found?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 16, 2022, 07:22:37 am
Ok, it's been a week.  Anything new to see?  Any new bugs found?

Nothing to report really.  Progress is slow due to time constraints (as always).  I've broken down the example C code in the interface project and translated that to Z80 assembly to successfully initialise the card down to obtaining CID, CSD data and RCA address from the SDHC card I'm using.  I'm currently working on reading a block of data from the SD card, but I'm not getting back the correct data expected from the SD card (and further down the chain it's not getting written to DDR3, correct or not).  This is likely to do with the poorly-documented SD interface HDL and something I'm doing wrong with its software setup as data is being read from the card, but is turning into a stream of zeros from the RX buffer or some other point in the interface, so I'm currently using SignalTap to probe and see what's going on. :-BROKE
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 17, 2022, 11:21:07 am
Further to the above writing issues, I'm definitely getting no writes to GPU memory, as verified by my CP/M test program and the rs232_debugger.

I've extensively tested the SD interface with SignalTap and found data being read from the SD card and passed through to the DDR3/Wishbone interface module.  From there, it attempts to write the data to DDR3 - but nothing is actually getting written.

Below are two SignalTaps - the first is a working write from the Z80_Bridge, simply writing 0xAA to DDR3 memory at location 0x5001:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1464787)

This second image shows the first two of 128 consecutive 32-bit writes to DDR3 memory from the DDR3/Wishbone interface, starting at address 0x5000:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1464793)

I had written an AA55AA55 pattern to the first 16 bytes of GPU RAM from 0x5000 to 0x5010, so even with zeros being read from the SD card, that pattern should have been overwritten, but nothing is happening.  Is there an issue with the CMD_write_mask or something else going on?

I'm using port 5 for the SD/Wishbone interface to the DDR3 controller.  I've attached relevant modules in case they're of any use, but I suspect I've made a silly mistake somewhere. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 17, 2022, 06:24:21 pm
How the mask works:
The write mask (each bit being equal to 8 bits of the data bus) needs to be high for a write to actually take place, for example: (32 bit data interface)

MASK = 4'bxxxx  DATA = 32'h11223344

So, the red mask bit X will enable a write on  the red data 11.
The mask green bit X will enable a write on the green data 22.
The mask blue bit X will enable a write on the blue data 33.
The mask purple bit X will enable a write on the purple data 44.

If there are no '1' in the mask during a write, nothing will make it to the DDR3.
You appear to be using it correctly as your mask is set to 4'hF, or, 4'b1111.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 17, 2022, 06:41:03 pm
Your data bus width parameter is in error.  See what I made red...

Quote
parameter bit [8:0]  PORT_R_DATA_WIDTH [0:15] = '{  8,  8, 16, 16,128,128,128,128,128,128,128,128,128,128,128,128},
parameter bit [8:0]  PORT_W_DATA_WIDTH [0:15] = '{  8,  8, 16, 16,128,128,128,128,128,128,128,128,128,128,128,128},
                                                // Use 8,16,32,64,128, or 256 bits, maximum = 'PORT_CACHE_BITS'
                                                // As a precaution, this will prune/ignore unused data bits and write masks bits, however,
                                                // all the data ports will still be 'PORT_CACHE_BITS' bits and the write masks will be 'PORT_CACHE_WMASK' bits.
                                                // (a 'PORT_CACHE_BITS' bit wide data bus has 32 individual mask-able bytes (8 bit words))
                                                // For ports sizes below 'PORT_CACHE_BITS', the data is stored and received in Big Endian. 

However, with the 128 settings, only the first 4 bytes at address $5000 should have been filled with $00, while all the other bytes should have your original Z80 data.  Once you fix the 2 data bus width parameters, then all 16 bytes should change.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 17, 2022, 06:58:46 pm
ALSO:  You need to assign 0's to the unused input ports on my DDR3 controller...

You did not assign these 2:
CMD_priority_boost[5], CMD_read_vector_in[5]
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 17, 2022, 08:59:48 pm
How the mask works:
The write mask (each bit being equal to 8 bits of the data bus) needs to be high for a write to actually take place, for example: (32 bit data interface)

MASK = 4'bxxxx  DATA = 32'h11223344

So, the red mask bit X will enable a write on  the red data 11.
The mask green bit X will enable a write on the green data 22.
The mask blue bit X will enable a write on the blue data 33.
The mask purple bit X will enable a write on the purple data 44.

If there are no '1' in the mask during a write, nothing will make it to the DDR3.
You appear to be using it correctly as your mask is set to 4'hF, or, 4'b1111.

Yes, that's my understanding of how it works - it's identical to the sel line in the Wishbone interface, which is handy.  It's not that, then! :-+

Your data bus width parameter is in error.  See what I made red...

Quote
parameter bit [8:0]  PORT_R_DATA_WIDTH [0:15] = '{  8,  8, 16, 16,128,128,128,128,128,128,128,128,128,128,128,128},
parameter bit [8:0]  PORT_W_DATA_WIDTH [0:15] = '{  8,  8, 16, 16,128,128,128,128,128,128,128,128,128,128,128,128},
                                                // Use 8,16,32,64,128, or 256 bits, maximum = 'PORT_CACHE_BITS'
                                                // As a precaution, this will prune/ignore unused data bits and write masks bits, however,
                                                // all the data ports will still be 'PORT_CACHE_BITS' bits and the write masks will be 'PORT_CACHE_WMASK' bits.
                                                // (a 'PORT_CACHE_BITS' bit wide data bus has 32 individual mask-able bytes (8 bit words))
                                                // For ports sizes below 'PORT_CACHE_BITS', the data is stored and received in Big Endian. 

However, with the 128 settings, only the first 4 bytes at address $5000 should have been filled with $00, while all the other bytes should have your original Z80 data.  Once you fix the 2 data bus width parameters, then all 16 bytes should change.

Ah okay, so these red values should be 32 instead of 128 - the SD interface accesses the DDR3 controller via a 32-bit data bus - but as you've already identified, the first four bytes would still have been written okay thanks to the correct mask being used.

ALSO:  You need to assign 0's to the unused input ports on my DDR3 controller...

You did not assign these 2:
CMD_priority_boost[5], CMD_read_vector_in[5]

That seems to have fixed the memory writing issue - I knew it'd be something I'd missed somewhere ::) - thanks. :-+

It's writing data to GPU RAM now - on to the next issue; it's not writing what I expect it to write (I have a raw dump of the first 4 sectors on the SD card to compare against) - likely a problem with the SD interface setup! Onwards and upwards! ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 18, 2022, 02:47:10 pm
I've got another (small - hopefully) issue I've run into, which I think is being caused by the DDR3 memory caching... possibly.

To start testing SD block reads, I write 512 bytes (all 0xAA) to the SD RD/WR buffer in GPU RAM.  That way I can see if the data has been changed, as the SD seems to be reading a lot of 0x00s at the moment (with some other sporadic byte values, but that's not the issue).

I read the SD card's SCR register, which is 8 bytes of data relating to that SD card.  The result is written to the start of the SD buffer in GPU RAM directly via the SD interface's DMA and my Wishbone/DDR3 interface.

Now the issue - the register data is written to the GPU RAM; I can see it using the RS232_debugger.  However, when I try to read that data from the host, I'm getting the 0xAA's I've written (from the host before the SCR register read).  So what the host is reading doesn't match what the RS232_debugger is seeing.

This seems to me like an issue with the cache not updating and still presenting the host with the cached data instead of the new data written by the SD interface.  Do I need to do something to make the SD interface writes update the cache?  I seem to recall having this issue once before, but I can't find it in the thread history (not using the right search terms, obviously!)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 18, 2022, 05:30:54 pm
Now the issue - the register data is written to the GPU RAM; I can see it using the RS232_debugger.  However, when I try to read that data from the host, I'm getting the 0xAA's I've written (from the host before the SCR register read).  So what the host is reading doesn't match what the RS232_debugger is seeing.

This seems to me like an issue with the cache not updating and still presenting the host with the cached data instead of the new data written by the SD interface.  Do I need to do something to make the SD interface writes update the cache?  I seem to recall having this issue once before, but I can't find it in the thread history (not using the right search terms, obviously!)
Ok, what seems to be happening is that the Z80 read cache is it's own on a different channel compared to the SD-Card's cache.  So, it doesn't know that something has been written into that address.

Try this fix:
Read any GPU memory location which is at least 16 bytes outside the read address you desire forcing the old read data in the DDR3 Z80's read cache to be dumped.
Now, read the address you actually want to read, now being on a different cache bank read address, this will now force a fetch direct from the DDR3.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 18, 2022, 06:04:02 pm
Try this fix:
Read any GPU memory location which is at least 16 bytes outside the read address you desire forcing the old read data in the DDR3 Z80's read cache to be dumped.
Now, read the address you actually want to read, now being on a different cache bank read address, this will now force a fetch direct from the DDR3.

Ah yes, that does it. :-+   I had the idea to try that earlier, but didn't bother for some reason. ::)

Would a fix for this be easy enough to do, or shall I just remember this 'hack' for whenever I need to read the SD buffer? :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 18, 2022, 06:10:54 pm
Try this fix:
Read any GPU memory location which is at least 16 bytes outside the read address you desire forcing the old read data in the DDR3 Z80's read cache to be dumped.
Now, read the address you actually want to read, now being on a different cache bank read address, this will now force a fetch direct from the DDR3.

Ah yes, that does it. :-+   I had the idea to try that earlier, but didn't bother for some reason. ::)

Would a fix for this be easy enough to do, or shall I just remember this 'hack' for whenever I need to read the SD buffer? :)
Or any other device which can write to the DDR3.  For example, if your Z80 wrote and monitored a byte while the RS232 debugger edit's a memory address, the Z80 will not see the change until the Z80 once again flushes it's cache.

I'm thinking of enhancing my ddr3 with version 2.0 to look for such cross-multiport writes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 18, 2022, 07:19:12 pm
I can imagine the same situation for the SD card interface.

If you tell the SD-Card to read 4 bytes from DDR3 to write to the card.  If after that the Z80 changes those 4 bytes and you tell the SD-Card to write the same 4 bytes again without any other DDR3 read access from the SD-Card, the SD interface will not see the new 4 bytes that the Z80 wrote.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 18, 2022, 07:30:59 pm
I can imagine the same situation for the SD card interface.

If you tell the SD-Card to read 4 bytes from DDR3 to write to the card.  If after that the Z80 changes those 4 bytes and you tell the SD-Card to write the same 4 bytes again without any other DDR3 read access from the SD-Card, the SD interface will not see the new 4 bytes that the Z80 wrote.

Hmmm, yes, possibly. I suppose there's a number of scenarios where the cross-cache-hit issue will be a problem - if not for the SD peripheral, then possibly for others that we haven't yet implemented or thought of. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 18, 2022, 07:58:11 pm
Well, all you have left is my VGA processor, and believe me, it reads way more than the size of the DDR3 read cache...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 18, 2022, 09:47:32 pm
Well, all you have left is my VGA processor, and believe me, it reads way more than the size of the DDR3 read cache...

I think the project is hitting around 82% LE usage.  I can't run a build at the moment so I'm working from memory, but I think it has around 8,000 LEs left.  I guess that should be enough for everything; VGA processor, 8-bit programmable sound generator, maybe even a softcore Z80 processor.  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 18, 2022, 10:00:34 pm
We'll have to check and see if the SD card reader is using logic elements as a data buffer, or ram blocks.  You should only be at ~65% full.  Using LE for data buffer eats up so many.

As for a Z80 softcore, we are talking something like 1k logic elements.
Audio will be around 1-2k LE depending on how you do it and how many features and channels, like 16bit stereo, 16 channels would eat ~2k LE.

What else do you want to put in there.

RS232 Com ports are something like 150LE.
Old fashioned joystick ports are something 20 LE.
I don't know about USB.  I guess it depends on the USB interface chip.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 19, 2022, 08:33:24 am
We'll have to check and see if the SD card reader is using logic elements as a data buffer, or ram blocks.  You should only be at ~65% full.  Using LE for data buffer eats up so many.

The project stats without my SignalTap instance:

39,451 / 49,760 LEs (79%)
24135 registers
796,392 / 1,677,312 memory bits (47%)

According to Quartus, the SD controller is using 2,449 combinational ALUTs, 1,785 dedicated logic registers, 1,024 memory bits, 2 DSP elements and one DSP 18x18...

As for a Z80 softcore, we are talking something like 1k logic elements.
Audio will be around 1-2k LE depending on how you do it and how many features and channels, like 16bit stereo, 16 channels would eat ~2k LE.

This is a subject for a whole other thread, or section of this one, but as you've mentioned it:  ;)

Initially at least, my requirements for audio are very limited - just a straight simulation of the AY-3-8910 PSG is all I want.  I have a Verilog module that does just that - but it has three analogue outputs (like the real chip), which ideally would be output directly to an audio amp, so I am glacially slowly researching how I would interface it's outputs to the audio DAC on the DECA boardEDIT:  I've just found a YM2149 project (https://github.com/dnotq/ym2149_audio) (essentially the same as the AY) with a 14-bit PCM output - the only downside is it's in VHDL, but so long as it works then that shouldn't be a problem.  It's a bit annoying that there aren't a lot of DECA projects out there, and most (if not all) of the example projects supplied for the DECA all use a NIOS core, making reverse-engineering how the audio works an opaque and difficult process that I have little time for at the moment.  I'll be going to the datasheet for the DAC chip and seeing if I can work out how to send data to it.

I'm actually really surprised at how 'simple' the module is to emulate the PSG.  I don't understand any of it - analogue electronics and music is a dark art to me at the best of times - but it surprises me how apparently basic the HDL is to replicate an (admittedly very basic) programmable sound generator chip.

What else do you want to put in there.

RS232 Com ports are something like 150LE.
Old fashioned joystick ports are something 20 LE.
I don't know about USB.  I guess it depends on the USB interface chip.

USB won't take up many LEs at all - it'll be around 150LE like the RS232 com ports you've quoted, as I'm likely to use a CH559 as the USB host chip and link this to the FPGA via serial (or SPI if I ever get time to really put some effort into researching/working on the CH559 more).  I have created dev boards to test out the RP2040, SAMD21 (boards already exist for these two, I know, but they all have mini/micro USB ports and I like designing and making boards! ;)) and CH559 and the CH559 seems to be winning out thanks to simplicity, cost and requiring least supporting components.  It also supports two USB slave ports 'out of the box', so attaching a keyboard and mouse would be simples.  I just need more hours in the day to work on all this stuff. :phew:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 19, 2022, 09:20:50 pm
Actually, ignore most of what I've said about audio output to the DAC above.  I forgot about the HDMI audio pathway, which is much more preferable as it doesn't require headphones, or an external amplifier, or messing around learning how to use the TLV320AIC3254 on the DECA.  I just need to feed a suitable audio signal to the HDMI output module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 19, 2022, 09:27:34 pm
Actually, ignore most of what I've said about audio output to the DAC above.  I forgot about the HDMI audio pathway, which is much more preferable as it doesn't require headphones, or an external amplifier, or messing around learning how to use the TLV320AIC3254 on the DECA.  I just need to feed a suitable audio signal to the HDMI output module.
I'm sorry to tell you this, but,... the HDMI audio pathway uses the same exact I2S audio port as the TLV320AIC3254.  Pin for Pin compatible.  If you are going to learn how to use the HDMI audio out port, then you are learning the TLV320AIC3254, just that you will ignore the serial audio input pin which runs in parallel containing the sampled Line-In audio.  You might as well just tie the 2 I2S busses together in Quartus and have simultaneous headphone line out and HDMI audio out running both at the same time in parallel.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 19, 2022, 09:39:47 pm
I'm sorry to tell you this, but,... the HDMI audio pathway uses the same exact I2S audio port as the TLV320AIC3254.  Pin for Pin compatible.  If you are going to learn how to use the HDMI audio out port, then you are learning the TLV320AIC3254, just that you will ignore the serial audio input pin which runs in parallel containing the sampled Line-In audio.  You might as well just tie the 2 I2S busses together in Quartus and have simultaneous headphone line out and HDMI audio out running both at the same time in parallel.

Ah nuts. Never mind. ;)  I'll work it out when I get to it.  Must get the SD interface working first!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 19, 2022, 09:47:26 pm
I'm sorry to tell you this, but,... the HDMI audio pathway uses the same exact I2S audio port as the TLV320AIC3254.  Pin for Pin compatible.  If you are going to learn how to use the HDMI audio out port, then you are learning the TLV320AIC3254, just that you will ignore the serial audio input pin which runs in parallel containing the sampled Line-In audio.  You might as well just tie the 2 I2S busses together in Quartus and have simultaneous headphone line out and HDMI audio out running both at the same time in parallel.

Ah nuts. Never mind. ;)  I'll work it out when I get to it.  Must get the SD interface working first!
Yes.

The TLV320AIC3254 has an I2C control port where you will need to set a few regs, just like the HDMI transmitter, but it can be setup to be compatible with I2S audio bus.  With a simple I2S LUT map, you will basically be setting sample rate, audio filter, which input and the bit direction and word length of the I2S port.

SEE this file as an example: https://github.com/BrianHGinc/BrianHG-DDR3-Controller/blob/main/BrianHG_DDR3_DECA_GFX_DEMO_v15_300MHz_HR/I2C_HDMI_Config.v (https://github.com/BrianHGinc/BrianHG-DDR3-Controller/blob/main/BrianHG_DDR3_DECA_GFX_DEMO_v15_300MHz_HR/I2C_HDMI_Config.v)

Just a copy & paste with a different host address and different look-up-table at the bottom of the file.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 25, 2022, 12:01:50 am
Ok, it's been around a week.  Anything new to see?  Any new bugs found?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 26, 2022, 04:48:52 pm
Ok, it's been around a week.  Anything new to see?  Any new bugs found?

Uh no, not this week anyway - have been really too busy to even look at it until just now.  Made some progress last week, however I've hit a bit of a block with the SD interface.  I can read sectors from the SD card, and have even managed to write a sector once (haven't been able to repeat that feat).  The problems I'm facing are:
I've gone as far as contacting the author of the SD interface IP, but he's a busy guy and made the interface a long time ago, so he's not really able to help much with my very specific use-case.

I'll have some more time this week to start plugging away at the problem(s) again, but I'm not feeling confident and wondering if the only option is to scrap this IP and see if I can find another, simpler, example that I can use.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 26, 2022, 09:44:21 pm
Is there an SD card reader which comes with the DECA cd?  And, who made it?  Is it complex, or can you edit it?

maybe : https://github.com/xesscorp/VHDL_Lib/blob/master/SDCard.vhd (https://github.com/xesscorp/VHDL_Lib/blob/master/SDCard.vhd)
However, it looks like it's 1 bit bus.


take a look here, they seem to support 4bit mode: https://github.com/WangXuan95/FPGA-SDcard-Reader (https://github.com/WangXuan95/FPGA-SDcard-Reader)
Also, if you want to ignore the file system and make the Z80 handle that, the code really shrinks down to 2 tiny modules.  However, can it write?


Just so we are clear, if you programmed this from scratch yourself giving simple read, erase, write access to an SD card and programmed the Z80 with the file system, it might have already been done and working as the interface isn't much more complex than the I2S audio bus, though you still need to read the specification.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 27, 2022, 07:43:53 am
Is there an SD card reader which comes with the DECA cd?  And, who made it?  Is it complex, or can you edit it?

Yes, there's an example project in the DECA materials, but it uses a NIOS core which puts it well out of my ability to pull it apart and understand what's going on (at the moment, anyway).

maybe : https://github.com/xesscorp/VHDL_Lib/blob/master/SDCard.vhd (https://github.com/xesscorp/VHDL_Lib/blob/master/SDCard.vhd)
However, it looks like it's 1 bit bus.

1-bit SPI by the looks of it, and would involve a little editing of the VHDL to make it work, which I have little confidence in doing without causing more problems.

take a look here, they seem to support 4bit mode: https://github.com/WangXuan95/FPGA-SDcard-Reader (https://github.com/WangXuan95/FPGA-SDcard-Reader)
Also, if you want to ignore the file system and make the Z80 handle that, the code really shrinks down to 2 tiny modules.  However, can it write?

No, it can't.  Funnily enough I'd looked at this project before starting on the SD journey, as it looks perfect for what I want and looks like it provides a possible future upgrade path to allow me to access files by filename on a FAT32 USB stick, potentially allowing me to break away from CP/M-formatted storage and use easily readable non-Jurassic storage filesystems.  The only issue is I need to write a write function.  I'll probably give that project a try this week to see how stable/effective it is at reading data and get my head around what I need to do to write a write block function for it.

Just so we are clear, if you programmed this from scratch yourself giving simple read, erase, write access to an SD card and programmed the Z80 with the file system, it might have already been done and working as the interface isn't much more complex than the I2S audio bus, though you still need to read the specification.

Without you leading me through it like you have done with all the GPU work, I'd still be reading the specifications and throwing random HDL at the wall to see what sticks. :-[  I don't need a file system at all, but I also want something better than a 1-bit SPI interface.  All I need is that and sector access to the SD card.  CP/M handles the filesystem as part of its BDOS module, all I'm doing is providing low-level hardware access to the SD card for the BDOS.  The BIOS already handles blocking/de-blocking for writes and reads to the CF card as that handles 512-byte transactions, so really there's not much to do once I get the read/write access to the SD card sorted.  The reason I went with the IP I'm using currently is because of the fast 4-bit access, but I think I'll cut it free and look at the other project you've mentioned again. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 29, 2022, 09:58:40 am
Okay, I have sector reads working with the modules attached below. :phew:

SDInterface.sv is the top-level of the SD interface, instantiated in GPU_DECA_DDR3_top as 'SID'.  I started writing this module last November (and I'd forgotten about it - it's fun being me) and it acts as an interface between the SDReader.sv module and the rest of the GPU/uCOM.  Its primary purpose is to send the sector address and a read request pulse to SDReader.sv when the host requests it and collates data returned from SDReader.sv (which is received a byte at a time) into a 16-byte cache.  When the cache is full, it's written to DDR3 memory as a single 128 bit-wide write transaction.  It also keeps track of the DDR3 buffer location (currently hardwired to 0x5000, but I might make this a register so the host can move it around if needed) and fills the 512-byte buffer in DDR3 memory with 32 successive writes over the course of the SD sector read.

SDReader.sv and SDCmdCtrl.sv are from a project very similar to the one BrianHG linked here:

take a look here, they seem to support 4bit mode: https://github.com/WangXuan95/FPGA-SDcard-Reader (https://github.com/WangXuan95/FPGA-SDcard-Reader)
Also, if you want to ignore the file system and make the Z80 handle that, the code really shrinks down to 2 tiny modules.  However, can it write?

Reads seem to be working perfectly - I still have some work to get the STATUS data out of the SDInterface module to Bridgette (it's an 8-bit value made up of a number of different signals); I'm looking into why it never changes from 0x00 currently, but other than that it's reading the SD sectors with no issues.  Ironically, it's reading the exact data that the last iteration of the interface wrote to the SD card.  I need to low-level reformat the SD card with FAT32 again and I'll see if I can get MBR data from it.

With no registers to worry about, all I have to do is set the sector address (using the same method I used previously to set any of the 32-bit registers in the previous version of the interface) and the read is executed when the 4th byte is written to Bridgette, making for a much simpler interface.  Also, there's no errors being returned (no feature for them), which is both good and bad, but sequential sector reads are working fine - no 'only working every odd attempt' like with the last version interface.

Once I've got the STATUS output working, I'll start looking at adding write functionality to the interface.  Further down the line will be opening it up from 1-bit to 4-bit transfers too.

EDIT:  Have reversed the byte-order for loading the cache in SDInterface.sv so each 16-byte write is in the correct sequence now.  ;)

EDIT 2: Attached latest files with correct-order byte output.  With the SD card reformatted, I'm now able to read the MBR with no issues.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2022, 07:51:30 am
This is frustrating me - I'm trying to set an 8-bit output port to a collection of other signals, so the host can query the status of the SD read and know when it's complete, amongst other things, rather than clumsily setting a timer or reading a memory location for a change of value (risky if the value doesn't change, e.g.).

The component values change - I can see in SignalTap that CARDTYPE, for example, has the value 3.  STATUS, however, remains zero throughout.  What am I doing wrong?

Here's the SignalTap showing CARDTYPE, SIDSTATE, RD_RDY, SID_BUSY - all have changing values at appropriate times:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1474798)

Code: [Select]
// SD Interface v0.1
//
// Connects the SD modules to the rest of the GPU and manages the
// 4KB dual-port M9K block RAM read/write buffer.
//
// TODO: Handle write requests to the SD card.

module SDInterface #(

    parameter int          CLK_DIV     = 3,      // clock divider
    parameter int          BUFFER_ADDR = 'h5000  // default DDR3 buffer location

)(

    input  logic           CLK,            // 100MHz system clock
    input  logic           RESET,          // reset active HIGH
    // interface <-> Bridgette
    input  logic           RD_REQ,         // HIGH for read request
    input  logic   [ 31:0] SECTOR,         // sector number to read/write
    output logic           RD_RDY,         // HIGH when read is complete from SD card
    output logic           SD_BUSY,        // HIGH when interface is busy
    output logic   [  3:0] SIDSTATE,       // current state machine value
    output logic   [  1:0] CARDTYPE,       // SD card type
    output logic           BUSY,           // HIGH when SDInterface is busy
    output logic   [  7:0] STATUS,         ****** THIS IS ALWAYS ZERO ******
    // SD phy connections
    inout  logic   [  3:0] SD_DATA,        // data from SDReader.sv
    inout                  SD_CMD,         // CMD signal to SDReader.sv
    output logic           SD_CLK,         // clock signal to SD card
    output logic           SD_CMD_DIR,     // HIGH = TO SD card, LOW = FROM SD card
    output logic           SD_D0_DIR,      // HIGH = TO SD card, LOW = FROM SD card
    output logic           SD_D123_DIR,    // HIGH = TO SD card, LOW = FROM SD card
    output logic           SD_SEL,         // SD select
    // DDR3 connections
    //    input  (DDR3 -> SD WR ops)
    input  logic           DDR3_busy,      // HIGH when DDR3 is busy
    input  logic   [127:0] DDR3_rd_data,   // read data from DDR3
    input  logic           DDR3_rd_rdy,    // data from DDR3 is ready
    //    output (SD -> DDR3 RD ops)
    output logic    [31:0] DDR3_addr_o,
    output logic           DDR3_ena,       // Flag HIGH for 1 CMD_CLK when sending a DDR3 command
    output logic           DDR3_wr_ena,    // HIGH signals write request to DDR3 Controller
    output logic   [127:0] DDR3_wr_data,   // 128-bit data bus
    output logic    [15:0] DDR3_wr_mask    // Write data enable mask

);

// data IO for read and write data, to connect to buffer
wire          cache_wren ;
wire          rd_ready   ;
wire          rd_req     ; // HIGH when not BUSY and RD_REQ is made by Bridgette
wire    [1:0] cardtype   ;
wire    [3:0] sd_state   ;
wire          sd_busy    ;

logic         cache_full ; // HIGH when 16-byte cache is full
logic         rEna       ; // HIGH whilst rData is being sent
logic [  7:0] SD_rData   ; // Data read from cache
logic [  8:0] buf_ptr    ; // 512-byte buffer address pointer
logic [  3:0] data_ptr   ; // pointer to current byte in cache
logic [127:0] data_cache ; // temporary 16-byte storage to be written to DDR3 or SD

//                          1         2          4        1
assign STATUS       = '{ rd_ready, cardtype, sd_state, sd_busy } ;    ******** THIS IS WHERE STATUS' VALUE IS SET ********
assign RD_RDY       = rd_ready                 ;
assign CARDTYPE     = cardtype                 ;
assign SIDSTATE     = sd_state                 ;
assign SD_BUSY      = sd_busy                  ;
assign rd_req       = BUSY ? 1'b0 : RD_REQ     ; // only pass rd_req if interface isn't busy
// DDR3 Write Request
assign DDR3_wr_ena  = cache_full && !DDR3_busy ; // Set the write enable.
assign DDR3_wr_data = data_cache               ; // Send write data.
assign DDR3_wr_mask = 16'hFFFF                 ; // Write enable for the byte.
// DDR3 transaction controls
assign DDR3_addr_o  = BUFFER_ADDR + buf_ptr    ; // DDR3 write address.
assign DDR3_ena     = DDR3_wr_ena              ; // Write full 128-bits.

// For more detail, see SDReader.sv
SDReader #(

    .CLK_DIV         ( CLK_DIV     )  // because clk=100MHz, CLK_DIV is set to 2 - see SDReader.sv for detail

) SDReader_inst(

    .clk             ( CLK         ),
    .rst_n           ( !RESET      ), // rst_n is active low, so RESET must be inverted
   
    // signals connect to SD bus
    .sdclk           ( SD_CLK      ),
    .sdcmd           ( SD_CMD      ),
    .sddat           ( SD_DATA     ),
   
    // bus direction controls
    .SD_CMD_DIR      ( SD_CMD_DIR  ), // HIGH = TO SD card, LOW = FROM SD card
    .SD_D0_DIR       ( SD_D0_DIR   ), // HIGH = TO SD card, LOW = FROM SD card
    .SD_D123_DIR     ( SD_D123_DIR ), // HIGH = TO SD card, LOW = FROM SD card
    .SD_SEL          ( SD_SEL      ), // SD socket select

    // status and information
    .card_type       ( cardtype    ), // 0=Unknown, 1=SDv1.1 , 2=SDv2 , 3=SDHCv2
    .card_stat       ( sd_state    ), // current state of SDReader's state machine
   
    // user read sector command interface
    .rstart          ( rd_req      ), // rstart HIGH starts read operation
    .rsector_no      ( SECTOR      ), // target sector to read in SDcard
    .rbusy           ( sd_busy     ), // signals read is ongoing or complete
    .rdone           ( rd_ready    ), // signals read is complete   ********* EVEN ASSIGNING STATUS TO THE PORT DIRECTLY DOESN'T WORK ***********
   
    // sector data output interface
    .outreq          ( cache_wren  ), // HIGH whilst data is received from SD card (for each byte?)
    .outaddr         ( readAddr    ), // cache address to be written to
    .outbyte         ( SD_rData    )  // data read from SD card

);

always @( posedge CLK ) begin

    if ( RESET ) begin

        buf_ptr    <= 'hFF0  ; // start at 0xFF0 so when first read completes, buf_ptr = 0 for first memory write
        cache_full <= 1'b0   ;
        data_cache <= 128'b0 ;
        data_ptr   <= 4'b0   ;
        BUSY       <= 1'b0   ;

    end else if ( rd_req ) begin // new read request received

        buf_ptr    <= 'hFF0  ;
        BUSY       <= 1'b1   ;

    end else if ( !RD_RDY && cache_full && !DDR3_busy ) begin // 16-byte cache is full

        cache_full <= 1'b0   ;

    end else if ( RD_RDY ) begin // End of SD Read; reset pointers and data bus
   
        buf_ptr    <= 'hFF0  ;
        cache_full <= 1'b0   ;
        data_cache <= 128'b0 ;
        data_ptr   <= 4'b0   ;
        BUSY       <= 1'b0   ;

    end else if ( cache_wren ) begin // byte received from SDReader

        case ( data_ptr )

            0  : data_cache[127:120] <= SD_rData ; // 127-120
            1  : data_cache[119:112] <= SD_rData ; // 119-112
            2  : data_cache[111:104] <= SD_rData ; // 111-104
            3  : data_cache[103: 96] <= SD_rData ; // 103-96
            4  : data_cache[ 95: 88] <= SD_rData ; // 95-88
            5  : data_cache[ 87: 80] <= SD_rData ; // 87-80
            6  : data_cache[ 79: 72] <= SD_rData ; // 79-72
            7  : data_cache[ 71: 64] <= SD_rData ; // 71-64
            8  : data_cache[ 63: 56] <= SD_rData ; // 63-56
            9  : data_cache[ 55: 48] <= SD_rData ; // 55-48
            10 : data_cache[ 47: 40] <= SD_rData ; // 47-40
            11 : data_cache[ 39: 32] <= SD_rData ; // 39-32
            12 : data_cache[ 31: 24] <= SD_rData ; // 31-24
            13 : data_cache[ 23: 16] <= SD_rData ; // 23-16
            14 : data_cache[ 15:  8] <= SD_rData ; // 15-8
            15 : begin
                 data_cache[  7:  0] <= SD_rData ; // 7-0
                 cache_full          <= 1'b1     ;
            end

        endcase
        buf_ptr  <= buf_ptr  + 1'b1 ;
        data_ptr <= data_ptr + 1'b1 ;

    end

end

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 30, 2022, 01:35:54 pm
What happens if you trigger on the signal tap on the RD_RDY (this may be a 1clk pulse on only pulse during certain commands) or wait for the SD_BUSY (this may be a more true state of the SD card interface) to go low?

Maybe the SD_BUSY never toggles because the controller can accept more than 1 command before it's command buffer gets full?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2022, 09:02:49 pm
What happens if you trigger on the signal tap on the RD_RDY (this may be a 1clk pulse on only pulse during certain commands) or wait for the SD_BUSY (this may be a more true state of the SD card interface) to go low?

This next image is triggered on the rising edge of RD_RDY:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1475422)

Maybe the SD_BUSY never toggles because the controller can accept more than 1 command before it's command buffer gets full?

It's not SD_BUSY that's the issue - it's STATUS.  It remains zero throughout, despite RD_RDY, CARDTYPE, SIDSTATE and SD_BUSY all having non-zero values.  This next line doesn't seem to be working:
Code: [Select]
assign STATUS       = '{ rd_ready, cardtype, sd_state, sd_busy } ;
Originally I had used the port names instead of wire names for RD_RDY, CARDTYPE etc, but I couldn't get them to show up in the node finder.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2022, 09:43:11 pm
Never mind, fixed it.  Removed the apostrophe from the start of the array declaration and added in the size for STATUS and it works now. :-//

Code: [Select]
assign STATUS       = '{ rd_ready, cardtype, sd_state, sd_busy } ;
Should be:

Code: [Select]
assign STATUS[7:0] = { rd_ready, cardtype, sd_state, sd_busy } ;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 30, 2022, 09:43:36 pm
assign STATUS       = ' { rd_ready, cardtype, sd_state, sd_busy } ;

Do not use a ' in front of a brace unless you are filling an array of data.  Status is not a multidimensional array, it is a wire or reg 8 bits wide, but 1 multidimensional word, not 4 8 bit words.


If that doesn't help, then try changing:

    output logic   [  7:0] STATUS,         ****** THIS IS ALWAYS ZERO ******
to:
    output           [  7:0] STATUS,         ****** THIS IS ALWAYS ZERO ******
or:
    output wire    [  7:0] STATUS,         ****** THIS IS ALWAYS ZERO ******
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 30, 2022, 09:45:02 pm
Shit, if I didn't preview, I would have posted the answer just before you.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2022, 09:48:27 pm
Shit, if I didn't preview, I would have posted the answer just before you.

 ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2022, 09:52:41 pm
Just have to wrap my head around how the modules work and write a WRITE module now.  I suspect that I won't need to touch SDCmdCtrl - in theory the workings of that module shouldn't need to be changed, a WRITE is just a different command to a READ, after all.  I just need to create an SDWriter.sv module and reverse the bitstream flow, essentially.  Will hit the specifications tomorrow and make a start then.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on April 30, 2022, 10:06:02 pm
Just have to wrap my head around how the modules work and write a WRITE module now.  I suspect that I won't need to touch SDCmdCtrl - in theory the workings of that module shouldn't need to be changed, a WRITE is just a different command to a READ, after all.  I just need to create an SDWriter.sv module and reverse the bitstream flow, essentially.  Will hit the specifications tomorrow and make a start then.
Writing is one thing, but I think with SD cards, you need to worry about an ERASE.
If I remember correctly, you can only erase complete blocks or sectors.
So if you want to edit data in a sector, you need to read it to local ram, erase the sector, modify the local ram, the write the sector.  During the first read, you should be able to tell if you need to erase or not due to the bits you want to change having a 0 or 1 already in them.

If the technology has progressed to erasing single bytes, then ignore what I have just said.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on April 30, 2022, 10:26:04 pm
No, AFAIK it's still sector/block erasing, with some SD cards reporting up to 4MB block sizes...  I'll look into this tomorrow, as I hadn't really thought about it before and just assumed you could write a sector over an existing one without worrying about erasing. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 05, 2022, 03:14:12 pm
Quick update.  I'm currently working on creating the module that will write data to the SD card.  Progress has been slow - combination of a lack of time to work on it and me being no expert. ::)

I do have the SDInterface controller sending a 512-byte stream to the Writer module, though.  It reads 16 bytes at a time from the DDR3 buffer, in much the same way as the Reader writes to DDR3, and presents those 16 bytes to the writer module so it can read each one when it needs to as it writes to the SD card.  The HDL may not be pretty, but it works (at least as far as I can tell via SignalTap).

I figured adapting the Reader module to create a Writer module would be a moderately sensible way to go about creating a write function.  I just need to look closely at the SD specs for write ops and adapt the Reader's state machine to fit the format required for writing data to the SD card.  I'm a little concerned I'm going to have to modify the SDCmdCtrl.sv module for writing (it looks to be a bit beyond my understanding) due to the CRC values required after the block is sent, but we'll see.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 05, 2022, 05:23:00 pm
Ok, what you have looks fine.  If signal-tap shows everything is ok, then it is a go.
I wont trouble you with functional shortcuts to address 8 bits of the 128bit array.

IE:
data_cache[byte_position*8 +:8] <= SD_dat ; //
or
wr_dat <= data_cache[byte_position*8 +:8] ; //


I have not seen the 'SDCmdCtrl.sv', but I can take a look if you provide the one you are using.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 05, 2022, 07:32:07 pm
Ok, what you have looks fine.  If signal-tap shows everything is ok, then it is a go.
I wont trouble you with functional shortcuts to address 8 bits of the 128bit array.

IE:
data_cache[byte_position*8 +:8] <= SD_dat ; //
or
wr_dat <= data_cache[byte_position*8 +:8] ; //

I knew there'd be a more efficient way of doing it, I just hadn't gotten around to optimising the HDL yet as I only got the byte stream for SDWriter working this afternoon. ;)  I'll try giving your suggestion a go. :-+

I have not seen the 'SDCmdCtrl.sv', but I can take a look if you provide the one you are using.

See attached zip file.  It has the SDInterface and its sub-modules, SDReader (which works fine) and SDWriter (which, at the moment, is little more than a test-bed for me to check SDInterface's byte stream to it).  Both SDReader and SDWriter implement SDCmdCtrl.sv as a sub-module, which is also in the zip obviously.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 05, 2022, 07:43:32 pm
I wont trouble you with functional shortcuts to address 8 bits of the 128bit array.

IE:
data_cache[byte_position*8 +:8] <= SD_dat ; //
or
wr_dat <= data_cache[byte_position*8 +:8] ; //


Actually, please do - if I can write it using less lines of code then I'm happy to learn! ;D

So, for the rd_op section (lines 218-238-ish of SDInterface.sv), I could replace that entire case...endcase structure with something like this?

Code: [Select]
data_cache[data_ptr*8+:8] <= SD_dat ;
if ( data_ptr == 'h0F ) cache_full <= 1'b1 ;

Wouldn't that reverse the byte-order though?  At the moment, if data_ptr is zero, it returns the byte at the highest end of the cache (bits 127-120).  Using the code above, wouldn't that return the LSB from the other end, or have I misunderstood how that shortcut works?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 05, 2022, 10:45:37 pm

Actually, please do - if I can write it using less lines of code then I'm happy to learn! ;D

So, for the rd_op section (lines 218-238-ish of SDInterface.sv), I could replace that entire case...endcase structure with something like this?

Code: [Select]
data_cache[data_ptr*8+:8] <= SD_dat ;
if ( data_ptr == 'h0F ) cache_full <= 1'b1 ;

Wouldn't that reverse the byte-order though?  At the moment, if data_ptr is zero, it returns the byte at the highest end of the cache (bits 127-120).  Using the code above, wouldn't that return the LSB from the other end, or have I misunderstood how that shortcut works?

Wouldn't that then be ' (15-data_ptr)*8 ' ?
Remember, the added ' 15- ' doesn't add gates or delay, the compiler just will end up wiring the 'data_cache' latch enables backwards.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 06, 2022, 10:49:21 am
Also, what's wrong with resetting the 'data_ptr' to 15, then subtracting 1 every clock, and ending on 0 instead of counting up?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 06, 2022, 09:32:12 pm
Also, what's wrong with resetting the 'data_ptr' to 15, then subtracting 1 every clock, and ending on 0 instead of counting up?

Well, that's just far too logical.  ;)

Think you might have missed a reply of mine earlier?  I'd attached the current SDInterface files (you asked about the SDCmdCtrl.sv file):

I have not seen the 'SDCmdCtrl.sv', but I can take a look if you provide the one you are using.

See attached zip file.  It has the SDInterface and its sub-modules, SDReader (which works fine) and SDWriter (which, at the moment, is little more than a test-bed for me to check SDInterface's byte stream to it).  Both SDReader and SDWriter implement SDCmdCtrl.sv as a sub-module, which is also in the zip obviously.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 10, 2022, 11:08:51 pm
I've been too busy here.  What's the latest on your side?  Did you load your first file?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 11, 2022, 07:15:03 am
I've been too busy here.  What's the latest on your side?  Did you load your first file?

Progress has been slow - whilst I haven't read my first file yet, I'm happy with the read function; it's getting the MBR and subsequent sectors from the SD card with no issues, so I have no concerns with that aspect of the interface.

I'm working on the write function at the moment as I really need that to format the card and get the CP/M tracks down onto it.  I've used the existing SDReader.sv file as a template to work from and am writing the HDL to build the 'write' function using SD specs and the read/writer (specifically the sd_data_serial_host.v file) from the previous SD interface IP core I wasted time on as a reference.

EDIT:  If I'm honest, I think I'm lost in writing the state machine to write data to the SD card.  I've started out tweaking the SDReader code to use a basic framework for the write SM, using the HDL from the previous IP core as a guide to set up the write process, but the more I look at it all, the more confused I'm getting.  It should just be a 'simple' case of:

I'm up to calculating the CRC and writing it back to the SD card.  The more I look at the module from the previous IP core, the more I want to convert it for use in the current interface as it combines writing and reading into one module and - most importantly - supports 4-bit mode.  I just worry I'd spend an age trying to convert it only for it not to work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 16, 2022, 01:35:42 pm
Help! :-//

Frustration has gotten the better of me and I'm about ready to pull the plug on the SD interface. |O

I managed to create a working interface that would read sectors from an SD card with no errors - that was pretty easy.

I have now spent the past four weeks thinking about, researching and experimenting in HDL to create a WRITE function so I can save data TO an SD card.

At first I thought I'd build on the existing READ side of the interface and repurpose the HDL framework to create a WRITE side (this is the SDCard_Interface/SDInterface_old.sv module).  After making tentative steps towards setting it up, I realised I didn't have a clue what I was doing with the state machine and how I would include CRC checks etc.

Then I had the hair-brained idea to look at the previous IP core (the one that was reading/writing gobbledook, it seems) to see how that was doing it, and found the sd_data_serial_host.v module which seemed to make more sense than what I was trying to do - plus it showed me how I could use 4-bit SD mode as well, so I thought I could tweak that to work and the SDInterface module to use it.  I got to the point where the module is building with no errors and I'm debugging via SignalTap, but I've spent since Thursday last week looking at SignalTap traces in my spare time trying to piece together why the interface isn't initialising the SD card.  Damned if I can work it out.

I've been trying to do it all on my own without asking for help, but all it seems I've got to show for a month's (or more) work is the ability to read from an SD card.

I'll continue to plug away at SignalTap as ideas for possible issues pop up, or as my understanding of the HDL improves, but it'll be at a much-reduced rate now.  If anyone has any time and inclination to give me a hand, it would probably be a project lifesaver at this point.

The attached zip file is the current GPU project, with the non-working SD interface which I'm trying to bug fix and get working.  It should initialise the SD card, read or write the SD card as three different operations, selectable by a value written by the host to the appropriate IO port (242).

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 22, 2022, 05:48:58 am
Arrrg, 3 days... 3 days of trying to track down this silly bug where a read port may freeze when running my DDR3 controller in Quarter Rate Mode with an unusual slip in the read address (when slanting 1 of 2 superimposed video layers on my VGA controller) only after millions of read commands issued.  I just cant simulate it and the signal tap would be useless as there are too many environment variables to track at 300MHz.  It's driving me nuts as it is the one thing I have left before issuing a proper v1.6 release.  There is no reason for this to operate properly in half-rate mode, but not quarter-rate mode and I know which modules are involved.  Worse, turning off the read-cache solves the problem at the expense of making repetitive reads slow.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 23, 2022, 01:45:00 am
@nockieboy, pls upload your complete latest GPU project.  I have ver 1.6 beta 2 ready for testing and I want to integrate it into your code.  Ok, I got your latest code above...

So far, I'm stumped about using the quarter rate mode, however, improvements along the way have made 400MHz half rate possible, though I know there is a bottleneck with regard to the ellipse command and it's 27bit multiply-add command.  At least 300MHz in half-rate mode should now hopefully achieve an all black timing report.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 23, 2022, 07:35:03 pm
Info on version BrianHG_DDR3_Controller 1.6 update:

https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg4192249/#msg4192249 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg4192249/#msg4192249)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 27, 2022, 07:16:48 pm
Arrrg, 3 days... 3 days of trying to track down this silly bug where a read port may freeze when running my DDR3 controller in Quarter Rate Mode with an unusual slip in the read address (when slanting 1 of 2 superimposed video layers on my VGA controller) only after millions of read commands issued.  I just cant simulate it and the signal tap would be useless as there are too many environment variables to track at 300MHz.  It's driving me nuts as it is the one thing I have left before issuing a proper v1.6 release.  There is no reason for this to operate properly in half-rate mode, but not quarter-rate mode and I know which modules are involved.  Worse, turning off the read-cache solves the problem at the expense of making repetitive reads slow.

Eesh - didn't realise it was such a pervasive little problem! :-\

I'll take a look at the updated DDR3 controller this weekend and update my project with it.

I've managed to keep plugging away at the SD interface this last week or so and have made some significant progress - I'm now at the testing and bug-hunting stage, having written a WRITE function for the interface.  It is somewhat based on the existing SDReader module, but I've leaned heavily on the HDL within the SD-card-controller sd_data_serial_host module for guidance.  I've also been deep-diving the SD Part_1_Physical_Layer_Specification (albeit version 3.01, but it's not the simplified version and has some key diagrams showing WRITE timings).

I'm reading Sector 0 off the SD card into the SD Buffer in GPU RAM.  Then I'm trying to write that data (the FAT32 MBR, basically) to Sector 3.  I'm writing it to Sector 3 as Sector 3 appears to be all zeros on the SD card, and failed writes erase the sector but don't write anything, so I'm not changing any data on the SD card with a failed write (which is all I'm managing to do at the moment).

It appears that I'm not getting anything back from the SD card when I attempt to write to it.  I'm sending CMD24, then writing the 512-byte payload, immediately followed by the 16-bit CRC and STOP bit, but I'm not seeing any life on DAT0 when the SD card should be responding with the CRC response byte (which should be an error or OK, if I've got the CRC function working correctly).

Here's a SignalTap of the start of the process, showing the start of payload transmission to the SD card (CMD24 is sent using the same module that the READ command is sent, I have no reason to think it's not working as intended):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1497025)

And here's a SignalTap of the end of the process, showing the last two bytes of the payload (0x55 and 0xAA being the last two bytes of Sector 0) and the 16 CRC bits and STOP bit:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1497031)

It seems there are quite a few possible points of failure in this process - I'm gravitating towards it being an issue with the DAT0 direction or the CRC being incorrect, but the SD card should respond if it's a CRC error.

I'd really, really appreciate the help of anyone who knows a bit about the SD interface and 1-bit SD mode, which is what I'm using here.  Latest project files attached for reference.  The SD modules are in the SDCard_Interface folder in the project folder - SDWriter is the module that I'm debugging. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 27, 2022, 08:12:30 pm
Question, don't you have to erase a block to change all the bits from 0's ti 1's, then, whatever you write, only 0's are actually written.  Meaning you can progressively keep on writing again and again changing any 1's to 0's, but once the bit is 0, you cannot flip it back to a '1' unless you do a block/sector erase with erases an entire chunk at once.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 27, 2022, 08:50:11 pm
Question, don't you have to erase a block to change all the bits from 0's ti 1's, then, whatever you write, only 0's are actually written.  Meaning you can progressively keep on writing again and again changing any 1's to 0's, but once the bit is 0, you cannot flip it back to a '1' unless you do a block/sector erase with erases an entire chunk at once.

I must have missed everything in the specification documents and even HDL examples I've been using where any kind of erase is performed before a write.  As far as I can tell, the SD card erases the sector when the write command is issued, then writes the new 512 bytes of data to the sector from its internal buffer once it has all been received and the CRC checks out.  Pre-erase seems to be for multi-block writes - you can let the SD card know how many blocks you intend to write and the SD card can pre-erase those blocks before you send all the data, eliminating the pauses between each block write whilst it erases the next block.

At least, that's how I understand it, but I've not actually read anything in the specification documents explicitly saying that's how it works.  This flowchart in the specifications also makes no mention of pre-erase for single-block writes:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1497058;image)

Of course, there's always the possibility I'm wrong - it isn't exactly unheard of.  ;)

EDIT: Also, when I've accidentally written to Sector 0, it has been set to all zeros.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on May 27, 2022, 10:14:42 pm
Arrrg, 3 days... 3 days of trying to track down this silly bug where a read port may freeze when running my DDR3 controller in Quarter Rate Mode with an unusual slip in the read address (when slanting 1 of 2 superimposed video layers on my VGA controller) only after millions of read commands issued.  I just cant simulate it and the signal tap would be useless as there are too many environment variables to track at 300MHz.  It's driving me nuts as it is the one thing I have left before issuing a proper v1.6 release.  There is no reason for this to operate properly in half-rate mode, but not quarter-rate mode and I know which modules are involved.  Worse, turning off the read-cache solves the problem at the expense of making repetitive reads slow.

Eesh - didn't realise it was such a pervasive little problem! :-\

I'll take a look at the updated DDR3 controller this weekend and update my project with it.

Once in a few hundred million bytes causing a random freeze is sometimes tough to find the true root cause, especially if it has more than one problem behind it.

No update yet.  I have some other priorities which is sapping my time.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on May 28, 2022, 05:55:50 am
@nockieboy

About the SD card write you are correct that the card does the erase when needed. Before sending command 24 you have to select the card with command 7 and only when it returns an OK it is ready to receive the write command.

When there are multiple 512 byte blocks to write you have to use command 25.

At least this is how it works for me in the FNIRSI 1013D. I guess you have to also get the low level interfacing done to make it work. The F1C100s has a dedicated SD card interface that takes care of this.

As I wrote before look at the code here https://github.com/pecostm32/FNIRSI_1013D_Firmware/blob/main/fnirsi_1013d_scope/sd_card_interface.c (https://github.com/pecostm32/FNIRSI_1013D_Firmware/blob/main/fnirsi_1013d_scope/sd_card_interface.c)

The function "int32 sd_card_write(uint32 sector, uint32 blocks, uint8 *buffer)" takes care of the users write request by calling the function "int32 sd_card_send_command(PSD_CARD_COMMAND command, PSD_CARD_DATA data)" with the needed commands.

This latter function does the controlling of the F1C100s low level SD card interface peripheral.

The card also has to be in the correct state to be able to select and deselect it. This is done with the "int32 sd_card_init(void)" function.

Hope this helps.

Cheers,
Peter
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on May 28, 2022, 06:35:59 am
Question, don't you have to erase a block to change all the bits from 0's ti 1's, then, whatever you write, only 0's are actually written.  Meaning you can progressively keep on writing again and again changing any 1's to 0's, but once the bit is 0, you cannot flip it back to a '1' unless you do a block/sector erase with erases an entire chunk at once.

This is true for FLASH ic's. They need a block erase command when a 0 needs to be turned into a 1.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 28, 2022, 06:11:37 pm
@nockieboy

About the SD card write you are correct that the card does the erase when needed. Before sending command 24 you have to select the card with command 7 and only when it returns an OK it is ready to receive the write command.

I think my setup should be working okay then - when the system boots up, the SD interface automatically interrogates any SD card plugged into the DECA board to establish if it's SDHC or some other standard.  The SDReader module sends the following commands as part of the bootup process:

CMD0, CMD8, ACMD41, CMD2, CMD3, CMD7 with RCA, CMD16 (set block length to 0x200).

It leaves the card in this state, so the SD card should be in 'transfer mode' by default.  When I write to the card, the SDWriter module assumes that the card is in this state and just transmits CMD24, then the payload and CRC.  I shouldn't have to send CMD7 every time I want to write, unless the SD card is not in 'transfer mode' or I want to select a different card (there's only one, by the way).

As I wrote before look at the code here https://github.com/pecostm32/FNIRSI_1013D_Firmware/blob/main/fnirsi_1013d_scope/sd_card_interface.c (https://github.com/pecostm32/FNIRSI_1013D_Firmware/blob/main/fnirsi_1013d_scope/sd_card_interface.c)

The function "int32 sd_card_write(uint32 sector, uint32 blocks, uint8 *buffer)" takes care of the users write request by calling the function "int32 sd_card_send_command(PSD_CARD_COMMAND command, PSD_CARD_DATA data)" with the needed commands.

This latter function does the controlling of the F1C100s low level SD card interface peripheral.

The card also has to be in the correct state to be able to select and deselect it. This is done with the "int32 sd_card_init(void)" function.

I'll take another look at this code - I seem to have forgotten about it amongst all the other stuff going off, so I'll revisit it to see if I can see what's going wrong with my HDL.  Thanks! :-+

EDIT: I'm going to modify SDWriter to send CMD7 before every write anyway, I think, just to make sure the card is selected.  SDReader (the module I didn't write) seems to go through the whole initialisation process from CMD0 to CMD16 before reading a block (I'm sure I can optimise that later) but for the moment, I think it's probably a good idea that SDWriter at least sends CMD7 before CMD24. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on May 28, 2022, 06:47:16 pm
EDIT: I'm going to modify SDWriter to send CMD7 before every write anyway, I think, just to make sure the card is selected.  SDReader (the module I didn't write) seems to go through the whole initialisation process from CMD0 to CMD16 before reading a block (I'm sure I can optimise that later) but for the moment, I think it's probably a good idea that SDWriter at least sends CMD7 before CMD24. :-/O

Then you also have to add it at the end to do the deselect. (See my write function)

I did my code based upon partially reverse engineering the original firmware, bits of linux source code, other samples I found on the net and the simplified SD card specifications you also mentioned a while back. Did not try it without the 7 commands. Was glad it was working. It also took its time to get it done. Had no previous experience with SD cards what so ever :)

I have tested it with a number of cards but not sure about the actual types. The code does have provisions for SDHC or other standards but to truly test it you need all these different types of cards, which I don't have |O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on May 28, 2022, 07:00:12 pm
The SDReader module sends the following commands as part of the bootup process:

CMD0, CMD8, ACMD41, CMD2, CMD3, CMD7 with RCA, CMD16 (set block length to 0x200).

In my code I see a command 55 before the ACMD41.

Also the response to command 8 should be OK to indicate it being a version 2.0 or later card. Otherwise a different initialization is needed.

The command 7 is send before and after every action my code takes, so you have to make sure yours does the same. So don't send it in the initialization. Use it before and after reading or writing.

Edit: Another thing I noticed is that the card needs to be set to the used clock speed and bus width depending on the type of card. Check this function "int32 sd_card_set_clock_and_bus(int32 usewidebus)" Also look at this function "int32 sd_card_check_switchable_function(void)" These are part of the initialization.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 28, 2022, 08:22:40 pm
The SDReader module sends the following commands as part of the bootup process:

CMD0, CMD8, ACMD41, CMD2, CMD3, CMD7 with RCA, CMD16 (set block length to 0x200).

In my code I see a command 55 before the ACMD41.

Yeah, sorry, I didn't bother listing CMD55 in there as it was implied in the ACMD41, but you're right to question whether it was actually there or not. :-+

Also the response to command 8 should be OK to indicate it being a version 2.0 or later card. Otherwise a different initialization is needed.

The initialisation is fairly basic, but works with the SDHC card I'm using currently.  The HDL is able to identify SDv1, SDv2 and SDHCv2 cards.

The command 7 is send before and after every action my code takes, so you have to make sure yours does the same. So don't send it in the initialization. Use it before and after reading or writing.

Okay, so instead of putting the SD card into 'transfer mode' and leaving it there after initialisation, I should select and deselect the card for each transaction?  Will give that a try.  Am in the midst of adding CMD7 select to the start of each WRITE at the moment.  Can't see how deselecting it will change anything, but might check that out later.

Edit: Another thing I noticed is that the card needs to be set to the used clock speed and bus width depending on the type of card. Check this function "int32 sd_card_set_clock_and_bus(int32 usewidebus)" Also look at this function "int32 sd_card_check_switchable_function(void)" These are part of the initialization.

The initialisation is all done using the SDReader module, which works perfectly - I have no issues with reading sectors from the SD card, so I am assuming initialisation is fine for the SD card.  The only difference with the SDWriter module is that it doesn't do the full initialisation that the SDReader module does before each read.  Unless the SD card 'times out' of transfer mode, it should still be selected and in transfer mode when I perform the first WRITE, hence I haven't bothered with any setup for the WRITE, it just sends CMD24.

We'll see if sending CMD7 and CMD16 again before each WRITE improves anything - hopefully might be able to work on this tomorrow a little more.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on May 29, 2022, 04:38:12 am
We'll see if sending CMD7 and CMD16 again before each WRITE improves anything - hopefully might be able to work on this tomorrow a little more.

I think a better approach is to have a separate initialization module that is only called once. At the end of initialization it should leave the card in a deselected state.

Then before reading select the card with the 7 command, do the read (single block or multiple block as needed) and deselect the card at the end. Do the same for the writing. The setting of the block size with command 16 only needs to be done in the initialization.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 29, 2022, 07:50:04 am
I think a better approach is to have a separate initialization module that is only called once. At the end of initialization it should leave the card in a deselected state.

Then before reading select the card with the 7 command, do the read (single block or multiple block as needed) and deselect the card at the end. Do the same for the writing. The setting of the block size with command 16 only needs to be done in the initialization.

Yes, sounds like a better idea.  I've been wanting to separate the initialisation from the read transaction in the original SDReader module - now is a good time to do that optimisation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on May 29, 2022, 01:10:00 pm
I think a better approach is to have a separate initialization module that is only called once. At the end of initialization it should leave the card in a deselected state.

Then before reading select the card with the 7 command, do the read (single block or multiple block as needed) and deselect the card at the end. Do the same for the writing. The setting of the block size with command 16 only needs to be done in the initialization.

That's done - I haven't created a separate module, I've just made SDReader a little smarter so that it will initialise or read as required by the host.  Working nicely.  Back to working on SDWriter now.  Have a couple of bugs to fix since modifying the HDL to pre-select and de-select the SD card around the write transaction.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 05, 2022, 11:22:33 am
I've been picking away at the WRITE transaction, fixing little timing errors here and there and sorting out the CRC calculation.

I'm now at a stage where I'm getting the correct CRC transmitted for the test block I'm writing - 512 bytes of 0xFF.  The CRC for this test payload is 0x7FA1, as you can see from the SignalTap trace below:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1503784)

The shaded-blue area is the CRC being written to the SD card.  Each vertical blue line is a bit of the CRC - feel free to check those bits, but the value written should be 0x7FA1.  The next bit written is the STOP bit (not marked), immediately after the CRC value.  Then immediately after the STOP bit is written on the rising clock edge of SD_CLK (1x 125MHz clock after, to be precise), SD_D0_DIR goes LOW to read from the SD interface.

According to everything I've read and seen in HDL elsewhere, the SD card should respond in 2 SD clocks with a CRC response.  I'm getting nothing back and the HDL is timing-out the transaction after a further 1,000 SD clocks, waiting for the SD card to pull DAT0 low to signify the start of its response byte.

In my SDWriter module, 512x8 bits are written, plus the 16 CRC bits, the start bit and stop bit for a total of 4,114 bits.  Am I missing something out?

Looking at the HDL for the sd_data_serial_host module used in the previous IP core I tried, it sends 512x8 + 8 bits for the payload.  What are the additional 8 bits for?  When I look at the end of the WRITE transaction in SignalTap for my HDL, it's sending the last byte fine, so I can't see what the additional 8 bits are for?  Anyone have any ideas?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 07, 2022, 05:58:36 am
Ok, here we go nockieboy, v1.6, final test.

I set it to 400MHz Quarter - rate.  It also now appears to work at 500MHz.
Now, remember, the CMD_CLK is now 100MHz, not 150MHz.
(125MHz when you set the DDR3 to 500MHz)

Note that you can achieve 2 x 32bit 1080p windows with the DDR3 set to 500MHz.  Please test the Z80, Geometry, and VGA window functions and report back.  I believe everything should work.

Also, be careful as your old 'BrianHG-DDR3-Controller' folder needs to be flushed as the DDR3 v1.6 has many changes.  The xxx.sdc, xxx_top.sv files, and 'BrianHG_DDR3_GFX_source_v16' folder have also changed.

Let me know how it goes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 09:05:58 am
Ok, here we go nockieboy, v1.6, final test.

I set it to 400MHz Quarter - rate.  It also now appears to work at 500MHz.
Now, remember, the CMD_CLK is now 100MHz, not 150MHz.
(125MHz when you set the DDR3 to 500MHz)

Note that you can achieve 2 x 32bit 1080p windows with the DDR3 set to 500MHz.  Please test the Z80, Geometry, and VGA window functions and report back.  I believe everything should work.

Also, be careful as your old 'BrianHG-DDR3-Controller' folder needs to be flushed as the DDR3 v1.6 has many changes.  The xxx.sdc, xxx_top.sv files, and 'BrianHG_DDR3_GFX_source_v16' folder have also changed.

Let me know how it goes.

Preliminary testing has thrown up no problems so far. :-+  I haven't gotten around to testing the window functions yet, but so far all stress-testing of the Geometry unit is looking good with no errors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 10:12:34 am
SD WRITE update.

Still getting no response from the SD card when I try to write a block to it.  When the write times-out waiting for a CRC response from the SD card, it now sends CMD13 to get the card's status.  Below is the SignalTap trace of that response, plus some labels to save anyone having to decode the response:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1505428)

According to the specs, CSD_OVERWRITE means this:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1505434)

Not sure what that means exactly, or how I can fix it.  Any ideas, @pcprogrammer?

EDIT: If it matters, I'm trying to write to Sector 3.

EDIT2: I've tried a different SD card as well - exactly the same response/error bits reported.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 12:00:52 pm
@nockieboy: Hi, I'm willing to help you, but do not know a lot about the low level workings of SD cards. I did the code for the 1013D as part of the reverse engineering and learned a bit about the commands.

To get a bit deeper I just soldered a bunch of wires to my 1013D and hooked up my Rigol MSO5074 as a logic analyzer. I made a single capture on 5ms time base but it still looks to short for a full write to sector 3.

I connected the 1013D to my PC and started a USB mass storage connection with it. This way I can write a single sector with the linux dd command.

Have to look into the data but it looks like the system runs into a lot of wait time with the clock running and D0 being low. Needs a bit more playing to figure things out.

Edit1: Changed the time base to 50ms and the sample memory to 100MB. Sample rate is then 200MSa/s, which should be enough. The full transaction is now captured. It yields a binary file of 50MB :palm: so no posting here unless it compresses very well. Attached is a picture saved on the Rigol.

Edit2: I zoomed in on the first activity of the signals and wonder if it is correct. D4 is the command line and D5 is the clock line. The data lines are all high. Also added the .csv export form the scope. The lower 6 bits of the hexadecimal entries are the signals. Pre trigger the clock is low and the command and data lines are high.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 01:05:50 pm
@nockieboy: Hi, I'm willing to help you, but do not know a lot about the low level workings of SD cards. I did the code for the 1013D as part of the reverse engineering and learned a bit about the commands.

To get a bit deeper I just soldered a bunch of wires to my 1013D and hooked up my Rigol MSO5074 as a logic analyzer. I made a single capture on 5ms time base but it still looks to short for a full write to sector 3.

Thanks so much for doing this - I really appreciate it.  I'd love to get my hands on a working write trace so I can see exactly what is going on with the bit count etc.

I connected the 1013D to my PC and started a USB mass storage connection with it. This way I can write a single sector with the linux dd command.

Have to look into the data but it looks like the system runs into a lot of wait time with the clock running and D0 being low. Needs a bit more playing to figure things out.

I can explain that.  A write transaction should go something like this:

1) Host sends CMD24 with sector address in the ARGUMENT.
2) SD responds with R1 response
3) Host sends START bit, a block of data (512 bytes), a 16-bit CRC and STOP bit.
4) SD responds with a CRC response (R1, I think) and pulls D0 LOW to signify that it's busy whilst it erases the sector and writes the new data to it.
5) Once the SD has finished writing, it releases D0 and can respond to further commands.

So what you're seeing is normal behaviour - the pause with nothing happening is whilst the SD card writes the new block of data to its addressed sector. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 01:22:17 pm
Thanks so much for doing this - I really appreciate it.  I'd love to get my hands on a working write trace so I can see exactly what is going on with the bit count etc.

You are welcome, and the full capture is attached in the previous post. It is a .csv file instead of the binary, which looks a bit weird. The .csv one shows the bits in a hex value, and the first line specifies the sample time.

I can explain that.  A write transaction should go something like this:

1) Host sends CMD24 with sector address in the ARGUMENT.
2) SD responds with R1 response
3) Host sends START bit, a block of data (512 bytes), a 16-bit CRC and STOP bit.
4) SD responds with a CRC response (R1, I think) and pulls D0 LOW to signify that it's busy whilst it erases the sector and writes the new data to it.
5) Once the SD has finished writing, it releases D0 and can respond to further commands.

So what you're seeing is normal behaviour - the pause with nothing happening is whilst the SD card writes the new block of data to its addressed sector. :-+

I was that thinking it had to be something like that, but the wait times seemed long :)

I'm also looking at the SD card specifications and wonder a bit about the CRC on the data line(s). I think you have to calculate them separately per line, which means creating dedicated buffers or do the calculations on the fly. With multiple data lines the bits have to be distributed on a nibble basis, according to the picture.

It is not a simple system and I'm glad the F1C100s has a dedicated peripheral for it 8)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 01:29:38 pm
Edit1: Changed the time base to 50ms and the sample memory to 100MB. Sample rate is then 200MSa/s, which should be enough. The full transaction is now captured. It yields a binary file of 50MB :palm: so no posting here unless it compresses very well. Attached is a picture saved on the Rigol.

Edit2: I zoomed in on the first activity of the signals and wonder if it is correct. D4 is the command line and D5 is the clock line. The data lines are all high. Also added the .csv export form the scope. The lower 6 bits of the hexadecimal entries are the signals. Pre trigger the lock is low and the command and data lines are high.

If it makes it easier, I don't need to see all of the data lines (D0-D3) - what I really need is the SD_CLK line, CMD line and D0.  If you trigger on D0 going low, that should get the transaction from start to finish, but I need enough resolution so that I can use the clock to decipher what is going on.


You are welcome, and the full capture is attached in the previous post. It is a .csv file instead of the binary, which looks a bit weird. The .csv one shows the bits in a hex value, and the first line specifies the sample time.

I'll have to work on decoding that.  ;)


I'm also looking at the SD card specifications and wonder a bit about the CRC on the data line(s). I think you have to calculate them separately per line, which means creating dedicated buffers or do the calculations on the fly. With multiple data lines the bits have to be distributed on a nibble basis, according to the picture.

Yes, a separate CRC is required for each data line.  Whilst I'm developing the module, I'm working solely in 1-bit mode.  Once I've gotten that working, I'll upgrade it to 4-bit mode which won't take much effort at all - I'm working on the hard part at the moment. :-/O  I'm calculating the CRC on the fly, per data line (of which there's just one currently).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 01:38:57 pm
The trigger was set on the clock line. I looked at the clock speed and it looks low. Only 2MHz or so, were I recall it being set a lot higher in the software. Also not sure which commands are send in the whole transaction being done with the linux dd option.

It was a bit of a spur of the moment action :) I had been thinking about it before, but with your post asking for help I thought lets go and solder some wires and hook up the scope.

Doing a single data line involves more work, because the software needs to be changed then, so hopefully the given capture is good enough to get you going.

D0 is the lsb in the captured data. CLK is bit 5. CMD is bit 4.

Edit: Here is a capture of the startup of the SD card. For the first commands it only uses the single data line.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 01:51:24 pm
Doing a single data line involves more work, because the software needs to be changed then, so hopefully the given capture is good enough to get you going.

No no, don't change your software or anything.  I don't need to see complete bytes - really all I need is every clock in the write transaction and D0 as that includes the START and STOP bits, so don't worry about changing over to 1-bit mode or anything!

EDIT:  D0 is the most important data line, as it signals the start and end of the transaction, as well as the CRC for the data it has transmitted.  D1-3 are just data lines with their CRC at the end, nothing else, so I don't need those.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 01:57:30 pm
I think there is a speed problem. I'm looking at the startup sequence an can see that the clock is slower in the beginning, which is correct, but when it switches to 4 line mode the clk and cmd line seem wrong in relation to each other.

I did not see a signal diagram in the specification on how the clock and the command line relate so it is a bit phishing in the dark |O

Edit: I will connect a normal probe to the clock line and try to figure out what is going on. It could be that the threshold level is to high. Currently set to 1.8V.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 02:01:08 pm
I think there is a speed problem. I'm looking at the startup sequence an can see that the clock is slower in the beginning, which is correct, but when it switches to 4 line mode the clk and cmd line seem wrong in relation to each other.

I did not see a signal diagram in the specification on how the clock and the command line relate so it is a bit phishing in the dark |O

The clock dictates the speed of the CMD line and the DAT lines.  The SD card (and host) reads the value of the CMD line or DAT lines on the rising edge of the clock, so the data/CMD lines must coincide with the clock's rising edges to represent meaningful data.  That last image you posted of your oscilloscope trace didn't seem to have a valid signal on it, if either of the two lines displayed was the clock line.  Are you sure it's hooked up correctly?  Presumably Linux is reading/writing the SD card okay?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 02:19:23 pm
I think there is a speed problem. I'm looking at the startup sequence an can see that the clock is slower in the beginning, which is correct, but when it switches to 4 line mode the clk and cmd line seem wrong in relation to each other.

I did not see a signal diagram in the specification on how the clock and the command line relate so it is a bit phishing in the dark |O

The clock dictates the speed of the CMD line and the DAT lines.  The SD card (and host) reads the value of the CMD line or DAT lines on the rising edge of the clock, so the data/CMD lines must coincide with the clock's rising edges to represent meaningful data.  That last image you posted of your oscilloscope trace didn't seem to have a valid signal on it, if either of the two lines displayed was the clock line.  Are you sure it's hooked up correctly?  Presumably Linux is reading/writing the SD card okay?

I think I found the problem. Poor eyesight :-DD The wires I used are enamel-led so need tinning, which I did, but the connection of the probe with the clock line was not making good contact. It was half on the tinned part and half on the enamel. I'm going to make another capture and check if it works now.

Edit: It was not my eyes, but the clock. Aliasing on the sampling. As I wrote earlier I thought the clock was set higher and it is. 50MHz instead of the 2MHz the measurement showed. Which is a bit strange because the sampling rate according to the scope should have been 200MSa/s which should be high enough to catch the clock.

The question is if it is possible to still capture the whole sequence in 50ms if the clock is lowered to 5MHz? Does a lower clock also affect the erase and write time of the card?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 04:52:18 pm
It looks like I'm having an off day |O

Tried to switch to a lower clock in the software, but with 4.8MHz the scope would not start. On 400KHz, the initial speed, it did start but then the link to the computer fails. After that, finally the light went on :o I did another capture on 2GSa/s, which is at 5ms/div where I noticed that the write of the sector is only the first ~10ms and the rest of the communication is the reading of the card directory. On my linux system I have to un-mount the partition before using dd, and after the dd command it mounts the partition again. So here is a new capture which should do the trick.

Edit: just to be sure here is also a capture on 8GSa/s. 1ms/div.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 06:27:30 pm
It looks like I'm having an off day |O

Tried to switch to a lower clock in the software, but with 4.8MHz the scope would not start. On 400KHz, the initial speed, it did start but then the link to the computer fails. After that, finally the light went on :o I did another capture on 2GSa/s, which is at 5ms/div where I noticed that the write of the sector is only the first ~10ms and the rest of the communication is the reading of the card directory. On my linux system I have to un-mount the partition before using dd, and after the dd command it mounts the partition again. So here is a new capture which should do the trick.

Edit: just to be sure here is also a capture on 8GSa/s. 1ms/div.

Thanks for doing this pcprogrammer, it's a real help.  I'm just looking into viewing/manipulating the .CSV files.  Is there any chance you could post the .DAT version of those captures, rather than the CSV? :)  I can import the .DAT format into Octave and view it with minimal fuss, it seems, but I'm having trouble doing anything usable with the CSVs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 07, 2022, 06:40:40 pm
The Rigol only supports .bin, .wfm and the .csv. At first I looked at the .bin data, but it's not clear to me how the data is stored there. Don't know about the .wfm format. To try that one I would have to do a new capture since the scope won't load the .bin or .csv back into memory :palm:

Probably not to difficult to convert the .csv file with a bit of c code if you know the .dat format. I'm not familiar with it nor the Octave program you mentioned.

As I'm winding down now any action has to wait till tomorrow though.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 07, 2022, 06:59:14 pm
The Rigol only supports .bin, .wfm and the .csv. At first I looked at the .bin data, but it's not clear to me how the data is stored there. Don't know about the .wfm format. To try that one I would have to do a new capture since the scope won't load the .bin or .csv back into memory :palm:

Ah - I only suggested .DAT because I'd read in another forum where a question was asked about viewing .CSVs in something other than Excel (which won't open the whole file due to its size) and a respondent suggested saving the data in .DAT instead of .CSV, as a piece of freeware called Octave can view the .DAT with an add-on.  I'd assumed they were still talking about the Rigol the OP was asking for, but apparently not.

I'm not familiar with Octave (http://www.gnu.org/software/octave/index.html) either, was just hoping for a quick way to view the data - I'm away for four days after tonight, so it won't be until next week when I can spend some time checking out Octave to see if it will do what I want or write a program to do what I want.  I'll post an update next week!  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 08, 2022, 01:14:31 am
I found an easy to make game which uses tile mode where if you find the roms online, since it is an NES game, is has a separate tile rom file.  My GPU hardware should be able to do this quite easily with a text layer, another for the score and one extra layer for the player sprite: https://youtu.be/c_SPGJxZ1LM?t=2
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 08, 2022, 03:40:20 am
@nockieboy, new parameters in the DDR3 controller in your gpu top.sv:

Code: [Select]
parameter bit    PORT_R_CACHE_TOUT_ENA [0:15] = '{  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1},
                                                // A 0 will direct the read cache to indefinitely keep its contents valid until a new read address is
                                                // requested outside the the current cache contents.  Recommended for very slow read cycles where you may
                                                // manually read outside the current cached address if you wish to re-read from the DDR3.
                                                // A 1 will use the automatic timeout setting below to automatically clear the read cache address.
parameter bit [8:0]  PORT_R_CACHE_TOUT [0:15] = '{256,256,256,256,  0,256,256,256,256,256,256,256,256,256,256,256},
                                                // A timeout for the read cache to consider its contents stale.
                                                // 0   = Always read from DDR3, or no read caching.
                                                // 256 = Wait up to 256 CMD_CLK clock cycles since the previous read req before considering the cached read stale.

Looking at the 'PORT_R_CACHE_TOUT_ENA', you will see I have the 8bit Z80 port disabled, meaning that the read cache is held indefinitely.  If you change the Z80 port to a '1', then looking at the ***_TOUT setting set to 256, it means if the Z80 preforms a read within the cache within 256 CMD_CLK cycles, the Z80 will get an immediate answer from the cache.  If it takes longer than 256 CMD_CLKs since the last read on that port, then your read command will be fetched from the DDR3 even if there is a cache match.  Remember, the timer counts the 100 MHz CMD clock cycles, not the Z80 8MHz clock cycles.

Also note that the 128 bit VGA system on channel 4 has the cache enabled with the timeout set to 0 to prevent it from using the read cache system as it has compatibility issues with some video modes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 09, 2022, 05:00:21 am
I'm not familiar with Octave (http://www.gnu.org/software/octave/index.html) either, was just hoping for a quick way to view the data - I'm away for four days after tonight, so it won't be until next week when I can spend some time checking out Octave to see if it will do what I want or write a program to do what I want.  I'll post an update next week!  ;D

As I'm also intrigued by this SD card stuff I looked into it and converted the data to Sigrok input. At first I tried to do it with the Saleae format but that fails for some reason I can't put my finger on. Then I remembered some mention of the open source Sigrok project and that file format is very easy and it worked straight away :)

You can download the appimage for your system here: http://sigrok.org/wiki/Downloads (http://sigrok.org/wiki/Downloads)

Edit1: Sigrok supports SD card (SD mode) protocol decoding. Saves on doing work on that :-+
Edit2: Due to the ~50MHz signal speed and the way the logic analyzer probe is connected there are glitches in the data, but the protocol decoder seems to function properly. I noticed that the write is done with the multiple blocks command (CMD25). If the capture is not conclusive for your problem I can do another with some test software that only uses the one data line and CMD24. Just let me know if you need that.

Remove the .zip extension and load it into Sigrok.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 11, 2022, 06:32:46 pm
The final release v1.6!   :box:
All bugs fixed with some final fine tuning of internal controls.  :phew:
Your project should achieve timing FMAX once you finish up the timing .sdc for your SD card.
(Note it already passes at 0deg, plus a few Mhz slow on one VGA clock[1] at 85deg.)

Download attached file and assume all of my DDR3 folder, VGA System folder, your xxx_top.sv, .sdc and maybe some compiler controls in the project configuration have been changed.

See my new 2 layer LSD hallucination ellipse demo here: https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg4230856/#msg4230856 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg4230856/#msg4230856)

Yes, the demo would still run at 400MHz, like your GPU, but the ellipses draw slower.  Also, this means 4 full screen sized super-imposed 16 bit 1080p windows is now possible as well as 8 layers at 720p and all 16 layers at 480p 32bit color.  (If these windows are smaller than full screen, or X zoomed, or in text mode, then even 4x32bit color is possible.)  You should be able to increase the 'PDI_LAYERS' from to 4 to 8, allowing 8x 1080p layers with 8 bit pixels, maybe 1 of those 8 at 16 or 32 bit (maybe more running at 500MHz).  8 PDI layers would also double all the other layer counts as well.  You may need to increase the 'HW_REGS' size, or check that all the window controls don't interfere with the base address for the palettes and font/tile memory.  I would save this for after you get the SD card and audio are working as compile times will also vastly increase.  Temporarily lowering both the PDI and SDI layers to 1 would vastly shrink compile time, but should maintain compatibility so long as you are only using layer 0.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 12, 2022, 05:05:15 am
Full final BrianHG_DDR3_Controller_v16 with VGA window system here:
https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415 (https://www.eevblog.com/forum/fpga/brianhg_ddr3_controller-open-source-ddr3-controller/msg3606415/#msg3606415)

And here:
https://github.com/BrianHGinc/BrianHG-DDR3-Controller (https://github.com/BrianHGinc/BrianHG-DDR3-Controller)

And complete .zip package here:
https://github.com/BrianHGinc/BrianHG-DDR3-Controller/archive/refs/tags/v1.60.zip (https://github.com/BrianHGinc/BrianHG-DDR3-Controller/archive/refs/tags/v1.60.zip)

@nockieboy, don't forget to update the Fork of my DDR3 controller in your Github repository using the 'Fetch upstream' function.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 13, 2022, 03:48:14 pm
As I'm also intrigued by this SD card stuff I looked into it and converted the data to Sigrok input. At first I tried to do it with the Saleae format but that fails for some reason I can't put my finger on. Then I remembered some mention of the open source Sigrok project and that file format is very easy and it worked straight away :)

You can download the appimage for your system here: http://sigrok.org/wiki/Downloads (http://sigrok.org/wiki/Downloads)

Edit1: Sigrok supports SD card (SD mode) protocol decoding. Saves on doing work on that :-+
Edit2: Due to the ~50MHz signal speed and the way the logic analyzer probe is connected there are glitches in the data, but the protocol decoder seems to function properly. I noticed that the write is done with the multiple blocks command (CMD25). If the capture is not conclusive for your problem I can do another with some test software that only uses the one data line and CMD24. Just let me know if you need that.

What a stroke of luck, I'd already downloaded PulseView last week when I was first looking at decoding the .CSV file you'd posted.  It works really well with the .SR - makes viewing the data very easy.  Yes, there are some glitches in the data and the protocol decoder seems to be confusing commands with responses in the decoded values, but that's no problem - the important thing is that I can see what's going on at a clock-by-clock level.   It's a shame there isn't a single block write in there, that would really allow me to make a direct comparison with my SignalTap traces (no idea how or even if you could do that), but it's an excellent start - thanks very much for your work on this, pcprogrammer! :-+

Hopefully I'll have more time later this week to really dig into the data.

Full final BrianHG_DDR3_Controller_v16 with VGA window system here...

@nockieboy, don't forget to update the Fork of my DDR3 controller in your Github repository using the 'Fetch upstream' function.

Will do BrianHG and thanks again for this fantastic project.  Once I've got the SD interface sorted, I'll have to write a game like the one you linked previously. ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 14, 2022, 04:21:54 pm
Quick update.  Had a little time to look at the data @pcprogrammer posted of his SD write transaction in PulseView and do some graphical comparisons with my own SignalTap data from the uCOM's SD interface.

Nothing major to report so far, other than the clock is inverted in the data you've provided, @pcprogrammer.

Other than that, I've compared the response to my CMD24 (single block write) with the CMD25 (multi-block write) command in your data, and found that what I previously thought was an error report in this post (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4221643/#msg4221643) actually appears to be a correct and normal response, as it mirrors the response @pcprogrammer gets when his FNIRSI (is that what it is?) sends CMD25.  Here's a pic to illustrate the point:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1511932)

So as far as I can tell, my SD interface is sending the command to write to the SD card okay.  I'm going to have to look at other issues - the first being the timing.  There's a large gap between the response from the SD card after CMD24 is sent and the data block being written to the SD card, due to how the HDL handles the CMD transaction (I didn't write that HDL, but looks like I'll have to have a closer look at it).

(The image shows the SignalTap trace from my SD interface's CMD24 response, overlaid with the CMD25 response from @pcprogrammer's data.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 14, 2022, 04:47:28 pm
@pcprogrammer gets when his FNIRSI (is that what it is?) sends CMD25.

Yes it is the FNIRSI-1013D, but it will be the same for all these devices using the F1C100s MCU.

At least you found one difference between the two sets of data :)

Can you export the signal tap data to a file and use that in Sigrok PulseView? The protocol decoder might shed some light on the problem.

Edit: A bit strange that the clock has a different phase then yours. Could that be your problem? There is nothing on the PCB or the scope that could have inverted that signal. The SD card holder is connected straight onto the MCU with only pull-ups on the signals, and the scope logic analyzer probe was directly connected to the signals with no special settings on the scope.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 14, 2022, 06:37:31 pm
At least you found one difference between the two sets of data :)

Yes, and it's cleared up some confusion over the response to the write command!

Can you export the signal tap data to a file and use that in Sigrok PulseView? The protocol decoder might shed some light on the problem.

Unfortunately no, it would appear not.  SignalTap is fairly restrictive in how it can export the data - CSV is the only format compatible with PulseView, and I haven't worked out how to import it into PulseView yet without crashing it. ::)

Edit: A bit strange that the clock has a different phase then yours. Could that be your problem? There is nothing on the PCB or the scope that could have inverted that signal. The SD card holder is connected straight onto the MCU with only pull-ups on the signals, and the scope logic analyzer probe was directly connected to the signals with no special settings on the scope.

Nothing is ever straightforward, is it?  ;)  I did consider that the difference in phase might not be due to error and could be the cause of the issue, but that possibility can be discounted when you realise I have a fully functional READ side to the interface, using the same clock and phase.  Unless reads are done differently. ???

You gave me sufficient doubt to compile a new version of the interface with an inverted SD clock - this didn't work at all (reads were broken), so I tried another build with just an inverted WRITE clock, just for the hell of it.  SignalTap reports identical waveforms to the ones you've provided from your FNIRSI.  Communication with the SD card still worked - the commands being sent were being responded to in exactly the same way as before without the inverted sd_clk - unfortunately, still no change in the outcome of the write process, though; the block of 512 bytes is written, CRC and STOP bit but still no response from the SD card.  :-//

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 14, 2022, 06:59:37 pm
That is a bummer. It's these kind of things that can drive you nuts |O

Have you considered trying it with a lower clock speed?

FPGA retro computing is on my to do list and I believe the Xilinx Artix 7 board I have has a four bit SD card connection, but I'm still in infancy stage with modern FPGA. Also at the moment busy with the last bits of our house and that is taking a lot of energy, so not enough left to undertake such a new adventure :(

At first I'm thinking about just recreating a Tandy TRS-80, which was my first computer, on a Xilinx Spartan 6 board I have. Getting back in to it with ISE and work up to the Artix 7 and Zynq in Vivado. But also have to finish my DDS project Brian helped me with. The FPGA is done, but the software on the MCU needs to be made.

Lost of projects and ideas to work on.

Did you post pictures of your project? Have not read this whole thread, but am interested to see what you have got. Believe you are using a genuine Z80 connected to the FPGA?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 14, 2022, 10:21:53 pm
That is a bummer. It's these kind of things that can drive you nuts |O

Yes, this one sure is, but I've uncovered what I think could be an interesting lead.  Whilst looking at other sources of documentation about SD interfaces, I came across this application note (https://www.analog.com/media/en/technical-documentation/application-notes/ee335_rev1.pdf) which talks about interfacing SD cards with BlackFin processors.  I have no idea what a BlackFin processor is, but found an interesting nugget of information on page 17 under the heading 'Send Data'.  Item 5 in the list specifies exactly 4,121 clock cycles for the transaction.

Now I'd normally be very careful and sceptical about plucking random numbers from unknown sources and ascribing mystical importance to them, but in this case that number of clock cycles exactly matches the number of 'transfer cycles' (SD clock cycles, basically) used in the SD-card-controller IP core I tried previously with no luck to use (with the Wishbone interface).  I'm going to have to go back to the write function in its sd_data_serial_host module and really pick it apart to understand what those extra clocks are being used for.

My interface currently only sends 4,114 clock cycles - it is ~8 clock cycles short (give or take the STOP bit), which would explain why there's no response from the SD card at the end of the block transfer - as far as the SD card is concerned, it's still waiting for the final 8 clocks to complete the write transaction.   ??? :-/O

Did you post pictures of your project? Have not read this whole thread, but am interested to see what you have got. Believe you are using a genuine Z80 connected to the FPGA?

There've been screenshots of the video output when we were working on that, I think I posted a picture once earlier in the thread (about a year or two ago, maybe), so here's some more at the end of the post.  :)  Yes, it's a classic Z80-based 8-bit computer, modular design but vertical-stacking instead of the more common 'cards into a motherboard'-type setup, like the RC2014.  My goal was to create something more powerful than my first computer - an Amstrad CPC 464.  That has been achieved in spades..  It has 4MB of memory, runs at 8 MHz, has a CF card for storage (hopefully soon to be upgraded to SD card!), battery-backed clock, FRAM/anything else you can stick on I2C, had an authentic AY-8192 sound card at one point (looking to replicate that in HDL at some point), and graphics on par with 16-bit consoles of the early 90's.

This breadboard shot is where it all began, with a 7-chip computer I built thanks to Grant Searle.  I knew next to nothing about electronics before that.  Still don't, now.  ;)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1512175)

This is my uCOM at an early stage.  There's a couple more cards on the stack and a DECA at the bottom of it all at the moment:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1512187)

Here's a part-built prototype GPU card:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1512181)

And this last one is the uCOM with an early-prototype GPU card on the top, based on the Intel/Altera EP4CE10.  I'll get round to designing and building another card one day, once supplies of Cyclone V's and/or MAX10's improve.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1512193)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 14, 2022, 11:26:29 pm
Now I not sure whats going on, but I assume you had someone else's SD-card reader working.
Then, you piggie-backed your own writing module?

If so, this means you have to read the SD card spec anyways, right?

I did say around a month ago when this all started that you should write your own interface from scratch...

Like I was trying to tell you back then, if you wrote your own interface as a numeric 'case (program_counter_reg)' sequencer written like a assembly program with 'case(pc) ###: begin/end' using basic numbers as line counters to control the SD card, you would have been finished by now.  I have even used such a sequencer in my DDR3 controller to power up & initialize the DDR3 & tune the PLL. so, I know it is well within your capabilities.

If you don't think so, read lines 1028 and up here: https://github.com/BrianHGinc/BrianHG-DDR3-Controller/blob/9bf047511a7b38ac3fdf6dd8d5c34ce3bbeaddcc/BrianHG_DDR3/BrianHG_DDR3_PHY_SEQ_v16.sv#L1028 (https://github.com/BrianHGinc/BrianHG-DDR3-Controller/blob/9bf047511a7b38ac3fdf6dd8d5c34ce3bbeaddcc/BrianHG_DDR3/BrianHG_DDR3_PHY_SEQ_v16.sv#L1028)

Look, I have a program counter called 'init_pc', and inside my line numbers, I have the equivilant of GOTO, CALL/GOSUB, Wait for interrupt, and do a specific thing at any line number I like.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 15, 2022, 08:40:09 am
@nockieboy

Looks good your PCB stack. Did you design the boards yourself? If so, impressive for someone who knew next to nothing about it. :-+

About the number of clocks, did you also see this in the capture I made?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2022, 10:47:51 am
@nockieboy

Looks good your PCB stack. Did you design the boards yourself? If so, impressive for someone who knew next to nothing about it. :-+

Thank you. ;D Yes, I designed them myself, although the GPU card was with a lot of help from this forum.  I know my way around a 3D graphics program so I guess PCB design just flowed on from that - I've learned a hell of a lot from the guys in this forum, especially when it got to designing the GPU card.  Up to that point, the smallest components I'd soldered were a couple of 0805 resistors, the rest was through-hole.  Now I'm happily designing for an FBGA-256 package, with 0402 components, QFNs etc. and have produced these little cards to test a suitable USB host solution - I know you can buy RP2040 cards really cheaply, the same for SAMD21 cards from Adafruit etc, but nothing I could find had a full-size (Type A) USB socket where I needed it so I could plug a keyboard in and use it as a USB host.  The CH559 is a real niche chip too with no open-source test cards for it, so I built my own:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1512553)

About the number of clocks, did you also see this in the capture I made?

I haven't counted the clocks in your capture - I wasn't sure if there was some glitching and clocks were being missed out - there's gaps in the clock signal every 8 bits or so.  Plus, the transaction you've recorded is a multi-block write, so it's unlikely to have the same clock count as a single-block write.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2022, 11:05:26 am
Now I not sure whats going on, but I assume you had someone else's SD-card reader working.
Then, you piggie-backed your own writing module?

If so, this means you have to read the SD card spec anyways, right?

I did say around a month ago when this all started that you should write your own interface from scratch...

Essentially, yes.  I have a working READ example which I have built upon to add the WRITE function.  To be fair, I'm not sure where I'd have started if I'd attempted to do it all from scratch.

Like I was trying to tell you back then, if you wrote your own interface as a numeric 'case (program_counter_reg)' sequencer written like a assembly program with 'case(pc) ###: begin/end' using basic numbers as line counters to control the SD card, you would have been finished by now.  I have even used such a sequencer in my DDR3 controller to power up & initialize the DDR3 & tune the PLL. so, I know it is well within your capabilities.

I have no issue with using a numeric sequencer - it's not too different to the state machine I'm using now, but I guess it'd be easier to read.  The problem I've had is the lack of information I can make use of.  I know it should all be in the SD spec docs, but accessing and understanding that information is no mean feat when I've been as busy as I have been.  I haven't found any explicit documentation, tables or charts explaining what a single-block WRITE transaction should look like, clock-by-clock, aside from this:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1512571)

But that doesn't explain the discrepancies I've found when I calculate the bit count for a WRITE transaction and compare that with what is used in the IP core I tried initially:

START bit + 512*8 data bits + 16 CRC bits + STOP bit = 4,114 bits - not 4,122 bits which the IP core uses and now appears to be backed-up by a separate source which I found last night, so I'm going to have to look into that in more detail.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 15, 2022, 11:17:53 am
Well hats off to you, and indeed the forum is great. Lot of knowledge among all of us.

This FBGA-256 package you mention do you mount these your self or do you use an assembly service for them?

The trickiest I did so far is a lqfp-48, replacing a Chinese CS32F103 with a STM32F303. For the rest the smallest SMD was 0805 on some boards I designed for my central heating system. A raspberry pi based system with opto isolated valve control and also opto isolated 1 wire temperature sensors.

(http://[attachimg=1])
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2022, 11:36:32 am
This FBGA-256 package you mention do you mount these your self or do you use an assembly service for them?

No, I'll be mounting it myself, unless I get really lazy.  I have a hot plate and a half-decent hot air gun, so I'm fairly confident I'll be able to manage it successfully after checking out lots of online information/videos and picking the brains of the good people here. ;)  There's plenty of people in this forum who have DIY-soldered BGA chips to seek advice from.

The trickiest I did so far is a lqfp-48, replacing a Chinese CS32F103 with a STM32F303. For the rest the smallest SMD was 0805 on some boards I designed for my central heating system. A raspberry pi based system with opto isolated valve control and also opto isolated 1 wire temperature sensors.

LQFPs shouldn't be an issue at all once you've gained a little confidence in mixing and using some solder paste.  My prototype GPU (pictured above) uses the EP4CE10 in an E-QFP144 package.  The only awkward part of soldering it was the ground pad beneath the package - just had to add some paste, position the chip, solder a couple of legs to pin it in place, then heat from underneath with my hot air gun to get the pad hot enough to melt the solder.  Worked fine.  For the pins, I just mixed a little flux with some cheap Chinese solder paste to make it easier to spread (and less likely to ball or form bridges) and drag-soldered the pins.  Once you get confident with the technique, you can use the flux/solder-paste for just about everything and now I find it easier than through-hole soldering.  ;D

re: SD timings
I've had a close look at the original IP core and realise why it was calculating the payload size as 512*8 + 8.  Because the block size was set to 511, not 512 - so it was actually 511*8 + 8, which clears up the confusion about the extra 8 bits.  I think I may have identified a couple of timing issues with my HDL too, so I'll need to look closer at those.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 15, 2022, 01:10:40 pm
You are right about smt being easier then through hole. No snipping of the wires sticking out of the board. Having the proper tools also helps. And practice, lots of practice. A good microscope helps a lot.

Yeah compensation for a wrong size can easily be overlooked. Hopefully you get it sorted out soon. Success :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 15, 2022, 03:51:28 pm
You are right about smt being easier then through hole. No snipping of the wires sticking out of the board. Having the proper tools also helps. And practice, lots of practice. A good microscope helps a lot.

I use a loupe at the moment, but might invest in a microscope of some description as and when I get started on the final graphics card.

Yeah compensation for a wrong size can easily be overlooked. Hopefully you get it sorted out soon. Success :-+

I'm tying myself up in knots with 0-based and 1-based counting - such basic math concepts are real issue to me for some reason, which I think is causing me a lot of confusion and mistakes in the HDL.  :palm:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 20, 2022, 10:43:44 am
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1517014)

Finally. :phew:

I have the write module working for the SD card.  My stubbornness has finally paid off and I've fixed the two remaining bugs that were preventing it from working! ;D  I can now read/write to the SD card at the sector level in 512 byte blocks.  I still need to give the module the ability to switch between 1-bit and 4-bit SD modes, but it's working fine in 1-bit mode currently.  Then I just need to write some drivers for it to replace the CF card in the uCOM - yay! ;D :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: pcprogrammer on June 20, 2022, 11:27:39 am
The bus width switching is simple.

Code: [Select]
    //Check if 4 bit bus should be used
    //Send application specific command follows command to the card
    sd_command.cmdidx    = 55;
    sd_command.cmdarg    = cardrca;
    sd_command.resp_type = SD_RESPONSE_CRC | SD_RESPONSE_PRESENT;
    result = sd_card_send_command(&sd_command, 0);
     
    //Send set bus width command
    sd_command.cmdidx    = 6;
    sd_command.cmdarg    = 2;
    sd_command.resp_type = SD_RESPONSE_CRC | SD_RESPONSE_PRESENT;
    result = sd_card_send_command(&sd_command, 0);

(Left out the checks on result)

Basically a command 55 followed by a command 6.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 20, 2022, 11:49:10 am
Basically a command 55 followed by a command 6.

Yes, sending the command is simple enough, I just need to update my HDL to work in 1-bit and 4-bit mode.  It's simple enough too - just need to change from sending single bits of data down D0 like this:

Code: [Select]
sddat_o[3:0]  <= { 3'h7, writebyte[rlsb] } ;
to sending 4 bits at a time down D3-D0 something like this:

Code: [Select]
sddat_o[3:0]   <= { writebyte[7-rlsb], writebyte[6-rlsb], writebyte[5-rlsb], writebyte[4-rlsb] } ;
... and decrementing rlsb by 4 instead of 1 each sd_clk.  CRC calculations will also be modified in the same way.

Before I do that, though, I've made a start on the SD driver for the uCOM.  It won't make any material difference to the driver if the SD card works in 1-bit or 4-bit mode - one will just involve waiting about a quarter of the time for stuff to happen. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 20, 2022, 05:39:03 pm
 :-+  Way to go...

So, what's next?
Will we soon see a .bmp or .tif picture viewer working on your Z80.  So long as you use the uncompressed variants, you should be able to copy the file into DDR3 ram and set the right window registers to view the picture with the one caveat of needing to copy the palette data to the lower palette address space for 256 color images.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 21, 2022, 02:15:15 pm
So, what's next?
Will we soon see a .bmp or .tif picture viewer working on your Z80.  So long as you use the uncompressed variants, you should be able to copy the file into DDR3 ram and set the right window registers to view the picture with the one caveat of needing to copy the palette data to the lower palette address space for 256 color images.

That'd be nice, but first I have to get CP/M working with the SD card.  I'm at the bug-hunting and fixing stage with the SD BIOS and CP/M driver currently.  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 22, 2022, 03:38:21 pm
Okay the operating system seems to be happy now and I've got it all running on the uCOM without the CF interface card in the stack, which is an achievement in itself.  I'm finally rid of Compact Flash as the uCOM's storage medium.  Plus the SD card is slightly quicker, even in 1-bit mode.

Will we soon see a .bmp or .tif picture viewer working on your Z80.  So long as you use the uncompressed variants...

Yeah, about that - I've just had a quick look to see how to save BMP and TIFF images without compression (I'm using Paint.NET) - it's saving them compressed, which doesn't help.  I need to dig out my notes that I made previously when I put the parallax scrolling demo together on how to save uncompressed images, but I think that was raw data I was saving, not an image format like BMP or TIFF.

@BrianHG - As for what's next - aside from some minor work on CP/M programs - I'm probably going to start on moving the MMU from hardware on one of the memory cards to HDL in the FPGA, unless you have any more plans for the GPU side of things?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 22, 2022, 03:53:26 pm
Yeah, about that - I've just had a quick look to see how to save BMP and TIFF images without compression (I'm using Paint.NET) - it's saving them compressed, which doesn't help.  I need to dig out my notes that I made previously when I put the parallax scrolling demo together on how to save uncompressed images, but I think that was raw data I was saving, not an image format like BMP or TIFF.

Funny, most .bmp arent compressed at all.  For .tif, there is usually a feature in the save dialog to choose since not all .tif readers can handle compressed .tif.

Anyways, here is one of my old .bmp savers : https://github.com/BrianHGinc/SystemVerilog-TestBench-BPM-picture-generator/blob/06fd942d861b9408b6644238e501734a1bc3aa7c/ellipse_generator_tb.sv#L177 (https://github.com/BrianHGinc/SystemVerilog-TestBench-BPM-picture-generator/blob/06fd942d861b9408b6644238e501734a1bc3aa7c/ellipse_generator_tb.sv#L177)

Though, I believe I got the header info from wiki.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 23, 2022, 02:06:25 am
@BrianHG - As for what's next - aside from some minor work on CP/M programs - I'm probably going to start on moving the MMU from hardware on one of the memory cards to HDL in the FPGA, unless you have any more plans for the GPU side of things?
It looks like I'm temporarily retiring.
Maybe in a ~year I might re-visit GPU stuff.

You need to catch up and test everything I have done up until now.  You will need a good strongly integrated file system and memory management working first for any new software attempts at running the sort of graphics processing you already have access to.  I mean, you have access to hi-res, 32bit color, 16 or 32 layer graphics, fonts/tiles, geometry acceleration, bitmap copy and scaling.  Anything new I generate will want to make use of all of that.  Without some infrastructure to feed it all, if I make a major piece of HDL, how long will it take until you can show me all the new commands working?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 23, 2022, 07:48:04 am
It looks like I'm temporarily retiring.
Maybe in a ~year I might re-visit GPU stuff.

Well, thanks for all your help and hard work so far!  I hope the work trying to fix that final bug in the DDR3 controller didn't burn you out.

I'll keep plugging away at the side projects in the meantime - moving the MMU to HDL will be my first priority.  Once that's done I'll be able to read the MMU and discover the current bank mappings (it's write-only at the moment) without having to keep trace of them in a set of variables (which has hardly proved that accurate so far!) ;)  Then I've got to finish my work on the USB HID interface.   Then integrate the sound generator.  Plenty to keep me busy for years to come at the rate I'm working currently. :-\  I'll create new threads for any questions I have about those specific sub-projects.

You need to catch up and test everything I have done up until now.  You will need a good strongly integrated file system and memory management working first for any new software attempts at running the sort of graphics processing you already have access to.  I mean, you have access to hi-res, 32bit color, 16 or 32 layer graphics, fonts/tiles, geometry acceleration, bitmap copy and scaling.  Anything new I generate will want to make use of all of that.  Without some infrastructure to feed it all, if I make a major piece of HDL, how long will it take until you can show me all the new commands working?

Good question. I don't have the free time to dedicate to software development AND HDL development at the same time, currently.  Let me spend some time putting a game or two together to see what can be done with the existing setup.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 23, 2022, 11:42:26 am
I'll keep plugging away at the side projects in the meantime - moving the MMU to HDL will be my first priority.  Once that's done I'll be able to read the MMU and discover the current bank mappings (it's write-only at the moment) without having to keep trace of them in a set of variables (which has hardly proved that accurate so far!) ;)

Hmmph, well that didn't take me long. I guess I'll start playing with the AY-8910 PSG HDL and integrate that into the design. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 23, 2022, 08:05:36 pm
I'll keep plugging away at the side projects in the meantime - moving the MMU to HDL will be my first priority.  Once that's done I'll be able to read the MMU and discover the current bank mappings (it's write-only at the moment) without having to keep trace of them in a set of variables (which has hardly proved that accurate so far!) ;)

Hmmph, well that didn't take me long. I guess I'll start playing with the AY-8910 PSG HDL and integrate that into the design. :-/O
Ok.  So quick and simple, care to share what you did?
What did the code look like?
Can you address all 512mb?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 23, 2022, 09:21:27 pm
I'll keep plugging away at the side projects in the meantime - moving the MMU to HDL will be my first priority.  Once that's done I'll be able to read the MMU and discover the current bank mappings (it's write-only at the moment) without having to keep trace of them in a set of variables (which has hardly proved that accurate so far!) ;)

Hmmph, well that didn't take me long. I guess I'll start playing with the AY-8910 PSG HDL and integrate that into the design. :-/O
Ok.  So quick and simple, care to share what you did?
What did the code look like?
Can you address all 512mb?

I've been able to address all 512MB for some time now, with a couple of additional registers accessible to the host via IO that give the host access to the full DDR3 memory space by changing the 512KB 'window' that is presented.  The changes I made today were more about upgrading my existing hardware MMU, the original one that gives the Z80 access to 4MB of memory space in 16KB pages using two 74LS670s (which seem to be getting more and more scarce).  The big problem with the existing MMU setup was that it was write-only, so I had no easy way of knowing which bank was mapped to which area without keeping track of every write to the MMU in four bytes of RAM.  I was still unable to work out exactly which ROM bank the DMI or Bootstrap was loading from at cold boot.

What I did this morning was more a quick hack than a true solution to the HDL MMU task, but it gives me the same results - I'm just copying the writes to the MMU's IO addresses in the Z80_Bridge and recording the bank values.  Any reads to the MMU's four Area addresses are responded to by Bridgette with the stored value (current Bank #).  Simples.

The github project (https://github.com/nockieboy/gpu) has been updated with the latest project code, including the fully working SD interface (1-bit mode currently).

Now I'm fully aware that I haven't actually replaced the hardware MMU on the uCOM's memory card just yet, but what I've done in about 10 minutes work is provide all the benefits of the HDL MMU and none of the headaches (the HDL MMU will still be limited to 16KB banks because of how the EA bus is wired on the DECA interface card).  When I decide later that I've got to build another memory card and can't find any spare LS670s any more, I can just add a few lines of HDL to Bridgette swapping the direction of the EA bus buffer and where it intercepts memory read/writes I can tell it to output the appropriate additional address data according to the current mapping value for the 16KB Area being addressed and output the correct address lanes via the EA bus.

I did have the thought this morning that I could just get the HDL MMU to map the Z80's entire 64KB RAM space into the DDR3 and remove the memory card entirely from the stack- but at the moment I feel that's a step too far in reducing my hardware project that I have enjoyed learning about, designing and building to bland HDL.  I could also make the banks smaller - say 4KB instead of the current 16KB - which would provide more flexibility.  That's a job for another day, though.  My 'quick hit' objective was completed, so it's time to move on to the sound (hopefully!) 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 23, 2022, 09:55:35 pm
Replicating the 74LS670 shouldn't be a problem to replicate in HDL with nothing more than a logic array: x bits by x words.

Feeding bank address bits position into that logic array, where the logic data output is wired to the upper address of the DDR3 controller to address all your ram bank by bank should also be easy.

Reset clears the array to 0,1,2,3.... to feed through the full Z80 upper address bits, 64k uninterrupted.
Also, I assume you have a write data or port into the array to fill the upper address for each bank group.

Code: [Select]
IE: to get the full rw addr:

// register to hold 16 banks of 4096 words each with an extra 16 address bits.
// (This is a 256 megabyte example)
logic [15:0] page_remap [0:15] = '{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} ; // Default passes through the Z80's upper address bits untouched.

// Drive the DDR3 address with the stored banks inserted above the first 12 address bits.
assign DDR3_addr[31:0] = {4'd0, page_remap[z80_addr[15:12]], z80_addr[11:0] };

// To set a bank :
if (reset) page_remap <= '{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} ; // After reset, everything runs as a direct address feed-through.
else if (port_data_bankset_pulse) page_remap[port_data_bankset[3:0]] <= {port_data_bankadr_h,port_data_bankadr_l} ;

If so, how is this so difficult to implement?
Obviously, you can parameterize the width and address bit locations, like making each bank size like 4 banks of 16k instead of 16 banks of 4k, leaving you with 1gbyte addressable space.

Also, you can make 2x page_remap arrays.  One for write data, and one for read data.

You can also pipe out an asynchronous EA bus with 1 line:
Code: [Select]
EA_bus <= page_remap[z80_addr[15:12]];generating your FPGA based MMU upper address bits for external use, just don't forget to move the address bits on your peripherals.

You can go extra dumb by just using 32 ports, every 2 ports being 16 bit word of your 'page_remap' saving Z80 cpu cycles when filling the MMU table.  The 'page_remap' could also be 32 bytes of writable ram, but this will leave a hole in your address space as the MMU needs access no matter what it's contents are whereas ports wont.  Also remember, you can read as well as write ports.  Just tie the 32 port outputs into 32 port inputs of the same port number.

IE:
Code: [Select]
wire [15:0] page_remap [0:15] = '{ // assign 16 banks of 4kb
{port0,port1},
{port2,port3},
{port4,port5},
{port6,port7},
{port8,port9},
{port10,port11},
{port12,port13},
{port14,port15},
{port16,port17},
{port18,port19},
{port20,port21},
{port22,port23},
{port24,port25},
{port26,port27},
{port28,port29},
{port30,port31}};

or:
IE:
Code: [Select]
wire [15:0] page_remap [0:3] = '{  // assign 4 banks of 16kb
{port0,port1},
{port2,port3},
{port4,port5},
{port6,port7}};

Only now your reset needs to be setting ports #0-31 or 0-7.

Dont forget you can also have a separate page_remap for data and another for OP-code since our Z80 bus already decodes the op-code VS data.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on June 24, 2022, 08:37:33 am
Replicating the 74LS670 shouldn't be a problem to replicate in HDL with nothing more than a logic array: x bits by x words.

Feeding bank address bits position into that logic array, where the logic data output is wired to the upper address of the DDR3 controller to address all your ram bank by bank should also be easy.

Reset clears the array to 0,1,2,3.... to feed through the full Z80 upper address bits, 64k uninterrupted.
Also, I assume you have a write data or port into the array to fill the upper address for each bank group.

....

If so, how is this so difficult to implement?

I didn't say it was, just that having thought through it all yesterday, there's no advantage to implementing it fully yet and my short gaps of time to work on this project are better spent elsewhere for the time being.

You can go extra dumb by just using 32 ports, every 2 ports being 16 bit word of your 'page_remap' saving Z80 cpu cycles when filling the MMU table.  The 'page_remap' could also be 32 bytes of writable ram, but this will leave a hole in your address space as the MMU needs access no matter what it's contents are whereas ports wont.  Also remember, you can read as well as write ports.  Just tie the 32 port outputs into 32 port inputs of the same port number.

...

Only now your reset needs to be setting ports #0-31 or 0-7.

I think ports are the way to go - no memory holes, I have the free ports etc.

Dont forget you can also have a separate page_remap for data and another for OP-code since our Z80 bus already decodes the op-code VS data.

Although the Z80 can differentiate opcodes from data, it is still a von Neumann processor; it doesn't separate commands from data like a Harvard processor does.  It has variable-length opcodes which would make the task of separating code from data an epically tedious process, requiring the writing of custom assemblers/disassemblers and so on, with no real benefit that I can perceive whilst writing this.

Off on a tangent now - is there any easy way to convert VHDL to Verilog other than manually?  Way back when I started this project, the choice of developing in Verilog or VHDL was a toss-of-a-coin for me as I had no experience (or knowledge) of either and I went with what the expert helping me out was familiar with. ;D  I find myself now looking at some VHDL and really wishing I could translate it to Verilog so I could understand it better and, personal opinion, I'm glad I learned Verilog and not VHDL - it looks unnecessarily wordy!
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 24, 2022, 12:49:10 pm
Off on a tangent now - is there any easy way to convert VHDL to Verilog other than manually?  Way back when I started this project, the choice of developing in Verilog or VHDL was a toss-of-a-coin for me as I had no experience (or knowledge) of either and I went with what the expert helping me out was familiar with. ;D  I find myself now looking at some VHDL and really wishing I could translate it to Verilog so I could understand it better and, personal opinion, I'm glad I learned Verilog and not VHDL - it looks unnecessarily wordy!
First make sure you need to.  You can make a verilog module which calls / instantiates your VHDL modules in the same way as if it were another verilog module.  Otherwise you are in for a ride which either may lead you back to just using the VHDL as is, or debugging a tone of peculiarities if you do not understand what the VHDL is exactly supposed to do.

Read full example here: https://www.eevblog.com/forum/fpga/vhdl-code-to-verilog-code/msg4123399/#msg4123399 (https://www.eevblog.com/forum/fpga/vhdl-code-to-verilog-code/msg4123399/#msg4123399)

  Until I finally did the authentic translation here all the way at the bottom.  We had to simulate side-by-side and verify the 2 codes were returning the same results with a list of matched random inputs going to both modules.

  Comparing the original VHDL to my final Verilog shows it can be done.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on June 24, 2022, 08:40:06 pm
In my above link, don't forget to download my final .zip showing you how to parallel simulate your VHDL vs Verilog to proof your design.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 04, 2022, 03:11:51 pm
In my above link, don't forget to download my final .zip showing you how to parallel simulate your VHDL vs Verilog to proof your design.

I think I'll stick with the VHDL.  I don't think I'll gain much from translating it to Verilog, I was just wondering if there was an easy way to do it.

In other news, I seem to be hitting some glitches in the GPU.  I've noticed that the display on the TV keeps cutting out, quite frequently at first, almost as if the screen display is changing mode or the HDMI cable is loose (it's not).  After a few minutes it seems to stabilise and not do it any more.

Another glitch I noticed earlier today whilst writing some code to display a cursor caret in the DMI.  I noticed these vertical blue lines down the left edge of the screen - a little flickery, there for a short time, then disappeared, then reappeared briefly a few times then went completely.  Hadn't noticed these before.  Here's a pic:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1529473)

Any ideas what could be causing this?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2022, 06:44:32 pm
(Wait... before the rest, I used to get this problem before changing my HDMI cable as the plug on the DECA board keeps on eating a contact in my HDMI cable every time I plug one in and out a few times...)

If not the cable, then:

Strange.  What does your final timing report say?
It looks like a problem with the HDMI data or CLK line timing or noise.
Are you powering your project from USB alone, or using the power supply?  What happens if you insert or remove the SD card?
How warm is the FPGA getting?  What happens if you cool it?
Note that mine runs cool, however, my ellipse demo is a far simpler design.

If all else fails, send an update of your latest complete project with a 1mb RS232 debug capture file of your system where those blue dots appear to see if I can see them here.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 04, 2022, 07:51:19 pm
Note that some of my above point may be that you could be overloading the onboard switcher PSU and you are seeing noise during my DDR3 video line buffer bursting which runs at the full 1600mb/sec once every H-sync.

The system limit of the DECA is ~2 watts when powered by the USB.
Are you powering any of you Z80 circuitry as well?

(note that on my side, I found the DECA hdmi transmitter is really weak.  I even had to ensure that my monitor's AC plug when into the same power bar as my PC powering the DECA for 1080p to work.  (Most likely frame GND interference via a gigantic GND loop)  This is not a DDR3 issue as either an active HDMI cable amplifier or a really short cable would also solve the issue on my side.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2022, 08:42:20 am
Note that some of my above point may be that you could be overloading the onboard switcher PSU and you are seeing noise during my DDR3 video line buffer bursting which runs at the full 1600mb/sec once every H-sync.

The system limit of the DECA is ~2 watts when powered by the USB.
Are you powering any of you Z80 circuitry as well?

(note that on my side, I found the DECA hdmi transmitter is really weak.  I even had to ensure that my monitor's AC plug when into the same power bar as my PC powering the DECA for 1080p to work.  (Most likely frame GND interference via a gigantic GND loop)  This is not a DDR3 issue as either an active HDMI cable amplifier or a really short cable would also solve the issue on my side.)

It's a really intermittent issue, which makes it hard to solve.  More often than not, there's no issue - perhaps one time in ten or more I see screen blanking, I saw the blue lines down the side for the first time when I took the picture yesterday.

I've tried wiggling (gently) the HDMI connector, haven't noticed any interference as a result and the image is rock-steady today.

I am currently powering both the DECA and the uCOM from the same USB 3.1 port for convenience.  The entire setup is drawing about 0.85A - which is close to the maximum 900mA for a standard USB 3 port. :-\  I can always connect the DECA via another USB port (i.e. one off the back of the PC) to split the power demand, this takes the uCOM's power draw down to just under 2.5W.

I'll see if I can get temperatures and more information the next time the issue crops up.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2022, 12:38:43 pm
It may not be the USB port limit, but DECA's the onboard PSP which may be designed for the 500ma limit of USB1.

As for intermittent, remember to grab the RS232 debugger and capture 1mb snapshot when you see the problem.

The you TX the 1mb file lateron when the problem isn't there to see if it comes back.

You can also try changing the HDMI from HDMI mode to DVI mode in the I2C controls to see if that helps.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2022, 05:47:05 pm
On a separate tangent,  I'm working on integrating an HDL PSG and, initially at least, am looking to output audio via the TV rather than the DECA's DAC.  What do I need to do to the project to get the audio output via HDMI again? (Just after the test audio tone we worked on some time ago?)

I've uncommented the two blocks that instantiate sys_pll and AUDIO_IF, and added those files back into the project from a previous version (though maybe not the working version of those files.. :-// ).  Getting no audio at the moment.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2022, 08:41:28 pm
Make sure that the I2C setup for your HDMI transmitter is set to HDMI instead of DVI to get audio through the HDMI out.

Line 141 in I2C_HDMI_config.v:
Code: [Select]
25 : LUT_DATA <= 16'haf14;  //*********************************16'haf14=Select DVI mode //16'haf16=Select HDMI mode


Once you get the 1kHz sine tone in the HDMI audio, you should tie the I2S audio lines of the HDMI audio to the audio DAC audio output and you should have parallel copy of the audio on the HDMI and line out jacks in parallel.  Though, check to see if the line out DAC has I2C controls of it's own, then you need to make sure it is set to the same audio bit depth and clock rate of the HDMI transmitter so both will be expecting the same data.

Worry about first getting the existing 1 khz tone generator working on both.

They worry about adapting your sound synthesizer HDL.

(Don't forget to try a new HDMI cable, or a different input on your monitor to see if that blue garbage disappears.  My old desktop garbage LG Flatron monitor is garbage with it's HDMI input and the DVI in wont even accept a HDMI encoded video signal.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2022, 09:25:26 pm
Get the data sheet on the 'TLV320AIC3254'.
Check the DECA .pdf.

It uses a 1 bit data I2S while the HDMI transmitter seems to have a 4 bit one.  However, this may be due to supporting more than 2 channel audio.

Wire up an IC2 transmitter with a configuration for 16bit 48khz audio in with a quality over-sampled sound out at full volume wired to the line-out or headphone jacks according to the DECA schematic.  Also use it to pass the reset line.

Make a module which will generate your 48khz pulse from the bclk and wclk, taking in 16 bit stereo sampled on that 48khz, and sending out the serial data to the audio codec.

Go to my HDMI serialize and get the 1khz test tone generator to make the 16 bit data using the 1khz pulse.

Also remember that my 'BrianHG_GFX_PLL_i50_o297  VGA_PLL', ~line 1121 in the GPU top.sv has a 54MHz output you can use.

You probably want an MCLK of 48000 x ( 16bit L + 16bit R ) = 1536000 Hz for the BCLK
For your serializer, use 4x that clock so you may plan the clk and data bit outputs at timing edges, ie: 6.144 Mhz exactly, where the 48khz pulse is generated once every 128 clocks.

Or, just use the DECA HDMI example which runs their audio serializer exactly at 1536000Hz and use their serializer code tied to the 'TLV320AIC3254' I2S inputs noting that you only need 1 data bit.
(Note that their dumb serializer uses posedge and negedge clocks instead of a 2x/4x source clock to set the outputs, but they have the right PLL for you potentially wasting a valuable clock which may be needed for the FM synthesizer, or you may generate your own compatible PLL if needed...)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2022, 09:40:02 pm
Yes, that was it - had to update line 141 in I2C_HDMI_config.v.   I have tone.  8)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1530592)

Good suggestion re: getting audio out to the DAC before worrying about the PSG.

I'll hopefully have time tomorrow to hit the datasheets, manuals and guides but, in the meantime, do any of these outputs from the sound generator HDL appear to be usable?

* unsigned 12-bit output x 3 channels
* unsigned 14-bit summation of the channels
* signed 14-bit PCM summation of the channels, with each channel converted to -/+ zero-centred level or -/+ full-range level

Which will be best to use, bearing in mind I'll need to take a look at how to convert it to I2S (won't look at conversion right now, want to get some sleep and not have my brain working all night!)

Ah, you beat me to it whilst I was writing the above reply! ;)

Get the data sheet on the 'TLV320AIC3254'.
Check the DECA .pdf.

It uses a 1 bit data I2S while the HDMI transmitter seems to have a 4 bit one.  However, this may be due to supporting more than 2 channel audio.

Wire up an IC2 transmitter with a configuration for 16bit 48khz audio in with a quality over-sampled sound out at full volume wired to the line-out or headphone jacks according to the DECA schematic.  Also use it to pass the reset line.

Make a module which will generate your 48khz pulse from the bclk and wclk, taking in 16 bit stereo sampled on that 48khz, and sending out the serial data to the audio codec.

Go to my HDMI serialize and get the 1khz test tone generator to make the 16 bit data using the 1khz pulse.

Also remember that my 'BrianHG_GFX_PLL_i50_o297  VGA_PLL', ~line 1121 in the GPU top.sv has a 54MHz output you can use.

You probably want an MCLK of 48000 x ( 16bit L + 16bit R ) = 1536000 Hz for the BCLK
For your serializer, use 4x that clock so you may plan the clk and data bit outputs at timing edges, ie: 6.144 Mhz exactly, where the 48khz pulse is generated once every 128 clocks.

Or, just use the DECA HDMI example which runs their audio serializer exactly at 1536000Hz and use their serializer code tied to the 'TLV320AIC3254' I2S inputs noting that you only need 1 data bit.

I'll make a start on all this tomorrow, hopefully, if work allows.

At the moment, I've only got two questions - the first is the one asked above - which is the best output from the synthesizer to use, and the second is easier perhaps - I need a 1.789MHz clock, or as close as possible to it for accuracy of tone, for the sound generator module.  I know there's the 1.536MHz signal from the HDMI's audio PLL, but just wondered as you'd mentioned a 54MHz clock I'd not known about, if there were any other clocks in the project I could use/divide down?  That 54MHz clock will divide down to 1.6875MHz, which is even closer than the HDMI audio PLL I was intending to use, but is there anything I could use that would get me closer to 1.789MHz?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 05, 2022, 09:46:40 pm
Oh, one last thing - putting the output into HDMI mode seems to cause the layering to fail.  In DVI mode, the display is 720x480, but with a layer 40 pixels thinner and shorter than the display resolution, centred on the screen to show a 20-pixel wide border around the edge.  When I switch to HDMI mode, it's as if the layer becomes 720 pixels wide and the border disappears except for a thin strip and the top and bottom.

Any ideas?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2022, 10:15:22 pm
Take the 14bit parallel output.  Add 2'b00 as the bottom 2 bits and you got a 16bit parallel output.

You can also use the 3 separate output and place channel 1 on left added to channel 2, and channel 3 on right added to channel 2, making 2 a mono center channel.

Or, make 2 synths, one on left, one on right.

Make 3 control ports.  control port A would drive both synths in parallel meaning a fallback mono audio.  Control port B and C do the same as A, but B exclusively drives the left synth and C exclusively drives the right synth for stereo sound.  Or, do whatever you like.  Add 4 synths, 1 left, 1 center, 1 right, 1 rear offering 12 audio channels.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 05, 2022, 10:27:55 pm
Oh, one last thing - putting the output into HDMI mode seems to cause the layering to fail.  In DVI mode, the display is 720x480, but with a layer 40 pixels thinner and shorter than the display resolution, centred on the screen to show a 20-pixel wide border around the edge.  When I switch to HDMI mode, it's as if the layer becomes 720 pixels wide and the border disappears except for a thin strip and the top and bottom.

Any ideas?
When in HDMI mode, some monitors may be applying an overscan-scale.  Look for a 1:1 pixel setting on the monitor, or, maybe there is an automatic border set by the HDMI transmitter IC as we are basically adding dummy borders around the image to make the 148.5MHz pixel clock appear as a 108MHz clock.  IE: try 720p or mode 0 instead of mode 7 480p and see if the problem persists.  (Because of the fixed pixel clock, mode 0 480p will be at a higher framerate than 60hz.  IE: 66hz instead of 60hz when using pixel divide by 5.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 06, 2022, 08:06:02 am
When in HDMI mode, some monitors may be applying an overscan-scale.  Look for a 1:1 pixel setting on the monitor, or, maybe there is an automatic border set by the HDMI transmitter IC as we are basically adding dummy borders around the image to make the 148.5MHz pixel clock appear as a 108MHz clock.  IE: try 720p or mode 0 instead of mode 7 480p and see if the problem persists.  (Because of the fixed pixel clock, mode 0 480p will be at a higher framerate than 60hz.  IE: 66hz instead of 60hz when using pixel divide by 5.)

Can't find a 1:1 pixel setting, but if I switch modes to 1080p, the border is preserved and all is good, so it looks like the monitor is doing some kind of scaling/overscan as you've suggested. Will just have to live with it for the time being in the lower-res modes. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2022, 11:52:36 am
When in HDMI mode, some monitors may be applying an overscan-scale.  Look for a 1:1 pixel setting on the monitor, or, maybe there is an automatic border set by the HDMI transmitter IC as we are basically adding dummy borders around the image to make the 148.5MHz pixel clock appear as a 108MHz clock.  IE: try 720p or mode 0 instead of mode 7 480p and see if the problem persists.  (Because of the fixed pixel clock, mode 0 480p will be at a higher framerate than 60hz.  IE: 66hz instead of 60hz when using pixel divide by 5.)

Can't find a 1:1 pixel setting, but if I switch modes to 1080p, the border is preserved and all is good, so it looks like the monitor is doing some kind of scaling/overscan as you've suggested. Will just have to live with it for the time being in the lower-res modes. :-+
So, the authentic mode 0 480p doesn't work?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 06, 2022, 09:36:55 pm
Also, what happened to the speckle dots?
Did you get the line-out to run with the 1khz tone from copying the HDMI I2S output to the audio codec?
Note that since the line out is only stereo, you should only be using data bit 0, but the Mclk, Wclk, Sclk should match and there might be 1 high frequency control clock added to that.

You should be able to re-configure or make your own PLL clock replacement to match the HDMI audio PLL clock rate, but, add a few extra clock outputs for your sound generator module.

The HDMI audio serializer has a parallel data LUT table in it.  You will be taking that table, making sure you separate out the left and right, and make a new parallel 16bit stereo input port with said serializer to send raw parallel digital audio through the HDMI.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 07, 2022, 01:24:01 pm
So, the authentic mode 0 480p doesn't work?

I actually haven't tested that mode yet.  Have a lot going on, so am having to prioritise.  I'll get to this soon, hopefully.

Also, what happened to the speckle dots?

I saw the blue lines again briefly yesterday, but that was for 2 seconds and haven't seen them since.  Like I said, they're very infrequent. :-//

Did you get the line-out to run with the 1khz tone from copying the HDMI I2S output to the audio codec?
Note that since the line out is only stereo, you should only be using data bit 0, but the Mclk, Wclk, Sclk should match and there might be 1 high frequency control clock added to that.

You should be able to re-configure or make your own PLL clock replacement to match the HDMI audio PLL clock rate, but, add a few extra clock outputs for your sound generator module.

The HDMI audio serializer has a parallel data LUT table in it.  You will be taking that table, making sure you separate out the left and right, and make a new parallel 16bit stereo input port with said serializer to send raw parallel digital audio through the HDMI.

:-[ Okay, I've deviated from the plan very slightly in terms of the order of doing things.  I had a successful couple of hours yesterday, and got the synthesiser output wired into the HDMI audio feed and now get beeps out of the TV when I try to delete past the start of the screen (so basic audio is working in the DMI).  I figured that was an easy hit (and my end goal, ultimately), so I haven't yet started on linking the synth up to the DAC on the DECA board, as that looks to be a little more involved and will take me more time.

My focus today has been on trying to sort out the tuning/timing issues and getting music to play.  I'm able to play notes in the DMI, but can't get the CP/M program to play PT3s at the moment, which is a pain - so I'm debugging that.  Once that's done, I'll turn my attention to the DAC output.

The YM2149 module has some pretty specific requirements - some of which may still cause me issues.  Here's a snip of the text at the start of the module:

Code: [Select]
-- Clock, Clock-enable, and Sel.
--
-- The clk_i input should be the full-speed clock of the system, and
-- en_clk_psg_i must be a strobe (single clk_i tick) at the PSG operating
-- frequency.
--
-- This core can use a much faster clock-enable than the original PSG, however
-- the clock-enable frequency affects the output audio frequency directly.  If
-- producing sounds similar to the original ICs is desired, then using an
-- accurate input clock-enable is important.

The clk_i input is fed by CMD_CLK.  The clock-enable is created by a module I wrote that takes the CLK_54 output from the VGA_PLL and divides it down to get a 1.78 MHz clock signal.  It then creates a strobe (with a pulse width of CLK_54) at 1.78 MHz frequency which is passed to the YM2149 module via en_clk_psg_i.

One issue is that the YM2149 module won't do anything until the rising edge of one of these strobes at 1.78 MHz.  This means it can miss entire I/O reads or writes from the host when a rising edge on en_clk_psg_i doesn't perfectly coincide with the right part of the host's I/O cycle.  To get around this, I've just OR'd the strobe with the control signal from the host to the synth, so a pulse is always generated at the start of an I/O op and is never missed.  This pulse is obviously out of frequency and the pulse width is wider than the normal strobe, but it seems to get the job done for the moment.

EDIT: I've added a zip with some key files in it used in the project to produce sound, including the updated project _top file linking the major parts together.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 07, 2022, 07:27:01 pm
If you wanted verilog, then look here: https://github.com/jotego/jt49 (https://github.com/jotego/jt49)
Includes test-benches.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2022, 09:13:42 pm
Code: [Select]
-- Clock, Clock-enable, and Sel.
--
-- The clk_i input should be the full-speed clock of the system, and
-- en_clk_psg_i must be a strobe (single clk_i tick) at the PSG operating
-- frequency.
--
-- This core can use a much faster clock-enable than the original PSG, however
-- the clock-enable frequency affects the output audio frequency directly.  If
-- producing sounds similar to the original ICs is desired, then using an
-- accurate input clock-enable is important.

The clk_i input is fed by CMD_CLK.  The clock-enable is created by a module I wrote that takes the CLK_54 output from the VGA_PLL and divides it down to get a 1.78 MHz clock signal.  It then creates a strobe (with a pulse width of CLK_54) at 1.78 MHz frequency which is passed to the YM2149 module via en_clk_psg_i.

One issue is that the YM2149 module won't do anything until the rising edge of one of these strobes at 1.78 MHz.  This means it can miss entire I/O reads or writes from the host when a rising edge on en_clk_psg_i doesn't perfectly coincide with the right part of the host's I/O cycle.  To get around this, I've just OR'd the strobe with the control signal from the host to the synth, so a pulse is always generated at the start of an I/O op and is never missed.  This pulse is obviously out of frequency and the pulse width is wider than the normal strobe, but it seems to get the job done for the moment.

EDIT: I've added a zip with some key files in it used in the project to produce sound, including the updated project _top file linking the major parts together.

I'll help you out here if you setup a modelsim workbench with these 2 modules with a 100mhz source clock.
No pll, just the divider plus a means of entering a few test sound commands.

Then we will worry about the precision reference 1.78 mhz needed for it internal tone generator from a 100MHz clock without a PLL as I have already created the fractional divider code in our HDMI serializer project.  In fact, that divider can be used multiple times to generate the second sample clock of 1.536/1.4112 MHz needed for the I2S sclk signal and it's shifter used for the 48/44.1khz sample rate of the HDMI audio and audio codec/dac.

Other methods exist to approach this, but everything on the 100MHz clock will operate the best.

An audio filter may be needed when going from the YM2149's 1.78Mhz sample rate to the 48KHz rate to prevent son weird tones, but this isn't a problem.

Our other choice is to run all the PSG at 54 MHz, with the same above code, to achieve decimal perfect clock dividers,
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 08, 2022, 09:25:43 pm
I'll help you out here if you setup a modelsim workbench with these 2 modules with a 100mhz source clock.
No pll, just the divider plus a means of entering a few test sound commands.

Okay, no worries, it might take me some time to set up as I'm still extremely inexperienced with Modelsim, but I'll see what I can get done.

Then we will worry about the precision reference 1.78 mhz needed for it internal tone generator from a 100MHz clock without a PLL as I have already created the fractional divider code in our HDMI serializer project.  In fact, that divider can be used multiple times to generate the second sample clock of 1.536/1.4112 MHz needed for the I2S sclk signal and it's shifter used for the 48/44.1khz sample rate of the HDMI audio and audio codec/dac.

Other methods exist to approach this, but everything on the 100MHz clock will operate the best.

An audio filter may be needed when going from the YM2149's 1.78Mhz sample rate to the 48KHz rate to prevent son weird tones, but this isn't a problem.

Our other choice is to run all the PSG at 54 MHz, with the same above code, to achieve decimal perfect clock dividers,

I just threw together a divider based on a 28-bit counter, so I fully expect you'll have a better solution up your sleeve. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2022, 09:44:30 pm
I'll help you out here if you setup a modelsim workbench with these 2 modules with a 100mhz source clock.
No pll, just the divider plus a means of entering a few test sound commands.

Okay, no worries, it might take me some time to set up as I'm still extremely inexperienced with Modelsim, but I'll see what I can get done.

Then we will worry about the precision reference 1.78 mhz needed for it internal tone generator from a 100MHz clock without a PLL as I have already created the fractional divider code in our HDMI serializer project.  In fact, that divider can be used multiple times to generate the second sample clock of 1.536/1.4112 MHz needed for the I2S sclk signal and it's shifter used for the 48/44.1khz sample rate of the HDMI audio and audio codec/dac.

Other methods exist to approach this, but everything on the 100MHz clock will operate the best.

An audio filter may be needed when going from the YM2149's 1.78Mhz sample rate to the 48KHz rate to prevent son weird tones, but this isn't a problem.

Our other choice is to run all the PSG at 54 MHz, with the same above code, to achieve decimal perfect clock dividers,

I just threw together a divider based on a 28-bit counter, so I fully expect you'll have a better solution up your sleeve. ;)
I have linked here : https://www.eevblog.com/forum/fpga/vhdl-code-to-verilog-code/msg4129318/#msg4129318 (https://www.eevblog.com/forum/fpga/vhdl-code-to-verilog-code/msg4129318/#msg4129318)

Begin by downloading the .zip I posted and editing the setup/run.do to have the new file names and rename/edit the _tb file wire together and feed your sound modules.  You will notice that in the setup_xxx.do files, there is a different compile command for the .vhd VS the .sv files.

Get a waveform on the display and then we will work from there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 08, 2022, 11:32:52 pm
Here is a snipet of my floating point clock divider:
Code: [Select]
// Forcing 64 bits is required due to a ModelSim internal bug where if 'PLL1_OUT_TRUE_HZ*4096' exceedes 31 bits, it's considered negative and cropped
// when computing the localparam.  So, never use 'localparam int' when going above 2 billion anywhere inside, or you will get bogus results.
localparam bit [63:0] aud_per_x4096  = PLL1_OUT_TRUE_HZ*4096/HDPLL_AUDIO_HZ ;                               // Determine the audio period 4096 fold.
localparam bit [63:0] aud_per_round  = aud_per_x4096 + 2048 ;                                               // Prepare a rounded version.
localparam bit [12:0] aud_per_int    = HDPLL_AUDIO_TCK_FLOAT ? aud_per_x4096[24:12] : aud_per_round[24:12]; // Select between the rounded integer period or true integer period.
localparam bit [11:0] aud_per_f      = HDPLL_AUDIO_TCK_FLOAT ? aud_per_x4096[11:0]  : 12'd0  ;              // select between no floating point and floating point adjusted audio clock generation.
localparam bit [63:0] aud_tru_hz     = PLL1_OUT_TRUE_HZ*4096 / (aud_per_int*4096+aud_per_f)  ;              // Calculate the true audio output clock based on oscilator frequencies & HDPLL_AUDIO_TCK_FLOAT settings.

assign          clk_audio_true_hz    = 32'( aud_tru_hz );        // pass the true audio sample frequency to an output port.
assign          clk_pixel_true_hz    = 32'( PLL1_OUT_TRUE_HZ ) ; // pass the true pixel clock frequency to an output port.

logic   [12:0]  aud_cnt_m  = 13'd0;
logic   [12:0]  aud_cnt_n  = 13'd0;

always_ff @(posedge clk_pixel) begin

if ( aud_cnt_m == (aud_per_int - !aud_cnt_n[12]) ) begin                          // Add 1 extra count to the period if the carry flag aud_cnt_n[12] is set.
                                        aud_cnt_m        <= 13'd0;
                                        audio_ena        <= 1'b1;
                                        clk_audio        <= 1'b1;
                                        aud_cnt_n        <= aud_cnt_n[11:0] + (aud_per_f) ; // add the floating point period while clearing the carry flag aud_cnt_n[12].
                        end else begin
                                        aud_cnt_m        <= aud_cnt_m + 1'b1;
                                        audio_ena        <= 1'b0;
                        if (aud_cnt_m[11:0]==aud_per_int[12:1]) clk_audio <= 1'b0; // generate an aproximate 50/50 duty cycle clk_audio output.
                        end

end

You need to simulate this one on it's own, making a testbench which provides a 100mhz clock and counting the ' audio_ena ' over a 0.1 second and 1 second optional.  You may use your clock divider instead.

You will need to add the input and output ports on the module.  Maybe a reset as well.  Rename the pixel clock to clk.  Add 2 parameters, a clock frequency in parameter and a clock output parameter in hz.

Once tested as is, we will increase the floating point bits from 12 to 16 or 24 depending on your tolerance for the final average frequency error of the output 1.78MHz.

Let's see your edits and sim just for this module.

This code was located at the bottom on my 'HDMI_PLL.sv' inside my HDMI serializer project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 10, 2022, 12:37:49 am
Line 956:
Code: [Select]
ym2149_audio ARYA(

   // inputs
   .clk_i        ( CMD_CLK     ), // system clock
   .en_clk_psg_i ( strb_ovrd   ), // PSG clock enable strobe - 1.6875 MHz
   .sel_n_i      ( 1'b1        ), // divide select, 0 = clock-enable/2
   .reset_n_i    ( !reset      ), // active low
   .bc_i         ( psg_ctrl[0] ), // bus control
   .bdir_i       ( psg_ctrl[1] ), // bus direction
   .data_i       ( psg_data_i  ), // (7:0)
   // outputs
   .data_r_o     ( psg_data_o  ), // (7:0) -- registered output data
   .ch_a_o       (             ), // (11:0)
   .ch_b_o       (             ), // (11:0)
   .ch_c_o       (             ), // (11:0)
   .mix_audio_o  (             ), // (13:0)
   .pcm14s_o     ( pcm_14_o    ), // (13:0)   <<<<<<<<<<<<<<<<<<<<

Instead of the pcm14s_o, shouldn't you be using the mix_audio_o ?

Also, I looked at your 'clock_strobe', don't you want the 1.789MHz?

Also, you cannot use a clock enable to cross clock domains from the CLK_54MHz CMD_CLK, which may be 100MHz, or 75MHz, or 150Mhz.  This will cause random tone glitch clocking assuming my guesses about how the PSG works is correct.

Fix up my example code in the above post and run it from the CMD_CLK and create proper parameter inputs and a test bench to time the output and see how it works so you may extend it's precision.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 10, 2022, 07:54:54 am
Instead of the pcm14s_o, shouldn't you be using the mix_audio_o ?

Maybe? :-\  Have switched to the mixed output (adding 2 LSbs to make it 16-bit).  Seems to sound more authentic now. :-+

Also, I looked at your 'clock_strobe', don't you want the 1.789MHz?

As close to it as I can get, but for testing it's not essential.  It'll just move the sound output higher or lower in the pitch range compared to the target systems of the 80's.  It's pretty much on the nose as far as I can tell, using SignalTap to calculate the pulse width (it needs to be 559ns).  Ignore the comments with other frequencies, I forgot to change/update them before posting that code, sorry. ::)

Also, you cannot use a clock enable to cross clock domains from the CLK_54MHz CMD_CLK, which may be 100MHz, or 75MHz, or 150Mhz.  This will cause random tone glitch clocking assuming my guesses about how the PSG works is correct.

Yes, I suspect this is the cause of a fair bit of interference in the output currently.  I think the PSG updates and outputs a new value every clock enable, so random/out-of-sync pulses on that line will cause glitches.  I knew this would be an issue when I initially solved the problem of the PSG missing IO RD/WRs from the host because of its slow clock speed. Injecting clk_ens to force the PSG to react to asynchronous IO interactions is, no doubt, causing sound issues too.  These are the two big problems I know I need to fix.

The interface speed issue will require some clever thinking, or editing of the PSG module itself to accept asynchronous interface commands and respond to them immediately (or on the next clock enable if the sound registers are being updated).  :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 10, 2022, 08:03:26 am
Yes, I suspect this is the cause of a fair bit of interference in the output currently.  I think the PSG updates and outputs a new value every clock enable, so random/out-of-sync pulses on that line will cause glitches.  I knew this would be an issue when I initially solved the problem of the PSG missing IO RD/WRs from the host because of its slow clock speed. Injecting clk_ens to force the PSG to react to asynchronous IO interactions is, no doubt, causing sound issues too.  These are the two big problems I know I need to fix.

The interface speed issue will require some clever thinking, or editing of the PSG module itself to accept asynchronous interface commands and respond to them immediately (or on the next clock enable if the sound registers are being updated).  :-/O

That being said, switching from CLK_54 to CMDCLK for the PSG clock source seems to have cleared up just about all the problems.  I just need to sort out the correct divisor, but the tone output I got just now was really good.  My concerns re: the interface and botching asynchronous IO interactions actually seems to have a really minor, if any, effect. ^-^
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 10, 2022, 08:28:16 am
Yes, I suspect this is the cause of a fair bit of interference in the output currently.  I think the PSG updates and outputs a new value every clock enable, so random/out-of-sync pulses on that line will cause glitches.  I knew this would be an issue when I initially solved the problem of the PSG missing IO RD/WRs from the host because of its slow clock speed. Injecting clk_ens to force the PSG to react to asynchronous IO interactions is, no doubt, causing sound issues too.  These are the two big problems I know I need to fix.

The interface speed issue will require some clever thinking, or editing of the PSG module itself to accept asynchronous interface commands and respond to them immediately (or on the next clock enable if the sound registers are being updated).  :-/O

That being said, switching from CLK_54 to CMDCLK for the PSG clock source seems to have cleared up just about all the problems.  I just need to sort out the correct divisor, but the tone output I got just now was really good.  My concerns re: the interface and botching asynchronous IO interactions actually seems to have a really minor, if any, effect. ^-^
Read my clock divider code at the top of this page.........
Adapt it....
Clean it up a little.....
Use it......
It will make any frequency you like with 2 parameter inputs.
Simulate it and see.
Show me your work.
Also, with a sample rate of 1.7Mhz for the PSG, a little jitter of +/-5ns there would not be heard.


As for sending commands, aren't they an async separate event from the 1.7mhz strobe?
Don't they take effect immediately, or aren't they latched once a block is sent?
You do have the link I sent earlier to the Verilog version of the PSG, right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 11, 2022, 10:36:53 pm
Hello, did something go wrong?

     The my above clock divider code and the link to my VHDL-Verilog source gave you an example modelsim setup which was a single page of test-bench code which had a source 100MHz clock generator for you with a programmable end-time.

     All you had to do was rename a few things, give a name with inputs and outputs to my clock divider, or even begin by using your clock divider and just see it run.  Then, put my clock divider in place of yours and test again.

     The second step would be to add the PSB in the test-bench and a few more inputs to generate a sound with analog output to see the waveform output.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 12, 2022, 02:08:44 pm
No, nothing has gone wrong - I just literally have had no time to work on any of this.  Maybe over the next week or so. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 19, 2022, 01:30:42 am
Will we see anything this week?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 21, 2022, 09:55:02 am
Maybe.  I should have a little time later today perhaps to make a start on the sim stuff.  Concentrating on this is hard enough at the best of times with all the distractions I have going on around me.

I'm quite happy with my clock divider providing a reasonable 1.78 MHz signal to the PSG - it's a helluvalot closer to the target frequency than my hardware PSG card ever was.  I've also added in some HDL in the _top file to handle the asynchronous nature of the PSG module's interface, running at a much slower clock.  Any signals to the module are now held until the next 1.78 MHz strobe.  The only downside is that the Z80 is sometimes able to send two IO RD/WRs in-between the strobe pulses if the timing falls just right, but that was an issue with the original 80's hardware and why they made prolific use of NOPs in the assembly (or set up an interrupt on a similar frequency that send the commands), so I can work around that.

What do you want me to start on first?  I guess I'll use the 'cordic' project you linked to previously as a base and start getting a simulation of the PSG module up and running?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 21, 2022, 04:25:06 pm
Start with just wiring in your clock divider and showing that it works.

Will you correct your clock divider to auto receive and adjust it's rate based on parameters set by the CMD_CLK frequency?

You may also calculate and count the output frequency in the testbench if you like.

Quote
I'm quite happy with my clock divider providing a reasonable 1.78 MHz signal to the PSG - it's a helluvalot closer to the target frequency than my hardware PSG card ever was.

Yes, but if you want to run compatible music home computers which used this PSG, without having a clock within their crystal frequency, you may have slightly bad pitch and long term tempo if there is some kind of timer involved.

Quote
The only downside is that the Z80 is sometimes able to send two IO RD/WRs in-between the strobe pulses if the timing falls just right, but that was an issue with the original 80's hardware and why they made prolific use of NOPs in the assembly (or set up an interrupt on a similar frequency that send the commands), so I can work around that.

Well, if you are using an IO port, if you remember, we added a programmable Z80 wait state for the reads.  We can add a wait for the 1.78 MHz strobe when writing to the PSG's port.  However, I find it strange that the designer of the HDL for the PSG didn't allow multiple writes, accepting them all even in-between each 1.78 MHz strobe for the core audio clock.  I wonder if the Verilog version I pointed you to has the same limitation.  I mean, if you update the same voice's frequency once or twice within 1.78MHz, it should not be noticed.  If you update a number of voice settings within a strobe, then all those settings should take effect by the next strobe.

Well, if not, what you need to create is a 'PSG_Busy' flag.  This flag should go high after every write an clear itself at each strobe.  Make a parameter to select whether the write or strobe has higher priority.  This flag will need to be sent to the Z80 Bridge (which may need adjusting as I know we adapted an input for the IO port read, but not sure about an IO port write).  It needs to be setup so that when a matching port address write happens while the 'PSG_Busy' is high, that the Z80 wait state will be inserted until the busy is cleared.

Again, it helps that we can simulate this to verify that this is where your current bug originates as you did not create the PSG's VHDL, so you cannot be sure.  (Though, you can point me to the documentation for the PSG's VHDL which states this limitation.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 24, 2022, 01:38:45 pm
Start with just wiring in your clock divider and showing that it works.

It's been busy here - first chance I've had today to work on this, but I've got the clock divider test bench up and running.  Here's the output:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1547425)

I've also attached the test bench for info.

Will you correct your clock divider to auto receive and adjust it's rate based on parameters set by the CMD_CLK frequency?

Yes, that's something I'd like to add later.

You may also calculate and count the output frequency in the testbench if you like.

The output period of the strobe is 560ns currently, which equates to 1.786 MHz.

Quote
The only downside is that the Z80 is sometimes able to send two IO RD/WRs in-between the strobe pulses if the timing falls just right, but that was an issue with the original 80's hardware and why they made prolific use of NOPs in the assembly (or set up an interrupt on a similar frequency that send the commands), so I can work around that.

Well, if you are using an IO port, if you remember, we added a programmable Z80 wait state for the reads.  We can add a wait for the 1.78 MHz strobe when writing to the PSG's port.  However, I find it strange that the designer of the HDL for the PSG didn't allow multiple writes, accepting them all even in-between each 1.78 MHz strobe for the core audio clock.  I wonder if the Verilog version I pointed you to has the same limitation.  I mean, if you update the same voice's frequency once or twice within 1.78MHz, it should not be noticed.  If you update a number of voice settings within a strobe, then all those settings should take effect by the next strobe.

Not sure if I did it before or after I wrote the above, but IO reads from the PSG insert WAIT states as required and hold the Z80 until data is valid from the PSG.  The amount of WAIT states inserted varies according to where in the 1.78 MHz cycle the IO read occurs.  It's just IO writes to the PSG that don't insert WAITs, instead relying on the Z80 leaving a little breathing space between IO writes.

Again, it helps that we can simulate this to verify that this is where your current bug originates as you did not create the PSG's VHDL, so you cannot be sure.  (Though, you can point me to the documentation for the PSG's VHDL which states this limitation.)

Here's the source I'm using for the PSG module: https://github.com/dnotq/ym2149_audio (https://github.com/dnotq/ym2149_audio) - there's information on the module there, though I think I surmised the asynchronous interface nature from my own experiments rather than it being documented.

Next step is to get the PSG module integrated into the testbench then?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 24, 2022, 07:02:59 pm
Excellent work.

Next, what would happen if you added to your _tb this line right at the end:

Code: [Select]
always @(posedge clk) if (p_stb) f_count <= f_count + 1 ;  // Make f_count a 24 bit reg, or just a normal integer.

endmodule

This line in your setup:

Code: [Select]
add wave -hexadecimal sim:/clock_strobe_tb/DUT/strb_o
add wave -decimal     sim:/clock_strobe_tb/f_count       <<<<<<<<<<<

do run_div.do

And changed your _tb endtime to :
localparam  ENDTIME    = 1000 * 1000 ; // Number of ns to stop simulation at.

What will you see at the end of your simulation?

Also, try  ENDTIME    = 1000 * 1000  * 100 ;
Now what will the f_count show at the end of the sim?

*** Do not bother with ' 1000 * 1000  * 1000 ', it will take forever to simulate.  Once you understand the concept, 1000*1000 is plenty.

Next, after you instantiate your 'clock_strobe' in the _tb, next instantiate and wire the VHDL PSG.
You will define a few regs before to drive the input and to show in the simulation waveform.  The wiring should look exactly like what you would be doing in in you GPU source.  The setup waveform display should show the digital inputs and 4 analog output waveforms.  I believe the output wires should be signed numbers, but if the output show a crap step, then they should be changed to 'unsigned' and go from 0-max, max being the number of 2^bits.

Also remember in your setup/run.do, you use the 'vlog -sv ...' for verilog source files and 'vcom -93 ...' for VHDL source files.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 24, 2022, 09:32:42 pm
Next step after you get the PSG working, we need another clock generator for the I2S audio which runs at exactly 48000Hz X 32.  Or, within +/- 1hz.  Then, you will need to modify or create your own parallel audio to I2S serial audio running on that 48000Hzx32 clock.  (IE: 1536000Hz, or 1.536000MHz.)

Then, copy/plug/rename the TB into a single sound module copied into your GPU_TOP and you should be able to get PSG out of your GPU's HDMI.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 24, 2022, 09:33:35 pm
Excellent work.

Next, what would happen if you added to your _tb this line right at the end:

Code: [Select]
always @(posedge clk) if (p_stb) f_count <= f_count + 1 ;  // Make f_count a 24 bit reg, or just a normal integer.

endmodule

This line in your setup:

Code: [Select]
add wave -hexadecimal sim:/clock_strobe_tb/DUT/strb_o
add wave -decimal     sim:/clock_strobe_tb/f_count       <<<<<<<<<<<

do run_div.do

And changed your _tb endtime to :
localparam  ENDTIME    = 1000 * 1000 ; // Number of ns to stop simulation at.

What will you see at the end of your simulation?

Also, try  ENDTIME    = 1000 * 1000  * 100 ;
Now what will the f_count show at the end of the sim?

*** Do not bother with ' 1000 * 1000  * 1000 ', it will take forever to simulate.  Once you understand the concept, 1000*1000 is plenty.

Okay, a little light HDL coding before bedtime.  ;)  So it's a pulse counter, basically - running the sim for a million cycles results in the final f_count value being 1785, suspiciously close to my calculated clock speed (minus three orders of magnitude) for the PSG.  Looks like a handy (and simpler) way of calculating the output clock frequency?  Thanks for that.  :-+

Will work on getting the VHDL PSG module wired-in to the test bench tomorrow, hopefully.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 24, 2022, 09:40:01 pm
Okay, a little light HDL coding before bedtime.  ;)  So it's a pulse counter, basically - running the sim for a million cycles results in the final f_count value being 1785, suspiciously close to my calculated clock speed (minus three orders of magnitude) for the PSG.  Looks like a handy (and simpler) way of calculating the output clock frequency?  Thanks for that.  :-+

Will work on getting the VHDL PSG module wired-in to the test bench tomorrow, hopefully.

You are learning to exactly prove your code.
You also notice that the last pulse doesn't end right at the 1000000ns mark, so, there is a bit of error there.  This is also why you get additional decimal places when you run the sim for a greater time.  Running the sim for the full 1000x1000x1000 would leave you with a 1hz accurate readout.

As for easy calculation, your code calculation should be exactly 100000000 / loop_size.  That easy.  My divider code is a little more complex as it has an accumulated floating point error correction feature, but all the pre-calculations are in my posted source with 2 integers which reveal the true audio frequency output down to the Hz.

My source is posted here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4288510/#msg4288510 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4288510/#msg4288510)
Your gonna need it to get an accurate audio clock for the HDMI sample rate.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 25, 2022, 11:03:53 am
Update - I've wired-in the YM2149 VHDL module.  I just need to work out how to send some test commands to get it to output some audio now.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1548250)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 25, 2022, 02:10:13 pm
Update 2 - now have commands to the PSG working.  Trace below shows a simple command being sent to the PSG to make it play a tone.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1548319)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 25, 2022, 05:22:26 pm
Ok, after running your sim, no audio out.  (0.001 seconds in real life)
After increasing the sim end time by 10x, still nothing.  (0.01 seconds in real life)
After increasing the sim end time by another 10x, still nothing. (0.1 seconds in real life)
After increasing the sim end time by another 10x, still nothing.  (1 second in real life)
( :-\ Pathetic PSG if it cannot produce a tone within 1 second of the issued command.)

Well, after that sim:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1548442)

Looking at the 1 000 000 000ns point (1 second), your f_count made it past 1785714 times, or 1785714Hz.  Plus a few extra fractional 0.xxx hz as it reached that count just before the 1 second point.  This should match your calculated hz.  (Fin=100 000 000hz / divider 56 = 1785714.286 hz)


Assuming you sent the commands correctly and the same way you have been doing it currently with the 'Z80', you may have just identified your first bug.  Now, this may be an issue with the way the VHDL is either configured, or the way it is designed to interface with.

Ok, your setup is ok, in a Verilog way, though you did not need to write such code, but I will make a suggestion for the reset, place it inside the initial like this:

Code: [Select]
    initial begin

        clk     = 1'b0  ;
        f_count = 24'b0 ;
        step    = 3'b0  ;
        reset   = 1'b0  ;

        #(CLK_PERIOD*5) reset   = 1'b1  ; // release reset after 5 clocks

    end


In fact, get rid of your verilog at the bottom and do this:

Code: [Select]
    initial begin

        clk     = 1'b0  ;
        f_count = 24'b0 ;
        step    = 3'b0  ;
        reset   = 1'b0  ;

        #(CLK_PERIOD*CMD_CLKS)  // Wait for CMD_CLKS oscillations of the system clk period before releasing reset

        reset   = 1'b1  ;       // release reset.

        #(CLK_PERIOD*CMD_CLKS)  // Wait for CMD_CLKS oscillations of the system clk period before sending commands.

        // Count the command counter until the end, waiting a CMD_CLKS between each command step.
        for (step = 0; step < (CMD_COUNT -1); step++ ) #(CLK_PERIOD*CMD_CLKS) ;

    end
With this new parameter at the top:
Code: [Select]
    // Test parameters
    parameter DIVISOR = 28'd56   ; // clock divisor value
    parameter CMD_CLKS = DIVISOR ; // numbers of clk per command.

This With this, you can now set the CMD_CLKS to anything, like 1 which would send a command every 100MHz system clock.

I also added a blank dead '0' beginning command.  (See attached updated source _tb code).

Now, we know the PSG is doing something as after the last command is sent, the 'pcm14s_o' output changes to 0x0353 at the last transmitted command byte, but, nothing after that.

Playing with then new 'CMD_CLKS' parameter doesn't seem to help.
I made it 4x longer and the 'pcm14s_o' now changes before the last command is sent.
Perhaps your command output is wrong in some way?

I made it literally equal to 1 and 2, but now, nothing happens.  This confirms that the poor VHDL PSG needs the commands to be slowed down, though I suspect it was done for backwards compatibility with the original IC.  I also tried 1/2 your divisor 'DIVISOR' parameter making the command exactly twice as fast and it still fails.

I also tried inverting the 'bc' and nothing again.

So, we can assume you are sending a proper command timing, but something is missing in the commands as there is no triangle waveform coming out.

There is also that verilog version of the Yamaha PSG I linked to earlier which you may give a try.  It should have the same IO ports.  If it has the same slow input road-block, you might be able to easily bypass it and write commands right up to the top 100MHz clk input speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 25, 2022, 07:40:28 pm
Have any VHDL programmers have seen this warning before:
Code: [Select]
# Loading work.ym2149_audio(rtl)
# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
#    Time: 0 ns  Iteration: 0  Instance: /psg_tb/PSG
# ** Warning: NUMERIC_STD."<": metavalue detected, returning FALSE
#    Time: 0 ns  Iteration: 0  Instance: /psg_tb/PSG
# ** Warning: NUMERIC_STD."<": metavalue detected, returning FALSE
#    Time: 0 ns  Iteration: 0  Instance: /psg_tb/PSG
# ** Warning: NUMERIC_STD."<": metavalue detected, returning FALSE
#    Time: 0 ns  Iteration: 0  Instance: /psg_tb/PSG
# ** Warning: NUMERIC_STD."<": metavalue detected, returning FALSE
#    Time: 0 ns  Iteration: 0  Instance: /psg_tb/PSG
# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0
#    Time: 0 ns  Iteration: 0  Instance: /psg_tb/PSG
# ** Note: $stop    : psg_tb.sv(92)

How do we fix this, how do we figure out where the bug is?
The source code is called 'ym2149_audio.vhd' located inside this .zip:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1548325 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1548325)
Or, located here:
https://github.com/dnotq/ym2149_audio/blob/master/rtl/ym2149_audio.vhd (https://github.com/dnotq/ym2149_audio/blob/master/rtl/ym2149_audio.vhd)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 26, 2022, 11:24:07 am
Issue posted here:
https://github.com/dnotq/ym2149_audio/issues/1 (https://github.com/dnotq/ym2149_audio/issues/1)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 26, 2022, 12:19:53 pm
@nockieboy, it may be useful to try this verilog version:
https://github.com/jotego/jt49 (https://github.com/jotego/jt49)

It has features like DC removal filter (don't want to blow your amp or speakers (this would be done with a series cap on the computer sound card PCB)) and enough people used it that there were posted issues and they were fixed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 26, 2022, 12:25:39 pm
@nockieboy, it may be useful to try this verilog version:
https://github.com/jotego/jt49 (https://github.com/jotego/jt49)

It has features like DC removal filter (don't want to blow your amp or speakers (this would be done with a series cap on the computer sound card PCB)) and enough people used it that there were posted issues and they were fixed.

Already have that repo in the GPU project folder - just never tried it as it appears more complicated than the YM2149 single-file module (though I've never taken the time to look, really).  If you're thinking the YM2149 is bugged, then I'll start looking at getting the jt49 set up.  I've already tried the other Verilog module - yt49 - and had a hard time getting it to work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 26, 2022, 01:00:30 pm
The simulator will help.
All you need to run/instantiate is the jt49.v in place of VHDL and match the IOs names.

You will need to add these vlog files:
 - jt49.v
  - jt49_div.v
  - jt49_cen.v
  - jt49_eg.v
  - jt49_exp.v
  - jt49_noise.v

Skip the 'jt49_bus.v' as it is just a different CPU interface.
Note that this does not include the DC filter, but that's ok for now.

I do not necessarily think the VHDL PSG is flawed, just something which may require an extra equals or quote somewhere in its source.  That is unless it doesn't sound exactly correct.

Note that there also exists this YM2151, 8 channel, 16bit stereo, but more controls needed to make a sound:
https://github.com/jotego/jt51/tree/master/doc/yamaha (https://github.com/jotego/jt51/tree/master/doc/yamaha)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 26, 2022, 04:01:59 pm
Here's the jt49 testbench setup.  Haven't tried the jt49 in hardware yet, but it looks like something is happening on the A-channel output.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1549060)

Zooming right out shows the output flipping between 0xB4 and 0x00 values.  No idea if that's a valid output or not, to be honest.  I'm not 100% certain my commands are correct, but they are identical to the ones sent by the DMI to make a 'beep' sound when the user tries to delete past the first screen column.  The only difference is that the DMI tells the PSG to stop making the noise after a predetermined time, whereas I don't do that in the simulation.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 26, 2022, 06:33:50 pm
Ok, I got it working.

Take a look: (Note that I shrunk your clock divider from 56 down to 2 so that we see a waveform without having to simulate for 100s seconds before we see anything meaningful...)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1549141)

     Now, download my source code and read every line in the _tb.  You went way overboard with the coding.  This Verilog PSG source is easy to interface with and does NOT require you to time your commands.  You can send commands at a full 100MHz ignoring that clk_strobe timing and the PSG will registers them all.  This means all you had to do was feed an address and a data in parallel with the write strobe.

     In other words, use Z80 port #10 bottom 4 bits into the address, use Z80 port #11 into data, and use the data strobe of port #11, invert it, feed it to the the wr_n input.  To send a command, just write port 10 with the address 0-15, and then write port 11 with the data and you are done.  No delay, no waits, no absurd routine to generate that 8bit multiplexed bus timed to the clk_enable.

     Now, we have one new problem.  This PSG was designed with a cheap DC output,  the actual IC.  The HDL is just replicating it.  This is very bad for HiFi audio equipment, but good enough for a tiny PC speaker.  Like I said earlier, this problem would be solved with analog circuitry in the PC RF modulator, or output op-amp with nothing more than a wired series cap which blocks DC.  But with direct digital audio or a HiFi DAC which supports low frequencies, you could be sending frequencies below 10hz, or even below 1hz every time the sound starts and stops.  For this, we will need to add this software DC filter code (emulated that DC blocking series cap) to the 10bit 'sound' output:

https://github.com/jotego/jt49/tree/master/hdl/filter (https://github.com/jotego/jt49/tree/master/hdl/filter)

I'll take a look later tonight as it has some extra unused components for simulation, not the way we would do it.  (And if we never simulated this chip, I would have never known and you would have potentially burned out someones expensive amp, burned out or popped out some unsuspecting user's expensive woofer/subwoofer.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 26, 2022, 07:30:39 pm
Update 2 - now have commands to the PSG working.  Trace below shows a simple command being sent to the PSG to make it play a tone.

Nope, your command was for generating random noise at volume 14 out of 15....

Well... There is a bunch a junk to do.

1) You need to verify fix your clock pulse generator to my accurate one, add a second for the HDMI sample clock, add the linked example DC filter, create your own I2S serializer and test the PSG as is.

If sound is OK, we need to:

2) Make our own smarter DC filter which will allow no pops or DC but still allow low frequency sound by interpreting the bottom of the graph outperforming all other strategies.

4) Modify the PSG HDL's to Increase the depth of each channel from 8 bit to 12 bit.  The YM PSG uses a proper volumetric logarithmic DAC for 16 volume steps which needs to sound linear to the ear, but our hi-res audio DACS today are linear, so we need a few more bits for precision since the current design's first few volume steps are too loud and with a few repeats in the first 3 steps.

5) A proper 3 channel mixer which will deliver 16 bit full amplitude output and a ~12-15Khz low pass filter so that resampling the 1.78Mhz square wave samples to 48000Hz or 44100Hz will not produce really sharp spiky toned result when mixing high frequency tones.

6) Generate a new Github page with the enhanced project offering from input to the final I2S output with built in clock generators.

You wanted a 'ym2149_audio', now you will have the best sounding one.  Note that the YM2151 wouldn't need to DC filter or low pass filter as it makes proper AC waveforms at a full 16 bit.

(Note that I will rely on you to create me a sample 10khz tone with a few ramp settings.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 27, 2022, 03:57:40 am
 |O Ok, thanks to a bunch of unassigned power-up values in the jt49 source, his DC filter wont simulate unless I patch a bunch of regs assigning their default equal to '0'.

Here you go:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1549633)

So, download this latest source, and you still need to read everything like I said 2 posts ago!!!

Next, fix the clocks, adding an I2S clock.
And make an I2S transmitter.

Now, I better see it being 1 or 2 if/else lines of code.  Plus a double latched DFF outputs.
Within this simulation.  It is that simple.
(You will need to see an I2S waveform example and also convert the signed input to unsigned.  Also, the HDMI IS has 4 dat inputs for 8 channel audio, just wire the 4 dats together)

Just so we are clear, in my floating point clock divider, my 'audio_ena' output is your strobe and my 'clk_audio' output is the 50/50 duty cycle clock signal.  Make 3 parameter inputs, CLK_IN_HZ, CLK_OUT_HZ, and USE_FLOATING_POINT.  The rest you should be able to figure out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 27, 2022, 01:27:38 pm
Ok, I got it working.

Take a look: (Note that I shrunk your clock divider from 56 down to 2 so that we see a waveform without having to simulate for 100s seconds before we see anything meaningful...)

Awesome! ;D

     Now, download my source code and read every line in the _tb.  You went way overboard with the coding.  This Verilog PSG source is easy to interface with and does NOT require you to time your commands.  You can send commands at a full 100MHz ignoring that clk_strobe timing and the PSG will registers them all.  This means all you had to do was feed an address and a data in parallel with the write strobe.

     In other words, use Z80 port #10 bottom 4 bits into the address, use Z80 port #11 into data, and use the data strobe of port #11, invert it, feed it to the the wr_n input.  To send a command, just write port 10 with the address 0-15, and then write port 11 with the data and you are done.  No delay, no waits, no absurd routine to generate that 8bit multiplexed bus timed to the clk_enable.

Wow, that's much simpler.  It'll mean I can remove some of the bridging interface from the GPU_DECA_top module and simplify the connection from Bridgette to the PSG massively. :-+

     Now, we have one new problem.  This PSG was designed with a cheap DC output,  the actual IC.  The HDL is just replicating it.  This is very bad for HiFi audio equipment, but good enough for a tiny PC speaker.  Like I said earlier, this problem would be solved with analog circuitry in the PC RF modulator, or output op-amp with nothing more than a wired series cap which blocks DC.  But with direct digital audio or a HiFi DAC which supports low frequencies, you could be sending frequencies below 10hz, or even below 1hz every time the sound starts and stops.  For this, we will need to add this software DC filter code (emulated that DC blocking series cap) to the 10bit 'sound' output:

https://github.com/jotego/jt49/tree/master/hdl/filter (https://github.com/jotego/jt49/tree/master/hdl/filter)

I'll take a look later tonight as it has some extra unused components for simulation, not the way we would do it.  (And if we never simulated this chip, I would have never known and you would have potentially burned out someones expensive amp, burned out or popped out some unsuspecting user's expensive woofer/subwoofer.)

Yeah, I'll hang fire on testing the jt49 on the physical device for this reason; although it probably won't do much harm to the TV I'm using, I can hold off the excitement until we've got the filter working properly. ^-^
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 27, 2022, 05:29:47 pm
Ok, I got it working.

Take a look: (Note that I shrunk your clock divider from 56 down to 2 so that we see a waveform without having to simulate for 100s seconds before we see anything meaningful...)

Awesome! ;D

     Now, download my source code and read every line in the _tb.  You went way overboard with the coding.  This Verilog PSG source is easy to interface with and does NOT require you to time your commands.  You can send commands at a full 100MHz ignoring that clk_strobe timing and the PSG will registers them all.  This means all you had to do was feed an address and a data in parallel with the write strobe.

     In other words, use Z80 port #10 bottom 4 bits into the address, use Z80 port #11 into data, and use the data strobe of port #11, invert it, feed it to the the wr_n input.  To send a command, just write port 10 with the address 0-15, and then write port 11 with the data and you are done.  No delay, no waits, no absurd routine to generate that 8bit multiplexed bus timed to the clk_enable.

Wow, that's much simpler.  It'll mean I can remove some of the bridging interface from the GPU_DECA_top module and simplify the connection from Bridgette to the PSG massively. :-+

     Now, we have one new problem.  This PSG was designed with a cheap DC output,  the actual IC.  The HDL is just replicating it.  This is very bad for HiFi audio equipment, but good enough for a tiny PC speaker.  Like I said earlier, this problem would be solved with analog circuitry in the PC RF modulator, or output op-amp with nothing more than a wired series cap which blocks DC.  But with direct digital audio or a HiFi DAC which supports low frequencies, you could be sending frequencies below 10hz, or even below 1hz every time the sound starts and stops.  For this, we will need to add this software DC filter code (emulated that DC blocking series cap) to the 10bit 'sound' output:

https://github.com/jotego/jt49/tree/master/hdl/filter (https://github.com/jotego/jt49/tree/master/hdl/filter)

I'll take a look later tonight as it has some extra unused components for simulation, not the way we would do it.  (And if we never simulated this chip, I would have never known and you would have potentially burned out someones expensive amp, burned out or popped out some unsuspecting user's expensive woofer/subwoofer.)

Yeah, I'll hang fire on testing the jt49 on the physical device for this reason; although it probably won't do much harm to the TV I'm using, I can hold off the excitement until we've got the filter working properly. ^-^

 :-// Hun ?  I just showed you a proper working DC filter....
That output is already safe...  It's ready to test and go...  I just stated we can do better than anyone else out there in history.  I also stated that we can also make the tone a bit more pleasant to the ear.  For now, let's get some audio out with what we have immediately!

Next, change your clock divider to mine.  I literally sent you all the code to copy and paste.  You just need to rename a few things...  You should have done this first, but, here we are now.  Don't forget to leave proper credits at the top as we will be making a new Yamaha PSG repository with 4 wire direct drive to any modern I2S audio DACs and patching up the jt49 author's little mistakes.

Then, and for some reason you have been avoiding like a plague, we will make an I2S transmitter and get your sound working.  We will do this code live on this thread as it is too easy and you will be baffled at your confusion.

Just pm me when you will be around and everything in this post should take less than an hour.

(Since I never owned a YM2149, I only looked at its data sheet, wrote a moving tone ramp, saw a result in Modelsim similar to a scope shot in the data sheet and assumed its OK.  You will need to be the judge here.  It only 3 x 12bit oscillators with 1 bit output, IE counters with the top MSB flipping a 1 bit as an output + another 16bit counter for tied to a 5bit counter for the volume ramping.  If you had the time, it looks like you could have programmed your own. )
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 04:10:54 am
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1550566)

Ok, here is the I2S audio data sheets.

     For the TI part, it only supports the 32 clocks or more per channel, IE 64 clocks per stereo sample.  So we need our own I2S transmitter.  You can also see the HDMI transmitter can do both the 16 and 32 clocks per channel, so we will create a 32 clocks per channel transmitter so that a single I2S output can drive both ICs in parallel.

     Now, the TI audio codec DAC also requires a separate MCLK from the I2S buss' SCLK, LRCLK and I2SDATA.  You also see it has an internal PLL which can operate at the our new SCLK frequencies (see red notes).  If using our SCLK to feed the MCLK in parallel is too jittery for good DAC performance based on it being a fractional divide of our core 100 MHz clock, then we can use a pll to generate & feed a 12 MHz or 16 MHz clock for the MCLK while the SCLK is allowed to run independently.

Also, we now can send 24bit audio...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2022, 08:02:09 am
Yeah, I'll hang fire on testing the jt49 on the physical device for this reason; although it probably won't do much harm to the TV I'm using, I can hold off the excitement until we've got the filter working properly. ^-^

 :-// Hun ?  I just showed you a proper working DC filter....

Oh sorry, must have misunderstood your post then - I though we still had to add the filter in.

That output is already safe...  It's ready to test and go...  I just stated we can do better than anyone else out there in history.  I also stated that we can also make the tone a bit more pleasant to the ear.  For now, let's get some audio out with what we have immediately!

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1550644)

Next, change your clock divider to mine.  I literally sent you all the code to copy and paste.  You just need to rename a few things...  You should have done this first, but, here we are now.  Don't forget to leave proper credits at the top as we will be making a new Yamaha PSG repository with 4 wire direct drive to any modern I2S audio DACs and patching up the jt49 author's little mistakes.

Righto.  You mean the floating point divider?  I had a look at that and there were parameter references that I had to copy from the HDMI serialiser that were linked to other parameters which were themselves linked to blocks of HDL that just made it all a bit of a rat's nest.  I certainly didn't interpret it as a 'simple copy and paste', but I was probably overthinking something as usual.

Then, and for some reason you have been avoiding like a plague, we will make an I2S transmitter and get your sound working.  We will do this code live on this thread as it is too easy and you will be baffled at your confusion.

I just haven't needed it - I can hear the audio fine through the TV, having a set of headphones lying around as well just added another cable to the spaghetti on my desk already. ;)

Just pm me when you will be around and everything in this post should take less than an hour.

Okay, will do - tomorrow's looking good at the moment.  Will PM you with more details.

(Since I never owned a YM2149, I only looked at its data sheet, wrote a moving tone ramp, saw a result in Modelsim similar to a scope shot in the data sheet and assumed its OK.  You will need to be the judge here.  It only 3 x 12bit oscillators with 1 bit output, IE counters with the top MSB flipping a 1 bit as an output + another 16bit counter for tied to a 5bit counter for the volume ramping.  If you had the time, it looks like you could have programmed your own. )

Yeah, I was amazed how simple the HDL for the PSG was.  The problem is, music/audio is more a dark art to me than electronics ever was.  All this talk of envelopes, sustains, attack/decay etc makes me want to run for the hills. :scared:  One of the reasons I wanted to emulate the AY-8910 chip was that it was familiar to me (in the sense I'd 'used one before' in my first computer) and I had some software in CP/M that could play some tunes to test on it.  Writing my own PSG, or using some other PSG (note the YM2149 is, to all intents and purposes, the same as the AY-891x chips) would have meant a huge problem with finding test music to run on it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2022, 08:13:43 am
:-// Hun ?  I just showed you a proper working DC filter....

Just realised, I've somehow missed an entire post of yours at the top of this page.  That's how I'd didn't know about the working DC filter.  I'll download that code and work from that.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 03:01:25 pm
Quote
Righto.  You mean the floating point divider?  I had a look at that and there were parameter references that I had to copy from the HDMI serialiser that were linked to other parameters which were themselves linked to blocks of HDL that just made it all a bit of a rat's nest.  I certainly didn't interpret it as a 'simple copy and paste', but I was probably overthinking something as usual.

Actually, it is a copy and paste.

You just need to create the CLK input and 2 outputs, then assign the signals in my code to them or just name the IOs accordingly.
Also, one again, just make the 3 parameters I requested.  Then either rename the parameters in my localparams to the new names, or, make 3 additional localparams which has the OLD_LOCAL_PARAM names = NEW_PARAMETER_INPUTS.

And the code should work.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2022, 03:10:36 pm
Actually, it is a copy and paste.

You just need to create the CLK input and 2 outputs, then assign the signals in my code to them or just name the IOs accordingly.
Also, one again, just make the 3 parameters I requested.  Then either rename the parameters in my localparams to the new names, or, make 3 additional localparams which has the OLD_LOCAL_PARAM names = NEW_PARAMETER_INPUTS.

And the code should work.

:o Okay, I think I'm taking your previous post too literally then.  I need to copy the entire module, rather than just the code snippet you quoted in that post, as there's no way that snippet of code will work without defining what PLL1_OUT_TRUE_HZ and HDPLL_AUDIO_HZ are, amongst others?

In other news, I've just had a spare five minutes to wire the jt49 module (and DC filter!) into the GPU module and briefly test it.  It produces the best sounds yet. :-+

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 03:17:54 pm
Code: [Select]
Yeah, I was amazed how simple the HDL for the PSG was.  The problem is, music/audio is more a dark art to me than electronics ever was.  All this talk of envelopes, sustains, attack/decay etc makes me want to run for the hills. :scared:  One of the reasons I wanted to emulate the AY-8910 chip was that it was familiar to me (in the sense I'd 'used one before' in my first computer) and I had some software in CP/M that could play some tunes to test on it.  Writing my own PSG, or using some other PSG (note the YM2149 is, to all intents and purposes, the same as the AY-891x chips) would have meant a huge problem with finding test music to run on it.
The YM2149 is a piece of (... well lets just call is an old 3 channel 1 bit audio device ...).  You can make a total of 3 tones, each a square or noise.  Each with a frequency period.  Each with a 5bit volume.  The envelope (a single envelope for all 3 channels) is an auto volume ramp with speed select for fade in, fade out, modulate up and down, and repeat.

The YM2151 looks much better (again, I linked to the IC's .pdfs and verilog source code a few posts back).  It has 8 channels.  Each channel you can select sine, square, triangle, saw, or noise.  The period/pitch of the sound.  The attach time (envelope volume up speed to an initial peak) for when you turn on the note, the sustain time, constant volume after the attach peak while you keep the note on, and decay time, the envelope volume fate out time of the note once you turned off your note.  As you can see, this chip has controls and responds a whole lot more like a real 8 channel midi instrument.  Set your parameters for each of the 8 instrument, then just feed the 8 channels with notes and let the IC worry about the fancy volume envelopes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 03:20:29 pm
Actually, it is a copy and paste.

You just need to create the CLK input and 2 outputs, then assign the signals in my code to them or just name the IOs accordingly.
Also, one again, just make the 3 parameters I requested.  Then either rename the parameters in my localparams to the new names, or, make 3 additional localparams which has the OLD_LOCAL_PARAM names = NEW_PARAMETER_INPUTS.

And the code should work.

:o Okay, I think I'm taking your previous post too literally then.  I need to copy the entire module, rather than just the code snippet you quoted in that post, as there's no way that snippet of code will work without defining what PLL1_OUT_TRUE_HZ and HDPLL_AUDIO_HZ are, amongst others?

In other news, I've just had a spare five minutes to wire the jt49 module (and DC filter!) into the GPU module and briefly test it.  It produces the best sounds yet. :-+

Yes, I wasn't joking... Take it literally...  That is the entire program.

Just copy the test code text in my post on the previous page.
All it needs is the clk in, clk out, and strobe out.
3 parameters in, INPUT_CLK_IN_HZ, OUTPUT_CLK_IN_HZ, and USE_FLOATING_POINT_PRECISION_DIVIDE.

Or, whatever names you choose, or just use the names in my code snipet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 03:27:45 pm
Look:

parameter INPUT_CLK_HZ = 100000000 ;
parameter OUTPUT_CLK_HZ = 3579545 ;
parameter USE_FLOATING_DIVIDE = 1 ;

Now, this:
Code: [Select]
localparam bit [63:0] aud_per_x4096  = PLL1_OUT_TRUE_HZ*4096/HDPLL_AUDIO_HZ ;                               // Determine the audio period 4096 fold.
localparam bit [63:0] aud_per_round  = aud_per_x4096 + 2048 ;                                               // Prepare a rounded version.
localparam bit [12:0] aud_per_int    = HDPLL_AUDIO_TCK_FLOAT ? aud_per_x4096[24:12] : aud_per_round[24:12]; // Select between the rounded integer period or true integer period.
localparam bit [11:0] aud_per_f      = HDPLL_AUDIO_TCK_FLOAT ? aud_per_x4096[11:0]  : 12'd0  ;              // select between no floating point and floating point adjusted audio clock generation.
localparam bit [63:0] aud_tru_hz     = PLL1_OUT_TRUE_HZ*4096 / (aud_per_int*4096+aud_per_f)  ;              // Calculate the true audio output clock based on oscilator frequencies & HDPLL_AUDIO_TCK_FLOAT settings.

Changes to this:
Code: [Select]
localparam bit [63:0] aud_per_x4096  = INPUT_CLK_HZ*4096/OUTPUT_CLK_HZ ;                               // Determine the audio period 4096 fold.
localparam bit [63:0] aud_per_round  = aud_per_x4096 + 2048 ;                                               // Prepare a rounded version.
localparam bit [12:0] aud_per_int    = USE_FLOATING_DIVIDE ? aud_per_x4096[24:12] : aud_per_round[24:12]; // Select between the rounded integer period or true integer period.
localparam bit [11:0] aud_per_f      = USE_FLOATING_DIVIDE ? aud_per_x4096[11:0]  : 12'd0  ;              // select between no floating point and floating point adjusted audio clock generation.
localparam bit [63:0] aud_tru_hz     = INPUT_CLK_HZ*4096 / (aud_per_int*4096+aud_per_f)  ;              // Calculate the true audio output clock based on oscillator frequencies & USE_FLOATING_DIVIDE settings.

How hard was that?

You can also rename all the ' aud_ ' to ' clk_out_ ' to make things read even better.

The 2 assigns after that are useless.
The in the code, just rename the clk in and 2 output strobes as I specified earlier.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2022, 03:48:10 pm
Okay, so the testbench is showing a final value of 7159, which is okay I guess considering the simulation runs for 2000ns and the requested output is 3579545 Hz?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 03:58:39 pm
Okay, so the testbench is showing a final value of 7159, which is okay I guess considering the simulation runs for 2000ns and the requested output is 3579545 Hz?

If you are not sure, run the sim for 1 second, or 0.1 second if you do not want to wait.  You may need to wait for 2 minutes, but you will see the true Hz.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 04:01:29 pm
Okay, so the testbench is showing a final value of 7159, which is okay I guess considering the simulation runs for 2000ns and the requested output is 3579545 Hz?
:palm: You attached the wrong code...
That one still has your old divider.
And, already 3 have downloaded the error code...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 04:13:25 pm
@nockieboy, do you know how much you are costing me in Haagen-Dazs and an increasing waist-line?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on July 28, 2022, 04:22:29 pm
@nockieboy, do you know how much you are costing me in Haagen-Dazs and an increasing waist-line?

Whuh?  No idea how that happened.  I'll try again here - don't know if it was the forum messing me about, but attaching the zip file to that last post just seemed to link to the old copy again.  :-//

EDIT: I've double-checked - it's the right zip file.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 04:54:13 pm
Ok, it's because yo used a new source code name, not entering my code into your divider.

Ok, the analysis...

In jt49_tb.sv, You should have:
Code: [Select]
`timescale 1 ns/1 ns

localparam  CLK_IN_HZ  = 100000000                   ; // Frequency of simulated clock
localparam  CLK_PSG_HZ = 1789000                     ; // PSG of simulated clock
localparam  CLK_I2S_HZ = 3072000                     ; // I2S bit clock rate of simulated clock

localparam  CLK_PERIOD = 1000000000/CLK_IN_HZ        ; // Period of simulated clock.
localparam  CMD_COUNT  = 8                           ; // Number of commands to send to PSG.
localparam  ENDTIME    = (1000 * 1000 * 10) + 20     ; // Number of ns to stop simulation at.

and, you should have: (Just download the attached new tb source)
Code: [Select]
    // Instantiate DUT
    fp_div #(
   
    .INPUT_CLK_HZ  (CLK_IN_HZ ),
    .OUTPUT_CLK_HZ (CLK_PSG_HZ)
   
    ) DUT (

        .clk_in     ( clk   ), // source clock for strobe (divided by DIVISOR if >1)
        .clk_out    ( p_div ), // divided clock 50:50 duty cycle output
        .strobe_out ( p_stb )  // divided clock strobe output

    );

Now, after simulating and inspecting both the waveform and the 'DUT' module to see it's registers, we see:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1551049)

You can see a simulation of 0.01 seconds of real time gives us a result of 17890 just prior to the 0.01 second mark and my localparam of 'aud_tru_hz' is 1789005, in other words, 5hz too fast.

So, your integer divider was set to 56, IE 100000000/56 = 1785714hz, 3286Hz too slow.

We can still do better, lets modify my code to go from 12bit float to 16bit float to iron out that last bit of error.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 05:14:55 pm
Ok, after the 12 to 16 bit floating accumulator change, we see this:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1551088)

A tighter timing at the 0.01 second mark and aud_tru_hz reports that if we simulated for 1 full second, we would have 1789000Hz.  Though, we do not see the fractions after the last Hz, so we can say this output will be within dead perfect to 0.999999Hz faster than the readout instead of the 12bit version output which would be anywhere from +5.0000 to +5.999999Hz too fast.

Just download the attache source code changes and lets next develop the I2S transmitter.

(Separate sim project as we will first replicate the DECA's HDMI demo 1Khz sine wave with our I2S transmitter, but now using our new clock divider instead of the old DECA pll design, running off of one of my simple 1080p video out demos.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on July 28, 2022, 06:09:53 pm
Ok, after a billion ns of simulated runtime, IE: 1 second, with the new 16bit float, we can now see that the oscillator is only around 0.25hz to fast compared to the requested hz, not 3286Hz too slow when using an integer only clock divider.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1551112)

Next, I will make a quick-sim patch as simulating a second can be done much faster for testing the PSG.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 02, 2022, 07:25:48 pm
Ok Nockieboy, here is your serializer hint:

module name I2S_transmitter.

Parameter int BITS         = 16  // Audio width, can be anything from 8 to 24...
Parameter bit INV_BCLK = 0   // When set, make I2S_BCLK fall during valid data...

Inputs:
clk_in              // High speed clock.
clk_i2s            // 50/50 duty cycle serial audio clock to feed through.
clk_i2s_pulse  // Should pulse for one clk_in cycle at the beginning of each new clk_i2s.

sample_in                    // Optional input to reset the sample position.  This should either be tied to GND or only pulse once every 64 'clk_i2s_pulse's.
[BITS-1:0] DAC_Left    // Left channel digital audio sampled once every 'sample_pulse' output.
[BITS-1:0] DAC_Right  // Right channel digital audio sampled once every 'sample_pulse' output.

Outputs:
reg sample_pulse   // Pulses once when a new stereo sample is taken from the DAC_Left/Right inputs.  Hint: once every 64 clk_i2s_pulse's.
reg I2S_BCLK    // I2S serial bit clock output, basically the clk_i2s input in the correct phase.
reg I2S_WCLK  // I2S !left/right output.
red I2S_DATA  // Serial data output.

This is all we need this module to do.
Since we have 64 clock pulses there will be obviously one 6 bit reg counter.
I expect a serial shift out register plus a second register to buffer the right DAC input.
The code should be a few embedded if(), 1 for the main counter, one for the serial load/shifter, and a last reg buffering the output regs.

Lets see what you can come up with.
We will copy/rename the PSG and make a new module testing the serializer with our fp_divider driving the serializer to show our I2S output in the waveform view.  The left and right inputs should be created in the _tb module.
 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2022, 01:52:47 pm
Ok Nockieboy, here is your serializer hint:

module name I2S_transmitter.

Parameter int BITS         = 16  // Audio width, can be anything from 8 to 24...
Parameter bit INV_BCLK = 0   // When set, make I2S_BCLK fall during valid data...

Inputs:
clk_in              // High speed clock.
clk_i2s            // 50/50 duty cycle serial audio clock to feed through.
clk_i2s_pulse  // Should pulse for one clk_in cycle at the beginning of each new clk_i2s.

sample_in                    // Optional input to reset the sample position.  This should either be tied to GND or only pulse once every 64 'clk_i2s_pulse's.
[BITS-1:0] DAC_Left    // Left channel digital audio sampled once every 'sample_pulse' output.
[BITS-1:0] DAC_Right  // Right channel digital audio sampled once every 'sample_pulse' output.

Outputs:
reg sample_pulse   // Pulses once when a new stereo sample is taken from the DAC_Left/Right inputs.  Hint: once every 64 clk_i2s_pulse's.
reg I2S_BCLK    // I2S serial bit clock output, basically the clk_i2s input in the correct phase.
reg I2S_WCLK  // I2S !left/right output.
red I2S_DATA  // Serial data output.

This is all we need this module to do.
Since we have 64 clock pulses there will be obviously one 6 bit reg counter.
I expect a serial shift out register plus a second register to buffer the right DAC input.
The code should be a few embedded if(), 1 for the main counter, one for the serial load/shifter, and a last reg buffering the output regs.

Lets see what you can come up with.
We will copy/rename the PSG and make a new module testing the serializer with our fp_divider driving the serializer to show our I2S output in the waveform view.  The left and right inputs should be created in the _tb module.

Okay, so something like the attached file?  I haven't had the time to test it in ModelSim yet, so it's barely more than pseudo-code - but is it going in the right direction? ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 02:27:22 pm
Ok, that's one way to go about it.

Your:
Code: [Select]
            I2S_DATA     <= DAC_Buffer[ bitcounter ] ;Is valid, but the extra addressing and position counter wont hamper anything at this rate, but the clues of a serial shift register.  For now, just a simple logic error on your part here:

Code: [Select]
        // Strobe sample_pulse once every 64 cycles & sample appropriate L/R input
        if ( I2S_counter == 0 ) begin

            DAC_Buffer   <= DAC_Left  ;
            sample_pulse <= 1'b1      ;
            bitcounter   <= ~0        ; // set bitcounter to all 1's
            I2S_WCLK     <= LEFT      ;

        end else if ( I2S_counter == 32 ) begin

            DAC_Buffer   <= DAC_Right ;  <<<<<<
            sample_pulse <= 1'b1      ;     <<<<<< REMEMBER, we want to do 1 stereo sample every 64 clocks.
            bitcounter   <= ~0        ; // set bitcounter to all 1's
            I2S_WCLK     <= RIGHT     ;
       
        end else begin

Ok, let's take a look at a simpler serial shifter.
Some other changes is that everything except the I2S_BCLK is now inside the 'if ( clk_i2s_pulse ) begin':

Code: [Select]
// Initial I2S_transmitter code, untested, by nockieboy August 2022.

module I2S_transmitter #(

    parameter int           BITS     = 16,  // Audio width, can be anything from 8 to 24
    parameter bit           INV_BCLK = 0    // When set, make I2S_BCLK fall during valid data

)(

    //Inputs
    input  logic            clk_in,         // High speed clock
    input  logic            clk_i2s,        // 50/50 duty cycle serial audio clock to feed through
    input  logic            clk_i2s_pulse,  // Should strobe for one clk_in cycle at the beginning of each new clk_i2s
    input  logic            sample_in,      // Optional input to reset the sample position.  This should either be tied to GND or only pulse once every 64 'clk_i2s_pulse's
    input  logic [BITS-1:0] DAC_Left,       // Left channel digital audio sampled once every 'sample_pulse' output
    input  logic [BITS-1:0] DAC_Right,      // Right channel digital audio sampled once every 'sample_pulse' output

    //Outputs
    output logic            sample_pulse,   // Pulses once when a new stereo sample is taken from the DAC_Left/Right inputs.  Hint: once every 64 clk_i2s_pulse's
    output logic            I2S_BCLK,       // I2S serial bit clock output (SCLK), basically the clk_i2s input in the correct phase
    output logic            I2S_WCLK,       // I2S !left / right output (LRCLK)
    output logic            I2S_DATA        // Serial data output

);

    logic              [5:0] I2S_counter       <= 0 ;
    logic         [BITS-1:0] DAC_right_buffer  <= 0 ;
    logic         [BITS-1:0] DAC_serial_buffer <= 0 ;

    // Since I2S uses 64 clock pulses, we need one 6-bit reg counter.
    // I expect a serial shift out register plus a second register to buffer the right DAC input.
    // The code should be a few embedded if(), 1 for the main counter, one for the serial load/shifter,
    // and a last reg buffering the output regs.

    // We will copy/rename the PSG and make a new module testing the serializer with our fp_divider driving
    // the serializer to show our I2S output in the waveform view.  The left and right inputs should be
    // created in the _tb module.


assign I2S_WCLK = I2S_counter[5] ;             // Hard wire the I2S Word Clock to the I2S_counter MSB.
assign I2S_DATA = DAC_serial_buffer [BITS-1] ; // Hard wire the I2S serial data bits to the MSB of the serial data buffer.

  always_ff @( posedge clk_in ) begin

    // Optional Invert clk_i2s for correct I2S_BCLK phase
    I2S_BCLK <= clk_i2s ^ !INV_BCLK ;

        // Manage I2S pulse counter and serialisation
    if ( clk_i2s_pulse ) begin

            if (sample_in) I2S_counter  <= 0               ; // Optional clear to I2S counter position '0'
            else           I2S_counter  <= I2S_counter + 1 ;


            sample_pulse       <= ( I2S_counter == 0 )     ; // Pulse the output reference sample clock.

        // Strobe sample_pulse once every 64 cycles & sample appropriate L/R input
        if ( I2S_counter == 0 ) begin

            DAC_right_buffer   <= DAC_Right              ; // Keep a copy of the Right channel data to be transmitted during the second half.
                                                           // This was done to make sure both left and right channel data are captured in parallel on the same clock.

            DAC_serial_buffer  <= DAC_LEFT               ; // Transfer the left channel for immediate transmission.

        end else if ( I2S_counter == 32 ) begin

            DAC_serial_buffer  <= DAC_right_buffer       ; // Transfer the right channel's sample for immediate transmission.
       
        end else begin

            DAC_serial_buffer  <= DAC_serial_buffer << 1 ; // Left shift the serial out data.

        end


    end // if ( clk_i2s_pulse ) begin
  end // always

endmodule

This code should do it.  If it simulates ok, we will test wire in this sine-table with counter to verify that you still hear a clean sine tone once wired into the HDMI output project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 02:32:23 pm
Don't forget this sine table code:
Code: [Select]
module Sine_1KHz_16b_48ksps (

input  logic               clk,
    input  logic               clk_ena,
output logic signed [15:0] audio
);

logic [5:0] sam_pos;

always_ff @(posedge clk) begin

  if (clk_ena) begin

    if   (sam_pos==6'd47) sam_pos <= 6'd0 ;
    else                  sam_pos <= sam_pos + 1'b1 ;

// 48 word sine table.
if (sam_pos==6'd0) audio <= 16'(0);
if (sam_pos==6'd1) audio <= 16'(4276);
if (sam_pos==6'd2) audio <= 16'(8480);
if (sam_pos==6'd3) audio <= 16'(12539);
if (sam_pos==6'd4) audio <= 16'(16383);
if (sam_pos==6'd5) audio <= 16'(19947);
if (sam_pos==6'd6) audio <= 16'(23169);
if (sam_pos==6'd7) audio <= 16'(25995);
if (sam_pos==6'd8) audio <= 16'(28377);
if (sam_pos==6'd9) audio <= 16'(30272);
if (sam_pos==6'd10) audio <= 16'(31650);
if (sam_pos==6'd11) audio <= 16'(32486);
if (sam_pos==6'd12) audio <= 16'(32767);
if (sam_pos==6'd13) audio <= 16'(32486);
if (sam_pos==6'd14) audio <= 16'(31650);
if (sam_pos==6'd15) audio <= 16'(30272);
if (sam_pos==6'd16) audio <= 16'(28377);
if (sam_pos==6'd17) audio <= 16'(25995);
if (sam_pos==6'd18) audio <= 16'(23169);
if (sam_pos==6'd19) audio <= 16'(19947);
if (sam_pos==6'd20) audio <= 16'(16383);
if (sam_pos==6'd21) audio <= 16'(12539);
if (sam_pos==6'd22) audio <= 16'(8480);
if (sam_pos==6'd23) audio <= 16'(4276);
if (sam_pos==6'd24) audio <= 16'(-1);
if (sam_pos==6'd25) audio <= 16'(-4277);
if (sam_pos==6'd26) audio <= 16'(-8481);
if (sam_pos==6'd27) audio <= 16'(-12540);
if (sam_pos==6'd28) audio <= 16'(-16384);
if (sam_pos==6'd29) audio <= 16'(-19948);
if (sam_pos==6'd30) audio <= 16'(-23170);
if (sam_pos==6'd31) audio <= 16'(-25996);
if (sam_pos==6'd32) audio <= 16'(-28378);
if (sam_pos==6'd33) audio <= 16'(-30273);
if (sam_pos==6'd34) audio <= 16'(-31651);
if (sam_pos==6'd35) audio <= 16'(-32487);
if (sam_pos==6'd36) audio <= 16'(-32767);
if (sam_pos==6'd37) audio <= 16'(-32487);
if (sam_pos==6'd38) audio <= 16'(-31651);
if (sam_pos==6'd39) audio <= 16'(-30273);
if (sam_pos==6'd40) audio <= 16'(-28378);
if (sam_pos==6'd41) audio <= 16'(-25996);
if (sam_pos==6'd42) audio <= 16'(-23170);
if (sam_pos==6'd43) audio <= 16'(-19948);
if (sam_pos==6'd44) audio <= 16'(-16384);
if (sam_pos==6'd45) audio <= 16'(-12540);
if (sam_pos==6'd46) audio <= 16'(-8481);
if (sam_pos==6'd47) audio <= 16'(-4277);

  end
end
endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2022, 02:48:21 pm
Code: [Select]
           sample_pulse       <= ( I2S_counter == 0 )     ; // Pulse the output reference sample clock.

Just a quick question about the quoted line of code above.  Would the following also be a valid method of testing for a zero value?

Code: [Select]
sample_pulse <= ( !I2S_counter ) ;
And if so, which would be best and why? :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 02:55:28 pm
Code: [Select]
           sample_pulse       <= ( I2S_counter == 0 )     ; // Pulse the output reference sample clock.

Just a quick question about the quoted line of code above.  Would the following also be a valid method of testing for a zero value?

Code: [Select]
sample_pulse <= ( !I2S_counter ) ;
And if so, which would be best and why? :-//
Hmm, !I2S_counter has multiple bits.  I guess what you wrote is acceptable, but what if you want to change it to (I2S_counter == 63) to give you a pulse ahead of time by 1 clock?  Or 2, or give you a pulse after the sample period giving you a bunch of time to fetch the data and get it ready for the next sample.

I guess what I am saying is the ' == ' illustrates a specific singular value regardless of the source bit count, or the output will be guaranteed to be a 1 bit result.  You could have also placed it inside the 'if()', but then you need to remember to un-set it in the 'else'.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2022, 04:10:56 pm
Hmm, okay, here's a testbench simulation with the fixed 16-bit values 0xAAAA on the LEFT channel and 0x5555 on the RIGHT channel.  Doesn't look right to me - should it be sending 32 bits per L/R channel or 16 bits?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1556911)

Also, in this block of code below:

Code: [Select]
            if ( I2S_counter == 0 ) begin

                DAC_right_buffer   <= DAC_Right             ; // Keep a copy of the Right channel data to be transmitted during the second half.
                                                              // This was done to make sure both left and right channel data are captured in parallel on the same clock.
                DAC_serial_buffer  <= DAC_Left              ; // Transfer the left channel for immediate transmission.

            end else if ( I2S_counter == 32 ) begin

                DAC_serial_buffer <= DAC_right_buffer       ; // Transfer the right channel's sample for immediate transmission.
           
            end else begin

                DAC_serial_buffer <= DAC_serial_buffer << 1 ; // Left shift the serial out data.

            end

Shouldn't the module be sending out a bit of data when I2S_counter equals 0 and 32?  At the moment, if it equals either of those two values no bit of data is sent to the DAC_serial_buffer.  Is that right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 04:48:44 pm
This looks correct.  The I2S standard is up to 32bits per channel.
Look here:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1556956)

Your pattern looks correct.

Now, say we want 3 dacs in our system, a cheap 16 bit one with a headphone output and a 20 bit line level one and 24 bit for the HDMI, all with the same sound.  Notice how the MSB is at the beginning.  What would happen if we feed all 3 digital sources the same signal, all expecting 32 clocks per channel, but each outputting the most bits they can?

Also, look at it the other way around, say we can only generate 8 bit audio, meaning after our 8th bit lsb, we just send a bunch of blank zeros until the 32nd clock when the right channel begins and we send it's msb?  Will all 3 dacs on our bus still work OK?

There is one thing we should change, change line 43 to:
Code: [Select]
            sample_pulse <= ( I2S_counter == 63 ) ; // Pulse the output reference sample clock.
It is a good idea to have the active sample pulse be at the right time when we sample the left and right inputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 03, 2022, 05:07:15 pm
Now, say we want 3 dacs in our system, a cheap 16 bit one with a headphone output and a 20 bit line level one and 24 bit for the HDMI, all with the same sound.  Notice how the MSB is at the beginning.  What would happen if we feed all 3 digital sources the same signal, all expecting 32 clocks per channel, but each outputting the most bits they can?

Ah of course, yes, I understand. :-+

Right, so what's next?  Wire up the sine table to this?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 05:17:07 pm
Yes, wire up the sine table, test, and wire it up to HDMI out to verify a clean sine sound at full volume.  Once good, we will add a volume boost to the PSG's output, add a low pass filter to round the edges, then place it into you GPU.  Then you will decide if you are done, or you want to improve the DC filter with a few new lines of code.

Extra, here is the I2S spec from TI's audio dac's datasheet app-notes:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1556980)

It's the same story, though, they do have I2C register controls to invert the bit-clock input sensitivity and the ability to shift the MSB further to the right by a second clock.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 05:47:32 pm
After applying these 2 patches which are missing in the latest I2S _tb:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4326349/#msg4326349 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4326349/#msg4326349)

Make this change at the top:
Code: [Select]
localparam bit QUICK_SIM = 0                                  ; // When running long simulations, turning this on will multiply the sim speed.
localparam  CLK_PSG_HZ   = 1789000                            ; // PSG of simulated clock
localparam  CLK_I2S_HZ   = 3072000                            ; // I2S bit clock rate of simulated clock
localparam  CLK_IN_HZ    = QUICK_SIM ? CLK_PSG_HZ : 100000000 ; // Select operating frequency of simulation.

localparam  CLK_PERIOD = 1000000000/CLK_IN_HZ        ; // Period of simulated clock.
localparam  CMD_COUNT  = 8                           ; // Number of commands to send to PSG.
localparam  ENDTIME    = (1000 * 1000 * 10) + 20    ; // Number of ns to stop simulation at.

We need accurate timing to check that my low pass filter wont be too strong.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 10:15:57 pm
@nockieboy, are you sure this PSG was meant to run at 1.789MHz?

For example, a frequency setting of 11 = ~10.165 Khz while a setting of 10 = ~11.181 Khz.  That's a 1khz jump and the jumps get larger the lower the frequency number, IE higher frequency.

Wouldn't a faster chip at least give you some more granularity at the higher pitches?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 03, 2022, 11:04:22 pm
We had to wire the PSG's .sample() output as the new clock strobe for the DC filter.
Like this:
Code: [Select]
    wire sample_stb ; // A new strobe for when the sample is ready.

    // Instantiate PSG
    BHG_jt49 #(

        .DAC_BITS   ( DAC_BITS   ),
        .VOL_ATT_DB ( VOL_ATT_DB )

    ) PSG (

        .rst_n    ( reset      ),
        .clk      ( clk        ),
        .clk_en   ( p_stb      ),
        .addr     ( addr[step] ),
        .cs_n     ( 1'b0       ),
        .wr_n     ( wr_n       ),
        .din      ( data[step] ),
        .sel      ( 1'b1       ),
        .dout     ( dout       ),
        .sound    ( sound_mix  ),
        .A        (            ),
        .B        (            ),
        .C        (            ),
        .sample   ( sample_stb ),
        .IOA_in   (            ),
        .IOA_out  (            ),
        .IOB_in   (            ),
        .IOB_out  (            )

    );

    jt49_dcrm2 #(

        .sw    (  DAC_BITS+2   )

    ) PSG_DCFILT (

        .clk   (  clk         ),
        .cen   (  sample_stb  ),
        .rst   (  ~reset      ),
        .din   (  sound_mix   ),
        .dout  (  sound       )
    );

This should further improve sound quality with better low frequencies.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2022, 01:59:59 am
Ok, every file has been changed.  So, anything you have done on your side should be backed up and replaced.

Damn, those jt49 filters were buggy.
I also increased the core DAC bits to an adjustable parameter setting with a volume attenuation dynamic range setting.

I added the low pass filter, see: (parameter LPFILTER_DEPTH = 4)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1557394)

That should be more comfortable to the ears, though you might want to tune the LPFILTER_DEPTH parameter to your liking.  It is like a treble control.

Download the updates.
Also, when the new QUICK_SIM=1, the I2S transmitter is a chunky mess.  Turning off the quick_sim fixes the problem, but simulations are ~10x slower, so you would need to shrink the 'endtime'.


First get the 1khz sine test going.

Then make a new PSG_TOP module to the name of your liking and stuff lines 25 through 152 of your TB inside and make the used relevant parameters & IO for that module and replace lines 25 through 152 in the TB with that one new module as it is your complete PSG ready to place in your GPU.


EDIT:
LPFILTER_DEPTH = 5 or 6 might be the sweet spot.  My sim snapshot above used 4.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 04, 2022, 09:28:29 am
That's looking really good!  Fortunately, even with QUICK_SIM set to 0, it only takes about 10 seconds to simulate without changing the length of the simulation.

I'm keeping about seventeen plates spinning at the moment and I'm going to be away for a week next week, so there's going to be a big(ger than usual) delay in getting anything done and it'll be even harder for me to focus for the rest of this week/weekend.

I'm marvelling at what you've done with the filters, the simulation output and trying to get my head around all these audio-related terms, and failing miserably.  Then I realised I need to be doing something... :-DD

So I need to wire the sine table to the HDMI serialiser to make sure that's working okay?  In simulation or actual HDL?  Or wire the sine table through the new filters in place of the PSG output and test that in simulation?

Sorry for the confusion, I've only got small pockets of time to work on this this week so I probably need a little more basic instruction than usual. :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2022, 09:34:22 am
So I need to wire the sine table to the HDMI serialiser to make sure that's working okay?  In simulation or actual HDL?  Or wire the sine table through the new filters in place of the PSG output and test that in simulation?

Sorry for the confusion, I've only got small pockets of time to work on this this week so I probably need a little more basic instruction than usual. :-\

You don't need to sim, just wire the sine table to the i2s transmitter in a test hdmi out project to see if you get the clean tone.

Dont forget to get rid of the audio pll and use the fp_div, and, the sine's input .clk_ena() needs to be the (fp_strobe && i2s_sample_pulse) so it only increments once every 48khz sample.

(I do not have a monitor with HDMI input and speakers to test this I2S transmitter myself, so you have to do it...)

If that works at a clean full volume, then my latest sim should sound correct, or as intended.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2022, 10:01:46 am
I'm marvelling at what you've done with the filters, the simulation output and trying to get my head around all these audio-related terms, and failing miserably.  Then I realised I need to be doing something... :-DD

What the filters are doing:

The jt49 output sample speed is really fast.  It is running at the (1.789Mhz / 4).

The low pass filter, which removes the high frequencies basically takes in the sound samples and 'averages' a small number of these samples (2^LPFILTER_DEPTH) from left to right, removing the sharp edges on it's output.

The dc filter is a high pass filter.  It does the opposite of the low pass filter.  It looks at the average of the past few thousands of samples (a large number means low frequencies are still allowed), and if the average is too high, it subtracts the output offset, position.  If the average is too low, then it adds to the output offset position.  The end result is generating a continuous corrective push, centering the output waveform around the mid 0 point.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 04, 2022, 12:34:32 pm
You don't need to sim, just wire the sine table to the i2s transmitter in a test hdmi out project to see if you get the clean tone.

Dont forget to get rid of the audio pll and use the fp_div, and, the sine's input .clk_ena() needs to be the (fp_strobe && i2s_sample_pulse) so it only increments once every 48khz sample.

Uh, still lost on this.  Instead of messing about creating a new project, I'm just using the existing GPU_DECA project and tweaking the GPU_DECA_DDR3_top file to get this sine wave table set up.

I've gotten rid of u_sys_pll which produced the pll_1536k signal and replaced it with an fp_div instance.  Does this need to output the 1536k clock signal or a 3072k one?  Will I need to change the HDMI transmitter's mode at all if I switch to a double-speed clock for the audio_i2s module?

I'm guessing I need another fp_div to create a 48k clock signal to feed a strobe to the clk_ena input of the sine table module?

Code: [Select]
fp_div #(

   .INPUT_CLK_HZ        ( 100000000 ),
   .OUTPUT_CLK_HZ       (   3072000 ),
   .USE_FLOATING_DIVIDE (         1 ) 

) fp_div_i2s (

   .clk_in     ( CLK_IN    ),
   .clk_out    ( i2s_3072k ),
   .strobe_out ( i2s_stb   )

);

// ***************************************************************************************************************
// Test Sine Wave Table Generator
// ***************************************************************************************************************
wire [15:0] aud_test ;

Sine_1KHz_16b_48ksps test_audio(

   .clk     ( CLK_IN   ),
   .clk_ena ( (i2s_stb && i2s_sample_pulse) ),
   .audio   ( aud_test )

);

// ***************************************************************************************************************
// HDMI Audio I2S interface
// ***************************************************************************************************************
audio_i2s u_AVG(

   //.clk     ( pll_1536k  ),
   .clk     ( i2s_3072k  ),
   .reset_n ( !RST_IN    ),
   //.audio_i ( aud_16_o   ),
   .audio_i ( aud_test   ),
   .sclk    ( HDMI_SCLK  ),
   .lrclk   ( HDMI_LRCLK ),
   .i2s     ( HDMI_I2S   )

);

I'm probably going to give up on this today - I might have some time tomorrow, but I clearly can't put the time into this right now to understand what I need to be doing. :-[
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2022, 02:59:48 pm
You don't need to sim, just wire the sine table to the i2s transmitter in a test hdmi out project to see if you get the clean tone.

Dont forget to get rid of the audio pll and use the fp_div, and, the sine's input .clk_ena() needs to be the (fp_strobe && i2s_sample_pulse) so it only increments once every 48khz sample.

Uh, still lost on this.  Instead of messing about creating a new project, I'm just using the existing GPU_DECA project and tweaking the GPU_DECA_DDR3_top file to get this sine wave table set up.

I've gotten rid of u_sys_pll which produced the pll_1536k signal and replaced it with an fp_div instance.  Does this need to output the 1536k clock signal or a 3072k one?  Will I need to change the HDMI transmitter's mode at all if I switch to a double-speed clock for the audio_i2s module?

I'm guessing I need another fp_div to create a 48k clock signal to feed a strobe to the clk_ena input of the sine table module?


I'm probably going to give up on this today - I might have some time tomorrow, but I clearly can't put the time into this right now to understand what I need to be doing. :-[

Ok, take a look below...

Code: [Select]
// ------------------------------------------------------------------------------------------------------------
// -------- This little bit is a give-me, I did not expect you to work this out nor is it needed to test ------
// ------------------------------------------------------------------------------------------------------------
localparam DDR3_CLK_HZ = (CLK_KHZ_IN*CLK_IN_MULT/CLK_IN_DIV*1000); // Calculate the DDR3 hz speed.
localparam CMD_CLK_HZ  = INTERFACE_SPEED[0]=="Q" ? DDR3_CLK_HZ/4 :
                         INTERFACE_SPEED[0]=="q" ? DDR3_CLK_HZ/4 : DDR3_CLK_HZ/2 ; // Generate the correct CMD_CLK_HZ.
// ------------------------------------------------------------------------------------------------------------

wire i2s_3072k ;  <<<<<<<<<<< need these 2 wires...
wire i2s_stb ;

fp_div #(

   .INPUT_CLK_HZ        ( CMD_CLK_HZ ),   <<<< Choose one of the 2 below in case the tone isn't 1khz
//   .INPUT_CLK_HZ        ( 100000000 ),
   .OUTPUT_CLK_HZ       (   3072000 ),      <<<< You may optionally call this (48000 * 64), in case in the future you want to use 44100Hz and do not remember that I2S clock frequency.
   .USE_FLOATING_DIVIDE (         1 ) 

) fp_div_i2s (

   .clk_in     ( CMD_CLK   ),  <<<<<<<<<<<<<<
   .clk_out    ( i2s_3072k ),
   .strobe_out ( i2s_stb   )

);

// ***************************************************************************************************************
// Test Sine Wave Table Generator
// ***************************************************************************************************************
wire signed [15:0] aud_test ; <<<<< forgot signed.
wire i2s_sample_pulse ;         <<< Need this wire

Sine_1KHz_16b_48ksps test_audio(

   .clk     ( CMD_CLK   ),   <<<<<<<<<<<<<
   .clk_ena ( (i2s_stb && i2s_sample_pulse) ),
   .audio   ( aud_test )

);

// ***************************************************************************************************************
// HDMI Audio I2S interface
// ***************************************************************************************************************
audio_i2s u_AVG(   <<<<<<<<<<<<<<<<<<<<   W...?   THIS IS NOT OUR I2S TRANSMITTER

   //.clk     ( pll_1536k  ),
   .clk     ( i2s_3072k  ),
   .reset_n ( !RST_IN    ),
   //.audio_i ( aud_16_o   ),
   .audio_i ( aud_test   ),
   .sclk    ( HDMI_SCLK  ),
   .lrclk   ( HDMI_LRCLK ),
   .i2s     ( HDMI_I2S   )

-------------------------------------------------------------------
THIS DOWN HERE
------------------------------------------------------------------

wire     i2s_data ; <<<< need this temporary wire.

    I2S_transmitter #(

        .BITS     ( 16 ),  <<<<<< the size of the wire 'aud_test'.
        .INV_BCLK (  0 )

    ) I2S_TX (

        .clk_in         ( CMD_CLK   ), // High speed clock
        .clk_i2s        ( i2s_3072k ), // 50/50 duty cycle serial audio clock
        .clk_i2s_pulse  ( i2s_stb   ), // Strobe for 1 clk_in cycle at the beginning of each clk_i2s
        .sample_in      ( 1'b0      ), // Optional input to reset the sample position.  This should either be tied to GND or only pulse once every 64 'clk_i2s_pulse's
        .DAC_Left       ( aud_test  ),  // Left channel digital audio sampled once every 'sample_pulse' output
        .DAC_Right      ( aud_test  ),  // Right channel digital audio sampled once every 'sample_pulse' output

        .sample_pulse   ( i2s_sample_pulse ), // Pulses once when a new stereo sample is taken from the DAC_Left/Right inputs.  Hint: once every 64 clk_i2s_pulse's
        .I2S_BCLK       ( HDMI_SCLK   ), // I2S serial bit clock output (SCLK), basically the clk_i2s input in the correct phase
        .I2S_WCLK       ( HDMI_LRCLK  ), // I2S !left / right output (LRCLK)
        .I2S_DATA       ( i2s_data    )  // Serial data output   

    );

// Wire all 4 stereo channels together.
// We must BLAST that incredible YM2149 sound on every speaker possible so that we are bathed in its infinite beauty!
assign HDMI_I2S[0] = i2s_data  ; // (front left and right)
assign HDMI_I2S[1] = i2s_data  ; // (rear left and right)
assign HDMI_I2S[2] = i2s_data  ; // (Front Center and Sub-woofer)
assign HDMI_I2S[3] = i2s_data  ; // (side left and right)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 04, 2022, 06:42:33 pm
If you achieve a nice clean 1khz tone, ignore the rest of this message... (Don't forget to patch line 141 of the I2C_HDMI_Config.v first in case you are running in DVI mode.)

Quote
If you fail to get any sound, there is a slight chance you might need to set the HDMI transmitter's I2C config address 0x0A with 0x00, or 0x03.

See: I2C_HDMI_Config,

You will need to add a new entry to the bottom of the table:

Code: [Select]
31 : LUT_DATA <= 16'h0A00;  // or 16'h0A03, default 16'h0A01   MCLK Ratio The ratio between the audio sampling frequency and the clock described using N and CTS
And adjust the parameter on line 32,  LUT_SIZE = 31 to 32.

Do not do this until all other avenues of bugs have been worked out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 06:07:53 am
@nockieboy, I need to see a schematic of how the analog outputs for the YM2149 are wired to the audio jack.  Since it has 3 individual outputs, 1 per channel, depending on the wiring, I believe that the jt49 filters we are using and the way they are wired will not generate the appropriate sound.  We want to include the proper math formula to replicate the circuit's analog sound.

See attached example filters:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2022, 07:54:37 am
@nockieboy, I need to see a schematic of how the analog outputs for the YM2149 are wired to the audio jack.  Since it has 3 individual outputs, 1 per channel, depending on the wiring, I believe that the jt49 filters we are using and the way they are wired will not generate the appropriate sound.  We want to include the proper math formula to replicate the circuit's analog sound.

Below is a section of my hardware soundcard schematic that I made a few years ago for the uCOM using a real AY-8910 chip and analogue output stage.  The output mirrors almost exactly the channel mix setup of the Amstrad computers that I wanted to reproduce (apart from having an amplifier built-in too, ignore the volume control (R7-R9) and LM386 that sits off-shot for that):

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1558303;image)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 08:11:48 am
Ok, I can throw something together on the weekend.

The way you have that circuit, if you plug the headphone out to an audio amp or powered speakers, the bass should seem ok.  But, if you plug in headphones, the bass should become crapped out and the volume should suffer.

Also, there is no low pass filter.  Doesn't that output have a high pitched tin sound?

Anyways, copy my code from here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4339420/#msg4339420 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4339420/#msg4339420) and get the 1khz sine test working.  Make sure the tone is soft and pure without any clicks or pops.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2022, 08:35:02 am
Ok, I can throw something together on the weekend.

The way you have that circuit, if you plug the headphone out to an audio amp or powered speakers, the bass should seem ok.  But, if you plug in headphones, the bass should become crapped out and the volume should suffer.

Also, there is no low pass filter.  Doesn't that output have a high pitched tin sound?

Anyways, copy my code from here: https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4339420/#msg4339420 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4339420/#msg4339420) and get the 1khz sine test working.  Make sure the tone is soft and pure without any clicks or pops.

It sounded pretty authentic to be fair, but I literally just copied existing (old) schematics and referred to modern schematics for the amp stage, wired it together and hoped it worked.  I'm not an audiophile by any stretch of the imagination, I certainly know nothing about audio/analogue electronics (apart from the need for decoupling, I understand that!) and am probably tone-deaf too, so there's that.  :-DD
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2022, 08:39:54 am
Yes, getting a nice clear 1KHz tone from the TV now. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 08:42:44 am
Yes, getting a nice clear 1KHz tone from the TV now. :-+
It seems it's ok.  If the sine had the wrong bit position, or not being 'signed' representation, you would have heard a tin-sounding effect like a square or saw-tooth wave.

Now, bundle all the '_tb' PSG core with filters and clock dividers into a new PSG system .sv module with just the clk, command and parameter inputs, and I2S outputs.  Then use that 1 module to replace the current sine test section only keeping my 'localparam' CMD_CLK_HZ calculator so the new PSG system will automatically receive the CMD_CLK frequency no matter how you configure the DDR3 system clock.

Quote
Then make a new PSG_TOP module to the name of your liking and stuff lines 25 through 152 of your TB inside and make the used relevant parameters & IO for that module and replace lines 25 through 152 in the TB with that one new module as it is your complete PSG ready to place in your GPU.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 09:00:55 am
Once working and sounding good, replace lines 25 through 152 in your _tb with the new PSG system like it is wired in your GPU.  Upload the new tb so I may engineer the new stereo output mixer with the new singular 'PSG system' module.

As for the DECA audio codec, I have the programmer's app notes data sheet and it has a few I2C registers which need to be set 1ms after reset.  Then with nothing more than a hard-wired I2S signal, you should get both HDMI and line out audio simultaneously working.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2022, 11:31:00 am
Here's my PSG _top module.  Haven't had time to merge it into the DECA_DDR3_top module yet, so there's probably mistakes and errors in it.  Just wondering about the DAC_BITS parameter.  This determines the width of the sound output to the I2S transmitter, as well as the depth of the DAC I guess.

If I understand it all correctly, I'm going to need a 16-bit output to the I2S transmitter, which means DAC_BITS can only be 15, unless I add in some code to automatically 'make up' the width to 16 bits no matter what DAC_BITS value is entered - is that right?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 02:15:07 pm
Ok, only a minor error:

Line 60:
.INPUT_CLK_HZ        ( CMD_CLK_HZ ),
Change to: CLK_IN_HZ

The parameter 'CMD_CLK_HZ' is outside this module feeding this module's parameter 'CLK_IN_HZ'.

Line 61:
.OUTPUT_CLK_HZ       ( (48000*64) ),   // 48KHz signal
Change to: CLK_I2S_HZ.

You may place the '(48000*64)' in place of the '3072000' on parameter line 5.

Or, even better, rename parameter on line 5 from 'CLK_I2S_HZ' to 'I2S_DAC_HZ' and just place 48000 there.

Then on line 61, change it's output clock setting to this:
.OUTPUT_CLK_HZ       ( I2S_DAC_HZ*64 ),   // 48KHz signal


We don't need line 27, that is specifically for the _tb.sv module and its simulated master clock.


That's it.  You did very well.

Quote
If I understand it all correctly, I'm going to need a 16-bit output to the I2S transmitter, which means DAC_BITS can only be 15, unless I add in some code to automatically 'make up' the width to 16 bits no matter what DAC_BITS value is entered - is that right?

The 'DAC_BITS' (currently set to 10) now defines the depth of each channel's, A-B-C audio output.
When mixing/adding the 3 together, we then need at least 12 bits for the mixed sound output.

As I told you earlier, the I2S transmitter can operate anywhere between 8 bits and 32 bits in, so for the way the system is currently setup, the PSG's output is feeding 12bit audio through the I2S TX.

Remember the second half of what you missed to acknowledge here:
Now, say we want 3 dacs in our system, a cheap 16 bit one with a headphone output and a 20 bit line level one and 24 bit for the HDMI, all with the same sound.  Notice how the MSB is at the beginning.  What would happen if we feed all 3 digital sources the same signal, all expecting 32 clocks per channel, but each outputting the most bits they can?

Ah of course, yes, I understand. :-+

The paragraph right after that one I wrote:
Also, look at it the other way around, say we can only generate 8 bit audio, meaning after our 8th bit lsb, we just send a bunch of blank zeros until the 32nd clock when the right channel begins and we send it's msb?  Will all 3 dacs on our bus still work OK?

So setting the I2S DAC_BITS to 12 bits is the correct action and it will just shove the 12 data bits from the left and right inputs all the way up to the left-most on the output, and if the DAC's is actually a 16bit one, it will just receive a bunch of zeroes for it's LSBs.

That should do it for your 'arya_top'.  Once you placed it in your GPU and verify that it sounds ok, next place it in your 'jt49_tb.sv', replacing lines 28 through 151 and polish the setup_psg.do.  Upload everything here and I will make my own new proper output stereo mixer and filter module from scratch, then we will close up this part of the project.


QUESTION: Why did you call it 'arya_top', what does 'arya' stand for?
Keep in mind that after we finish the filter, we will Github publish this customized fork of jt49's original.  Maybe you should more carefully think about the name.

Too bad you didn't want to do this the right way.  You could have had a 16-64 voice stereo HD audio experience with full stereo sampled instruments held in DDR3.  Anyways... The stereo 8 channel YM2151 would have been a much nicer PSG.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2022, 09:53:06 pm
QUESTION: Why did you call it 'arya_top', what does 'arya' stand for?
Keep in mind that after we finish the filter, we will Github publish this customized fork of jt49's original.  Maybe you should more carefully think about the name.

Erm... no reason in particular, to be honest.  I may have been thinking along the lines of an 'aria', being to do with music etc, and the Y instead of an I because it emulated the YM2149...  :-//  I'm more than happy for better suggestions! ;)

Too bad you didn't want to do this the right way.  You could have had a 16-64 voice stereo HD audio experience with full stereo sampled instruments held in DDR3.  Anyways... The stereo 8 channel YM2151 would have been a much nicer PSG.

Well, now this 8-bit lobotomised version of that fantastic PSG system is done, perhaps we could move on to the all-singing and dancing version?  It'll likely benefit somebody somewhere who is more musically-minded than I am, and may even benefit me if I get around to building my 16-bit 68010 DIY computer.

The reason I wanted it done 'the wrong way' was so that I could use it with my uCOM.  There is a pool of music available in CP/M compatible with the AY-3-8910 / YM2149 which I have, so I'm able to test the PSG and listen to stuff with virtually no effort at all (I have a bug in the CP/M player program I'm needing to fix, but that shouldn't be impossible).  But I literally am not joking or overstating things when I say I don't have a musical bone in my body.  A fancy PSG that can do all those marvellous things will be wasted on my current host system as I have absolutely no music, in any format, that can make use of all those features/channels/voices and I absolutely do not have - nor will I ever have - the skill necessary to write a musical piece to test those features.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 10:12:50 pm
Ok, no problem.

     I would call it the 'YM2149_PSG_system'.

     Now, just make sure your latest PSG works and upload the new GPU & testbench.  There are a bunch of things I want to clean and need to create the new stereo filter/mixer.  It will take a 2-3 days and I would like to get started tonight.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 05, 2022, 10:41:23 pm
Ah this is annoying.  I've wired-in the YM2149_PSG_system into the GPU's top module and connected it up, but I'm getting no sound at all from the hardware.  I've obviously made a mistake in the connections somewhere, but I've got no time left tonight to hunt it down and I'm mindful that you want to get started tonight, so I've attached the current GPU project.  I'll take a look at this tomorrow and get it working, I just haven't had the time tonight.  I haven't done the testbench for the new module either, again I'll get that done tomorrow hopefully. :-\
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 05, 2022, 11:00:13 pm
Try lines 939 -> 942:
Code: [Select]
logic        [  3:0] psg_addr   ;
logic        [  7:0] psg_data_i ;
logic        [  7:0] psg_data_o ;
logic                psg_wr_en  ;
Maybe need to be moved to 673 so that they are available when first used up by the Z80_bridge.
Everything else looks ok.  However, the simulations are for proofing.

:( It's sad that you haven't begun to use the unified output arrays 'WRITE_PORT_STROBE, WRITE_PORT_DATA' everywhere with a [parameter_address] when wiring modules instead of all these random names.  All those port names on the Z80_bus have gotten absurd.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2022, 12:51:35 pm
(No sound) Quartus is having trouble with 'real' or floating point parameters.
I'm making a temporary work around...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2022, 01:43:26 pm
(No sound) Quartus is having trouble with 'real' or floating point parameters.
I'm making a temporary work around...

 :palm:  Good old Quartus.  I wonder if these issues are fixed in later versions?  I'm using 20.1.1.

:( It's sad that you haven't begun to use the unified output arrays 'WRITE_PORT_STROBE, WRITE_PORT_DATA' everywhere with a [parameter_address] when wiring modules instead of all these random names.  All those port names on the Z80_bus have gotten absurd.

Yeah, that's just me being belligerent and stubborn.  ;)   I'll get around to doing it at some point in the future when I have the time. :-/O

In the meantime, here's the latest testbench with integrated YM2149_PSG_system module, all apparently working fine.  Note that I haven't yet added any waveforms for the I2S top-level outputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2022, 03:37:06 pm
Ok, I just finished the Floating point work around.
I have yet to sleep since yesterday.
Update coming in 5 minutes.

The floating point bug is in all Quartus as it just ignore 'real' parameters.  So I had to write a program to render the audio dac volume look-up tables manually from Modelsim.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2022, 03:59:04 pm
Here you go, this took a good bunch of hours, so please follow the instructions and test...

A) Question, why are you doing this in the Z80 bridge>
Lines 598 to 609:
Code: [Select]
        // PSG writes
        if (WRITE_PORT_STROBE[PSG_LATCH]) psg_addr   <= WRITE_PORT_DATA[PSG_LATCH] ;
        if (WRITE_PORT_STROBE[PSG_WRITE]) psg_data_o <= WRITE_PORT_DATA[PSG_WRITE] ;
        psg_wr_en <= WRITE_PORT_STROBE[PSG_LATCH] | WRITE_PORT_STROBE[PSG_WRITE]   ;

You do know I went through the trouble of latching and holding everything for you...

Why didn't you just do this located right at the top, just after the IO port definitions? :
Code: [Select]
        // PSG writes
        assign  psg_addr   = WRITE_PORT_DATA[PSG_LATCH] ;
        assign  psg_data_o = WRITE_PORT_DATA[PSG_WRITE] ;
        assign  psg_wr_en  = WRITE_PORT_STROBE[PSG_LATCH] | WRITE_PORT_STROBE[PSG_WRITE]   ;

Also, isn't this all wrong?  Shouldn't it be:
Code: [Select]
        // PSG writes
        assign  psg_addr   = WRITE_PORT_DATA[PSG_ADDR][3:0]  ; // Wire out the PSG address, just the bottom 4 bits.
        assign  psg_data_o = WRITE_PORT_DATA[PSG_DATA] ; // Wire out the PSG data, all 8 bits.
        assign  psg_wr_en  = WRITE_PORT_STROBE[PSG_DATA]; // Only perform the write enable when the data is sent and not when the address is sent.
//  IE, set the address, PSG wont do anything, then set the data, the PSG will use the previously sent address and the data strobe will tell it to write that data at the address which was already set prior.

(I changed the port names because what you had is confusing.)

The only thing I can think of is some sort of required reset value.  If so, then you can add this line to the reset:

Code: [Select]
        WRITE_PORT_DATA   <= '{default:0} ;
Now, when a reset comes in, all the write ports will be 0'ed out.  I hope this clears thing up.
I've attached an updated code.  I did not touch the Z80 stuff as you will need to fix that.


Ok, hopefully the sound should work, but it is still the jt49 audio filters which do occasionally clip-invert making a nasty crackle buzz noise when all 3 channels are at full volume (something I saw in Modelsim).  The one I am working on tomorrow should not have this problem.

Everything has changed as I moved to using `include "xxxx.v' instead of Quartuses include files in project.  (Just for the audio right now...)  So, update everything and take a look at the Z80 bridge for the audio stuff above.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2022, 04:48:23 pm
Here you go, this took a good bunch of hours, so please follow the instructions and test...

Thank you.

A) Question, why are you doing this in the Z80 bridge>
Lines 598 to 609:
Code: [Select]
        // PSG writes
        if (WRITE_PORT_STROBE[PSG_LATCH]) psg_addr   <= WRITE_PORT_DATA[PSG_LATCH] ;
        if (WRITE_PORT_STROBE[PSG_WRITE]) psg_data_o <= WRITE_PORT_DATA[PSG_WRITE] ;
        psg_wr_en <= WRITE_PORT_STROBE[PSG_LATCH] | WRITE_PORT_STROBE[PSG_WRITE]   ;

You do know I went through the trouble of latching and holding everything for you...

Oooohhh...  |O  I'd probably forgotten that, then got into the routine of adding latches for the data and not thinking about why.  :-\

When I get round to it, I'll just remove all these ports from the Z80_Bridge and have the other modules in GPU_DECA_DDR3_top use the correct WRITE_PORT_DATA value and WRITE_PORT_STROBE signal directly.

Also, isn't this all wrong?  Shouldn't it be:
Code: [Select]
        // PSG writes
        assign  psg_addr   = WRITE_PORT_DATA[PSG_ADDR][3:0]  ; // Wire out the PSG address, just the bottom 4 bits.
        assign  psg_data_o = WRITE_PORT_DATA[PSG_DATA] ; // Wire out the PSG data, all 8 bits.
        assign  psg_wr_en  = WRITE_PORT_STROBE[PSG_DATA]; // Only perform the write enable when the data is sent and not when the address is sent.
//  IE, set the address, PSG wont do anything, then set the data, the PSG will use the previously sent address and the data strobe will tell it to write that data at the address which was already set prior.

(I changed the port names because what you had is confusing.)

Ah, the port names.  Yes, they may be confusing but they match what is on the AY-3-891x and YM2149, and therefore make sense to me.  The way those old chips are interfaced, you can write a register address to the LATCH port, then write data to the WRITE port.  But for some strange reason, you read data back from the LATCH port, not the WRITE port, so I can't just rename the WRITE port to the (more sensible) DATA port.  I can't change the functioning of the interface either, as I have some very complex software (to me, anyway) that plays PT3 and MYM music files in CP/M and if I change how the interface works, I'd either have no way of playing those music files or I'd have to mess with the source code.  Admittedly, I'm going to have to do that anyway as the player isn't working at the moment, but I suspect that's to do with some error in the PSG interface - probably the one you've identified already where psg_wr_en was being assigned to either PSG_WRITE OR PSG_LATCH strobes.

Ok, hopefully the sound should work, but it is still the jt49 audio filters which do occasionally clip-invert making a nasty crackle buzz noise when all 3 channels are at full volume (something I saw in Modelsim).  The one I am working on tomorrow should not have this problem.

Everything has changed as I moved to using `include "xxxx.v' instead of Quartuses include files in project.  (Just for the audio right now...)  So, update everything and take a look at the Z80 bridge for the audio stuff above.

We have sound again and it sounds nice and clear!  I just need desperately to get the module player working in CP/M so I can listen to some chiptunes again.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2022, 05:21:08 pm
I seem to have gotten MYM module player working.  Still no progress on PT3s, but at least I can hear something other than beeps and boops.

https://www.youtube.com/watch?v=O2MGfbAZ6aI (https://www.youtube.com/watch?v=O2MGfbAZ6aI)

Yeah, okay, so they're still beeps and boops but what do you expect from an 8-bit system? ;)

Sorry about the sound quality, it's literally filmed on my mobile whilst it played on the TV via the HDMI connection, so it's not a perfect representation, but it sounds great to me! :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 06, 2022, 08:43:49 pm
For now, that sounds fine, though lack of bass.
The question is how does it sound on real hardware?
Since you do not have a HDMI capture card, we cannot hear if there supposed to be any bass/low frequencies, or, is it the DC filters?

Anyways, tonight I will do my audio mixer / filter module (no floating point 20*log(1/255) or 10^((Volume/20) *(2^DAC_BITS)) calculations to worry about...), so thing should be a bit easier.  I will also see about getting the 'Line Out' working.  If so, make sure you have headphones, then a 3.5mm - 3.5mm line patch cable so it may be possible to sample the stereo audio direct from your PC's line in and you can send us a full quality .mp3.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 06, 2022, 10:21:58 pm
For now, that sounds fine, though lack of bass.
The question is how does it sound on real hardware?

I can't compare unfortunately, certainly not at the moment, as digging out the old sound card requires setting up all the old (version 1) uCOM cards, as the latest ones aren't compatible.  I don't have the time to do that this weekend, and I'll be away for a week from Monday, so it'll be a while before I can even think about it.

Since you do not have a HDMI capture card, we cannot hear if there supposed to be any bass/low frequencies, or, is it the DC filters?

Anyways, tonight I will do my audio mixer / filter module (no floating point 20*log(1/255) or 10^((Volume/20) *(2^DAC_BITS)) calculations to worry about...), so thing should be a bit easier.  I will also see about getting the 'Line Out' working.  If so, make sure you have headphones, then a 3.5mm - 3.5mm line patch cable so it may be possible to sample the stereo audio direct from your PC's line in and you can send us a full quality .mp3.

I certainly have some 3.5-3.5mm patch cables knocking about somewhere, so an MP3 shouldn't be outside the realms of possibility once the DECA's DAC is running sound through the line out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 07, 2022, 05:12:02 am
Ok, 1 module left to do.  Here is the specification of our Github Repo:
Code: [Select]
// ********************************************************************************************************************************
// YM2149_PSG_system Programmable Sound Generator based on Jose Tejada's GitHub repository [url]https://github.com/jotego/jt49.[/url]
//
// Enhancements by BrianHG    : [url]https://github.com/BrianHGinc[/url]
//           and Nockieboy    : [url]https://github.com/nockieboy[/url]
// You can also find use here : [url]https://www.eevblog.com/forum/fpga/[/url]
//
//
// ***************************************************
// New included source code:
// ***************************************************
//
// BHG_clock_fp_div.sv      -> Precision floating point clock divider to generate any desired system clock down to the Hz.
// I2S_transmitter.sv       -> I2S digital audio transmitter for all Audio DACs/Codecs and HDMI transmitters.
// BHG_jt49.v               -> An enhanced modified version of the original jt49.v offering higher # of bits for the sound output channels.
// BHG_jt49_exp_tablegen.v  -> A generator the precision volumetric tables.  Generates the BHG_jt49_exp_lut.vh file.
// BHG_jt49_exp_lut.vh      -> The parameter table generated after Sim running the BHG_jt49_exp_tablegen.v.
// BHG_jt49_exp.v           -> A replacement for the original jt49_exp.v using the tables in BHG_jt49_exp_lut.vh.
// BHG_jt49_filter_mixer.sv -> Offers a programmable channel mixing levels (use 2 for custom stereo), DC filter with clamp, and treble control.
//
//
// Enhancements include:
// ----------------------
// Stereo sound with control registers for channel mixing volume and phase.
// Registers for Treble and Bass adjustments.
// Smart DC filtering allowing lower frequency output while managing peaks and switch on/off pops when necessary.
// Improved precision 8 thru 14 bit exponential DAC support.  (10 bit almost exactly replicates the YM2149 normalized output voltage).
// Precision floating point system clock divider offering parameter select-able PSG reference frequencies with accuracy down to the Hz.
// Integrated standard I2S transmitter output with resampling & floating point system clock divider offering DAC Khz settings down to the Hz.
//
// Functional simulation setup for Modelsim, with example YM2149 presets and full outputs with analog waveforms.
//
// *** Simulation also includes a switch to run Jose Tejada's original jt49 project for direct comparison.
//
// ********************************************************************************************************************************
//Only include one of the following:
//
`include "YM2149_PSG_system.sv" // This will simulate the new BrianHG & Nockieboy YM2149_PSG_system.
// or:
//`include "YM2149_PSG_jt49.sv"   // This will simulate the original jt49 YM2149 PSG source code
//                              // from Jose Tejada's GitHub repository [url]https://github.com/jotego/jt49[/url]
//                              // *** Remember, when using, parameter YM2149_DAC_BITS must be set to 8!
//
//                              // Patched files: 'jt49_dly.v', found a few bugs, see lines:
//                              // 29, 30, 31, & 39.
//
//                              // Also found clip-inversion overflow bug in jt49_mave.v & jt49_dcrm2.v, which the
//                              // DC filter seems to sometimes patch.  Though this may be looked at by Jose Tejada's,
//                              // it is no longer in use because of the new 'BHG_jt49_filter_mixer.sv' replacement.

Note that the ADDR input has been changes from 4bit to 8bit.  This way, you can add more YM2149 PSGs if you like, and I have reserved upper addresses to allow controls for our stereo mixer filter.  (LOL, place 10 of them and get 30 channel audio.  Can the Z80 fill all those registers fast enough?)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 15, 2022, 09:23:50 pm
For now, that sounds fine, though lack of bass.
The question is how does it sound on real hardware?
Since you do not have a HDMI capture card, we cannot hear if there supposed to be any bass/low frequencies, or, is it the DC filters?

Yep, definitely lacking a little bass.  Really need to hear it from the DAC on the DECA first, but it certainly seems to be lacking punch.

So, what do I need to do next?  I'll set the github repo up once the PSG work is done, I think.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 16, 2022, 02:56:25 pm
Ok,
     I attached a test which copies the audio to both HDMI and the green line out jack.

     Now, the engineers who made the ArrowDECA wired that jack to the Line out outputs of the audio codec instead of the high powered Headphone out pins.  This means headphone may not sound proper, but, it will have no problem feeding an audio amp or the line-in of you PC's sound card.

     Please test and let me know if it works.

     Not included, I've done a lot of work on the YM2149 module and only have my filters left to do.  If the attached project works, I'll incorporate my first simple test filter.

     As for the work done so far, here are the latest modules I've created and released on their own:

Verilog floating point clock divider:
https://github.com/BrianHGinc/Verilog-Floating-Point-Clock-Divider (https://github.com/BrianHGinc/Verilog-Floating-Point-Clock-Divider)
https://www.eevblog.com/forum/fpga/verilog-floating-point-clock-divider-release/ (https://www.eevblog.com/forum/fpga/verilog-floating-point-clock-divider-release/)

And, I2C initializer with RS232 monitor/debugger: (used in the attached code.)
https://github.com/BrianHGinc/BHG_I2C_init_RS232_debugger (https://github.com/BrianHGinc/BHG_I2C_init_RS232_debugger)
https://www.eevblog.com/forum/fpga/bhg_i2c_init_rs232_debugger-an-i2c-initializer-with-integrated-rs232-debugger/ (https://www.eevblog.com/forum/fpga/bhg_i2c_init_rs232_debugger-an-i2c-initializer-with-integrated-rs232-debugger/)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 16, 2022, 05:32:55 pm
I'm getting no video out from the new project above?  Haven't had a look for a patch cable yet, just thought I'd build the project and test that it works as expected in all aspects other than audio, but I'm getting no signal on the TV.

It looks like you've moved the content of I2C_HDMI_Config into GPU_DECA_DDR3_top, but as far as I can see you've got the right HDMI mode selected, so not sure just yet what's going wrong.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 16, 2022, 11:53:51 pm
 :scared: You got to be FN kidding me....  :scared:

     I spent all day trying to fix this.  Thankfully, my new I2C initializer with RS232 monitor/debugger had all the tools built in to see what was going on and play with the ADV7513 HDMI transmitter in real-time to see why it sometimes fails.

     The ADV7513 HDMI transmitter needs to be sent and I2C command to power-up the transmitter after a monitor has been disconnected and reconnected.  Thankfully, it sends an 'INTERRUPT'.  But wait, around 50% of the time you freshly power up the IC, the interrupt actually does nothing.  And yes, all the proper I2C commands have been sent to enable it.

     So, how did the original DECA's I2C HDMI initializer work?  They did have the interrupt wire wired in.

 :scared:  Believe it or not, they inverted the signal, meaning, the powerup I2C sequence is being transmitted non-stop.  So, after disconnecting the monitor, or on a lemon power-up where the interrupt would never trigger to turn on the HDMI output, they just blasted away the 'enable output' command.  And, if an interrupt did come in pulsing for a few milliseconds, during those few milliseconds they would actually stop sending the script, then continue sending away bypassing the 'non' problem in that instance.

     Well, I've attached a patched GPU_DECA_DDR3_top.sv replicating the same thing.  Please let me know if this one works and you get sound out of both the HDMI and Line Out analog jack.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2022, 12:08:11 am
Besides the above fix, my new FP logs the ppm error of the output clocks.

Integer divider mode PPM results for the YM2149:
Code: [Select]
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#   XXX   BHG_FP_clk_divider.v settings/results.   XXX
#   XXX   https://github.com/BrianHGinc            XXX
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#   XXX   USE_FLOATING_DIVIDE = 0
#   XXX   Set INPUT_CLK_HZ    = 100000000 Hz.
#   XXX   Set OUTPUT_CLK_HZ   = 1789000 Hz.
#   XXX   --------------------------------------------- (Floats only accurate to 2 decimal places)
#   XXX   True output freq    = 1785714.280000 Hz.
#   XXX   Frequency error     = -5878.150000 ppm.
#   XXX   Periodic jitter     = +/- 0.000000 ns.
#   XXX   ---------------------------------------------
#   XXX   Integer Divider     = 56.
#   XXX   Divider Fraction    = 0/65536.           OutHz = InHz/(ID+(DF/65536))
#   XXX   ~Divider to 6dp.    = 56.000000.
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Floating point divider mode PPM error:
Code: [Select]
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#   XXX   BHG_FP_clk_divider.v settings/results.   XXX
#   XXX   https://github.com/BrianHGinc            XXX
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#   XXX   USE_FLOATING_DIVIDE = 1
#   XXX   Set INPUT_CLK_HZ    = 100000000 Hz.
#   XXX   Set OUTPUT_CLK_HZ   = 1789000 Hz.
#   XXX   --------------------------------------------- (Floats only accurate to 2 decimal places)
#   XXX   True output freq    = 1788999.790000 Hz.
#   XXX   Frequency error     = -0.370000 ppm.
#   XXX   Periodic jitter     = +/- 5.000000 ns.
#   XXX   ---------------------------------------------
#   XXX   Integer Divider     = 55.
#   XXX   Divider Fraction    = 58796/65536.           OutHz = InHz/(ID+(DF/65536))
#   XXX   ~Divider to 6dp.    = 55.897156.
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

-0.370000 ppm VS -5878.150000 ppm, well, its not as bad as the I2S audio clock in integer mode:
Code: [Select]
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#   XXX   BHG_FP_clk_divider.v settings/results.   XXX
#   XXX   https://github.com/BrianHGinc            XXX
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
#   XXX   USE_FLOATING_DIVIDE = 0
#   XXX   Set INPUT_CLK_HZ    = 100000000 Hz.
#   XXX   Set OUTPUT_CLK_HZ   = 3072000 Hz.
#   XXX   --------------------------------------------- (Floats only accurate to 2 decimal places)
#   XXX   True output freq    = 3030303.030000 Hz.
#   XXX   Frequency error     = -128093.090000 ppm.
#   XXX   Periodic jitter     = +/- 0.000000 ns.
#   XXX   ---------------------------------------------
#   XXX   Integer Divider     = 33.
#   XXX   Divider Fraction    = 0/65536.           OutHz = InHz/(ID+(DF/65536))
#   XXX   ~Divider to 6dp.    = 33.000000.
#   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-128kppm...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 17, 2022, 05:05:05 pm
:scared: You got to be FN kidding me....  :scared:

     I spent all day trying to fix this.  Thankfully, my new I2C initializer with RS232 monitor/debugger had all the tools built in to see what was going on and play with the ADV7513 HDMI transmitter in real-time to see why it sometimes fails.

     The ADV7513 HDMI transmitter needs to be sent and I2C command to power-up the transmitter after a monitor has been disconnected and reconnected.  Thankfully, it sends an 'INTERRUPT'.  But wait, around 50% of the time you freshly power up the IC, the interrupt actually does nothing.  And yes, all the proper I2C commands have been sent to enable it.

     So, how did the original DECA's I2C HDMI initializer work?  They did have the interrupt wire wired in.

 :scared:  Believe it or not, they inverted the signal, meaning, the powerup I2C sequence is being transmitted non-stop.  So, after disconnecting the monitor, or on a lemon power-up where the interrupt would never trigger to turn on the HDMI output, they just blasted away the 'enable output' command.  And, if an interrupt did come in pulsing for a few milliseconds, during those few milliseconds they would actually stop sending the script, then continue sending away bypassing the 'non' problem in that instance.

     Well, I've attached a patched GPU_DECA_DDR3_top.sv replicating the same thing.  Please let me know if this one works and you get sound out of both the HDMI and Line Out analog jack.

Haven't had time to give this patch justice in testing, but I can confirm that the image is back on the TV, but no HDMI sound output.  Can't test line out yet as I'm having trouble finding a cable.  ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2022, 06:19:17 pm
Give these 2 alternate top .sv a try.
You know, you could try connecting a headphone to the line out.

Also, I've been working off of the 'GPU_DECA_DDR3_version_16_pre_BHG_audiofilter.zip' code from above.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 17, 2022, 06:23:34 pm
Give these 2 alternate top .sv a try.
You know, you could try connecting a headphone to the line out.

I'll give them a try as soon as I can.

Also, I've been working off of the 'GPU_DECA_DDR3_version_16_pre_BHG_audiofilter.zip' code from above.

That's probably the issue then.  I've made a few changes since I last uploaded the project, I think.  Here's the latest version (not including your latest changes to duplicate sound out of the DECA's DAC).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2022, 06:26:34 pm
Give these 2 alternate top .sv a try.
You know, you could try connecting a headphone to the line out.

I'll give them a try as soon as I can.

Also, I've been working off of the 'GPU_DECA_DDR3_version_16_pre_BHG_audiofilter.zip' code from above.

That's probably the issue then.  I've made a few changes since I last uploaded the project, I think.  Here's the latest version (not including your latest changes to duplicate sound out of the DECA's DAC).
Does that version have sound?
You should label your .zip with some info.  I have too many overwrites without knowing which does what.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2022, 06:32:16 pm
 :palm:  Copy over the 'YM2149_PSG_system' folder from your latest download to my last upload...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 17, 2022, 06:37:01 pm
Give these 2 alternate top .sv a try.
You know, you could try connecting a headphone to the line out.

I'll give them a try as soon as I can.

Also, I've been working off of the 'GPU_DECA_DDR3_version_16_pre_BHG_audiofilter.zip' code from above.

That's probably the issue then.  I've made a few changes since I last uploaded the project, I think.  Here's the latest version (not including your latest changes to duplicate sound out of the DECA's DAC).
Does that version have sound?
You should label your .zip with some info.  I have too many overwrites without knowing which does what.

Yes, that version has working sound through the HDMI. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2022, 06:43:03 pm
Ok, re-dooing everything for you 1 last time now...

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 17, 2022, 07:11:23 pm
Here you go:

If there is no sound, change this on 1260 of the _top.sv:

Code: [Select]
                                    .rst_in         ( RST_OUT || (HDMI_RESET && !HDMI_TX_INT)),  // Synchronous reset.
It will enable the intended interrupt based reprogramming of the HDMI's I2C registers instead of the circular constant re-programming.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2022, 09:02:56 am
That's working fine, getting audio from TV via HDMI and via the line out socket on the DECA.  Both sound the same - no loss of bass on the TV compared to the headphone output (which is surprisingly clear and loud, actually).

I'm having some trouble with CP/M at the moment, so can't test music, but beeps and boops in the DMI sound identical between the TV and headphones!

(No need to modify the _top file, worked straight away.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2022, 09:58:12 am
Ok, only a little work to do on my mixer-filters.  Then you will have the proper equivilant analog sound, with proper bass.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2022, 04:26:48 pm
I'm not 100% sure on this, but it seems as though one of the channels (probably channel C) is weaker than the other two.  I've listened to a couple of tracks now that start with a beat and a single 'instrument', and when a third 'instrument' starts, the beat becomes very quiet.  It's a song I know pretty well and it seems that the drop in volume for the beat isn't intentional.  Just something to be aware of, I guess, as it's possibly an artefact left over from the way my hardware mixed the three channels together - don't know if that will be fixed with the new filters?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2022, 08:43:35 pm
Could it be this? (jt49's DC filter)

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569034)

You also see at 100hz, over half of the signal strength is lost.

Also remember, if you have a Headphones on the line out of the DECA, it mutes down it's output with any loud signals because that plug is connected to the DAC's line out (being overloaded) instead of it's high powered headphone outputs.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 18, 2022, 09:40:48 pm
Could it be this? (jt49's DC filter)

That doesn't look good. :o

You also see at 100hz, over half of the signal strength is lost.

Also remember, if you have a Headphones on the line out of the DECA, it mutes down it's output with any loud signals because that plug is connected to the DAC's line out (being overloaded) instead of it's high powered headphone outputs.

Something to do with impedances, I'm guessing?  After the initial audio test with my headphones earlier, I've unplugged them and am back to listening on the TV again.  The loss of volume on one channel was through the TV, but as the audio is duplicated after the filters, both outputs should only be affected by the end hardware (i.e. the headphone speakers or whatever DAC/amplifier/speaker is in the TV).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 18, 2022, 09:54:51 pm
The line out was only designed to drive 10kohm.  Headphones are 32ohm.  For the same voltage, the headphones draw a tone more current.

No, plugging in and out the headphone should not affect the HDMI sound.  2 completely different things.

You will just have to wait a day for my first filter release to test, but, all 3 channels should have the same volume.

Though, the way the PSG's dac is internally wired on the silicon and the way you resistor load them at the output can have unforeseen effects different than the linear channel mixing we are doing.

Or, the jt49 filters are just crap.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 19, 2022, 04:41:47 pm
New filter preview:  All 3 channels playing 27Hz, 100% volume for 100ms, mute 100ms, 100% volume 100ms.

jt49 output:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569442)

BHG1, mixer settings=33% A, 33% B, 33% C, bass = 10.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569448)

BHG2, mixer settings=16% A, 16% B, 16% C, bass = 10.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569454)

BHG3, mixer settings=33% A, 33% B, 33% C, bass = 5.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569460)

BHG4, mixer settings=33% A, 33% B, 33% C, bass = 20.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569466)

My mixer settings are real-time programmable by the Z80.
The lower the bass#, the more bass.  The higher the bass#, the less bass.

BHG#2 with lower volume per channel mixer settings may be useful as it offers breathing room for the initial DC filter charge generated 'POP' which would more closely replicate the analog DC filter response at the cost of half volume.  BHG#1 engages my 'DC filter Peak Limiter' circuit rapidly pushing the DC offset instantly into the center during the initial peak.  This would lessen that initial POP if all 3 voices of the PSG begin at full volume exactly after half a second of silence.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 19, 2022, 04:54:19 pm
Approximating the jt49 without his overflow bug...
BHG5, mixer settings=16% A, 16% B, 16% C, bass = 48.
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1569493)

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2022, 07:12:11 am
  :phew: OK, here we go.  You'll need to test everything as my availability will be shrinking at the end of the month.

I configured the sound system in Dual YM2149 & Stereo mixer-filter mode.

PSG_a operates on address 0-15 and outputs channels A,B,C.
PSG_b operates on address 16-31 and outputs channels D,E,F.

The Left channel Mixer operates on address 128-143.
The Right channel Mixer operates on address 144-159.

These are each mixer's controls and their power-up defaults:
Code: [Select]
        .RST_REGS   ( '{  64,  64,  64,  64,  64,  64,   0,  8'b00000000 ,   3, 128, 128,  0,  0,  0,  0,  0 } )
                        VolA,VolB,VolC,VolD,VolE,VolF, n/a, INV{xxFEDCBA},bass,treb,mvol,n/a,n/a,n/a,n/a,n/a.

1) Volume A-F:
     A volumes of 255 will output full amplitude for that channel, however, remember that there are normally 3 channels and usually having 3 on means if the PSG outputs full volume on all 3 voices, you will get distortion due to the impossible 300% required output waveform.  For maximum distortion free output, you would want to set each volume to 33.3% of 256, IE: 85,85,85.  Now, this leaves zero room for deliberate analog switching on and off 'POP' effect which you may want.  Cutting this volume in half to 43,43,43 will guarantee every nuance and full amplitude of the effect matches an original analog circuit.  Using values like 64,64,64 offers a middle ground givin you greater sample volume yet still offer most of that 'pop' effect.  If you want to mix all 6 channels, A-F, then I would probably use 43,43,43,43,43,43.

     Note that when changing volume, there will usually be a 'pop' effect due to the DC output nature of the YM2149 PSG.  The only way to get rid of this is to ramp the volume figures up and down.  All 6 channels may be ramped simultaneously and I recommend incrementing / decrementing 1 at a time, ~0.01-0.02 sec each step.  Note that the invert waveform 'INV{F,E,D,C,B,A}' also will make a loud pop, so to prevent this, ramp down the volume of that or all channels down to 0, swap the INV bits you wish to, then ramp back up the volume.  I recommend using Dolby-Pro-Logic 2 mixing factors for side and rear channels to generate your desired simulated surround wide stereo effect.

2) Bass :  Supports 1 through 63.  Upper bits are ignored. 0 allows DC through, so, do not use except for special circumstances.  1 has very low frequency support.  I set the default to 3.  32 should have very little bass.  This control can be freely changed without the worry of any 'pop' effect.

3) Treble : 255= unfiltered full bandwidth through. 128 = some really high frequency smoothing.  64= a bit softer. 0 = muffled.  This control can be freely changed without the worry of any 'pop' effect.

4) MVol : Master volume.  128 = default full volume.  255= a 2x boost, signals over the edges here will be clipped. anything below 128 will just lower the volume by that 1/128 factor.  Though this volume wont really pop like the individual volume channels A-F, it is still good practice to smoothly move it.  I personally would leave it at 128 unless you need a headphone volume control for the DECA's line out.

Let me know how it goes.  I could only visually see the PSG waveforms in Modelsim, so I did everything by eye.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2022, 08:34:48 pm
Here is an update for the 'YM2149_PSG_system' source folder called:
'YM2149_PSG_system_now_with_readback_filter_regs.zip'.

Internal changes: Consolidated an additional multiplier in the audio filter section making the entire filter run on 1 multiplier and 1 adder.  (If I was truly motivated, it could have been possible to run 2 channel stereo from one of these modules.)  Changed the unnecessary 24 bit regs down to 16 bit except for the 1 crucial 24bit DC filter accumulator.  Cleaned up the code comments in the audio mixer / filter section for those who want to know.

External changes:
1) Moved the 'mvol' register from address 4'hA to 4'h6.  New reg addresses:
Code: [Select]
         // Address =      0    1    2    3    4    5    6         7         8    9
        .RST_REGS   ( '{  64,  64,  64,  64,  64,  64, 128,  8'b00000000 ,   3, 128 } )
                     // VolA,VolB,VolC,VolD,VolE,VolF,mvol, INV{xxFEDCBA},bass,treb

2) The Z80 can now read back the stored settings inside the left and right Mixer/Filter's registers.  This will help if you make a master volume/filter configuration utility, reading the current settings before making adjustments to allow you to smoothly step the volume settings to prevent the 'pop' effect.

3) For simulation, I added stereo view and some more specific tests of the filters separated on the left and right channel now using both PSGs simultaneously.

Just replace contents of the .zip with the entire 'YM2149_PSG_system' folder in the GPU project.
****(I also added the Quartus .qsf compiler settings file which generates the best FMAX with the current source files)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 20, 2022, 10:33:25 pm
This is a comparison of the different volume ramps based on parameter '.YM2149_DAC_BITS ( 8 ),' at line 965 in 'GPU_DECA_DDR3_top.sv'.  What I have done is grabbed the YM2149 .PDF data sheet page 11 and used the D-A converter normalized voltage illustration as a background, ran Modelsim to produce the same ramp at the same scale, copy & pasted Modelsim's analog waveform output (in red) over this graph.

Here are DAC settings 8 through 11:

.YM2149_DAC_BITS ( 8 )
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1570546)

.YM2149_DAC_BITS ( 9 )
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1570552)

.YM2149_DAC_BITS ( 10 )
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1570558)

.YM2149_DAC_BITS ( 11 )
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1570564)


     As you can see, 10 bits track the amplitude the closest.  Looking at the lower bit depths, the resulting sound output will have a 'brighter' sound with instruments played at lower volume settings, but to the ear, the volume will not appear to ramp up linearly with the 32 available PSG volume steps.  IE: The 8 bit mode will appear to have some slight auto-volume compression like with old analog tape recorders making soft sounds easier to hear while lowering the volume of the louder sounds by comparison.

    As for the original 8bit only jt49 volume table, he tracks the YM2149 exactly as well, however, with only 8 bits, the lower volumes have repeats in them unlike my 10bit modification.

See file 'jt49_hdl/jt49_exp.v' for the original volume VS 8bit DAC levels:
Code: [Select]
initial begin
    lut[0] = 8'd0;
    lut[1] = 8'd1;    <<<
    lut[2] = 8'd1;    <<< These 3 steps are actually all the same amplitude level
    lut[3] = 8'd1;    <<< even though they are volumes 1,2,3.
    lut[4] = 8'd2;
    lut[5] = 8'd2;    <<< These 2 are the same.
    lut[6] = 8'd3;
    lut[7] = 8'd3;    <<< These 2 are the same.
    lut[8] = 8'd4;
    lut[9] = 8'd5;
    lut[10] = 8'd6;
    lut[11] = 8'd7;
    lut[12] = 8'd9;
    lut[13] = 8'd11;
    lut[14] = 8'd13;
    lut[15] = 8'd15;
    lut[16] = 8'd18;
    lut[17] = 8'd22;
    lut[18] = 8'd26;
    lut[19] = 8'd31;
    lut[20] = 8'd37;
    lut[21] = 8'd45;
    lut[22] = 8'd53;
    lut[23] = 8'd63;
    lut[24] = 8'd75;
    lut[25] = 8'd90;
    lut[26] = 8'd107;
    lut[27] = 8'd127;
    lut[28] = 8'd151;
    lut[29] = 8'd180;
    lut[30] = 8'd214;
    lut[31] = 8'd255;

As for my code (BHG_jt49_exp_lut.vh) here are my DAC tables:
Code: [Select]
// *************************************************************************************************************************************
// *** 8  bit DAC LUT with a dynamic range of -48 decibels.
// *************************************************************************************************************************************
localparam logic [15:0] dlut_8  [0:31] = '{   0,   1,   2,   3,   4,   5,   6,   8,  10,  12,  14,  17,  19,  23,  26,  31,
                                             35,  41,  47,  54,  62,  70,  80,  92, 104, 119, 135, 154, 175, 198, 225, 255};
// *************************************************************************************************************************************
// *** 9  bit DAC LUT with a dynamic range of -54 decibels.
// *************************************************************************************************************************************
localparam logic [15:0] dlut_9  [0:31] = '{   0,   1,   2,   3,   4,   6,   7,   9,  12,  14,  17,  21,  25,  30,  36,  42,
                                             50,  59,  69,  81,  95, 111, 130, 151, 177, 206, 240, 279, 325, 378, 439, 511};
// *************************************************************************************************************************************
// *** 10 bit DAC LUT with a dynamic range of -60 decibels.
// *************************************************************************************************************************************
localparam logic [15:0] dlut_10 [0:31] = '{   0,   1,   2,   3,   5,   6,   8,  11,  14,  17,  21,  26,  32,  39,  48,  58,
                                             70,  84, 101, 121, 145, 174, 208, 248, 297, 354, 423, 505, 603, 719, 858,1023};
// *************************************************************************************************************************************
// *** 11 bit DAC LUT with a dynamic range of -66 decibels.
// *************************************************************************************************************************************
localparam logic [15:0] dlut_11 [0:31] = '{   0,   1,   2,   3,   5,   7,   9,  12,  16,  20,  26,  33,  41,  51,  63,  78,
                                             96, 118, 146, 179, 220, 270, 331, 406, 497, 609, 745, 913,1117,1367,1673,2047};
// *************************************************************************************************************************************

     Though I do not have the low volume repeats for my 8bit mode, as you see in the above images, I had to loose a proper exponential curve in the process whereas my 10bit table follows the curve almost perfectly without any low volume level repeats.

     The best and most accurate way would have been to use a 16bit table and specifying the -60db over 32 volume steps attenuation level of the YM2149 dac.  But it's a little late now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 21, 2022, 06:29:30 pm
Just compiled the project you've uploaded after including the updated YM2149 project folder and .qsf file and I'm getting no audio at all.  The Z80 can read the registers, including the new registers (mvol, bass, treble etc) and is getting the default values back, but I'm not able to hear anything.  The TV definitely isn't muted. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 21, 2022, 07:10:34 pm
Try writing to the second PSG.
I think Quartus only sees the second one for some reason as it only reports the second LUT, I don't know why.

Also, inside 'YM2149_PSG_system.sv', comment out lines 1 and 2 making it a single PSG, mono.

I'll try to rig something here.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 21, 2022, 07:39:05 pm
Try writing to the second PSG.
I think Quartus only sees the second one for some reason as it only reports the second LUT, I don't know why.

Haven't had time to try this yet - it'll require some manual writes to the PSG to target the second module and I won't be able to test that until tomorrow now.

Also, inside 'YM2149_PSG_system.sv', comment out lines 1 and 2 making it a single PSG, mono.

Just compiled and tried the project with the two lines commented out - still no sound.  :(
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 21, 2022, 08:29:03 pm
Just compiled the project you've uploaded after including the updated YM2149 project folder and .qsf file and I'm getting no audio at all.  The Z80 can read the registers, including the new registers (mvol, bass, treble etc) and is getting the default values back, but I'm not able to hear anything.  The TV definitely isn't muted. ;)
Did you check the headphone out?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 21, 2022, 09:21:04 pm
Just compiled the project you've uploaded after including the updated YM2149 project folder and .qsf file and I'm getting no audio at all.  The Z80 can read the registers, including the new registers (mvol, bass, treble etc) and is getting the default values back, but I'm not able to hear anything.  The TV definitely isn't muted. ;)
Did you check the headphone out?

Yes, no sound there either.  :-\

Try writing to the second PSG.
I think Quartus only sees the second one for some reason as it only reports the second LUT, I don't know why.

I'm getting data back from the first PSG registers - or the only PSG registers with the two lines commented out for single-PSG mode.

I've reloaded the previous version of the GPU project and sound was coming out fine from that, so it's definitely something to do with the latest update.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 21, 2022, 10:21:53 pm
When you write a register, do you read back the written value.
Check my mixer-filter values.
If any of the volumes are 0, or the mvol is set to 0, there will be no sound.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 01:51:53 am
Hmmm, Running my FP clock divider at 100MHz to create the I2S 3.072Mhz clock has a jitter too high for the audio codec's PLL to function properly.

Running with a source clock of 148.5MHz, 150MHz or 200MHz, works fine.  I'm assuming even higher frequencies will work fine too as my FP clock divider's output jitter spec drops as the source clock frequency increases.

Maybe the 100MHz sits on a 'flaky' functional point.  But, this shouldn't have affected the HDMI sound.

Ok, here is what I did.  I've sent you a new test project which has nothing but the Dual Stereo PSG system wired up to the RS232 debugger.  I provided multiple 'sound.bin's to load in the RS232 debugger which turns on everything for testing.  I have proven it functional here as I now can hear Dual PSGs with functional Stereo sound settings.

* Don't forget to check lines 525-533 in the GPU_DECA_top.sv to verify the RS232 connections.  Absolutely everything else has been removed from the project.

Only the 'Line-Out' should generate sound as there is no longer any video GPU system to drive the HDMI.

*** I changed the Bass settings.  They can now go from 1 to 255.
*** Reading off-address registers now returns '0's instead of repeats.
*** I also now mimicked my DDR3 dual clock PLL running the PSG at 100MHz CMD_CLK and the I2S transmitter at the 200MHz DDR3_CLK_50 core to get the Line out to work.

******** Yes I did listen turning on and off different voices.  Turning up the volume of one voice does not lower the volume of the other voices.  (Test file 'sound_surround.bin' performs this test continuously automatically ramping in and out 3 additional voices on top of the background 3.)  Could your TV have a built in auto-level / auto-volume feature?  I know Windows has one and if you arent aware (called loudness equalization), it's usually turned on, hidden in the system settings and it 'Fucks' up music.  Though it does makes Youtube videos easier to hear forcing everything to 1 volume level.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 04:41:14 am
Ok, after you tested the above post, next move onto the new 'GPU_DECA_Stereo_Dual_PSG_beta_2.zip'.

I know that the 'Line Out' on this one does indeed now activate after programming the DECA as it makes a 'click' sound after reset.  This did not happen with the earlier test release.

Possible failure modes:

1)  If the Line Out works, but not the HDMI, then go to line 1270 in 'GPU_DECA_DDR3_top.sv' and re-enable / comment in the '!HDMI_TX_INT'.

2)  If there is still no sound on either outputs, then verify that when the Z80 writes to the PSG system, you can read back what was written and not the defaults.  If you only read the defaults back, then something happened to the 'Strobe' signal for the write enable.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 10:41:37 am
When you write a register, do you read back the written value.
Check my mixer-filter values.
If any of the volumes are 0, or the mvol is set to 0, there will be no sound.

I can write to the registers and read back the written values.  The mixer-filter defaults are all as you've posted in your previous post here:

Code: [Select]
         // Address =      0    1    2    3    4    5    6         7         8    9
        .RST_REGS   ( '{  64,  64,  64,  64,  64,  64, 128,  8'b00000000 ,   3, 128 } )
                     // VolA,VolB,VolC,VolD,VolE,VolF,mvol, INV{xxFEDCBA},bass,treb

I've written 0x07 to register 7 in the above table (address 135) to see if the enable bits (for channels A, B and C at least) are inverted, but still nothing.  All volumes are positive (and default settings).

I'll move on to your more recent posts now.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 11:28:20 am
Ok, after you tested the above post, next move onto the new 'GPU_DECA_Stereo_Dual_PSG_beta_2.zip'.

I know that the 'Line Out' on this one does indeed now activate after programming the DECA as it makes a 'click' sound after reset.  This did not happen with the earlier test release.

Possible failure modes:

1)  If the Line Out works, but not the HDMI, then go to line 1270 in 'GPU_DECA_DDR3_top.sv' and re-enable / comment in the '!HDMI_TX_INT'.

2)  If there is still no sound on either outputs, then verify that when the Z80 writes to the PSG system, you can read back what was written and not the defaults.  If you only read the defaults back, then something happened to the 'Strobe' signal for the write enable.

I jumped straight to testing this last project version instead of the previous PSG-only one as I don't have the spare TTL-serial adapter available at the moment.  Will be able to test it later tonight if it's still beneficial to run through the different setups, but I can confirm that I've got sound from the latest project files you uploaded.  I can't verify the audio quality at the moment (too noisy) but will give it all a good test later. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 01:28:27 pm
I've been playing some music and marvelling at the sound quality - sounds as close to the old chiptunes as it can possibly be, absolutely marvellous!  Well done on an excellent piece of work with that PSG, it's fantastic!  :-+ :clap:

I'll get the github repo set up tomorrow, unless there's any more testing or development that needs to be done?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 01:54:36 pm
I guess I have a 'good eye' for sound...  Still, try playing with the treble and bass settings (left and right simultaneously) to be sure.  Also prepare a .mp3 example sampled from the line-out direct to a PC's line in making sure you don't have the volume up too high.

2 things left.  I also have 1 item to minimize in the new code. and some documentation as I added a few things.

a) My metastability code is overkill and just needs a few regs to minimize.
b) A 'legacy' Z80 port which would allow you to access the PSG the old way instead of the current direct access.  Yes, we can have both access methods running in parallel as you can use a group of 2 separate Z80 ports, one old, one new to do this.
c) Interrupt timer if needed.

For ' b) ', I need an example of a read/write sequence used to make this work for you.
For ' c) ', I guess most of these old systems might use interrupt or reg timers to time the music.  Some may be tied to video hardware timers like h-sync / v-sync, or system clocks.  If you need any of these, let me know.

Let's start with ' b) '.  Please provide me with an example read and write steps to the Z80 port so I can compare with the data sheet and make you a proper translation layer.

Also let me know if I should be thinking about ' c) '.

*Bonus, going by eye, I bet if you were to change line 966 in you GPU _top.sv from 10 to ' .YM2149_DAC_BITS ( 9 ),   I bet it will sound a little better.  10 is a bit too quiet at lower volumes which may be hiding some minor subtlety as 9 it a bit too loud, but at least you could hear it.  I can always do it right and provide a true 14bit authentic dead perfect table output instead of the current bit-depth tapered versions of the tables.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 02:21:05 pm
Before making the .mp3, give this a try:

On the left and right channels, assuming that a volume of 64 is our 100% default reference...

Change channel B on the left and right to 90% volume.
Change channel A on the right to INVerted 80% volume.
Change channel C on the left to INVerted 80% volume.

Now give a listen, especially with headphones and compare to the default mono.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 03:50:09 pm
Before making the .mp3, give this a try:

On the left and right channels, assuming that a volume of 64 is our 100% default reference...

Change channel B on the left and right to 90% volume.
Change channel A on the right to INVerted 80% volume.
Change channel C on the left to INVerted 80% volume.

Now give a listen, especially with headphones and compare to the default mono.

Hmmmm... not sure I can tell a difference, but as I said previously, my ears aren't my most finely-tuned organs.  I've attached a zip with three mp3s in it - two are the same game soundtrack, PULSE1 and PULSE2.  PULSE2 was recorded after the volume changes you suggested above were made.  I think the original soundtrack was based on the screen update, as there's a couple of longer-than-usual pauses in the soundtrack that coincide with big screen updates in the original game, so pay them no attention in the recording.

IMPERIAL.mp3 is not from any game (or source) I recognise, included for a change of tune, recorded after the suggested volume changes.

b) A 'legacy' Z80 port which would allow you to access the PSG the old way instead of the current direct access.  Yes, we can have both access methods running in parallel as you can use a group of 2 separate Z80 ports, one old, one new to do this.
...
For ' b) ', I need an example of a read/write sequence used to make this work for you.

Are you talking about a legacy YM2149 port, with BDIR and BC1 pins?  I've not changed any host code at all to access the PSG - the music I've been playing (and recorded as mp3s) are being played in a generic CP/M MYM/PT2/PT3 player (https://github.com/GrreenZ/play-tune) - all I had to change was the IO port addresses for the PSG specific to my uCOM.  Bridgette already does the job of interfacing to the PSG module?

c) Interrupt timer if needed.
...
For ' c) ', I guess most of these old systems might use interrupt or reg timers to time the music.  Some may be tied to video hardware timers like h-sync / v-sync, or system clocks.  If you need any of these, let me know.

The CP/M player can either use interrupts or a loop-based timer (the option I'm using at the moment as it works well enough for the player).  The interrupts would be driven by the Z80's CTC, a dedicated counter/timer chip, but in the original hardware of the day could well have been driven by a video interrupt or similar.  In any case, the timing of the commands being sent to the PSG are handled by the CPU, not by the PSG - unless you have other plans?

Let's start with ' b) '.  Please provide me with an example read and write steps to the Z80 port so I can compare with the data sheet and make you a proper translation layer.

As I mentioned above, I'm not sure exactly what you're asking for here.  In the YM2149_PSG_system/jt49_hdl folder, there's a file called jt49_bus.v.  That implements the original BDIR/BC1/DIN/DOUT interface - if you want to create an authentic YM2149/AY-3-891x interface then that provides a working template that could be tweaked as necessary?

*Bonus, going by eye, I bet if you were to change line 966 in you GPU _top.sv from 10 to ' .YM2149_DAC_BITS ( 9 ),   I bet it will sound a little better.  10 is a bit too quiet at lower volumes which may be hiding some minor subtlety as 9 it a bit too loud, but at least you could hear it.  I can always do it right and provide a true 14bit authentic dead perfect table output instead of the current bit-depth tapered versions of the tables.

I'll try this out later. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 03:50:40 pm
... I can only attach one mp3 zip at a time due to their size...  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 03:53:35 pm
Last one. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 05:14:44 pm
Before making the .mp3, give this a try:

On the left and right channels, assuming that a volume of 64 is our 100% default reference...

Change channel B on the left and right to 90% volume.
Change channel A on the right to INVerted 80% volume.
Change channel C on the left to INVerted 80% volume.

Now give a listen, especially with headphones and compare to the default mono.

Pseudo (or actual) stereo?  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 06:43:06 pm
Pulse 2 is in actual surround stereo (usually just the accent instruments/voices), though a few large portions of it are mono since they are done using all channel B.  The effect works out good for that tune.  Just listen with headphones and it will be clear.  Pulse 1 is nothing but center mono.

Since there is so little bass, you might increase my BASS setting default of 3 to something like 8 or 16 at this will better center the waveform.  If you take a look at the waveforms in an audio editor, you will notice that a lot of it looks unbalanced 'high'.  Some of this is normal as some sound effects are tiny single vertical spikes and there isn't much we can do unless I re-write my filter specifically for those circumstances.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 06:50:25 pm
b) A 'legacy' Z80 port which would allow you to access the PSG the old way instead of the current direct access.  Yes, we can have both access methods running in parallel as you can use a group of 2 separate Z80 ports, one old, one new to do this.
...
For ' b) ', I need an example of a read/write sequence used to make this work for you.

Are you talking about a legacy YM2149 port, with BDIR and BC1 pins?  I've not changed any host code at all to access the PSG - the music I've been playing (and recorded as mp3s) are being played in a generic CP/M MYM/PT2/PT3 player (https://github.com/GrreenZ/play-tune) - all I had to change was the IO port addresses for the PSG specific to my uCOM.  Bridgette already does the job of interfacing to the PSG module?

It was only an option for music players which you cannot edit the source code to use our current better direct access.  If you do not need it, then we do not bother.

Well, with 2 PSG in the system, you can now play one of these chiptunes in your home brew video games, while having a second PSG dedicated to sound effects with external mixer volume controls allowing channel placement and lower volume for the background music VS player sound effects.  LOL, we could probably throw in 2 Atari Pokeys, and 2 commodore SID chips as well giving you a total of 20 sound channels, with the compatibility of any 8 bit system sound out there.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 07:28:26 pm
Here is how to adjust your 'bass' settings.  Currently in 'PULSE2.mp3', this is what the middle of your sample looks like:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1571875)

I want you to increase the 'BASS' setting until it is almost looks like this:
(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1571881)

You wont hear a difference, but it is more natural for the audio equipment you will be feeding.
Overshooting what I illustrated above will begin to lower the volume of some of the lower frequency notes.
My guess is that it will be around 15-25.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 09:09:37 pm
Well, with 2 PSG in the system, you can now play one of these chiptunes in your home brew video games, while having a second PSG dedicated to sound effects with external mixer volume controls allowing channel placement and lower volume for the background music VS player sound effects.  LOL, we could probably throw in 2 Atari Pokeys, and 2 commodore SID chips as well giving you a total of 20 sound channels, with the compatibility of any 8 bit system sound out there.

Haha - don't tempt me with the SID chip! :o  It would be awesome to have one of those in the system, but I think it would create an awful lot of work for me writing software to use it that could read whatever format Commodore 64s (or their modern-day emulators) saved their music in.  Not impossible, though...  ;)

I've adjusted the bass settings to 25 and got the waveform below for the same section of 'PULSE' that you've focused on:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1571974)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 22, 2022, 09:14:47 pm
That looks fine.
You are done.
I'll just clean up a line or 2 in the source HDL and update it tonight.
What else do you need?


I think the sid music players just had a table being sent to the sid addresses, using the system timer interrupts for delays for when to copy the next control bytes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 09:46:49 pm
 :palm:  |O

Now that the sound reproduction is so good, I've realised everything is too high pitched.  I've done some digging into schematics and old forums and found that the AY-3-8912 PSG in the Amstrad was clocked at 1Mhz, not 1.789MHz (which I think was what the Sinclair Spectrum was running at)...

So I've recompiled the project with the ARYA clock generator set to 1MHz, and the sound is just sublime.  Really takes me back. 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 22, 2022, 10:15:31 pm
That looks fine.
You are done.
I'll just clean up a line or 2 in the source HDL and update it tonight.
What else do you need?

In terms of additional functionality, I just really need to get the USB keyboard working.  I've got a working hardware interface that uses a CH559 which I created and outputs keycodes on a serial interface, but I've not had any time to think about linking it up to the uCOM yet.  I've found a project for the DECA that implements a basic HID from the USB2GO port on the DECA board, but that uses a softcore CPU.  I really just want an easy way to plug a USB keyboard in and get keycodes out that the host can read via Bridgette in the GPU core.  I figure the CH559 is probably the cheapest and easiest route to go, but it involves an additional chip on the board.  Any thoughts?

The other thing that would be of immense use would be an FPU - either a general FP math unit or something geared towards matrix transformations for 3D graphics?  I know there's a couple of examples out there in HDL, think I saw at least one on OpenCores *shudder*, but haven't had time to look into them in any detail yet.  Again, any thoughts or advice would be appreciated.

Then there's the FPGA selection, PCB design and making a board.  That won't come for a while yet though, until the chip shortage really clears up.  I'm still waiting on an LFE5U-25F-6BG256C, which I ordered back in November 2021 and I think is due next month, so that I can have a go at designing a BGA-based FPGA dev board and have a go at soldering a BGA without busting the bank if it all goes horribly wrong.

The only other thing registering in my memory was something you mentioned ages ago when we were working on the GPU which sparked my interest - an instruction set for the GPU - but I think that was a big modification and upgrade to the GPU that would involve a lot of work.

I think the sid music players just had a table being sent to the sid addresses, using the system timer interrupts for delays for when to copy the next control bytes.

I'll take a look into them in a bit more detail when I get the chance - a friend had a C64 back in the day, but the odd rainy afternoon playing Booty was about as close as I got to the SID chip.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 23, 2022, 07:39:36 am
Ok, here we go.  This is the PSG system release.

Everything seems to work OK.
I changed the BASS default to 25.

One thing I didn't do was change the default Volume A-F to 85, which you may test to see if that works OK without generating distortion in the sound.  That level should generate a 'Full' volume 16bit audio.

All the documentation is in the header of the _tb.sv file.
Everything will simulate in Modelsim.

All the technical screenshots and specs begin here:
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4366420/#msg4366420 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4366420/#msg4366420)

Let me know how it works.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 23, 2022, 03:22:20 pm
That's working fine.  I haven't tested the volume change to 85 yet, but I'll add a comment to the repo about that.  Just setting it up now.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 23, 2022, 03:57:03 pm
Github repo is up at https://github.com/nockieboy/YM2149_PSG_system/ (https://github.com/nockieboy/YM2149_PSG_system/).
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 23, 2022, 05:51:05 pm
Github repo is up at https://github.com/nockieboy/YM2149_PSG_system/ (https://github.com/nockieboy/YM2149_PSG_system/).
You need to fill in a relevant description.

Something like:
YM2149 / AY-3-8910 Programmable Sound Generator.  Offers Dual PSGs, programmable stereo mixer with bass and treble controls, standard I2S 44.1KHz or 48KHz 16 bit digital audio out, and built in floating system point clock divider / generator.

Add the tags - Verilog, System Verilog, Sound Generator, (and anything else you can think of...)

One think to change, in your 'Parameters and Ports':

Code: [Select]
   .CLK_IN_HZ       (    50000000 ),   // Input system clock frequency
   .CLK_I2S_IN_HZ   (   200000000 ),   // Input I2S clock frequency

and

   .clk             (      CLK_50m ),   // Master clock for interfacing with the PSG.
   .clk_i2s         (     CLK_200m ),  // Reference clock for the I2S generator's output.  Should be 148.5MHz or higher.

Also, in enhancements include:
Quote
Improved precision 8 thru 14 bit exponential DAC support. (10 bit almost exactly replicates the YM2149 normalized output voltage).

It actually only goes up to 12.  And I think maybe we should limit this to 10 as 12 will have super low volumes...

I would also add:
-  Included extensive Modelsim setup_xxx.do batch files and YM2149_PSG_system_tb_tb.sv which simulate multiple settings of the PSG and mixer with preset sounds to view the filter's effects and a  DAC ramp visualization to compare to the YM2149_dac_normalized_voltage.png.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 23, 2022, 06:10:31 pm
Github readme updated. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 23, 2022, 06:19:28 pm
Should add my short-form description to the right place, see:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1572418)

When you do a Github search, this is what's shown along the project page's name in the search results.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 23, 2022, 06:42:58 pm
Oh yes, forgot about that! D'oh! Sorted now. :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 23, 2022, 06:45:34 pm
Oh yes, forgot about that! D'oh! Sorted now. :-+
:-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 24, 2022, 02:40:36 am
Found a minor mistake in the your Github description:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1572925)

It is not the 'include' you should be changing to switch which PSG system will be used.
It is here: YM2149_PSG_system_tb.sv Line 48. (https://github.com/nockieboy/YM2149_PSG_system/blob/0d790274a1d5ea0469e18f374292be210ecb375d/YM2149_PSG_system_tb.sv#L48)

Commenting in or out this line is the proper way to switch between our PSG system and the original jt49 one.


Also, no pinning of the project on your Git homepage?

Note that once again, include these comments:
Quote
  .clk             (      CLK_50m ),   // Master clock for interfacing with the PSG.
   .clk_i2s         (     CLK_200m ),  // Reference clock for the I2S generator's output.  Should be 148.5MHz or higher.

I would also add, if you want a 0 jitter for the clk_i2s, then you should use a source PLL generated clock which is 256x, or higher multiples thereof the source clock frequency.  This is the one case where you may use frequencies below 148.5MHz.

IE: if you want 48000khz I2S audio with no jitter, use 12.288 MHz, or 2x that, or 4x that, ect...
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 24, 2022, 06:58:25 am
Found a minor mistake in the your Github description:

It is not the 'include' you should be changing to switch which PSG system will be used.
It is here: YM2149_PSG_system_tb.sv Line 48. (https://github.com/nockieboy/YM2149_PSG_system/blob/0d790274a1d5ea0469e18f374292be210ecb375d/YM2149_PSG_system_tb.sv#L48)

Commenting in or out this line is the proper way to switch between our PSG system and the original jt49 one.

Also, no pinning of the project on your Git homepage?

Note that once again, include these comments:
Quote
  .clk             (      CLK_50m ),   // Master clock for interfacing with the PSG.
   .clk_i2s         (     CLK_200m ),  // Reference clock for the I2S generator's output.  Should be 148.5MHz or higher.

Okay, all updated - and I've cleared up some of the code comments on the inputs/outputs.

I would also add, if you want a 0 jitter for the clk_i2s, then you should use a source PLL generated clock which is 256x, or higher multiples thereof the source clock frequency.  This is the one case where you may use frequencies below 148.5MHz.

IE: if you want 48000khz I2S audio with no jitter, use 12.288 MHz, or 2x that, or 4x that, ect...

Not sure I fully understand what you're going for here, so I've updated the README.md with hopefully the right interpretation of the above.  Check the last paragraph in the 'HDL project notes' section, just to make sure the meaning hasn't been lost.  Shouldn't it be zero jitter we want on the I2S output clock?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 24, 2022, 05:49:59 pm
I would also add, if you want a 0 jitter for the clk_i2s, then you should use a source PLL generated clock which is 256x, or higher multiples thereof the source clock frequency.  This is the one case where you may use frequencies below 148.5MHz.

IE: if you want 48000khz I2S audio with no jitter, use 12.288 MHz, or 2x that, or 4x that, ect...

Not sure I fully understand what you're going for here, so I've updated the README.md with hopefully the right interpretation of the above.  Check the last paragraph in the 'HDL project notes' section, just to make sure the meaning hasn't been lost.  Shouldn't it be zero jitter we want on the I2S output clock?

When my floating-point clock divider divides by a fraction, to do so, it must occasionally add a single clk input cycle delay to it's output to synthesize this fractional divided clock.  This delay, which is the period length of 1 clk input, is a type of output jitter.

When supplying my clock divider's input with a clock where it only needs to divide by a perfect integer, there is no occasional single clk delays added to it's output, meaning 0 added jitter.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 25, 2022, 02:25:59 pm
As far as one of my replies to your 'what's next?' question you posed some posts back, I've plucked an FPU example from Github (https://github.com/danshanley/FPU) and have tidied it up a bit (see attached zip file).

I was thinking the best way to insert it into the GPU project was to have it sit as an instantiated module in GPU_DECA_DDR3_top, with its inputs (A, B and opcode) linked directly to GPU RAM addresses in memory, so that the host could write two 32-bit floating-point numbers to the correct memory addresses, write the desired 2-bit opcode (to specify an add, subtract, multiply, divide operation), then read the result memory location for the 32-bit result.  No IO ports used, no additional ports or HDL in Bridgette, just a few memory writes and a read (or 4, to get the full 32-bit value) for the host.

Now it looks like the module is pretty quick - as far as I can tell, as long as A, B and OPCODE are valid then so is the result, which is pretty darn fast (to me, anyway).  If that's the case, then I don't see the need for an 'enable' or strobe to tell the module to calculate the result, might as well just leave it running, with its inputs and outputs constantly reading/writing to the chosen memory locations.  The exactly memory addresses would be specified by parameters in the top level HDL.  It's the constant reading/writing DDR3 memory that is causing me the most concern, though, hence this post.

Questions: 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: FenTiger on August 25, 2022, 03:21:47 pm
constant reading/writing DDR3 memory

It'll need input and output registers in the FPGA anyway. Why not expose them to the Z80 directly?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 25, 2022, 03:52:01 pm
constant reading/writing DDR3 memory

It'll need input and output registers in the FPGA anyway. Why not expose them to the Z80 directly?

Intercept memory RD/WRs to 98 bits of memory and map them to the registers instead of the DDR3 controller?  Now there's an idea - I like it. Thanks FenTiger! :-+
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 25, 2022, 05:11:38 pm
The code you attached would be slow as molasses.
It only has 4 opcode.
It doesn't doe INT <> FP conversion for you.
It has no integer 32bit math.


I would begin by making an MMU blitter for the DDR3 first, then make that MMU support 32bit INT & FP math within.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 25, 2022, 09:48:58 pm
The code you attached would be slow as molasses.
It only has 4 opcode.
It doesn't doe INT <> FP conversion for you.
It has no integer 32bit math.


I would begin by making an MMU blitter for the DDR3 first, then make that MMU support 32bit INT & FP math within.

Okie dokie - but err... what's an MMU blitter? ???
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 25, 2022, 10:44:49 pm
A nice one for you would contain these control registers:


functions:

Loop iterations, (number of cycles),
Source (A) bits (8/16/32/64/128),
source (B) bits (8/16/32/64/128),
dest bits (8/16/32/64/128),
function  -, +, *, /, int>float, float>int, stencil mask output, bit shift results by #.


source (A) begin address.
source (A) inc step size integer.
source (A) inc step size fractional.
source (A) address loop limiter.

source (B) begin address.
source (B) inc step size integer.
source (B) inc step size fractional.
source (B) address loop limiter.

dest  begin address.
dest  inc step size integer.
dest  inc step size fractional.
dest  address loop limiter.


What do you think you can do with that?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 26, 2022, 08:09:41 am
A nice one for you would contain these control registers:


functions:

Loop iterations, (number of cycles),
Source (A) bits (8/16/32/64/128),
source (B) bits (8/16/32/64/128),
dest bits (8/16/32/64/128),
function  -, +, *, /, int>float, float>int, stencil mask output, bit shift results by #.


source (A) begin address.
source (A) inc step size integer.
source (A) inc step size fractional.
source (A) address loop limiter.

source (B) begin address.
source (B) inc step size integer.
source (B) inc step size fractional.
source (B) address loop limiter.

dest  begin address.
dest  inc step size integer.
dest  inc step size fractional.
dest  address loop limiter.


What do you think you can do with that?

Well, I guess fast block operations on bulk memory?  Taking two sources, performing a mathematical operation on them and putting the result somewhere else implies some form of image manipulation, merging/blending?  Sprite blitting?  Plus an FPU as well...

EDIT: Throw in a third source and you could use it as a mask for colour-independent transparency in source A/source B...?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on August 26, 2022, 11:26:52 am
can you define and list the mathematical operations you need for image-manipulations?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 26, 2022, 01:05:02 pm
Well, using what I have listed above, say in channel B we generate a 8+8+8+8 bit ramp from 0-255.
In channel A, we have a line of a bit map 1024 pixels wide x 1024 pixels tall.

We can loop B to a limit of 1024, and increment A normally with a total 1048576 iterations, multiply 8x8 mode, result right shifted by 8.  With this, we would have created a gradient of our source bitmap, left dark to right bright.

Changing the source (B) inc step size integer to 0 and source (B) inc step size fractional to 1/1024, the same operation would vertically generate a gradient from the top of the image dark to the bottom bright.

Or, do not use function B and change the source (A) inc step size integer to 0 and  source (A) inc step size fractional of 1/3, and change the total iterations to 1048576*3 and we would stretch the image by 3.  Since this is linear, you could also change the bit depths to 16 and say we resampled an audio sample to 3x long.  Changing the source (A) inc step size integer to 3 and we can say we shrink the sample by 1/3.

Performing such a task 3 times with a different starting offset, using A and being the just resampled data, A beginning with an offset of 1 and B being the previous computed data, summing together and left shift the results by 3 would interpolate the results.

You can mix and multiply a table period of sine waves, loop processing the results with floats to perform complex filters on large data of sums as input B can be circular tables or even circular matrices for convolution filtering.  Since we can mix floating and integer sources and destinations, you can do processing like FFTs on source data, even 2D ones with multiple passes.

I know modern DSP can do much of this in 1 pass as they have lots of cache for 2D matrices each clock cycle, but we only have so much room left in this FPGA, so multipass with 1D, 2 point matrices will be what we are stuck with.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 26, 2022, 01:19:26 pm
Note that the function list would include logical and/or/xor/nor/nand/xnor ...
Also note that the write destination will have a read/modify/write function for superimposing stenciled graphics, or, 1 final summation/multiplication allowing for 2 functions to take place in 1 copy at the expense of slowing down to below half speed.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 26, 2022, 09:00:49 pm
You can mix and multiply a table period of sine waves, loop processing the results with floats to perform complex filters on large data of sums as input B can be circular tables or even circular matrices for convolution filtering.  Since we can mix floating and integer sources and destinations, you can do processing like FFTs on source data, even 2D ones with multiple passes.

I'm having a little trouble picturing what this could all be used for, beyond the required FPU functions to speed up floating-point calculations, multiplication and division (both integer and FP) for the host.  Convolution filters will allow effects like blurs, edge detection etc., right?

Where do I make a start with this?  Is there anything out there I could use as a base to start from, or can you walk me through this?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 26, 2022, 09:47:25 pm
Try X & Y scaling of geometric objects for the geometry processor.
Even X,Y,Z scaling.  How about a geometry rotation matrix.
Well it can do that as well as 1-D sample and 2-D bitmap scaling and rotation.

I cant imagine you getting anywhere if you want the Z80 to perform a floating point X&Y scale to a few thousand 32bit coordinates in ram.  How fast will the Z80 be just read 32bit X by read 32 bit scale X, get 32 bit result and copy into destination, then again for the 96bits total for the Y axis, then loop this around a thousand points to render a geometric image.

You asked for a FPU unit.  This unit just allows you to process huge chunks of data in the DDR3.

(Actually you need to remind me about how a rotation is done, I think we need to add a square-root to our available math operations.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on August 27, 2022, 01:58:49 am
can you list the mathematical functions you are talking about so I can see *what* you need to compute stuff?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 30, 2022, 02:34:20 am
can you list the mathematical functions you are talking about so I can see *what* you need to compute stuff?
Hello Nockieboy?  I believe this question is for you.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 30, 2022, 04:00:18 pm
can you list the mathematical functions you are talking about so I can see *what* you need to compute stuff?
Hello Nockieboy?  I believe this question is for you.

Oh, thought it was for you for some reason! ::)

can you list the mathematical functions you are talking about so I can see *what* you need to compute stuff?

Okay, well I'm no 3D graphics programmer so I'd be more than happy to be corrected by someone who knows more about this sort of stuff (or maths in general!), but I imagine that some of (if not all of) the following functions would be required for some sort of 3D graphics to be displayed, and thus would benefit from hardware acceleration and floating-point accuracy (this list is NOT exhaustive):
...all applicable to 3x3 or 4x4 matrices.  Would like to steer clear of quaternions if at all possible - in 4D quaternion space, everyone, everywhere, everywhen can hear you scream! ;)

Joking aside, having written the above list it's looking highly ambitious to my untrained eye.  All I really want is an FPU that will allow me to add/sub/div/mult 32-bit floating-point numbers, simply and quickly.  If all this additional stuff (block RAM operations etc) isn't going to cause big issues, then great, but I don't want to overstay BrianHG's patience or willingness to help.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: FenTiger on August 30, 2022, 04:55:23 pm
A lot of these are just 4x4 matrix multiplies. A hardware accelerated "multiply this list of 4-vectors by this matrix" could get you a long way.

For rotations you might want sin and cos operations too.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on August 30, 2022, 05:30:26 pm
A lot of these are just 4x4 matrix multiplies. A hardware accelerated "multiply this list of 4-vectors by this matrix" could get you a long way.

For rotations you might want sin and cos operations too.

Absolutely, it's 4D matrix multiplications, and fast sin/cos functions would be essential.

All of this requires an FPU that can perform 32-bit float multiplication very quickly.  The bottleneck is going to be the 8-bit host, I guess - for any of this to be even vaguely taxed in terms of performance, it's going to need to be able to work flat-out on data loaded into the GPU's DDR RAM, which the host can populate in slow-time during 'loading', but the FPU/GPU can work on very quickly once it's all set up.  All the host would need to do is update the position/rotation of the viewport camera and any actors in the scene - the rest could be handled by the GPU, I guess.

I could get a headache very quickly thinking about all this - I think it's all a step (or a few steps) on from creating the FPU, too.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on August 31, 2022, 12:44:23 pm
playstation-z80  :o :o :o
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on August 31, 2022, 12:52:13 pm
playstation-z80  :o :o :o
No, wasn't the Playstation using integer math, hence those chunky jumping square pixels.
Nockieboy wants floatingpoint.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on August 31, 2022, 02:31:20 pm
playstation-z80  :o :o :o
No, wasn't the Playstation using integer math, hence those chunky jumping square pixels.
Nockieboy wants floatingpoint.

That's exactly * THE * point.
Fixed point was/is enough for SONY' PSX-GTE.
What do you really want to achieve on the software side?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 02, 2022, 06:10:24 am
playstation-z80  :o :o :o
No, wasn't the Playstation using integer math, hence those chunky jumping square pixels.
Nockieboy wants floatingpoint.
That's exactly * THE * point.
Fixed point was/is enough for SONY' PSX-GTE.
What do you really want to achieve on the software side?

Speed wise, the FPGA can do 32bit int or float at 200MHz per multiplier and we are currently using ~5% of the available DSP blocks.  Remember, the Z80 is running at 2 mips max.

Absolutely, it's 4D matrix multiplications, and fast sin/cos functions would be essential.

Ok Nockieboy, ( with a note that you have been quiet for 3 days on this... )  First tell me what and from where you would be feeding into this so-called 4D matrix multiplication an what will be the outputs.  It is dumb to make an 8bit 2mips Z80 fille a 100mhz 32bit x 32bit multiplier multiple times to generate a 4d matrix (4*4+4*4=32 bytes input per computation not counting where to put the output bytes).  Just moving the data through the Z80 alone will be a waste of significant time.

Start by showing me how you would use 1 multiplier to make a 4x4d matrix and what would be the factors.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 02, 2022, 10:27:42 am
Ok Nockieboy, ( with a note that you have been quiet for 3 days on this... )  First tell me what and from where you would be feeding into this so-called 4D matrix multiplication an what will be the outputs.  It is dumb to make an 8bit 2mips Z80 fille a 100mhz 32bit x 32bit multiplier multiple times to generate a 4d matrix (4*4+4*4=32 bytes input per computation not counting where to put the output bytes).  Just moving the data through the Z80 alone will be a waste of significant time.

Start by showing me how you would use 1 multiplier to make a 4x4d matrix and what would be the factors.

I'm working away at the moment, so this is all even more vague than I'd usually be when confronted with technical questions like this on areas I have little knowledge about.

Just to set the scene, at this point I'd just like an FPU that can take two 32-bit floating point numbers and a 2-bit control signal and perform one of the basic mathematical operations on those two numbers to produce a 32-bit floating point result.  This isn't beyond my own ability using an existing FPU module available online (although as you've pointed out with the previous FPU module I suggested, I might need a little help in picking the best one for the job).  This is (initially, at least) purely to speed up integer and floating-point calculations on the host for BBCBASIC and general maths.

As usual though, I'm failing to see the full potential of what I'm asking for and it's clear that it could open up the possibility of some form of 3D graphics acceleration, which is the direction this conversation has taken and (in my opinion at least) is now several steps further on from my original idea of having an FPU as specified in the previous paragraph.

The 8-bit host will be the bottleneck in performance.
The only way I can see to bypass this is to pre-load the actors/camera etc into GPU RAM before the 3D processing starts and leave the 3D engine to deal with the data, with the host making changes to the actor/camera data as required based on user/program input, via the 3D engine - i.e. once it has loaded the objects into the GPU's RAM, the Z80's need to manipulate 3D data would be minimised to sending commands to the 3D engine to rotate/scale/translate objects or the camera as required, including enabling/disabling the drawing of specific objects; but already the language has changed from 'FPU' to '3D engine', with some big implications; there's a hell of a lot more to this than a basic FPU, although it can't be impossible because I remember playing Starglider, Driller and Total Eclipse and those games ran on 8-bit hardware with less than 64KB to play with and no hardware acceleration at all, it was all done in software.  Admittedly though, the bar was very low at around 1-3 fps with <100 vertices on screen.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 02, 2022, 05:58:12 pm
Ok.  When you got the time, then you can properly answer my question.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 02, 2022, 10:00:22 pm
Okay, so a typical operation on a 3D vertex would go something like this:

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1580722)
The maths required for an input vector and transformation matrix.  The values in the rows would be added together to create a final 4D vector output.

Each transformation matrix (on the left of the image above, comprising values a-p) would be pre-defined in the HDL and would define the translate, scale, rotation etc. operation.  This would be chosen by the host (or the engine itself) by specifying the operation to be performed on the provided vertex's 4D vector.

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1580728)
An example of a translation matrix to move a vertex in 3D space.

The 4D vector is the X,Y,Z and W values for the current vertex to be manipulated.  These values could be up to 32-bit floats or integers, I guess, depending on the complexity of the engine.  They'd be stored in GPU RAM, as part of an object's 3D model description, and be copied to the input vector location in RAM for the engine to read at the appropriate time.

The HDL would simply read the 4D vector and multiply its X,Y,Z,W values against the appropriate row/column values in the selected transform matrix, then reduce the resultant matrix down to a 4D vector again to produce the output which would be written to the output location in GPU RAM - the contents of the 3D space being rendered.

I'll have a think about the matrix multiplication and see if I can post some pseudo-HDL (or maybe even proper SystemVerilog) by the end of the weekend. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 02, 2022, 11:22:20 pm
A nice one for you would contain these control registers:


functions:

Loop iterations, (number of cycles),
Source (A) bits (8/16/32/64/128),
source (B) bits (8/16/32/64/128),
dest bits (8/16/32/64/128),
function  -, +, *, /, int>float, float>int, stencil mask output, bit shift results by #.


source (A) begin address.
source (A) inc step size integer.
source (A) inc step size fractional.
source (A) address loop limiter.

source (B) begin address.
source (B) inc step size integer.
source (B) inc step size fractional.
source (B) address loop limiter.

dest  begin address.
dest  inc step size integer.
dest  inc step size fractional.
dest  address loop limiter.


What do you think you can do with that?
Ok, now take a look at my function above and add 1 new function when rendering the 'destination', that being accumulate the results until each 'inc step size fractional' carries into the next integer.
Do you think you can make this work to perform your 4D matrix function?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on September 03, 2022, 08:43:00 am
Why don't you first write the software side for PC, and see how it will be?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 04, 2022, 10:14:28 am
A nice one for you would contain these control registers:


functions:

Loop iterations, (number of cycles),
Source (A) bits (8/16/32/64/128),
source (B) bits (8/16/32/64/128),
dest bits (8/16/32/64/128),
function  -, +, *, /, int>float, float>int, stencil mask output, bit shift results by #.


source (A) begin address.
source (A) inc step size integer.
source (A) inc step size fractional.
source (A) address loop limiter.

source (B) begin address.
source (B) inc step size integer.
source (B) inc step size fractional.
source (B) address loop limiter.

dest  begin address.
dest  inc step size integer.
dest  inc step size fractional.
dest  address loop limiter.


What do you think you can do with that?
Ok, now take a look at my function above and add 1 new function when rendering the 'destination', that being accumulate the results until each 'inc step size fractional' carries into the next integer.
Do you think you can make this work to perform your 4D matrix function?

Maybe.  Well, I'm guessing 'yes' as you've asked the question.

So let's make some assumptions and work on 8-bit integers for simplicity:
At this point I'm not too sure about the step size (integer or fractional), I'm assuming this increments to the next address for the next value in each factor?  Fractional values would allow bit operations?
I'm obviously missing something with the 'step size fractional' - looks like you're intending it to be used to step the loop through each column of the transform matrix?

EDIT:  In fact, if we're only ever doing a 4D vector x 4D matrix multiplication (fixed-dimension maths), is there any need to step at all?  Couldn't we just parallelise the entire system and have them feed the multiplied values into the accumulator simultaneously?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on September 04, 2022, 01:22:13 pm
is there any need to step at all?  Couldn't we just parallelise the entire system and have them feed the multiplied values into the accumulator simultaneously?

DSP slices are not magically 32bit, and they are not magically floating point, and even if you do fixed point you have larger infra logic.

Usually DSP slices are 16 bit sized

Can a 32x32 multiply be done with 16x16 multiplies?

               Z = UMUL(X, Y)

Let us now split each of X and Y into two subwords of k-bit each
               X = 2^k*X1 + X0
               Y = 2^k*Y1 + Y0

X1 is the integer formed by the k most significant bits of X
X0 is made of the k least significant bits of X.

The product Z=UMUL(X,Y) may be written

               Z = 2^k* X1*Y1 + 2^k* (X1*Y0 + X0*Y1) + X0*Y0  (1)

X0*Y0 ----> DSP slice
X0*Y1 ----> DSP slice
X1*Y0 ----> DSP slice
X1*Y1 ----> DSP slice
2^k*   ----> shifter
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 04, 2022, 07:51:29 pm
A nice one for you would contain these control registers:


functions:

Loop iterations, (number of cycles),
Source (A) bits (8/16/32/64/128),
source (B) bits (8/16/32/64/128),
dest bits (8/16/32/64/128),
function  -, +, *, /, int>float, float>int, stencil mask output, bit shift results by #.


source (A) begin address.
source (A) inc step size integer.
source (A) inc step size fractional.
source (A) address loop limiter.

source (B) begin address.
source (B) inc step size integer.
source (B) inc step size fractional.
source (B) address loop limiter.

dest  begin address.
dest  inc step size integer.
dest  inc step size fractional.
dest  address loop limiter.


What do you think you can do with that?
Ok, now take a look at my function above and add 1 new function when rendering the 'destination', that being accumulate the results until each 'inc step size fractional' carries into the next integer.
Do you think you can make this work to perform your 4D matrix function?

Maybe.  Well, I'm guessing 'yes' as you've asked the question.

So let's make some assumptions and work on 8-bit integers for simplicity:
  • Source A is the 3D vertex being worked on, presented as a 4D vector [X, Y, Z, W], with W being 1 and X, Y and Z being its position in 3D space.
  • Source B is the appropriate 4D transform matrix to use for the selected operation on the supplied 3D vertex.
  • Source A's start address is X in the 4D vector.
  • Source B's start address is the first element in the selected 4D transformation matrix, a.
  • 'Accumulated'-Destination address is simply pointing to the X location in the 4D vector output location.
At this point I'm not too sure about the step size (integer or fractional), I'm assuming this increments to the next address for the next value in each factor?  Fractional values would allow bit operations?
  • The multiplier performs the matrix multiplication as per the first image in my previous post, multiplying the values in each column of row 1 of Source B by the vector values in Source A, accumulating each result until the end of the loop (4 iterations) before writing the result to the Destination Address.
  • The Destination Address is incremented (by its step size) to the next output value (Y), then the previous step is repeated for row 2, then row 3, then row 4 in Source B.
  • Once row 4 has been completed, the last value is written to the Destination Address (W) and the operation is complete.
I'm obviously missing something with the 'step size fractional' - looks like you're intending it to be used to step the loop through each column of the transform matrix?

EDIT:  In fact, if we're only ever doing a 4D vector x 4D matrix multiplication (fixed-dimension maths), is there any need to step at all?  Couldn't we just parallelise the entire system and have them feed the multiplied values into the accumulator simultaneously?

Ok, well you are warming up to the idea.
A fractional step is used to re-iterate a source or destination value multiple times before going onto the next term.

Maybe this will help you better see things, where do you store everything?
Assuming everything is a 32bit float...

For example, place [a] in address 1000, [ b ] address 1004, [c] in address 1008... [p] in address 1060.

For [x,y,z,w], lets place them at address 0200000 to 0200012, a group of 1000000 these coordinates meaning addresses 0200000 -> 1799996.

And we want the output to begin at 8000000 consisting of the top row [ax+by+cx+dw] and so forth...

One method may be:
Code: [Select]
set source A-B function to 32x32bit floating multiply and output accumulator = on.
set loop iterations to 1000000x4.  (we neex 4x the number of iterations since every B needs to be multiplied 4 times the number of A inputs)

// Process all the [x]
A   begin address =    1000, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [a,b,c,d])
B   begin address = 0200000, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [x] to the next [x])
Out begin address = 8000000, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

// Process all the [y]
A   begin address =    1016, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [e,f,g,h])
B   begin address = 0200004, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [y] to the next [y])
Out begin address = 8000004, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

// Process all the [z]
A   begin address =    1032, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [i,j,k,l])
B   begin address = 0200008, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [z] to the next [z])
Out begin address = 8000008, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

// Process all the [w]
A   begin address =    1048, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [m,n,o,p])
B   begin address = 0200012, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [w] to the next [w])
Out begin address = 8000012, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

Since we are using 1 multiplier and 1 adder, to do the matrix 4x4, I ran the function 4 times to illustrate what was going on.  In actually, this can be combined down to:

Code: [Select]
set source A-B function to 32x32bit floating multiply and output accumulator = on.
set loop iterations to 1000000x16.  (we need 16x to process everything...)

// Process all the [x,y,z,w] in a single shot.
A   begin address =    1000, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 16.        (every 16 reads, loop back to begin address, A multiplier's input rotates around the read data [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p])
B   begin address = 0200000, B   inc size int =  4,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [x,y,z,w], to next [x,y,z,w])
Out begin address = 8000000, Out inc size int =  4, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

To run as fast as possible, you will need to choose base addresses which sit on 128bit boundaries as the 16 bytes used in 4x32bit words fit inside my DDR3 controller's cache.  My first solution only requires the [a...p] multipliers sitting on 128bit boundaries while the object's coordinates [x..w] only need to be located on 32bit boundaries.

To make things >20x faster, we would need 4 ALU sections, each running my first option all in parallel arriving taking in 128bits at a time and outputting 128 bits at a time with the table [a...p] pre-loaded from ram into a cache.  But this would be a dedicated ALU module just for this instead of a generic any copy & compute module.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 04, 2022, 08:03:38 pm
is there any need to step at all?  Couldn't we just parallelise the entire system and have them feed the multiplied values into the accumulator simultaneously?

DSP slices are not magically 32bit, and they are not magically floating point, and even if you do fixed point you have larger infra logic.

Usually DSP slices are 16 bit sized

Can a 32x32 multiply be done with 16x16 multiplies?

               Z = UMUL(X, Y)

Let us now split each of X and Y into two subwords of k-bit each
               X = 2^k*X1 + X0
               Y = 2^k*Y1 + Y0

X1 is the integer formed by the k most significant bits of X
X0 is made of the k least significant bits of X.

The product Z=UMUL(X,Y) may be written

               Z = 2^k* X1*Y1 + 2^k* (X1*Y0 + X0*Y1) + X0*Y0  (1)

X0*Y0 ----> DSP slice
X0*Y1 ----> DSP slice
X1*Y0 ----> DSP slice
X1*Y1 ----> DSP slice
2^k*   ----> shifter
We are not limited on available DSP slices.  We will have the room to individually allocate a FP 32x32 mult unit, an INT 32x32 mult unit, a FP 32x32 div unit,  an INT 32x32 div unit, same with adders, sine, (we may make cosine use an added FP offset of sine to save on resources here unless Altera though of that and built it into their trig functions.) and there is probably room for a square-root.  We will also allow auto-translate from INT-FP, back and forth in and out of each function's A and B inputs, + outputs in real time.  In fact, it may be more convenient to use FP64 for all the functions and just translate the inputs and outputs to the desired bit and INT/FP format.

However:
To make things >20x faster, we would need 4 ALU sections, each with 4x multiplies running my first option all in parallel arriving taking in 128bits at a time and outputting 128 bits at a time with the table [a...p] pre-loaded from ram into a cache.  But this would be a dedicated ALU module just for this instead of a generic any copy & compute module.

this would mean having 4x or 16x 32x32FP multiply-adds eating up most of our available DPS slices if not all.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 04, 2022, 10:59:33 pm
... inc size fraction=0  ,...

Earlier everywhere I wrote ' inc size fraction=0 ', it should have been ' inc size fraction=1 '.

As in add to the integer pointer every loop iteration.
When it was ' inc size fraction=0.25 ', this means add to the integer pointer every fourth loop iteration.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 06, 2022, 03:16:46 pm
Ok, well you are warming up to the idea.
A fractional step is used to re-iterate a source or destination value multiple times before going onto the next term.

Maybe this will help you better see things, where do you store everything?
Assuming everything is a 32bit float...

For example, place [a] in address 1000, [ b ] address 1004, [c] in address 1008... [p] in address 1060.

For [x,y,z,w], lets place them at address 0200000 to 0200012, a group of 1000000 these coordinates meaning addresses 0200000 -> 1799996.

And we want the output to begin at 8000000 consisting of the top row [ax+by+cx+dw] and so forth...

One method may be:
Code: [Select]
set source A-B function to 32x32bit floating multiply and output accumulator = on.
set loop iterations to 1000000x4.  (we neex 4x the number of iterations since every B needs to be multiplied 4 times the number of A inputs)

// Process all the [x]
A   begin address =    1000, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [a,b,c,d])
B   begin address = 0200000, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [x] to the next [x])
Out begin address = 8000000, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

// Process all the [y]
A   begin address =    1016, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [e,f,g,h])
B   begin address = 0200004, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [y] to the next [y])
Out begin address = 8000004, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

// Process all the [z]
A   begin address =    1032, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [i,j,k,l])
B   begin address = 0200008, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [z] to the next [z])
Out begin address = 8000008, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

// Process all the [w]
A   begin address =    1048, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 4.         (every 4 reads, loop back to begin address, A multiplier's input rotates around the read data [m,n,o,p])
B   begin address = 0200012, B   inc size int = 16,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [w] to the next [w])
Out begin address = 8000012, Out inc size int = 16, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

Since we are using 1 multiplier and 1 adder, to do the matrix 4x4, I ran the function 4 times to illustrate what was going on.  In actually, this can be combined down to:

Code: [Select]
set source A-B function to 32x32bit floating multiply and output accumulator = on.
set loop iterations to 1000000x16.  (we need 16x to process everything...)

// Process all the [x,y,z,w] in a single shot.
A   begin address =    1000, A   inc size int =  4,   A inc size fraction=1   , A   size loop limiter = 16.        (every 16 reads, loop back to begin address, A multiplier's input rotates around the read data [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p])
B   begin address = 0200000, B   inc size int =  4,   B inc size fraction=0.25, B   size loop limiter = 2billion.  (4 every loops, hop from [x,y,z,w], to next [x,y,z,w])
Out begin address = 8000000, Out inc size int =  4, Out inc size fraction=0.25, Out loop size limiter = 2billion.  (accumulate every 4 A*B together into 1 address, then jump 4 to the next output address.)
Run

To run as fast as possible, you will need to choose base addresses which sit on 128bit boundaries as the 16 bytes used in 4x32bit words fit inside my DDR3 controller's cache.  My first solution only requires the [a...p] multipliers sitting on 128bit boundaries while the object's coordinates [x..w] only need to be located on 32bit boundaries.

To make things >20x faster, we would need 4 ALU sections, each running my first option all in parallel arriving taking in 128bits at a time and outputting 128 bits at a time with the table [a...p] pre-loaded from ram into a cache.  But this would be a dedicated ALU module just for this instead of a generic any copy & compute module.


Ah okay, thanks for clearing up the fraction values.   I'll take a deeper look at this later, I might have some time tomorrow but otherwise this week (and weekend) aren't looking good, so it may be next week before I can work my way through your examples and make a start on some HDL.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on September 07, 2022, 11:43:26 am
Things like back-face culling needs to be don in software, here it's when z80 won't help.
That's why I asked you to write/think about the software side BEFORE implementing stuff in HDL.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 07, 2022, 01:36:04 pm
Things like back-face culling needs to be don in software, here it's when z80 won't help.
That's why I asked you to write/think about the software side BEFORE implementing stuff in HDL.

My focus is on creating a versatile FPU; if it can speed up 3D transformations, then that's a great bonus.  If we progress to the point where this turns into a fully-fledged 3D engine then back-face culling will be an issue for consideration.  Calculating vertex order shouldn't be too difficult (without thinking it through much more than working out if they're drawn in clockwise/anti-clockwise order - there could well be issues that I'm unaware of) so working out if they're reversed in a scene shouldn't be too hard in HDL.  Normals, back-face culling, clipping, occlusion culling; I'm still thinking about how to perform 3D transformations on vertices, let alone developing a system that will cope with all these extra features just yet. :phew:
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: DiTBho on September 07, 2022, 01:55:28 pm
The point is: isn't 3D too much for z80?

You want PlayStation-like but 1) floating-point and z80-based where on PlayStation things are fixed-point, accelerated by a GTE chip and scenes and misc performed on MIPS-R3K CPU with both higher CPI and clock frequency than your Z80.

I think the GTE is great, but the last part, the CPU contribution, is also very important for the final application.

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 07, 2022, 03:22:22 pm
The point is: isn't 3D too much for z80?

Very much so, if you're after ray-traced 3D worlds covering kilometres of play area.  I don't know what your experience of computing is (i.e. how far you go back), but I suspect you've got an entirely different picture of what you think I want when I talk about 3D graphics in this context.

Before I go any further, let me just reiterate that I want an FPU that could potentially be flexible enough to do 3D transformations.  That's all.   Anything else is a bonus - I have to add that, as I have found through experience that BrianHG has a talent for blowing my expectations out of the water and producing something truly "over the horizon" in terms of what I wanted or thought possible.  This whole thread is case-in-point for that.  When I think of 3D graphics in the context of the Z80, I'm thinking of graphics like this:

Starglider on the Amstrad CPC: https://www.youtube.com/watch?v=cglI0VanLs8 (https://www.youtube.com/watch?v=cglI0VanLs8)

i.e. simple wireframe graphics; no BFC, no occlusion-culling, no Gouraud shading, no texture mapping, no forward-rendering, and definitely no smegging flapjacks (see Red Dwarf for that last one). ;)

You want PlayStation-like but 1) floating-point and z80-based where on PlayStation things are fixed-point, accelerated by a GTE chip and scenes and misc performed on MIPS-R3K CPU with both higher CPI and clock frequency than your Z80.

I think the GTE is great, but the last part, the CPU contribution, is also very important for the final application.

Again, no argument from me - I totally agree that the Z80 would be a hideously limiting factor in that feature set (unless the 3D engine is smart enough);  but I'm not after PS1-like graphics, as I've stated above.  I am putting together an FPGA video engine that can work with any number of different host systems, not just Z80s.  If I ever get the time, I'll make a 16-bit Motorola 68010 system and be using this same FPGA video system with that - could you say that system wouldn't be able to handle PS1-style graphics with suitable hardware acceleration in the FPGA?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 07, 2022, 08:49:08 pm
What I described above, the setup factors will also be stores in DDR3 and multiples of these programs can call each other in a greater loop.  So, even such programs can calculate or LUT modify the factors of another.  You have enough to create a ray-caster engine equivalent to Doom.  Though, I would stick to 640x480 for this, though you may get away with 32bit color.  For this core, I only choose something super simple where you only need 4x 32bit adder counters for (A), the same thing for (B), the same thing for (OUT) while keeping track of an 'OP-Code'.   You will use 1 new read port to fetch the instructions, the next read port to fetch the (A) directed by it's 4x 32bit counters, another read port to fetch the (B), then one read/write port to write the (OUT) with it's control counters.

The opcode controls what function will be written.
The int and fractional counters allow us to for example split or selectively render just the red or green or blue, split them apart, do a contrast / brightness / rgb/yuv conversions.  For audio split / combine stereo audio, apply volume to individual channels.  For geometry, well we have already been discussing that.

However, the ALU with it's opcode itself will need some planning.  It is not the math functions themselves as Altera has all the floating point and integer functions, including trig, available for free in their IP store.  It's the decision of how we wire the int/FP in and out conversions as many thing will need int and float conversion and we want to do this on they fly instead of doing another FPU pass when it is not necessary.

Separate of the ALU, one last graphics function we never attempted was a raster graphics fill routing.  All our line / ellipse / box / triangle can perform fills on themselves, but what we are missing is a means of drawing a geometric shape, or have a ready picture made on the screen and decide to choose a pixel and begin a flood fill on all connected pixels of that same color to a new color.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 07, 2022, 09:20:49 pm
Separate of the ALU, one last graphics function we never attempted was a raster graphics fill routing.  All our line / ellipse / box / triangle can perform fills on themselves, but what we are missing is a means of drawing a geometric shape, or have a ready picture made on the screen and decide to choose a pixel and begin a flood fill on all connected pixels of that same color to a new color.

Ah yes, I'd forgotten about that! :o  That would round the geometry engine out nicely.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 08, 2022, 12:21:23 am
@Nockieboy, have you tried to wire an Altera FP unit to IO ports?

Just use the FP_Mult for example.

Wire the A & B inputs to out ports 0,1,2,3 & 4,5,6,7 and wire the read output to ports 8,9,10,11.

Then add a FP_ADD's inputs also to ports 0...7, but wire the output to read ports 12,13,14,15.

Then do a divide, sine, 32 bit integer add/sub & divide.

Use a dumb write port numbet to latch the results or something to the effect.

Also add an int -> FP and FP -> int converter, maybe piggybacked on ports 0...7 and output.

Like I said, start with a new module and add first 1 multiplier.
Configure the multiplier so that it can run up to 150MHz.
Note the pipeline delay.  (Though, it will be so fast the Z80 couldn't even read a result before it finishes).
Show your progress and don't forget to double check the features of you generated module & pack everything in a new folder not to mess up what you already have.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 08, 2022, 07:34:45 am
@Nockieboy, have you tried to wire an Altera FP unit to IO ports?

Not yet.  I'll try to have a go at this today - this will require some work in Quartus, right?  I'm going to need to create these modules from Quartus IP before wiring them up in the DECA_DDR3_top.sv?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 08, 2022, 07:52:06 am
@Nockieboy, have you tried to wire an Altera FP unit to IO ports?

Not yet.  I'll try to have a go at this today - this will require some work in Quartus, right?  I'm going to need to create these modules from Quartus IP before wiring them up in the DECA_DDR3_top.sv?
Make a module called nockieboy_alu.sv
do your work in there.
Place that module in _top.sv.
Wire it to the Z80-bus write and read ports.
Use 10 write ports for 32bit A & B and 2 more for alu function.
Use 4 read ports for 32bit return data from the ALU out.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 08, 2022, 08:05:30 am
@Nockieboy, have you tried to wire an Altera FP unit to IO ports?

Not yet.  I'll try to have a go at this today - this will require some work in Quartus, right?  I'm going to need to create these modules from Quartus IP before wiring them up in the DECA_DDR3_top.sv?
Make a module called nockieboy_alu.sv
do your work in there.
Place that module in _top.sv.
Wire it to the Z80-bus write and read ports.

I'm going to have to move the legacy ports out of Bridgette before I can wire the ALU up - that task has finally been upgraded to 'blocker' from 'nice-to-do'.  ;D
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 08, 2022, 06:38:26 pm
Okay, legacy IO has been moved out of Bridgette into its own module (which I may break up even further later for true modularity) and I can make a start on the ALU interconnects later.

In the meantime however, I have a question regarding this line in the _top module:

Code: [Select]
wire [  7:0] IO_RD_DATA [0:255] ; //= '{ default: 8'hFF } ;
I'm assuming that Quartus will prune IO_RD_DATA down to just the wires that are actually in use.  If I uncomment the code setting a default value of 0xFF to all the wires in IO_RD_DATA, will that then cause Quartus to keep them all in the FPGA, or will it still prune the unused ones?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 08, 2022, 07:45:26 pm
Unused wires will get pruned.  You might not get the option to to use the 'default' inside the Z80 module.
You might have to do this outside the module in your _top.sv: (example)

Code: [Select]
logic [7:0] READ_PORT_DATA [0:255] = '{default:8'hFF};  or '{default:8'hZZ};'Wire' might not work, which is why I used 'logic', in the case of this one port name.  'Wire' will work with everything else.


Wire that logic to the Z80 read port inputs.

Remember, when feeding another modules' 16bit device input port:

Code: [Select]
.din ( '{WRITE_PORT_DATA[port_name_hi],WRITE_PORT_DATA[port_name_lo]} )or 32bit (orient the +# to your preferred endian)
 
Code: [Select]
.din ( '{WRITE_PORT_DATA[port_name+3],WRITE_PORT_DATA[port_name+2],WRITE_PORT_DATA[port_name+1],WRITE_PORT_DATA[port_name+0]} )
Also use the write ena/strobe: (hi/lo depends on your write order scheme.
Code: [Select]
.din_ena ( WRITE_PORT_STROBE[port_name_hi/lo] )
Also use the read ena/strobe:  (not always used)
Code: [Select]
.dout_read_ena ( READ_PORT_STROBE[port_name_hi/lo] )
Just like the above 16bit and 32bit examples, you can concatenate larger size buses as you wish, or individually feed 8bit slots, you just feed through the entire 8bit x 256address array.

Read is a little more tricky as you cannot have bus conflicts.  So just keep to individual read port numbers to individual devices.


Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 08, 2022, 09:29:27 pm
Unused wires will get pruned.  You might not get the option to to use the 'default' inside the Z80 module.
You might have to do this outside the module in your _top.sv: (example)

Code: [Select]
logic [7:0] READ_PORT_DATA [0:255] = '{default:8'hFF};  or '{default:8'hZZ};

Yep, that's where the code I quoted in my previous post sits - in the GPU_DECA_DDR3_top.sv module. 

Remember, when feeding another modules' 16bit device input port:

Code: [Select]
.din ( '{WRITE_PORT_DATA[port_name_hi],WRITE_PORT_DATA[port_name_lo]} )or 32bit (orient the +# to your preferred endian)
 
Code: [Select]
.din ( '{WRITE_PORT_DATA[port_name+3],WRITE_PORT_DATA[port_name+2],WRITE_PORT_DATA[port_name+1],WRITE_PORT_DATA[port_name+0]} )
Also use the write ena/strobe: (hi/lo depends on your write order scheme.
Code: [Select]
.din_ena ( WRITE_PORT_STROBE[port_name_hi/lo] )
Also use the read ena/strobe:  (not always used)
Code: [Select]
.dout_read_ena ( READ_PORT_STROBE[port_name_hi/lo] )
Just like the above 16bit and 32bit examples, you can concatenate larger size buses as you wish, or individually feed 8bit slots, you just feed through the entire 8bit x 256address array.

I'm a step ahead, I already have it all running nicely. ;D

Code: [Select]
   .fifo_cmd_in      ( { IO_WR_DATA[GEO_HI], IO_WR_DATA[GEO_LO] } ), // 16-bit command bus from Z80_BRIDGE.
Above is a snippet from the current GPU_DECA_DDR3_top module as an example of what you're talking about, I think - feeding two 8-bit values into a 16-bit input?

(The latest code is viewable in the github project (https://github.com/nockieboy/gpu), btw).

Read is a little more tricky as you cannot have bus conflicts.  So just keep to individual read port numbers to individual devices.

I've kept the IO_RD_DATA bus in the GPU_DECA_DDR3_top module, as a number of sub-modules write data into that bus I've had to keep it a level above the sub-modules to avoid conflicts as you've mentioned.  See the _top module in the github repo for details (https://github.com/nockieboy/gpu/blob/master/GPU_DECA_DDR3_version_16/GPU_DECA_DDR3_top.sv#L852-L900).

On to linking up the FPU multiplier tomorrow. :-/O
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 09, 2022, 02:11:49 am
Just a note, reserve and pass 16 sequential write ports for your command as this is 128bit and the size of the op-code which we will eventually use when reading such code from DDR3 memory.

IE, the 128bits worth of IO port from the Z80 can sever as a direct bypass to the MMU-ALU controls when you do not want to bother getting the MMU / DDR3 part involved with simple calculations.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 10, 2022, 09:49:08 pm
I'm obviously making a silly mistake somewhere, because I can't get anything other than zeros out of the FPU.  I'm able to set factor_A and factor_B values in the nockieboy_FPU module, but output_Q remains stubbornly zero.  I can't seem to get traces in SignalTap for the reset and enable ports to the FPU either - I suspect they're being pruned out which is why the FPU isn't working, but I don't have the time this weekend to play around with it to find out why.

I've attached the key modules involved - if there's an obvious mistake I'm making then let me know, otherwise I might have more time tomorrow night to dig deeper and preserve some of these wires to see what's going on in SignalTap.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 10, 2022, 10:12:32 pm
Other than the extra steps, this looks like it should work.
You can try hard wiring the 'reset' to 0 as it wont make a difference here and it is not needed for now.

Can you successfully write a value to the A and B ports, then just read back port the A and B with the values you just written?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 11, 2022, 05:53:40 am
Other than the extra steps, this looks like it should work.
You can try hard wiring the 'reset' to 0 as it wont make a difference here and it is not needed for now.

Can you successfully write a value to the A and B ports, then just read back port the A and B with the values you just written?

Yes, I'm getting the written values back fine.  I'm wondering if there's a reset problem, as I'm unable to get that line in SignalTap.  Will have time later today (certainly next two days) to looker deeper.  I'd just assumed I'd made a simple mistake somewhere. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 11, 2022, 06:02:32 am
Use a different proper reset line which I have made available throughout your project.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 14, 2022, 06:52:19 pm
Well?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 14, 2022, 06:57:05 pm
No progress this week, I'm afraid.  I haven't had any time to even think about the project, let alone work on it.  The last thing I tried was a fixed reset line, no change.  Maybe I'll have some time at the weekend. :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on September 16, 2022, 08:58:18 pm
Have just tried with fixed reset, both high and low just in case it was active high, still getting zero from the FPU.  I'm setting A and B inputs to 7 and 9 respectively, I'm able to read the results back, and the Q output isn't changing at all - all I'm reading back is 0's.

Latest project attached so we're on the same page.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on September 16, 2022, 09:29:14 pm
Place in an absurd number.

Remember, it is floating point, the exponent needs to be set, though anything you enter besides 0 should work.

It may be a bug in the megafunction.

Can you try an integer 32x32bit multiply?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 09, 2022, 10:06:19 am
Eesh, didn't realise it had been this long - I've been flat out on work unfortunately.  I've had five minutes to look at this again and I think something is going on with Quartus optimising signals away.  I've added /* synthesis keep */ to the entirety of the IO_WR_STROBE and IO_WR_DATA buses and at least I can see those signals in SignalTap now and trigger on IO writes to the A and B input values to the FPU.  I can see that the values are getting written to the FPU, but the FPU's output (Q) is not changing.

I'm going to take a longer look at this signal optimisation when I have the time, but one thing I'm wondering is; does the FPU require a strobe on the enable line or is pulling it permanently high okay?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1610392)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 09, 2022, 11:25:36 am
Test a 32bit integer multiply.
I have a feeling the floating point unit isn't compiled properly leading to a dead module which simplifies out the source A&B input channels.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 10, 2022, 06:31:02 pm
Test a 32bit integer multiply.
I have a feeling the floating point unit isn't compiled properly leading to a dead module which simplifies out the source A&B input channels.

Hmm.  Well, I set up an integer multiplier using the Quartus IP wizard and it seems to be working perfectly.  I can multiply two 32-bit numbers by writing their bytes to 4 IO addresses each, and can read the (cropped to) 32-bit output via a third set of four IO ports, as intended.

Must be something wrong with the FP_MULT instantiation...  :-//
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 10, 2022, 06:51:15 pm
Heeehe....
Ok, I'll look for thee old original Altera FP functions before they combined them all into that single BS megafunction wizard which generates faulty non-functional functions.  It's like they have similar problems with their DDR3 controller.

You can post your question on Intel's website or:

Ok, here are the original direct call cores:
https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/mega/mega_list_mega_lpm_d1353e88.htm (https://www.intel.com/content/www/us/en/programmable/quartushelp/17.0/hdl/mega/mega_list_mega_lpm_d1353e88.htm)

Though, it was designed for Quartus 17 and earlier.

Now, Quartus is hiding these which have been replaced with the new garbage (ie: It don't function)  you can look at the old documents here:
https://www.manualsdir.com/manuals/746181/altera-floating-point.html?page=67 (https://www.manualsdir.com/manuals/746181/altera-floating-point.html?page=67)
(I know the pipeline should be around 11 though 5 or 6 or 10 may work depending if low numbers like 5 or 6 can reach your operational 100MHz clock.)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 10, 2022, 07:07:44 pm
The new IP cores don't work? :o

I hadn't checked the results of the previous test, it was enough that the output had changed and actually had a value in it for me. :-DD

I'm compiling the project again as I write this (it's taking over 5 minutes per compile now), with IP files in the right folder.  Using these IP cores is a no-no then?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 10, 2022, 07:10:57 pm
Did you check the compiler messages window?
Maybe there is a clue there, like couldn't find source file XXXX, or simplifying out module XXXX because it is not clocked, or net XXXX missing or wire XXXX generated which usually means a 1 bit wire....
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 11, 2022, 04:40:50 pm
Okay, so I've done some very quick and dirty testing of the FP_MULT core provided by Quartus and it's returning values that I'd expect (using integers to multiply each other).  I might have some time later to multiply some fractions, but for the moment it seems to be working okay..

I'll have a look at the compile messages later this week if I get some more time. :-+

EDIT: Fractions seem to be working fine too, at least in so far as the single-precision accuracy allows.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 11, 2022, 10:16:21 pm
EDIT: Fractions seem to be working fine too, at least in so far as the single-precision accuracy allows.
Are you saying that your Z80 basic also requires 64bit floating point number support?

Hmmm.
Maybe make an all 64bit ALU, then just select translate the source format to 64bit double, then down translate the 64 bit result to the selected format.

I thought that a 32bit int and 32bit float ALU would have been enough.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 12, 2022, 02:44:26 am
EDIT: Fractions seem to be working fine too, at least in so far as the single-precision accuracy allows.
PLS verify negative numbers.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 12, 2022, 04:34:01 pm
EDIT: Fractions seem to be working fine too, at least in so far as the single-precision accuracy allows.
Are you saying that your Z80 basic also requires 64bit floating point number support?

Hmmm.
Maybe make an all 64bit ALU, then just select translate the source format to 64bit double, then down translate the 64 bit result to the selected format.

I thought that a 32bit int and 32bit float ALU would have been enough.

No no, single precision is fine, I was just acknowledging slight rounding errors thanks to the single precision.  I don't need double precision (at least afaiaa).

PLS verify negative numbers.

Have tried multiplying negative x positive, and negative x negative as well as positive x positive.  All results appear correct. :-+

EDIT: Just need some coherent free time so I can sit down and get my head around displaying/reading 32-bit floats to/from ASCII.  There's some source code out there, I just need to interpret and repurpose it.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 12, 2022, 07:56:44 pm
EDIT: Just need some coherent free time so I can sit down and get my head around displaying/reading 32-bit floats to/from ASCII.  There's some source code out there, I just need to interpret and repurpose it.
I usually read a strict integer, then multiply by the correct base 10 decimal point position.

Setting the input integer as the mantisa and use the decimal to set the exponent value wont work because the exponent is in base 2, not base 10.

Note that there does exist FP unit conversion megafunctions to convert to and from integer and FP.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 16, 2022, 08:37:14 pm
When will you add the rest of the FP functions?

Also register moving/copying and FP <-> INT functions.

Also, don forget all the 32bit int functions...

Might as well add Zero and Negative & Carry/Overflow flags.
(IE, performing a FP subtract between A&B will tell you if A>B, A=B, or A<B by examining the flags, or if you use a separate FP_SUB function, Always leave it wired on and have dedicated A>B, A=B, or A<B as part of your FP flags as well as having INT flags.)

All together, this should make your Z80 perform 32 bit functions with absurd speed.

Though, making the ALU DMA right through the DDR3 ram with a start and stop memory coordinates like we were going on about a number of posts before would make it to ludicrous speed in Z80 terms.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 18, 2022, 01:12:24 pm
When will you add the rest of the FP functions?

Also register moving/copying and FP <-> INT functions.

Also, don forget all the 32bit int functions...

Might as well add Zero and Negative & Carry/Overflow flags.
(IE, performing a FP subtract between A&B will tell you if A>B, A=B, or A<B by examining the flags, or if you use a separate FP_SUB function, Always leave it wired on and have dedicated A>B, A=B, or A<B as part of your FP flags as well as having INT flags.)

All together, this should make your Z80 perform 32 bit functions with absurd speed.

Though, making the ALU DMA right through the DDR3 ram with a start and stop memory coordinates like we were going on about a number of posts before would make it to ludicrous speed in Z80 terms.

I'll get the other functions added as soon as I can get the FP_MULT function fully testable in BBCBASIC.  I have confirmed that it's working - have a small program that allows me to set and read values and it's producing the right results, but right now my next step is to get it integrated (i.e. replace the existing FP math routines) in BBCBASIC so it can accelerate the math in already-existing programs like the Mandelbrot generator, where I can see at a glance the improvements it's making.  Unfortunately, it's taking me a little time to pull the complex web of functions apart to work out what to isolate and replace in the BBCBASIC code with my FPU interface code.  Once that's working, I'll add the other functions - integrating them should be a lot easier then as I'll have an example to work from.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 19, 2022, 05:36:30 pm
Are you saying that your Z80 basic also requires 64bit floating point number support?

Hmmm.
Maybe make an all 64bit ALU, then just select translate the source format to 64bit double, then down translate the 64 bit result to the selected format.

I thought that a 32bit int and 32bit float ALU would have been enough.

Coming back to this comment - I've got the FP multiplier working with BBCBASIC now, but it uses 40-bit floats - 8-bit exponent, 1-bit sign, 31-bit mantissa.  Currently I'm dropping the last byte of the mantissa from BBCBASIC's floats for the FPU, but it would be trivial to build a new FPU that supports 40-bit floats.

My question is - should I?  Or should I just go for double-precision and dumb it down for BBCBASIC?

EDIT: Also, is this okay? (Referring to the minus 1 mathematical operation on the first byte)

Code: [Select]
q        <= { (output_Q[SIZE-2:SIZE-9] - 1), output_Q[SIZE-1], output_Q[SIZE-10:0] } ;
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 19, 2022, 10:16:51 pm
Well, you can make a 40bit FPU, and then make 2 sets of ports, one with 4xbyte 32bit wiring and another with 5xbyte 40bit wiring.

Or, go the 64bit route and make a 3 sets of IO ports, 32, 40 & 64 bit ports.
IE: A write to the 32 or 40 bit IO ports would properly fill/translate to the 64bit port with the correct padded number.  Writing to the 64bit port would be a raw direct feed to the FPU.  Your only problem is the Zero flag.  You will need to test the results to see if a true 0 has been reached because of an exponent which happens to be too far to the right to be seen by a 40bit result.  Same for the overflow flag having an exponent too far to the left.

 (Only a guess) I can imagine the 40bit mess was designed in BBC basic to exclusively run floats for all variables.  This way, when calculating integers, you can still maintain 32bit int precision.

Note that 64bit floats may require a 'NOP' on the Z80 before the read when doing a 64bit divide.  That one's pipeline may be a good 30-50 clocks to support 100MHz.  However, at Z80 speeds, my guess just the next instruction fetch will consume more time that that.  Then again, running a 40bit or 64bit divide with a single 'NOP' latency should still be much faster than calculating it with an 8bit CPU the long-way.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on October 27, 2022, 02:24:53 pm
Well, you can make a 40bit FPU, and then make 2 sets of ports, one with 4xbyte 32bit wiring and another with 5xbyte 40bit wiring.

Or, go the 64bit route and make a 3 sets of IO ports, 32, 40 & 64 bit ports.
IE: A write to the 32 or 40 bit IO ports would properly fill/translate to the 64bit port with the correct padded number.  Writing to the 64bit port would be a raw direct feed to the FPU.  Your only problem is the Zero flag.  You will need to test the results to see if a true 0 has been reached because of an exponent which happens to be too far to the right to be seen by a 40bit result.  Same for the overflow flag having an exponent too far to the left.

I went with a 40-bit FPU in the end, one set of IO ports and the ability to tell the FPU what format to use.

(Only a guess) I can imagine the 40bit mess was designed in BBC basic to exclusively run floats for all variables.  This way, when calculating integers, you can still maintain 32bit int precision.

Spot on. :-+

I've run the Mandelbrot BASIC program and am getting a ~14% speed increase drawing the image, using FP multiply, divide, add and subtract hardware acceleration.  That seems like a really small speed increase, but there's a lot of stuff going on in the background with BBCBASIC around the floating point math.  I suspect a true floating-point 3D application would speed up even more.

I'm probably doing it all wrong, but I've attached the top module and the FPU's top module so you can see what I've done.  This is all implemented using Altera's own FPU core IP generated in Quartus.  As always, feedback appreciated.  I'm away all of next week, so progress is going to remain slow for a while, unfortunately.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on October 29, 2022, 03:54:26 am
Ok, in the attached code, you forgot to include the FP_lpm functions.

Anyways, I would have not used all those dumb strobes in the _top.sv.

For the format, that should be I'm guessing a write port and you should include it's strobe into the ALU.

Using that strobe for the function, you can latch the all of the 'IO_WR_DATA' which should be directly tied to the input_A & input_B to your new ALU's internal register's in_A and in_B.

Now, it will be possible to add functions combined with the function's 'strobe' for a single stroke action to, for example, copy all of the multiply/divide/add/sub's output back into register in_A or in_B.  Or, you can swap in_A and in_B.

These are suggestions to allow a few more examples, like in the future having 16x in_A and 16x in_B registers with an output table of results.  This may help in storing rotation/scale factors and requesting a block of computation or transformation matrix in a single go.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 07, 2022, 10:30:50 am
Ok, in the attached code, you forgot to include the FP_lpm functions.

LPM_COMPARE, LPM_COUNTER, LPM_DIVIDE and LPM_MULT?

I'm in the process of looking up what the LPM functions are.  Not finding much info on them other than they're a library of parametrised modules, or Lagrangian Particle Methods (don't think they're the last one!)

What are they?  What's their use-case?

Anyways, I would have not used all those dumb strobes in the _top.sv.

For the format, that should be I'm guessing a write port and you should include it's strobe into the ALU.

Using that strobe for the function, you can latch the all of the 'IO_WR_DATA' which should be directly tied to the input_A & input_B to your new ALU's internal register's in_A and in_B.

Yes, it's an IO port that the host writes to so that it can set the ALU's function.  Currently, you set the function and the output of the ALU changes accordingly.  The output is 'live', so you send the floats to the ALU by writing to the 8 IO ports for them and read the result, either setting the function before or after the floats are sent (I do it before).

You're saying I should stop updating the IO_RD_DATA array with any writes to the FPU IO ports by using the FORMAT IO strobe to signal to the FPU to latch all the IO_WR_DATA ports to the appropriate inputs (a, b)?

I understand passing a strobe into the ALU module will be useful, but it's handy to be able to read the value on each ALU IO port so I'm not sure of the benefits of latching the IO_WR_DATA directly to the ALU's inputs?

Now, it will be possible to add functions combined with the function's 'strobe' for a single stroke action to, for example, copy all of the multiply/divide/add/sub's output back into register in_A or in_B.  Or, you can swap in_A and in_B.

Surely I can do this currently, as inputs a & b to the ALU module aren't passed directly to the FPU sub-modules and can be redirected by the ALU?

These are suggestions to allow a few more examples, like in the future having 16x in_A and 16x in_B registers with an output table of results.  This may help in storing rotation/scale factors and requesting a block of computation or transformation matrix in a single go.

Sounds good!  I think I just need to understand the reasoning behind moving the IO_WR_DATA bus directly into the ALU module; there's clearly something I'm misunderstanding. ::)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on November 08, 2022, 03:24:22 am
Ok, in the attached code, you forgot to include the FP_lpm functions.

LPM_COMPARE, LPM_COUNTER, LPM_DIVIDE and LPM_MULT?

I'm in the process of looking up what the LPM functions are.  Not finding much info on them other than they're a library of parametrised modules, or Lagrangian Particle Methods (don't think they're the last one!)

What are they?  What's their use-case?

 :palm: Where is the source code for the following functions in red?

Quote
  ADD40 addsubber (

    .clk    ( clk      ), // clk
    .areset ( areset   ), // reset
    .a      ( factor_A ), // a
    .b      ( factor_B ), // b
    .q      ( ADD_Q    ), // output
    .s      ( SUB_Q    )  // output

  );

  DIV40 divider (

    .clk    ( clk      ), // clk
    .areset ( areset   ), // reset
    .a      ( factor_A ), // a
    .b      ( factor_B ), // b
    .q      ( DIV_Q    )  // output

  );

  MULT40 multiplier (

    .clk    ( clk      ), // clk
    .areset ( areset   ), // reset
    .a      ( factor_A ), // a
    .b      ( factor_B ), // b
    .q      ( MUL_Q    )  // output

  );

endmodule
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on November 08, 2022, 08:16:16 am
I've included the entire FPU module in the attachment, so all files should be there.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2022, 08:34:38 pm
Eek.  Been so busy recently.  Have been pottering about with the graphics tile demo/game I started ages ago this evening and managed to take some pictures of these blue lines/artefacts that occasionally appear on screen - they'll fade in, flicker about, the pattern might change (as shown in the pics) and they'll disappear again.  I've tried cable-wiggling as my most serious attempt to debug the issue, but now I have photographic evidence thought I'd post here to see if there's an HDL or FPGA cause for this issue?

 
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 09, 2022, 09:17:59 pm
If the issue is with a too long or bad HDMI cable, then there is nothing you can do in firmware to fix.
(IE: if plugging and unplugging the cable or changing a HDMI cable, switching to a different monitor input changes the garbage pattern, then the issue is not in the firmware) \

(Note that my LG Flatron24 did this on the red channel when I used the HDMI input and the DECA board.  Switching to the DVI input using a HDMI-DVI adapter fixed the issue,)


Otherwise, we need to look at your compiler build's timing report.

If timing isn't met for the VGA output clock section, maybe just changing the compiler optimization technique will fix the issue.

Or, maybe, I need to invert the VGA output dac clock, or set the DVI encoder's CLK input phase using it's I2C controls.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 09, 2022, 10:19:33 pm
Okay, no worries, when I get a moment I'll plug it into my TV in the living room and see if the lines appear there.  It's only a 1-metre HDMI cable, but points taken about the cable quality etc.

Any follow-up on the FPU thread at all?  Is that implementation okay or are there issues?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 14, 2022, 06:15:25 am
Okay, no worries, when I get a moment I'll plug it into my TV in the living room and see if the lines appear there.  It's only a 1-metre HDMI cable, but points taken about the cable quality etc.

Any follow-up on the FPU thread at all?  Is that implementation okay or are there issues?
The FPU implementation is up to you.

Did you fix the video blue speckles?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 21, 2022, 01:34:10 pm
Did you fix the video blue speckles?

I think it must be interference on the HDMI cable somewhere, I've re-routed the cable and it hasn't come back since, but I've not had any long periods of time to test for it recently, so I'll hold fire on calling it fixed just yet.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 22, 2022, 11:36:01 am
I've started another thread to discuss the design of a PCB for a Xilinx FPGA for this project here (https://www.eevblog.com/forum/eda/planningdesignreview-for-a-6-layer-xilinx-artix-7-board-for-diy-computer/).

I'm starting to reach the limits of the 10M50 with LEs and want to move up to a larger FPGA.  With issues finding a reasonable Intel upgrade path from the 10M50 on Mouser, I figure it's a good time to switch to Xilinx perhaps - we can test out the GPU HDL on a different platform as well and perhaps fine-tune the DDR3 controller there as well.  Plus I have the itch to design a new PCB!  ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 22, 2022, 11:28:37 pm
Thought I'd reply to this post (https://www.eevblog.com/forum/fpga/planningdesignreview-for-a-6-layer-xilinx-artix-7-board-for-diy-computer/msg4598048/#msg4598048) in this thread as it's more relevant to the GPU discussion. ;)

Note that the 48$-39$ 85KLE fpgas from Lattice are finally available once again.
Though, you need to convert my DDR3 controller as Lattice's DDR3 costs money.

Note that in your current design, Parallel layers in my video controller eats a few K-LE per layer while the Sequential layers are near free in LE usage.  Obvious using the 2 layer types together is what gives you the 16-64 layers you may be using.

The way your current pixel writer is designed is slow and excessive in gate count because it was engineered to run on the old FPGA dual-port ram and support backward compatibility.  This is how things end up when you begin with engineering with a design for a 6KLE FPGA, then just recklessly add layers ontop.

As you know, starting with a 6,000 LE FPGA was a conscious decision as I'd never used FPGAs before and wanted to start small whilst I was learning about them and developing my very basic soldering skills and confidence.  The pixel writer was designed to access screen memory in the FPGA's dual-port RAM because that was all we had available to us.  Since we've had DECA boards to play with, and I will be including DDR3 RAM on the next custom board I build, the screen RAM has logically moved to DDR3.

So the next question is, what would be involved in fine-tuning the pixel writer to work with DDR3 via your controller more efficiently?  Knowing what is required of the memory interface could be useful in guiding my DDR3 component selection and design for the next board, although I guess just 'faster is better' generally?

Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 23, 2022, 01:24:43 am
Ohhh boy, Ohhh boy...

     Ok, currently, you pixel writer and geometry unit runs at 100MHz.  Let's call this a limit of the lower end FPGAs and they coding style architecture for now.  Right now, because we support less the 8bpp, every time we want to write a pixel, we first must read a byte (or in our case we read 32bits), edit the bits we want to draw on, then write the newly edited byte.

     Cheap optimization option 1, pipeline the read pixel through one of my DDR3 read ports, stuffing the write pixel command inside my 'read vector' feature, taking that vector and data output generate a new write data in a new DDR3 write channel.  This piping of the write-pixel command means our writ pixel module isn't waiting for a read to come back to edit, then write data out once ready.   This would probably increase pixel write speed by 2-3x and still maintain 100% backwards compatibility and still support the existing write pixel collision counter.

     Cheap optimization option #2, get rid of 1bpp, 2bpp, 4bpp support all together for writing pixels.  This means we loose the ability to paint pictures on anything less than 8bpp, 16bpp, or 32bpp screens.  This should increase pixel write speed by 3-5x, but, we will hit a hard limit of 100 million pixels a second but generally achieve only around 75-50 million pixels a second.  Since we no longer pre-read the memory address where we are painting pixels, we no longer have a write pixel collision counter.

     Proper optimization method #1.  Our DDR3 right now runs at full speed only at 128bits wide in the 100MHz clock domain.  In each 128bits, we have 16 8ppp pixels, 8 16bpp pixels, or 4 32bpp pixels.  This means to get the highest pixel writing speed in 8bpp mode, we need to fill 16 sequential pixels each 100MHz clock.  This means our geometry unit needs to change how it works.  The best way to describe this is when we request like a triangle, we first need to generate a rectangle box address area which the triangle fits inside containing the width rows padded to 128 bits and the columns padded to 128 bits.  Next, for every 100MHz clock, we go through each 128bit chunk, and with 16 parallel running pixel shaders, we decide which pixels get filled or not.  Compared to our old drawing routine, we get the ~4x of optimization technique #2 multiplied by 16 pixels, meaning we get a 64x speed increase over your current pixel writer.  We are beginning to enter the realm of a simple 3D accelerator and with an added texture reader prior to this writer, with proper design, and maybe a second DDR3 chip for a 256bit wide bus & 128x speed, we will pass the first Sony Playstation in rendering capability.

Now, as you can guess, though we might use the same geometry coordinate to initiate the drawings for this optimization, the geometry unit core guts will look completely different for this proper optimization method #1 & #2.  It is more akin to us having a bounding box to draw inside and at each 8 or 16 pixel chunk, our 8 or 16 pixel shaders all in parallel will be answering the same question:  At this point on the screen, does my pixel fit on or inside the line's / triangle's / rectangle's coordinates? (Yes/No)  This will produce 8-16 parallel sequential pixels in one shot, every 100MHz clock.  (Note that if we are paint 1 pixel thin vertical line, yes 7 of the 8 pixel writers will say no, but the DDR3 cannot draw vertical line any faster anyways.  And if we want antialiasing, then the question is how much so and if it isn't 0% or 100%, then we need to do a pixel read and do a pixel blend.

There are others ways to handle the vertical 1 pixel wide line issue by rendering multiple objects by cached screen square blocks, but, a lot of what is needed to process that is still technically needs the engineering step of designing multiple parallel pixel shaders.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 23, 2022, 02:42:00 am
I'm starting to reach the limits of the 10M50 with LEs and want to move up to a larger FPGA.
What kind of limits?
Can you show us the utilization by entity in your compiler report...
Which main entities are utilizing most of the LEs?
How much more do you need and for what?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 23, 2022, 03:43:31 pm
Ohhh boy, Ohhh boy...

 :-[  Don't get me wrong, I didn't think it'd be a walk in the park. ;)

     Cheap optimization option 1, pipeline the read pixel through one of my DDR3 read ports, stuffing the write pixel command inside my 'read vector' feature, taking that vector and data output generate a new write data in a new DDR3 write channel.  This piping of the write-pixel command means our writ pixel module isn't waiting for a read to come back to edit, then write data out once ready.   This would probably increase pixel write speed by 2-3x and still maintain 100% backwards compatibility and still support the existing write pixel collision counter.

I'm going to need to go away and read that a few times over to understand exactly what you mean.

     Cheap optimization option #2, get rid of 1bpp, 2bpp, 4bpp support all together for writing pixels.  This means we loose the ability to paint pictures on anything less than 8bpp, 16bpp, or 32bpp screens.  This should increase pixel write speed by 3-5x, but, we will hit a hard limit of 100 million pixels a second but generally achieve only around 75-50 million pixels a second.  Since we no longer pre-read the memory address where we are painting pixels, we no longer have a write pixel collision counter.

At the moment at least, I can't see the loss of <8bpp support being an issue.  The loss of the pixel counter may be an issue later down the line, but so far I haven't needed it.  I know originally I needed support for <8bpp because of the limited block RAM in the base Cyclone IV models.  Since the move to DDR3 though, I haven't used <8bpp at all and can't see any reason why I'd want to other than to reduce workload on the host, but the host doesn't have to do much anyway with all the work you've done on the GPU.

     Proper optimization method #1.  Our DDR3 right now runs at full speed only at 128bits wide in the 100MHz clock domain.  In each 128bits, we have 16 8ppp pixels, 8 16bpp pixels, or 4 32bpp pixels.  This means to get the highest pixel writing speed in 8bpp mode, we need to fill 16 sequential pixels each 100MHz clock.  This means our geometry unit needs to change how it works.  The best way to describe this is when we request like a triangle, we first need to generate a rectangle box address area which the triangle fits inside containing the width rows padded to 128 bits and the columns padded to 128 bits.  Next, for every 100MHz clock, we go through each 128bit chunk, and with 16 parallel running pixel shaders, we decide which pixels get filled or not.  Compared to our old drawing routine, we get the ~4x of optimization technique #2 multiplied by 16 pixels, meaning we get a 64x speed increase over your current pixel writer.

Right, so we're 'quantising' the geometry unit's access to the DDR3 RAM into 128-bit chunks, and thus making it operate all of its drawing functions within boxes to make the memory access as efficient as possible?  I wouldn't have a clue where to begin making changes to GEOFF for that.  Each rendering function, be it line, triangle, quad, ellipse, will need to be aware of the bounding box it's working within I guess and when it hits a boundary, either drops to the next line down within the box and carries on (remembering to continue the shape in the next bounding box along later) or waits for the DDR3 to update before moving into the next bounding box?

We are beginning to enter the realm of a simple 3D accelerator and with an added texture reader prior to this writer, with proper design, and maybe a second DDR3 chip for a 256bit wide bus & 128x speed, we will pass the first Sony Playstation in rendering capability.

Okay, that's what I'm talking about when I mentioned guiding my component selection for the external memory. ;)  Two DDR3 chips, check.

Now, as you can guess, though we might use the same geometry coordinate to initiate the drawings for this optimization, the geometry unit core guts will look completely different for this proper optimization method #1 & #2.  It is more akin to us having a bounding box to draw inside and at each 8 or 16 pixel chunk, our 8 or 16 pixel shaders all in parallel will be answering the same question:  At this point on the screen, does my pixel fit on or inside the line's / triangle's / rectangle's coordinates? (Yes/No)  This will produce 8-16 parallel sequential pixels in one shot, every 100MHz clock.  (Note that if we are paint 1 pixel thin vertical line, yes 7 of the 8 pixel writers will say no, but the DDR3 cannot draw vertical line any faster anyways.  And if we want antialiasing, then the question is how much so and if it isn't 0% or 100%, then we need to do a pixel read and do a pixel blend.

There are others ways to handle the vertical 1 pixel wide line issue by rendering multiple objects by cached screen square blocks, but, a lot of what is needed to process that is still technically needs the engineering step of designing multiple parallel pixel shaders.

This is all very exciting after the recent lull while I've been muddling through the SD card interface and FPU.  The question is, do you have the time/desire to help out any further? :)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 23, 2022, 03:52:23 pm
I'm starting to reach the limits of the 10M50 with LEs and want to move up to a larger FPGA.
What kind of limits?
Can you show us the utilization by entity in your compiler report...
Which main entities are utilizing most of the LEs?
How much more do you need and for what?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1670707;image)

As you can see in the image above, this is a build of the latest HDL with 4 PDI and 4 SDI layers, signal tap instance for HDL debugging, 2 PSGs, FPU and SD Interface.  I'm looking at the total utilisation of logic elements - sitting at 96% currently.  Obviously the signal tap instance some resources, but it's a very basic instance with only 16 or so waveforms being monitored.  I can obviously reduce the layers from 16 down to 4 with no impact on any software projects I'm working on currently, but what I'm thinking about is the future.  What if I want to add-in a softcore processor, or we decide to ramp-up the GPU's capabilities?

I'm also starting to think about producing a custom board again for this GPU and wouldn't want to hamstring future development by limiting myself to a 50k LE FPGA which is already at 96% usage.  I know you'd be the first to tell me I should have thought bigger at the design stage. ;)
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on December 24, 2022, 12:01:59 am
I'm starting to reach the limits of the 10M50 with LEs and want to move up to a larger FPGA.
What kind of limits?
Can you show us the utilization by entity in your compiler report...
Which main entities are utilizing most of the LEs?
How much more do you need and for what?

(https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/?action=dlattach;attach=1670707;image)

As you can see in the image above, this is a build of the latest HDL with 4 PDI and 4 SDI layers, signal tap instance for HDL debugging, 2 PSGs, FPU and SD Interface.  I'm looking at the total utilisation of logic elements - sitting at 96% currently.  Obviously the signal tap instance some resources, but it's a very basic instance with only 16 or so waveforms being monitored.  I can obviously reduce the layers from 16 down to 4 with no impact on any software projects I'm working on currently, but what I'm thinking about is the future.  What if I want to add-in a softcore processor, or we decide to ramp-up the GPU's capabilities?

I'm also starting to think about producing a custom board again for this GPU and wouldn't want to hamstring future development by limiting myself to a 50k LE FPGA which is already at 96% usage.  I know you'd be the first to tell me I should have thought bigger at the design stage. ;)

Well, as you can see, the largest chunk used is the VGA system at 18.3kle.  Either go to a larger FPGA, or, go down to 1 PDI layer and cut that by ~66%, then use those extra gates for the 64x speed geo unit and run software sprite layers.  Removing tile text support and going down to 1 or 2 SDI layers only you will save over 15kle.  However, there is quite a bit to discuss about what to do and still, a larger FPGA can still offer both systems simultaneously.

The multiport DDR3 (12.5kle) is large because of all those simultaneous RW ports, but everything else is chump change.  RS232 debug / signaltap / bridget = ~0.7kle each, stereo sound = 2kle, ALU = 4.6kle (though we can do a lot more with this with regards to 3D, the FP divide is the largest single consumer here), GEO = 5.1kle.

As for the SD card, well I didn't program it but 2kle seems a lot.  Maybe a bunch of regs are stored as regs instead of being stored in a memory block.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on December 24, 2022, 12:24:31 pm
Well, as you can see, the largest chunk used is the VGA system at 18.3kle.  Either go to a larger FPGA, or, go down to 1 PDI layer and cut that by ~66%, then use those extra gates for the 64x speed geo unit and run software sprite layers.  Removing tile text support and going down to 1 or 2 SDI layers only you will save over 15kle.  However, there is quite a bit to discuss about what to do and still, a larger FPGA can still offer both systems simultaneously.

As you know, I'm going to be making a development board to replace the DECA with a Xilinx XC7A100T, so once that's done we're going to be swimming in spare LEs anyway.

As for the SD card, well I didn't program it but 2kle seems a lot.  Maybe a bunch of regs are stored as regs instead of being stored in a memory block.

Yes, it does seem a lot.  I'll add a to-do list entry for a closer examination of that module to see what's going on with the regs.  I'm pretty sure you're right though, from what I remember it was using registers for the regs instead of memory.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on January 29, 2023, 03:03:32 pm
Hi Nockieboy,

    Please test my new modified code for my VGA processor.  If it works, check with asmi to see if all the way at the bottom of the code, my `ifdef / `else - home made dual port dual clock ram will be accepted by Xilinx.  Specifically line 1359 where I have a byte enable for the write data.  Quartus gets stuck in a loop here when compiling and generates an over 1 million logic gate design, yet the original 'altsyncram' function I have further above tied to the ' `ifdef ALTERA_RESERVED_QIS ' should compile fine.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: tchiwam on February 03, 2023, 12:05:42 am
I was thinking of a 6845 6847 drop in replacement that fits in a 40pin dip600 with a HDMI/DP/Dlinkk output
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: nockieboy on February 26, 2023, 02:44:34 pm
Hi Nockieboy,

    Please test my new modified code for my VGA processor.  If it works, check with asmi to see if all the way at the bottom of the code, my `ifdef / `else - home made dual port dual clock ram will be accepted by Xilinx.  Specifically line 1359 where I have a byte enable for the write data.  Quartus gets stuck in a loop here when compiling and generates an over 1 million logic gate design, yet the original 'altsyncram' function I have further above tied to the ' `ifdef ALTERA_RESERVED_QIS ' should compile fine.

Hi BrianHG,

Sorry for the delay replying, it's been hectic.  I've compiled the project with your new VGA processor HDL and it worked fine - no issues. :-+  I'll check with asmi regarding your conditional code at the bottom of the file and get back to you.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 26, 2023, 09:02:20 pm
Hi Nockieboy,

    Please test my new modified code for my VGA processor.  If it works, check with asmi to see if all the way at the bottom of the code, my `ifdef / `else - home made dual port dual clock ram will be accepted by Xilinx.  Specifically line 1359 where I have a byte enable for the write data.  Quartus gets stuck in a loop here when compiling and generates an over 1 million logic gate design, yet the original 'altsyncram' function I have further above tied to the ' `ifdef ALTERA_RESERVED_QIS ' should compile fine.
Xilinx has it's own primitives for true dual port RAM, you can either generate a primitive via IP wizard, you can use one of Xilinx-provided HDL primitives: XPM_MEMORY_TDPRAM (https://docs.xilinx.com/r/en-US/ug953-vivado-7series-libraries/XPM_MEMORY_TDPRAM) or BRAM_TDP_MACRO (https://docs.xilinx.com/r/en-US/ug953-vivado-7series-libraries/BRAM_TDP_MACRO) First one is more generic, and can use various underlined structures to implement it, the second one explicitly instantiates a BRAM.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 26, 2023, 09:24:32 pm
Hi Nockieboy,

    Please test my new modified code for my VGA processor.  If it works, check with asmi to see if all the way at the bottom of the code, my `ifdef / `else - home made dual port dual clock ram will be accepted by Xilinx.  Specifically line 1359 where I have a byte enable for the write data.  Quartus gets stuck in a loop here when compiling and generates an over 1 million logic gate design, yet the original 'altsyncram' function I have further above tied to the ' `ifdef ALTERA_RESERVED_QIS ' should compile fine.
Xilinx has it's own primitives for true dual port RAM, you can either generate a primitive via IP wizard, you can use one of Xilinx-provided HDL primitives: XPM_MEMORY_TDPRAM (https://docs.xilinx.com/r/en-US/ug953-vivado-7series-libraries/XPM_MEMORY_TDPRAM) or BRAM_TDP_MACRO (https://docs.xilinx.com/r/en-US/ug953-vivado-7series-libraries/BRAM_TDP_MACRO) First one is more generic, and can use various underlined structures to implement it, the second one explicitly instantiates a BRAM.
The question was is it even necessary.  Take a look at my code.  I created a generic verilog array with byte write enable in place of 'not defined ALTERA_RESERVED_QIS '.  The question is will Xilinx eat the code as is?
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 26, 2023, 10:15:45 pm
The question was is it even necessary.  Take a look at my code.  I created a generic verilog array with byte write enable in place of 'not defined ALTERA_RESERVED_QIS '.  The question is will Xilinx eat the code as is?
Can you post a code snippet here? I was under impression that it's not possible to model a true dual port RAM in pure Verilog because it's not possible to write to the same registers from multiple processes.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: BrianHG on February 26, 2023, 10:35:02 pm
The question was is it even necessary.  Take a look at my code.  I created a generic verilog array with byte write enable in place of 'not defined ALTERA_RESERVED_QIS '.  The question is will Xilinx eat the code as is?
Can you post a code snippet here? I was under impression that it's not possible to model a true dual port RAM in pure Verilog because it's not possible to write to the same registers from multiple processes.
Already done...
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4668115/#msg4668115 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4668115/#msg4668115)
It's the last module 'BHG_VIDEO_DPDC_BRAM', starting at line 1319, right at the bottom.
Title: Re: FPGA VGA Controller for 8-bit computer
Post by: asmi on February 26, 2023, 11:01:13 pm
Already done...
https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4668115/#msg4668115 (https://www.eevblog.com/forum/fpga/fpga-vga-controller-for-8-bit-computer/msg4668115/#msg4668115)
It's the last module 'BHG_VIDEO_DPDC_BRAM', starting at line 1319, right at the bottom.
That's not a true dual port RAM, as it only writes into one port and reads off another one. Xilinx calls that Simple Dual Port RAM, and there is a module for that too: XPM_MEMORY_SDPRAM (https://docs.xilinx.com/r/en-US/ug953-vivado-7series-libraries/XPM_MEMORY_SDPRAM), but your code might just work as-is. Leave it like that for now, once nockieboy completes the port, he can verify if it works or not.