1
\$\begingroup\$

I am using a Lattice LC4256V-5T144 CPLD and their ispLever Classic software. Simulation says this chip can run the 20-bit counter at 227 MHz; my requirement is 200 MHz. I have found that if the clock enable is used, code only runs at 182 MHz, which is too slow. I can design the circuit to avoid using clock enable, but the software always "optimizes" it to use the clock enable, and thus slows it down. There is plenty of space in the CPLD.

The counter is OK, my problem is latching the counter value upon the rising edge of an independent OneKHz signal derived from a 10MHz timebase. I use a 2-FF synchronizer for it.

QUESTION: When setting latch, how can I force Verilog to use logic on the D input rather than "optimizing" it to use the clock enable?

Here's the relevant Verilog code:

wire counterInput, OneKHz;  // defined and driven elsewhere in the module
                            // counterInput is 10kHz to 200 MHz
reg [19:0] counter, latch;  // latch is read via SPI elsewhere in the module
reg latchEn1, latchEn2;     // 2-FF synchronizer for OneKHz
reg latchEnable;            // also sets Ready (which is cleared by SPI read)

// latchEn1 and latchEn2 form a 2-bit shift register of OneKHz, so
// (latchEn1 & !latchEn2) means a rising edge on OneKHz happened
// on posedge of counterInput one clock earlier.

always @ (posedge counterInput)
begin
    counter <= counter + 1'd1;
    latchEn2 <= latchEn1;
    latchEn1 <= OneKHz;
    latchEnable <= (latchEn1 & !latchEn2);
    latch <= latchEnable ? counter : latch; // THIS LINE IS THE PROBLEM
//  latch <= (latchEnable & counter) | (!latchEnable & latch); // also fails
//          (that line also fails if I write out each bit)
end
\$\endgroup\$
5
  • \$\begingroup\$ which software, in particular, optimizes it (and, knowing vendor tools: which version of that software?) \$\endgroup\$ Apr 23, 2020 at 19:07
  • 5
    \$\begingroup\$ What has brought you come to the conclusion that conversion to clock enable is an issue? What simulation were you performing and how did you determine FMax? How did you determine that the design only runs at 182MHz? \$\endgroup\$ Apr 23, 2020 at 19:16
  • \$\begingroup\$ Why are you assigning a latch to itself? Just do latch = counter when latch enable. \$\endgroup\$
    – user110971
    Apr 23, 2020 at 21:16
  • \$\begingroup\$ Please show how counterInput and OneKHz are driven. My guess is counterInput is not a proper clock source or derived clock. That can skew setup/hold time and impact overall performance. \$\endgroup\$
    – Greg
    Apr 28, 2020 at 3:13
  • \$\begingroup\$ Response too long for a comment. See reply below. \$\endgroup\$ Apr 29, 2020 at 4:20

3 Answers 3

1
\$\begingroup\$

The software is Lattice's ispLever Classic, as I said, version 2.0 (the latest). That is a software suite, and the component doing this "optimization" is the fitter.

Clock enable is the issue, as the clock enable must be valid before the clock, while the data input needs to be valid at the clock. Looking at the post-fit equations in the "Fitter Report" shows that the clock enable is being used, and the "Timing Report" shows Fmax=185MHz with the limiting path involving the clock enables.

I kept playing with it, and found that the presence of seemingly unrelated wires can generate different answers, sometimes differing significantly in Fmax. Replacing the last line in the always block with this still uses the clock enable and gives FMax=185MHz:

if(latchEnable) latch = counter;

But if I also add a new wire "dummy" to the module command and add these lines, I get Fmax=210MHz:

output dummy;
wire [19:0] latchSelect = (latchEn1 & !latchEn2) ? counter : latch;
assign dummy = latchSelect[0] | latchSelect[1] | latchSelect[2] | 
    latchSelect[3] | latchSelect[4] | latchSelect[5] | latchSelect[6] | 
    latchSelect[7] | latchSelect[8] | latchSelect[9] | latchSelect[10] | 
    latchSelect[11] | latchSelect[12] | latchSelect[13] | latchSelect[14] | 
    latchSelect[15] | latchSelect[16] | latchSelect[17] | latchSelect[18] | 
    latchSelect[19];

