Day 3: Free-running a Motorola 68K

So today I set about getting a Motorola 68K up and running on my FPGA board. My goal was relatively simple: just get an M68K working, fed dummy 0 values on its data pins and tying the top two bits of its output address pins to a pair of LEDs. As the M68K runs, it should cycle through its entire address space trying to read instructions from the data bus and cause my LEDs to blink at some regular interval as a result.

Now, I’m a lazy guy, and I didn’t want to have to reimplement a whole chip from scratch in Verilog if someone else had already done the work, so I ended up going with the FX68K. It’s pin-compatible and cycle accurate to the original M68K so it seemed like a good pick.

The first thing I did, after dropping the files into my Quartus project, was put together a simple wrapper module (I just called it CPU_fx68k). Its only real job is to take an input 50MHz clock and do the clock division work. Note that the FX68K needs three signals for proper cycle operation: the clock signal (my 50MHz clock), but also phi 1 and phi 2. The idea is that the CPU will divide a single CPU clock cycle into two phases, and phi 1 and phi 2 will signal these phases to execute (and should never be asserted at the same time). Therefore in my case this gives a maximum speed of 25MHz, the result of interleaving phi 1 and phi 2 on my 50MHz clock. In my case I will actually be running it at 12.5 MHz, the result of dividing my 50MHz clock by four (for every four clock cycles, phi 1 will be asserted on the first, phi 2 will be asserted on the third, and on the second and fourth clock cycles neither will be asserted).

This was simple enough, it was just a simple four-bit counter register and some wire assigns for phi 1 and phi 2. My next task was to modify my reset signal generator. I already had it generating a good reset signal (I had verified this both in simulator and on hardware), but for the CPU I also wanted a cold start signal. This wasn’t very tough either, it required a bit of finagling to make sure signals lined up the way I wanted them to (I’m not sure if having the cold start signal last for one cycle longer than the reset signal would be a problem, but I made sure to eliminate the delay anyway just in case) but was pretty straightforward otherwise. Final behavior: Powering on or reprogramming the FPGA asserts a reset and cold start signal momentarily, and then from that point onward pressing one of the key switches on the board causes only the reset signal to be re-asserted (but not the cold start signal). Cool. Next task.

The next thing I did was put together a testbench for the CPU. Essentially I want to replicate the free-running test I will be doing on hardware later, but in simulation where I can watch the address pins counting up over time. Once again, this proved to be no real issue. Things mostly just worked as I expected.

That meant there was only one thing left to do: instantiate the CPU in my top module and program it onto the real thing.

So I instantiated it, wired up the necessary signals, set up some dummy values in an initial block (set DTACK to 0, de-assert any bus request or bus acknowledge lines, set input data lines to 0, etc), hit compile, and programmed it onto my FPGA.

Aaaand…… nothing. No lights. Hm.

I played around with which bits the lights were tied to, maybe they were just blinking too slowly? But nothing seemed to work. At some point I left them on 15 and 16 and focused my attention elsewhere. I did some googling online to see if maybe the readmemb commands for the CPU’s nano code ROM weren’t synthesizing correctly, didn’t get much traction on that besides reading that Quartus should be able to handle it just fine (and it wasn’t giving me any errors that would indicate it was failing to read the files somehow).

Then I saw my initial block setting the CPU’s input pins and, on a whim, decided to switch it out for an always block.

And then both LEDs lit up completely. Aha! That’s something! They didn’t appear to be blinking, mind you, until I hit the reset button on the board and noticed that they would randomly change states when the button was pressed (either both would suddenly brighten up, only one would be lit, the other would be lit, or both would turn off) and realized that actually they were blinking, but so fast that I couldn’t see them with my naked eyes and pressing the button basically halted the CPU and preserved whatever was on the address pins when I hit the button. And that meant success!

To verify, I just changed the LEDs to be tied to bits 22 and 23 of the address and recompiled and, lo and behold, blinking lights! To make a slightly better visual, I decided to add in the rest of the LEDs and tie them to more address bits so I could snap this photo.

An array of lights resembling a binary counter as the CPU cycles through its address space trying to fetch instructions

I’m very excited to see these simple blinking lights, as it means I now have a working 16-bit CPU at my disposal.

As for my next task? I might try and see if I can wire up a simple bus interface and get the CPU running some real code with a little baked-in ROM. Maybe even see if I can put together a little debug module to let me see some bus writes from code running on the CPU.

Published by KillaMaaki

I'm a programmer, a gamer, and author of Unity Multiplayer Games by Packt Publishing.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.