Wednesday, October 19, 2011

Life - One step forward, two backwards

The past couple days I've gained a little ground, then lost a bunch. I haven't had a ton of time to work on this due to other real life obligations, but I have major changes coming so I thought I'd update.




VGA
The VGA module I wrote for my Hack SoC wasn't sable enough for this project. I knew the driver had issues, but not as systemic as I had thought. I originally wrote it in VHDL based on a book I bought, and with a ton of tweaking I was able to use it for Hack.
I thought I'd be able to get it to work for this, but after 6 hours of fidgeting with it, I gave up. I started looking for other modules with different timing than mine, and I came across Steve Chamberlin's (of Big Mess of Wires fame) module. It has far less resolution than my module (less than 50%), but for this project it doesn't matter. I was able to modify my module using his counter timing and resolve much of all issues. I can render individual game boards! In the picture a single frame 16x16 board is repeated a bunch of times horizontally and vertically.

ISim
I couldn't get ISim to work properly with some of my logic. Many of my signals were displaying as unknown ("X"), even when I could verify that the synthesized version in hardware was working. For instance, the above mentioned VGA module was always outputting "X" for both hsync and vsync, yet I could get my monitor to sync correctly.
From what I can tell, ISim doesn't default the values in registers to zero, but the fpga does. I fixed this by declaring 'inital' blocks everywhere, but I don't know if this is a proper solution.

Memory design
This is by far the largest issue I am having, and still the most confusing. In the version I posted last time I use large register arrays to store the Game Of Life data. I knew at the time that I would have to rewrite parts of it when I wanted to run in SRAM, but I didn't expect it to cause any other issues.
I wanted to prevent the Game of Life from changing the data underneath the video render module, so I created an additional 'video' register array. When the video render module was in the vsync blank period, it would copy the contents of the appropriate bank to the video array.
This would, in theory, allow me to run GoL at full speed and still display something useful.
The problem with this design is that I had to compromising basically everything in order to implement it.

Issues:

  1. I had to clock the core GoL code to the slower video clock of 25Mhz. Accessing registers in two different clock domains would cause weird issues, if it would even synthesize. This brought GoL from 305 iterations per second to 127.
    • Obviously faster is better, so this change is bad.
  2. I had to modify the core GoL code to not modify its register banks during the vblank period.
    • Additional slowdown, difficult to calculate actual iterations per second
    • Explicitly made GoL aware of details of rendering. This isn't needed for GoL to run, so this just makes things harder to follow.
  3. This approach didn't even work. The simulator shows that the video registers are being updated, but nothing displays in the real world. 
    • I know from experience that the video register array render portion works, so something strange is happening during the copy. 
    • I lost some jumper wires, and I can't easily attach my logic analyzer without them, so what is happening in hardware is a mystery. 

I don't know 100% that the issue is related to copying working bank to video bank, but everything seems to point to that. Because ISE isn't erroring and I don't see anything obviously wrong, I must be violating something in some subtle way. I doubt I'll be able to locate exactly the cause of this, so I have a new plan!

Rewrite GoL to use BRAM instead of register arrays. If I use a true dual ported bram I can basically eliminate issues 1, 2, and hopefully 3.
It should also make it easier to port it to the external SRAM in the more final steps.

No comments:

Post a Comment