Update time!
Sorry, I completely forgot to post updates! (again…)
Ever since the last update I’ve been working on FPGA stuff to get the video output of my mainboard up and running and I guess I’m slowly getting there.
After the little experiments with my DPI LCD I know more or less what to expect when it comes to resolutions and video timings. The big blocker was the lack of memory to buffer at least one field of each frame. It made the bridge between the 2 clocking regions very tricky and at some point it stopped me from progressing with my design.
The next logical step was to look into the available RAM options. First, I wanted to try the DDR3 on my Artix 7 Development board, as it would provide plenty of memory at a sufficient speed.
Getting DDR3 working is not trivial, though. I figured that out the hard way after 2 evenings of fighting with vivado’s memory interface generator IP. That “experience” forced me to take a step back and to reconsider things.
At that point I knew already that I would like to use a cheaper FPGA for the final board and it made no sense to waste time with proprietary Xilinx IP, so instead I was looking into the RAM options with my FPGA of choice, the Trion T20. It didn’t take a lot of reading in the datasheet until I realized that the only package I can economically design a PCB for (0.8mm pitch) does not have a hard DDR3 controller & as I’m by far not experienced enough to write a soft DDR3 controller, that option was out of the game.
Instead, I chose a SDR SDRAM for the framebuffer, the IS42S32400F-6BL to be precise. Compared to DDR3 it mostly has drawbacks: it’s slower, it’s more expensive, SDR RAM is kinda outdated and on top of that it requires more pins. BUT it’s considerably easier to drive and it makes PCB layouting much simpler with less strict timing & impedance requirements.
You can imagine the next step…. Custom development board time!
View attachment 31269View attachment 31270
This one was like a 2-weekend project and it should include everything I need to continue with video processing. I tried to check all the boxes regarding compatibility with my existing PS2 mainboard while making it flexible enough to be reusable for future projects. The main features are:
- Trion T20F256
- IS42S32400F-6BL SDRAM + QSPI flash for the FPGA config
- All power regulators included, only requires 5V to operate
- 2 80 pin mezzanine connectors with as many IOs as I could fit -> great for custom shields
- 1 bank is selectable between 1.8V and 3.3V (mainly for the GS video interface)
- Status LEDs, 1 user button
- Programmable via JTAG (QSPI flash too)
- The BOM of the whole board (including PCB) is less than my old Artix 7 A35 FPGA (just the chip!!)
SDRAM length matching is a bit sloppy, KiCAD kinds sucks in that regard and I just could not be bothered to waste a lot of time there (especially with 56 signals…). So, all lengths are within ~7mm (ignoring the propagation speed of inner vs outer layers). Should be alright for the speeds I need, but for the next revision I should improve it.
Of course, I also designed a shield for interfacing with my PS2 and the LCD later & a little JTAG programming adapter PCB for the FTDI module:
View attachment 31271View attachment 31272
Assembly went smooth, during testing I had to solder three little bodges, though. The main issue was the RST. Short version: Efinix recommends to use a voltage supervisor with manual reset input to drive the reset pin of the FPGA at powerup. The RST signal is also required for JTAG and the application note says to connect all reset inputs to the manual reset input of the voltage supervisor. Doing that will delay all reset pulses from the debugger by ~200ms, which made JTAG programming impossible. I had to connect the JTAG RST to the FPGA directly and solder the voltage supervisor in parallel to handle startup, that fixed it.
With the hardware part done, I can focus on the video interface again. First step is to design a proper framebuffer as the heart of the scaler. That was done in the last 2 weeks over Christmas.
The Efinix SDRAM controller IP did not convince me and making things from scratch is fun, so I decided to design one myself as a learning exercise and to get some experience. I would not call the Efinity IDE and documentation beginner friendly, so it was a good opportunity to experiment with the tools too. There’s not a lot of features compared to vivado; no wizards, no templates, no simulator, no schematic view, no block designs; BUT it’s a million times faster, the entire flow from synthesis to bitstream takes just as long as the synthesis in vivado…I'm still using vivado for functional simulation, though.
Back to the SDRAM: The state machine was straight forward, but it was my first-time debugging timings. In the end I got it working at 150MHz, but at the max of 166MHz the controller just reads garbage still. 166MHz should be achievable according to the timing analysis, but maybe I just have to recalculate my timing constraints to find the culprit.
Anyway 150MHz should be plenty already, in the simulation the controller hits ~400Mbyte/s write and ~300Mbyte/s read MAX when there are no rows to open/close. The video stream should require about 160MByte/s in the worst case.
The controller is optimized for R/W speed over latency and I tried to make it as simple as possible without sacrificing too much of the bandwidth. There are no fancy functions like command scheduling (overlapping, canceling,...) or delaying refresh cycles, only one command at at a time. It does do 8-word read/write bursts, though - to maximize the bandwitdh (that's 32 bytes per command). On top of that it avoids auto-precharges and insteads keeps track of the open rows to minimize overhead. So far the controller is passing all my test cases in simulation (with some generic SDRAM memory model).
My goal is to make the SDRAM controller as stable as possible, as it is one of the core blocks of the scaler & maybe I can still shave off some clock cycles here and there to make it faster.
I will work on that the next week and then I will continue with the other blocks. Missing would be the video input and output blocks (kinda defined already from my experiments), the read/write scheduler for the framebuffer (probably the most complex block), the scaler and the block to write OSD info into the framebuffer. Still a LOT of work ahead!