3

I am using Verilog in Lattice Diamond IDE with a lattice MachXO2 7000HE breakout board.

I built a basic counter with a limit input which generates a variable period clock output. It works fine on its own, however, when I add two instances of this module and connect them in series (to scale the frequency twice), I get an odd result on the FPGA. The simulation, however seems to show what I had expected from the code.

Here is the top module:

 module clock_generator (fpga_clock, cnt1_clock, cnt2_clock, cnt2_counter);
    output  wire            fpga_clock;
    output  wire            cnt1_clock;
    output  wire            cnt2_clock;
    output  wire    [7:0]   cnt2_counter;

    reg     [7:0]   default_period_1    = 8'b00000011;
    reg     [7:0]   default_period_2    = 8'b00000011;

    defparam OSCH_inst.NOM_FREQ = "2.08";
    OSCH OSCH_inst(.STDBY(1'b0), .OSC(fpga_clock));

    counter Counter_1_inst(.clk_in(fpga_clock), .limit_in(default_period_1), .clk_out(cnt1_clock), .cnt_out());
    counter Counter_2_inst(.clk_in(cnt1_clock), .limit_in(default_period_1), .clk_out(cnt2_clock), .cnt_out(cnt2_counter)); 
endmodule

module counter (clk_in, limit_in, clk_out, cnt_out, rst);
    input   wire            clk_in;
    input   wire    [7:0]   limit_in;
    output  reg             clk_out     = 1'b1;
    output  reg     [7:0]   cnt_out     = 8'b00000000;
    input   wire            rst;

    always @(posedge clk_in or posedge rst) begin
        if (rst) begin
            clk_out <=0;
            cnt_out <=0;
        end else if (cnt_out == limit_in) begin
            clk_out <= !clk_out;
            cnt_out <= 0;
        end else begin
            cnt_out <= cnt_out + 1'b1;
        end
    end
endmodule

And here is the testbench for my simulation:

`timescale 1 ns / 1 ns

module testbench;
    wire            fpga_clock;
    wire            cnt1_clock;
    wire            cnt2_clock;
    wire    [7:0]   cnt2_counter;

    clock_generator dut(.fpga_clock(fpga_clock), .cnt1_clock(cnt1_clock), .cnt2_clock(cnt2_clock), .cnt2_counter(cnt2_counter));

    initial begin
        #1400000000
        $finish;
    end
endmodule

Here is the simulation output:

simulation output

And the scope output:

ch1 - fpga_clock

ch2 - cnt1_clock

ch3 - cnt2_clock

ch4 - cnt2_counter[1]

scope output And the probe setup: Setup1

Channel 3 (cnt2_clock) should have twice the period of cnt2_counter[1], as it is in the simulation output. Instead as you can see it's a burst of higher frequency edges where the single edge should be. I've been on this for a while now. What am I missing?

Let me also add the shematic: enter image description here

Thank you!

########## Edit with additional pictures

Scope output with cnt2_counter[0]

ch1 - fpga_clock

ch2 - cnt1_clock

ch3 - cnt2_counter[0]

ch4 - cnt2_counter[1]

[cnt2_counter0[4] And the probe setup: Setup2

Pin list Pin list

amfast
  • 33
  • 7
  • Introduce reset signal, and perform setting of registers on reset signal (rather than assign values at the beginning of the module - I suspect you should get a list of warnings?). According to your readings register changes when its input clock is low. Another input to perform reg state change is its set/reset input, and it is not explicitly routed anywhere here. – Anonymous Dec 19 '18 at 08:41
  • @Anonymous, no, the only warning is this: _.../top.v(12,2-12,49) (VERI-1927) port SEDSTDBY remains unconnected for this instance_. I added a reset as you suggested but it didn't have any effect on the scope output. – amfast Dec 19 '18 at 13:24
  • 1
    Are you absolutely certain that Ch3 on the scope plot is cnt2_clock? I ask as it is changing synchronously to Ch1 which you have said is fpga_clock. The code you have posted explicitly states that cnt2_clock is updated every cnt1_clock rising edge. – Vance Dec 19 '18 at 14:00
  • To @Vance 's comment... check your PAR report for IO assignments. – CapnJJ Dec 19 '18 at 17:08
  • @Vance, yes, I am sure. I have had _cnt2\_clock_ assigned to a couple different pins and the result is always the same. – amfast Dec 20 '18 at 07:53
  • @CapnJJ, sorry, I'm not sure what you mean by "PAR report". – amfast Dec 20 '18 at 07:56
  • There should be a report file after you run through Place-and-Route (PAR) that will tell you, among other things, where the pins were assigned.. It is generated during the last phase of your synthesis when you create the .bit (programming) file – CapnJJ Dec 20 '18 at 14:21
  • I think we're going to need some more information on your test setup. The scope results are very strange. Your code is quite simple (although I'm more au fait with VHDL than Verilog), and the simulation confirms the functionality so I don't think the problem lies there. You have also provided an RTL view of it which looks okay. Therefore there is something in the actual hardware that is causing this effect. So, this has become a more general debug problem. Could you describe, or post a picture of your test setup. Also, can we look at the trace cnt2_counter[0]. – Vance Dec 20 '18 at 15:24
  • @Vance, Well, it's a mess now, but I added pictures of the setup. I'm quite sure that it is not the problem. I also added the *cnt2\_counter[0]*. – amfast Jan 08 '19 at 15:57
  • 1
    @CapnJJ The only report I found regarding pin assignment is named "Signal/Pad" under "Process Reports". It shows the same pins that I have assigned. – amfast Jan 08 '19 at 15:57
  • Thanks for the update amfast. How certain are you that you are measuring _cnt2_clk_ in the first scope picture? Check the pin out that has been assigned to the device (either automatically or by your ucf/sdc file) and check the datasheet for the devkit's pin out. The fact is, _cnt2_counter_ is working as expected so the output should work. – Vance Jan 09 '19 at 14:51

2 Answers2

1

You're using a generated clock. This is usually inadvisable on an FPGA as it has to be done very carefully to prevent glitches and to ensure timing closure is possible. It looks like you might be getting some glitches on cnt1_clock that are screwing up the second instance. Try using clock enables and see what happens.

Also, fpga_clock should be an input and not an output in your top module.

alex.forencich
  • 40,694
  • 1
  • 68
  • 109
  • When you say "generated clock" do you mean *cnt1\_clock* and *cnt1\_clock*? Are you saying that I should use clock enable instead of clock divider like described [here](https://www.fpga4student.com/2017/08/how-to-generate-clock-enable-signal.html)? The fact that this is a problem is new to me, but reading about it gives the impression that my code is badly written from the start. – amfast Jan 08 '19 at 16:23
  • It's generally advisable to avoid doing @(posedge something_that_isn't_a_proper_clock) as this means your logic could be "clocked" by any sort of glitches that might be generated by whatever logic is generating your clock signal, and simulation will not catch this. It also makes timing analysis more complex, and it's more difficult to close timing in this way. Hence, clock enables are preferred. Now, it seems like your generated clock is being directly driven by a flip flop, so in theory there should be no glitches, so I'm not sure exactly why you're seeing the behavior that you are. – alex.forencich Jan 09 '19 at 03:13
0

How this should work?

always @(posedge clk_in) begin
    cnt_out <= cnt_out + 1'b1;
    if (cnt_out == limit_in) begin
        clk_out <= !clk_out;
        cnt_out <= 0;
    end
end 

Maybe you mean:

always @(posedge clk_in) begin
    cnt_out <= (cnt_out == limit_in) ? 0 : cnt_out + 1;
    clk_out <= (cnt_out == limit_in) ? ~clk_out : clk_out;
end 
strannyi
  • 11
  • 1
  • It's supposed to work just as it does in the simulation. And also on the FPGA as far as _Counter\_1\_inst_ goes. I have now changed the code above to include a reset function as well. – amfast Jan 08 '19 at 15:22
  • That code should synthesize exactly the same way, while being more difficult to read. – alex.forencich Jan 09 '19 at 03:14