Experimenting with TG68

Part 3 – Writing to the framebuffer

The previous instalment of this project saw a working VGA framebuffer being filled by an automated hardware process.  Since then I’ve managed to get the TG68 processor running a program from a blockram-based ROM, and writing to the DE1 board’s SDRAM.

The framebuffer being filled by the TG68.

The memory map for the TG68 looks something like this:

  • $000000: ROM (at the moment the ROM code just runs sequentially from $000008.  Will eventually need to put an interrupt table in place and move the code elsewhere.)
  • $0FFFFA: A couple of variables
  • $100000: The frambuffer
  • $7FFFFE: The initial stack pointer

For the ROM I use an M4K blockram, with initial contents specified with an MIF file.  To create the MIF I first assemble the code with Easy68K, then convert the S-Record file it produces to MIF format using srec_cat, like so:

srec_cat in.S68 -o out.mif -mif 16

The ROM program currently backfills the screen, then draws random rectangles in an incrementing colour.  The display is Hi-Colour (5-6-5) bit, which is dithered to fit the DE1’s 4-bit-per-gun output.

The complete project, for anyone who’s interested, can be found here.

Currently the fill-rate is pretty lousy since only a single 16-bit word can be written per slot.  I need to add a writethrough cache of some kind, preferably one capable of merging successive writes to a single burst.

Possible future plans for the project include:

  • CPU cache – separate instruction and data.  Just one burst (64 bit) initially.
  • Writeback cache – to allow (a) the CPU to continue working while a write is in progress, and (b) to gang sequential writes into a single burst write.
    Sprite controller – just one sprite for mouse pointer.
  • Multiple screenmodes.
    •  8bit
    •  lowres
    •  scandoubled?
    •  PAL?
  • Sprite controller.  Just one sprite, for a mouse pointer.
  • A colourtable for indexed modes
  • VBlank interrupt
  • Interrupts in general
  • SD card interface
  • PS/2 controller
  • Hardware registers for framebuffer address, sprite position, PS2 data, etc.
  • Sound

Experimenting with TG68

Part 2: A VGA controller

My first experiments with the TG68 processor didn’t involve RAM at all – it simply ran from a tiny hard-coded ROM and poked an incrementing counter into a hardware register.  In preparation for getting the processor working from RAM I’ve been experimenting with the SDRAM controller from the Minimig Project, and having combined it with the simple VGA timings generator used in the Chameleon Pong core, I now have a working VGA framebuffer

VGA Framebuffer in operation

Not much to look at, I know!

The DE1 Minimig’s SDRAM controller runs on a fixed 16-state cycle, using 4-word bursts, so it can move a maximum of 64 bits per round-trip.  I use the same clock for SDRAM and VGA master clock, and at 640×480 pixels, I need one pixel every 4 clocks.  I’m using 16-bits per pixel (5-6-5 hi-colour), so the display needs 4 words or 64 bits every 16 clocks, which means while data’s being displayed it’s saturating the SDRAM controller.

Luckily there are various tricks we can employ to provide extra bandwidth.  The most obvious one, using a smarter, more dynamic SDRAM controller isn’t actually ideal, because generally speaking the smarter a controller is the less predictable its response time will be.  The other reason I didn’t want to toss out the controller completely and start again is that I wanted to be able to bring any improvement I made to the controller back into the Minimig project.  (The third reason, of course, is that writing a good SDRAM controller is *hard*!)

SDRAM is organised into banks, and the chip used in the DE1 board uses four of them.  These are more-or-less independent, so it’s possible to start a read on one bank while a read to another is still taking place.  This means that it’s possible to add a second time-slot to the SDRAM controller, 180 degrees out of phase with the first.  All I have to do is ensure that I don’t allow the same bank to be accessed from both slots.

I split the RAM up such that adjacent 4-word bursts would come from different banks, like so:

|----------- bank 0 ---------|--------- bank 1 ----------|--------- bank 2 ----------
  word0  word1  word2  word3  word0  word1  word2  word3  word0  word1  word2  word3
 | 0  1 | 2  3 | 4  5 | 6  7 | 8  9 | A  B | C  D | E  F | ...

Because both the reading and writing processes in my design would be accessing memory sequentially, arranging the banks this way should prevent either process being held off for more than one slot.

The other thing I needed to take care of was refresh cycles.  Since both slots need to be held off while a refresh happens, I needed to prevent them happening while data was being displayed, so simply arranged for them to happen at the end of each scanline.

For anyone that’s interested, the demo project can be downloaded here.

There are still  a couple of timing glitches, but if you see them, pressing the reset button (key0) a few times should clear it.  The fill rate isn’t great, but that’s because writes are currently not happening in burst mode, so only one word at a time is written.  This means it takes at least four full frames to write to the entire screen.

The TG68 processor isn’t actually involved in this part of the project – instead there’s a simple hardware process filling the frame.  The next stage will be making the TG68 draw something.

 

GameSupport music example

Here’s a little demo program written in AMOSPro demonstrating how to use the “GSTrack Loop” commands from the GameSupport extension.  For this demo I used Yannis Brown’s cover of Tequila Slammer, found on Aminet.  When the program starts up, just the first two patterns in the module will play repeatedly, until you press a key, at which point the rest of the song will play.

As the song plays, the demo will report on any “command 8” events reported by the playroutine.  Command 8 is unused in ProTracker, so it’s a useful method of synchronising program events with the music.

Any time you press the space bar, the program will play a “jingle” (the last pattern of the song, in this case), then pick up where it left off.

If anyone finds this interesting or useful, it can be found here:

Download in ADF format

Download in LHA format

Pong revisited

Creating a Pong-style game seems to be a “Hello World” style project for FPGA developers, and was one of the first projects I attempted when I started experimenting with VHDL.

The platform for this project is the truly brilliant Turbo Chameleon 64 cartridge.  For anyone who’s not familiar with this piece of kit, it’s an FPGA device that can be used either as a standalone miniature computer, or as a cartridge attached to a Commodore 64!

Originally designed to provide a VGA output for a Commodore 64, the project’s grown and while it performs that initial task admirably, it has a near flawless emulation of the *entire* C64, provides SD card emulation of disk drives, REU emulation and even freezer cartridge emulation!

It can also run other cores, and has suffiicent flash onboard to store 16 of them.  So far, cores are available to emulate the C64, 48K Spectrum, Amiga (Minimig), and also a neat Game of Life core which makes use of the parallel nature of FPGAs to calculate an entire row of cells at a time.

There’s also a hardware test core, which I used as a starting point for this project.  To try it out, just use the Chameleon’s Chaco program to upload the .rbf file into a free slot, then launch the core from the Chameleon’s own menu.

When it starts up, it will launch into a game between two computer-controlled players.  To take over from one of the players, just click the left mouse button on an attached PS/2 mouse.  A second player can use a mouse attached to the keyboard socket.

The reset button resets the scores, and the menu button exits the Pong core and returns to the Chameleon C64 core.

Click here to download full source and binary.