BX portable game console | project collaboration


That’s great!

Yeah I noticed that afterwards, I guess that’s the good thing about FPGAs, these kind of mistakes are not hard to solve :slight_smile:.

The LCD screen is refreshing at 50Hz. It would be best to be able to send the entire frame faster than that so we avoid the tearing effect. This requires sending the bytes at more than 10Mhz. So far I didn’t achieve this speed, my FPGA/Verilog knowledge is limited.

Update on the prototype board, I have received the components and the PCBs should be here this week (fingers crossed).


Hi @Fabien, I am struggling to get your ili9341 working reliably.

The first problem is that it does not start up reliably. That seems to be because you are only setting nreset for one clock cycle. I added a delay_ticks of ms5 to the RESET state, and that seems to have fixed that.

Another problem is the colours. The initialisation sequence includes 0x36 (MADCTL) 08, which sets the colour mapping to BGR. You had set colours in RGB order, so I reversed those. Also you were setting the G value to 5 bits, not six when it was set (6’b11111 not 6.b111111) which messed up colours with green in them. So I fixed that. I have left it as BGR.

There is also the problem that the image is horizontally and (at least with my screen orientation) vertically flipped, so I I am changing things. so that xpos and ypos count down.

I also found a problem in @gundy’s top.v module that stopped buttons working when i2c was not defined, so it now sets i2c_iomem_ready to i2c_en not 1, when i2c is not defined and similarly for gpio, and that fixed that problem, so I can now use button input without having to include the i2c code.

The final (I hope) problem is that it appears to sending each 16-bit pixel twice, so that the screen is stretched vertically and you only see half of it. I am currently trying to understand the complex interaction between all the state variables to try to see what is going on., and will look at what the maximum rate that we can send data at, at the same time.


I have a feeling that may be because the VGA screen is actually 480 pixels deep (although we halved the pixel clock, we’re still drawing the same number of lines)… so there’s some code to halve the Y value coming from the VGA sync generator. If the same code has been moved across to the OLED module then it might help explain what’s going on.


This is my second Verilog module ever, so it is probably worth a complete re-write…


I have only been writing Verilog since earlier this year and most of my early attempts were awful, and I still struggle. It is hard.

I still haven’t quite got things to work. This is my closest attempt:

Battery operated, and with working button control:

@gundy was right about the problem with the vertical stretching. I thought I had investigated that and discounted it, but I was wrong. I got the width parameter wrong in the above build. Unfortunately builds take a long time on my rather slow Linux box and for most of them, the screen does not work for reasons I don’t yet understand. Also some of them fail to route. So the development process is very slow.

I am very close to having a fully working version but can’t quite get there.

Your code is mainly clear and good - there just seem to be minor problems with it.


The boards are here!

It looks and feel pretty good, the screen and audio are working (I didn’t test the buttons yet).

In this proto version the screen mounting is a bit goofy:

Also the TinyFPGA with female and male headers is higher than the battery holder. Which means that when the board is on a table, it is resting on the TinyFPGA board. I’m not sure how to fix that.

The cost (without the screen and TinyFGPA):

  • PCBs : 62,23 euros
  • PCBs import taxes: 29,5 euros
  • Parts (mouser): 121,23 euros

Total for 5 boards: 212,96 euros
Total for 1 board: 42,5 euros


Schematics: https://github.com/Fabien-Chouteau/field-programmable-game-console/blob/master/proto/rev-A/FPGC_rev-B_schematics.pdf


Looks good. I would like one please. How do we pay you for them? Are you planning to assemble them?

On my hand-soldered one, I found that it was easy to accidentally press the reset button on the TinyFPGa so I connected some spacers to the PCB to protect it.


Put me down for a board too - I’m happy to assemble myself if it’s easier :slight_smile:


We can use Paypal. Everyone interested can contact me direct message for the details.
(I only have 4 boards available for now)

I don’t really have time for that. It is very easy though so don’t worry.


Quick update: I’ve finally managed to get a version synthesised that has video, audio & gpio all working… and even managed to just squeak in at 17.1MHz timing… it’s been quite a fight to get it all to fit though, and naturally some things had to be sacrificed…

For one, the LCD CS, RW and backlight enable pins were all sacrificed - they were essentially constant drivers anyway.

On the audio side of things, some sacrifices were made:

  • it’s still 4 channel, and there are still 4 available waveform generators (square, saw, triangle, noise), but…
  • each channel’s waveform generator now produces only 6-bit output (down from 12)
  • there is no ring modulation or sync support
  • channel (and global) volume controls are now 4-bits instead of 8.
  • pulse-width selection for square waveform is now 4-bits instead of 12.
  • the phase accumulator width has been trimmed, and with it the sample rate (from 1MHz - which was way overkill anyway), to 62500Hz.

