I'm doing a simple seven segment display driver for class, using a MachXO3 dev board connected to 4 displays and 2 buttons on a breadboard. The 4 common-cathode displays have their anodes wired together so that the active display's cathode can be strobed to show a unique 4-digit number. Clock rate (input clk) is 12 MHz from the board's crystal oscillator, and I want to strobe the displays 250 times a second.
My first stab at the code to control strobing between the four displays is:
reg [15:0] strobe_count; reg [1:0] current digit = 2'b00; always@(posedge clk) begin if (strobe_count >= 16'd47999) begin strobe_count <= 16'd0; current_digit <= current_digit + 1'b1; end else strobe_count <= strobe_count + 1'b1; end
For some reason, with this code, the "strobe_count" counter works fine (resets to zero after 47999), but the "current_digit" register never updates, and thus the strobing never works. However, if I try to use Diamond Reveal debugger, it DOES work. That is, adding a Reveal core makes it strobe with that code...regardless of whether I actually use Reveal analyzer or not.
It's great that I can get it to work...but I'd really like to know why. I don't think adding a debug core should alter the behavior, and it really doesn't make sense to me. That code SHOULD just work without adding some unexplainable magic sauce, right?
Alternate coding works fine (with or without a debug loaded). For instance, if I remove the "current_digit" assignment from the conditional, and have a separate line like this:
always@(posedge clk) begin current_digit <= current_digit + (strobe_count == 16'd47999); if (strobe_count >= 16'd47999) strobe_count <= 16'd0; else strobe_count <= strobe_count + 1'b1; end
Breaking "current_digit" into its own separate always block also works fine.
I'm thinking it must be some quirk of Verilog, right? Sure enough, if I write a testbench to simulate that first try of the code, even in the simulation, it never updates "current_digit", so clearly Active-HDL knows something about this fabric that I don't. Also, if I try assigning these registers to output pins and check them with an external logic analyzer, I can see that "current_digit" never updates (and yet "strobe_count" DOES in fact successfully reset after 47999)...but using the integrated Reveal logic analyzer changes it to where it DOES work! I've also tried setting timing constraints (with zero reported timing errors in both map and place and route trace reports, and a fmax of 150.15 MHz in the map trace and 127.861 MHz in the P&R trace). I'm also not getting any unusual synthesis warnings, just the one I always get about no user .SDC file.
I'm sure it's got to be something really obvious that I'm missing here, and I'll feel real silly about it, but it's really driving me nuts! Why would it successfully perform one of two actions under a conditional, but not the other...unless a debug core is instantiated?