BX portable game console | project collaboration



The flickering might be because I changed the timing to 60Hz refresh and tweaked the front & back-porch parameters so that the display sat nicely in my screen. The timings that I based things on were here:


My ultimate goal was to get it working through a VGA -> HDMI adaptor that I have (which, in turn, is so that I can record the output directly)… The adaptor claims to work at 640x480@60Hz (but not the original 72Hz). I haven’t had any luck with it yet, even at 60Hz, even though the VGA input on the TV works fine. Your experience suggests that my 60Hz values may still need some tweaking.

In the mean-time, to get things working, you could always switch back to the original 31.5MHz PLL & screen parameters.

The sprites are weird though. I have no idea why they wouldn’t be working. :frowning:


I’ve updated my code now to use your single 16MHz clock idea Lawrie… Output is now 320x240(480)@75Hz, with the 16MHz pixel clock - and it seems to be working well on my TV. Still doesn’t work on the HDMI adaptor, but I’ve pretty much given up on that now.

It turns out there must have been some clock issues before, because some of the “tearing” that I had at the edges of tiles now seems to be gone.


Thanks. The flickering is gone and the sprites are there, but there are some artefacts on the left of the screen. I tried it through my VGA to HDMI adapter, which is alsio a bit hit and mess. I got the occasional flash of a screen.


I do have an alternative input device, which would take fewer resources:

It is an old PC 15-pin gamepad. Unfortunately the DPad doesn’t work as it is analog, but you can use the buttons. The adapter is off ebay.


You’ve just reminded me that I had a couple of these that came with a mini SNES… The connectors look the same as the nunchucks. They might work too.

ETA: what protocol does your adaptor use?


It is just simple buttons (apart from the analog dpad) so should work with my gpio button (with internal pullups) implementation.


Yes it looks like most Nintendo controllers are i2c and use address 0x52 - https://github.com/dmadison/NintendoExtensionCtrl/blob/master/src/controllers/SNESMiniController.cpp


I have your stuff merged in with my tiny_soc repo now, and can build your example with .v files and a Makefiile to select which modules to use. My build turned out bigger than yours because the modules were presented in a different order. Strangely my VGA monitor seems to work with some builds and not others. With that build, the signal was intermittent. I reordered the modules to what I think is the same order that your includes present them, and that build worked, but still turned out to use more PLBs than yours.


The idea of non-deterministic builds bothers me. I guess as long as arachne-pnr is using random seeds there’s probably not much we can do about it. Maybe when we get to the pointy end we’ll need to start sharing seeds that work :slight_smile:

I’m a little surprised that changing the build setup would make much of a difference. Maybe yosys optimises things differently if it has the whole model in a single file? I guess that might be a question for Clifford.


We could try nextpnr some time. The Yosys initial and final wire lengths were different for the different module orders.


For some reason, I can’t get nextpnr to work here. It just hangs on startup.

It might be something to do with the fact that I’m running it in a VM - I’m not sure - but if I run strace on it I get an essentially infinite trace of failing futex calls…

futex(0x7f5194a443e0, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f5194a44364, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1601, {1537526156, 904489000}, ffffffff) = -1 ETIMEDOUT (Connection timed out)
futex(0x7f5194a443e0, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f5194a44364, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1603, {1537526156, 910666000}, ffffffff) = -1 ETIMEDOUT (Connection timed out)
futex(0x7f5194a443e0, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f5194a44364, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 1605, {1537526156, 916621000}, ffffffff) = -1 ETIMEDOUT (Connection timed out)

I’d like to dig a little deeper before I raise any issues against the project, but other stuff has taken priority so far.


ETA: I just fired it up in gdb, and the stack trace looks like it’s deep in python land - which is way above my pay grade :-):

#0  pthread_cond_timedwait@@GLIBC_2.3.2 () at ../sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S:225
#1  0x00007ffff6e0047f in ?? () from /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0
#2  0x00007ffff6e00969 in PyEval_RestoreThread () from /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0
#3  0x00007ffff6e2067b in PyGILState_Ensure () from /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0
#4  0x00007fffbc33974f in ?? () from /usr/lib/python3.5/lib-dynload/readline.cpython-35m-x86_64-linux-gnu.so
#5  0x00007fffc56953e1 in rl_initialize () from /usr/lib/x86_64-linux-gnu/libedit.so.2
#6  0x00007fffbc33ad96 in PyInit_readline () from /usr/lib/python3.5/lib-dynload/readline.cpython-35m-x86_64-linux-gnu.so
#7  0x00007ffff6e3e011 in _PyImport_LoadDynamicModuleWithSpec () from /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0