It’s not great, but it could have been worse :slight_smile:

On the video side, fewer sacrifices were made, but the code is now incompatible with the VGA sync generator as I made a few changes to simplify the code somewhat. Turns out there were lots of savings to be made just by rearranging the way things like hsync/vsync worked.

I’ve also trimmed the number of available colours from 256 down to 64. (RRGGBB instead of RRRGGGBB). As well as allowing me to save a few gates, I believe this also allowed me to create a better palette with better neutral greys.

I’ve also added a raster interrupt register, that allows one to trigger an interrupt based on the y position currently being rastered out. This means that, in theory, it should be possible to set an interrupt at a particular line, and do things like swapping out the palette, or sprite pointers, or a bunch of other fun things :slight_smile: (eg. if you want more than 8 sprites, or more than the standard 16 colours you should be able to swap to a new set every 16 lines if you can process the interrupts fast enough)… Actually, this should allow you to do things like have multiple non-scrolling windowed areas on the screen at one time too.

Although the demo below doesn’t look much different to last time, there’s been a surprising amount of work that’s gone into it :slight_smile:

Now it’s time to start working on some C and assembly code again :wink:



I look forward to playing the gateroids game.

I have been looking through the beginning of the Wikipedia article on the best games ever, wondering which ones we can recreate.


I have received and assembled my board, and here is Pacman running on it:


I bought one of our rivals to see how it compares. The screen is not as big, but it is cheaper and has a volume control, built-in speaker, and audio and AV out. And 50 games.


I’ve received my board now too - just need to order a display for it and I’m sorted :slight_smile:



Here’s a (mostly) built FPGC sitting amongst a bunch of its relatives at the Syntax '18 demoparty in Melbourne :slight_smile:

(Time was too tight to get a ‘demo’ ready unfortunately)…



… and the proper display arrived today… :heart_eyes:

It took a little while to figure out the correct commands to get the lcd display the right way up, but I got there in the end.

I am currently running without audio as I couldn’t get things to fit. I’ll keep prodding away at it.



So today I found out that Clifford Wolf had done something wonderful, and added some major, major improvements to the mainline version of nextpnr. As well as speeding up routing time for the current iteration of the Game SoC from hours (or not at all) to seconds/minutes, it’s allowed me to finally get things to work with almost everything that I wanted in there.

This means that both audio and video fit! With the pin constraints for the FPGC!

As well as the eight standard sprites, I also managed to squeeze in a couple of extra “bullet” sprites (white 2x2 rectangles which are X/Y positionable), and a “horizontal interrupt” - ie. an interrupt that’s triggered when the raster hits a given scanline.

The horizontal interrupt has been interesting. I’ve been experimenting with “chasing the raster” – doing things like repositioning sprites when the raster hits a certain point. This allows for more than the 8 sprites (or two bullets) to be on the screen at once. It seems to work okay, although not particularly well in C code, nor with the standard ASM IRQ handler which takes a long time to save and restore all of the registers (more time than a single line takes to raster out :frowning: ).

I’m pondering maybe adding some more Q registers so I can do a super fast IRQ path for certain effects code.

It feels nice to be able to jump back up a layer again. Hopefully soon I’ll be able to start making some progress with the C code again.

Oh, my buydisplay LCD seems to have a few issues with the power-on init sequence - it often seems to just start up and stays fully white. I might be dreaming it, but it seems to happen more when it’s cold. I’ll try to dive into what’s going on there at some point too.




Feels like having an hardware upgrade :slight_smile:

Do you mind sharing binaries so that we can try on our FPGC?
I don’t have nextpnt yet.


Yes, I get this and other effects (screen corruption) as well. I often have to start games by pressing reset. They start more reliably then. One thing that definitely makes a different is how charged the batteries are. It works more reliably with more volts.

I currently have about 3 nearly playable games: Pacman, Tetris and Adventure, but they all have issues and are incomplete, with Pacman being the most playable. The SD card menu allows them all to be on an SD card and selectable from the menu, reverting to the menu on reset or power-on. Starting games from the SD card via the menu, again seems more reliable than starting them from power-on.

I am currently programming the Adventure Atari 2600 game without “chasing the beam” as I thought I would wait for you to get that working. It is still using the BRAM-only SoC and direct driver of the ili9341, but with some hardware assist.

I built nextpnr a month or so ago, but haven’t used it yet. Sounds like I need the latest version.