Note this new latchSelect is used ONLY to set dummy, which is an output pin (a real output is needed to prevent it being optimized away). But its presence changes the code used to set the latch. Now it uses the D input, not the clock enable; Fmax=210MHz. (Making dummy be a 20-bit bus slows it down.)

I can now replace the last line in the always block with this, and get FMax=208MHz (yes, slower than previous);

latch = latchSelect;

But if I remove dummy the latchSelect gets optimized away, it uses the clock enable, and Fmax=185MHz.

Another poor "optimization" I found is that if I connect a FF output like latchEn1 to an output pin, it also slows the circuit down, because wherever that signal is used, it uses the output pin, not the FF output (look at the post-fit equations). I connect important signals to output pins so my logic analyzer can see them for debugging -- it's OK if those output pins run somewhat slower, but reducing the counter/latch Fmax means I must remove those assignments once the circuit works.

Bottom line: fitting verilog equations to a device is complicated and subtle. Small changes in the code can make important changes in circuit performance. I do have code that meets my requirements with 5% margin (Fmax=210MHz, requirement is 200 MHz). Of course I still need to install the circuit and test it with real signals....

\$\endgroup\$
3
  • 2
    \$\begingroup\$ 'Clock enable is the issue, as the clock enable must be valid before the clock, while the data input needs to be valid at the clock.' - No. The data input needs to be valid before the clock in exactly the same way the clock enable does. It's called setup time (tsu). \$\endgroup\$ Apr 24, 2020 at 16:12
  • 2
    \$\begingroup\$ What's happening is each time you make seemingly inconsequential changes, the fitting is producing different wiring results which will give you different FMax. Changing one tiny part of a design can have a massing knockon effect on other parts. Have you specified counterInput as a clock with frequency of 200MHz in your timing constraints? \$\endgroup\$ Apr 24, 2020 at 16:14
  • \$\begingroup\$ Yes, but clock enable setup time is larger than data setup time. And yes, small changes in code can make major changes in layout, affecting Fmax. \$\endgroup\$ Apr 25, 2020 at 18:37
0
\$\begingroup\$

(Responding to comment by Greg.)

I don't know what a "proper clock source or derived clock" is. I thought any signal in the CPLD could be used as a clock.

Here's counterInput:

input In_1, In_248;    // 10kHz to 200Mhz input to be measured
input In_sel;          // dc signal from host, changes only when data are ignored
wire counterInput = (In_sel==0 ? In_1 : In_248);

counterInput is used as a clock for the counter, latch, and some FFs. It is the critical one.

Here's OneKHz -- it is much slower, and unrelated to counterInput:

input Timebase0, Timebase1;   // 10MHz from GPS receiver and internal oscillator
input Timebase_sel;           // dc from host, changes only when data are ignored
wire timebase = (Timebase_sel==0 ? Timebase0 : Timebase1); 
always @(posedge timebase)
begin
    if(divider >= 4999) begin
        divider <= 0;
        OneKHz <= !OneKHz;
    end else begin
        divider <= divider + 1;
    end
end

So both clocks come from input pins via a 2-input multiplexer controlled by the host. OneKHz is a toggle FF.

In_1 is a direct input, while In_248 comes via a 1.4 GHz prescaler that the host can set to 2X, 4X, or 8X, setting In_sel appropriately. Both come from comparators.

The host is a Teensy 4.0 that sends the data via USB for analysis and display.

\$\endgroup\$
0
\$\begingroup\$

I have been unable to define counterInput as a clock in the timing constraints. I have not figured out how to specify which signals can have timing constraints; the software seems to permit constraints only on signals connected to a CLK input pin and used as a clock in some always block. But counterInput is not a pin, it is an internal wire (there are two possible counter inputs selected by a dc signal from the host). So even though both external clocks are connected to CLK pins, the software does not permit me to specify timing constraints on them. What I have done is temporarily tweak the code to use one of them as the clock, just for checking the timing.

I have asked Lattice technical support how to add additional signals to the timing constraints, but they have not responded.

I am able to specify timing constraints on my clock pins (that generate counterInput) by adding dummy flip-flops toggled by them. I OR their outputs to a dummy output pin, to avoid their being optimized away.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.