... another ton of entries ...

#54 0x00007ffff6e1eeab in PyRun_SimpleStringFlags () from /usr/lib/x86_64-linux-gnu/libpython3.5m.so.1.0 
#55 0x00000000006d2d89 in pyinterpreter_initialize () at /../icestorm/nextpnr/3rdparty/python-console/modified/pyinterpreter.cc:131


Could you put your graphics stuff in a resources folder for the audio_song_player. It is useful to look at it and perhaps reuse some of it. I am particularly interested in how you deal with transparency in sprites.


I’ve just been pondering that it might be a good time to do a bit of a shuffle around and tidyup and do things like take on board some of your build improvements, so I’m happy to do what I can to help.

I’m a little unsure what you mean though - in terms of exactly what you’d like me to move and to where.

In terms of the transparency question - it’s handled in the assignment of the signals in video.v[h]:

  assign vga_r = video_active && ((sprite_read_data && sprite_r) || (!sprite_read_data && texture_read_data[0]));
  assign vga_g = video_active && ((sprite_read_data && sprite_g) || (!sprite_read_data && texture_read_data[1]));
  assign vga_b = video_active && ((sprite_read_data && sprite_b) || (!sprite_read_data && texture_read_data[2]));

video_active signifies that we’re in the active zone of the screen (ie. x>=0,x<320,y>=0,y<240). Anything outside of here is black.
sprite_read_data indicates that we’ve got a pixel ‘set’ for a sprite. It’s straight from the sprite memory read_data line. The sprite memory address line is chosen based on priority order - if multiple sprites are active at the same x/y coordinate, the lowest-number sprite wins.
sprite_r/g/b are the colours for the sprite from it’s configuration register
… and if we don’t have a sprite pixel to display (!sprite_read_data), then display the texture data underneath it.

There are downsides with this approach. Sprites overlapping the tilemap works fine. Sprites overlapping other sprites, not so much. This is because you’d really need to be able to read data from multiple sprites at the same exact pixel location in one clock cycle, which just isn’t possible with a single block of RAM.

I’ve thought about ways to make this work - for example, reading all sprite data for the next line during horizontal refresh, but most of the ways I can think of would make the logic quite a bit larger and more complex :confused:



Sorry, I did not make myself clear. My request was just for your image files, GIMP files and Tiler files in a resources directory like you did in your mode7 8bit example


Okay, no problems. I’ve created a resources folder and pushed the update.


For transparency, I had not looked at your sprite implementation and assumed that you were still doing what you said in the README file:

8 16x16 sprites @ 8 colours (4bpp; high bit = transparency).

and I wondered how you were creating that. As I understand in now, a sprite is effectively a 1-bit monochrome image and a single colour for the whole sprite is set from code.

I did not expect an answer from you today as I thought you would have gone to bed by now.


In terms of restructuring, I think moving to .v files and using something like my make files is a good idea.

I think moving common C code to something like my libraries folder is a good idea, as is moving the firmware files to their own directory.


Your top level file is beautifully clean and simple, but only works for immediate writes. I am interested in how you are going to support reads. We may or may not need support for extended writes, i.e. ones that take more than one clock cycle. I am using Clifford Wolf’s spi master code for my OLED screen and that waits multiple clock cycle before it sets iomem_ready. Supporting that seems to complicate things a bit. My top level file was based on Luke’s template and is a bit of a mess, so don’t copy that.


And we might start to need defines like I have in my top level module if we support different options, like different input devices or different screens (e.g. for a portable version). icoSoC uses a SoC generator approach for that with configuration files and a generated top level module. That is probably going too far if we want to keep things simple.


3/4bpp sprites were my original intention. I was planning to take the extra values from using the 4th bit, and pick one as a transparency marker. I may still play with that as an option. It would severely limit the amount of memory available for sprites though - both because of the extra bit depth, but also because the idea of a ‘colour’ register no longer makes much sense.

Hmmmmmmmm… unless… maybe that extra bit could also be used to encode a specific colour that could be swapped out per sprite and controlled via the register. 0xf = transparent, 0xe = pick colour from control register perhaps.

Thinking about it in pacman terms, you’d ideally want to be able to re-use the ghost sprite images for different ghosts, even though they’re different colours.

I guess we can always make sprite bit-depth and options configurable at build-time.

Anyway, all of that said, I’d like to have things running with your i2c code before getting too carefree with PLB’s and BRAMS. Once all of the basic bits are in place, then the real fun of cramming in all the extra “want-to-have” features begins :slight_smile:

… also, yes, I’m off to sleep now :slight_smile: