Saturday, October 28, 2023

Yet another digital clock


The classic *nix first program is one that prints "Hello world" on the console. For me, my first project seems to be a digital clock. I made one when I started experimenting with Microchip PICs in 1999. A few years back I made one using my Verilog emulation of an Intel 4004, So it made sense to make one as my first project using the PicoBlaze soft processor.

After recording this video I left it running overnight. The next morning, to my consternation, I found it had stopped with the display showing. 11:01:12.

My first thought was maybe there had been a power glitch or something that had caused the FPGA to reset, but the LCD had retained its contents. However, the 8 LEDs to the right of the LCD were still counting. These are driven from a simple Verilog counter that increments in response to the pulse-per-second "tick" signal that is also read by the PicoBlaze for timekeeping. That told me the FPGA was still loaded and working.

Maybe the LCD controller was wedged somehow? I've never seen one do this, but the state machines I'm using to drive the LCD interface beat on it basically at maximum speed. To check I used an oscilloscope to probe the LCD's I/O pins, but none of the signals were changing.

My next thought was maybe the PicoBlaze core was crippleware. Some FPGA tool vendors intentionally generate self-terminating logic when using their freeware tools to prevent their use for anything but brief experiments. Xilinx is not known for this (and I would not use any vendor's products that did) but maybe the PicoBlaze core was an exception?

Normally my next step would be to export a bunch of signals to the expansion port and use my Intronix LogicPort logic analyzer to observe the internal operations. However, the LogicPort is currently wired to my i4004 test board, and I really didn't want to have to rewire it later.

I've often wondered about using ChipScope, Xilinx's debugging tool. I'd looked into using this long ago, but it appeared to require a rather expensive license. Yet I'd seen recent discussions on using it with the WebPack (freeware) license. I found an old MIT lab exercise on using ChipScope and attempted to follow the procedure. When I tried to generate the ChipScope cores using Coregen, it refused for lack of a proper license.

Checking my Xilinx licenses I discovered that my WebPack license was for ISE 12.3. Logging on to the AMD website (they recently acquired Xilinx) I generated a new WebPack license for 14.7 and loaded it. I ran into a few snags along the way (see my previous post Running Xilinx ChipScope under Ubuntu) but eventually I got my cores generated and the ChipScope analyzer running.

I really wasn't looking forward to debugging a problem that only showed up after 11 hours of runtime. I've done that and it isn't fun at all. My first attempt at speeding this was to shorten the 1 second clock "tick" period. I knew from simulations that the clock's LCD update would only take about 400 microseconds -- at least that's what it took using my simulated LCD controller which uses delays taken from the datasheet. Changing the tick period to 1 millisecond proved to work with the real LCD, and I was excited when the clock halted after about 40 seconds, again showing 11:01:12.

My first ChipScope probe monitored the PicoBlaze's program counter. If the PicoBlaze had self-terminated, this would have stopped updating. I was happy to find it was still stepping through my code, polling the LCD output status waiting for it to go idle. Yet other ChipScope probes showed the output FIFO was empty and the two FSMs were idle. Finally, I added the PicoBlaze I/O port interfaces to the probe monitoring the program counter. This revealed my error.

Xilinx user guide UG129 documents the PicoBlaze. Figures 6-1 and 6-3 show the recommended input logic. Figure 6-3 shows the input data being registered both before and after the input multiplexer. I'd split the input port selection into two levels: port_id[7:4] selected which module provided the input data, while port_id[3:0] was passed to the modules to select what data within the module was provided. Thus I had two layers of multiplexer, and I was registering the data after both mux layers. This meant the LCD status  was delayed by an extra clock cycle, and arrived at the PicoBlaze after it was sampled by the processor. Removing the clocking from after the first mux fixed the issue.

I have no idea how this worked in the first place, and even less idea why it always stopped when displaying 11:01:12 and not some other value. But it taught me how to use ChipScope, and that may be very helpful in the future.

No comments:

Post a Comment