3
\$\begingroup\$

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

asked Dec 19, 2018 at 8:05
\$\endgroup\$
11
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Dec 19, 2018 at 8:41
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Dec 19, 2018 at 13:24
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Commented Dec 19, 2018 at 14:00
  • \$\begingroup\$ To @Vance 's comment... check your PAR report for IO assignments. \$\endgroup\$ Commented Dec 19, 2018 at 17:08
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Commented Jan 8, 2019 at 15:57

2 Answers 2

1
\$\begingroup\$

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.

answered Dec 21, 2018 at 20:22
\$\endgroup\$
2
  • \$\begingroup\$ 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? 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. \$\endgroup\$ Commented Jan 8, 2019 at 16:23
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Jan 9, 2019 at 3:13
0
\$\begingroup\$

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 
answered Dec 21, 2018 at 20:07
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Jan 8, 2019 at 15:22
  • \$\begingroup\$ That code should synthesize exactly the same way, while being more difficult to read. \$\endgroup\$ Commented Jan 9, 2019 at 3:14

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.