0
\$\begingroup\$

I have a Verilog design for a Basys 3 in which I display a number increasing by 1 each half second in a 7 segment display.

I'm running the timing analysis in Vivado, and I get a hold time violation caused by an async. reset, let me explain:

enter image description here

The blue path is the one that causes the violation.

  • The main clock (sys_clk onwards) is CLK100MHz_IBUF_BUFG. This is the Basys 3 main 100 MHz clock.
  • df is a debounce filter.
  • cd and cds are clock dividers. As you see, cd is clocked by sys_clk and cds by cd/clk, which is sys_clk divided.
  • The reset signal comes from an FPGA button, however it is passed through a debounce filter. Therefore, the rst signal depicted above will be synchronous with regards to sys_clk I suppose, and it will be so with regards to the others two given that they match the phase of sys_clk. If FPGA button that causes the reset would be pressed 'quick enough' I imagine it could generate a pulse that causes a setup and hold violation, but given that sys_clk is 100 MHz this is not humanly possible.

While I get a hold time violation, I think the actual problem is that rst leaves df, which is clocked by sys_clk, and goes into cds (clocked by a different clock) and Vivado thinks this could cause a meta state. That would explain why there is no violation at cd/rst.

I want to set this as a false path because I know that the rst signal is asynchronous in cds and therefore there can't be a meta state. Is this reasoning correct?

Edit: the explanation above is wrong because the signal is not actually asynchronous, it is a multiple of sys_clk and matches it phase. Then why do I get a hold violation?

PD.: Here is the error report:

enter image description here

Edit - possible fix

I tried to reduce the problem by removing the reset signal here. This gets fixed by setting both clock signals a physically exclusive. It turns out that it fixes the problem described in this post as well.

However, I don't think in this case these 2 clocks can be set as physically exclusive, let me explain:

My clock interaction report is now:

enter image description here

This is interesting because, unlike the link provided above, there is now a new clock interaction sys_clk_pin -> cd/clk (bottom left).

This occurs as a consequence of changing the reset in the flip-flop c (see schematics below) from 1'b0 (which is how it is in the link above), to rst. I have inspected the schematics:

enter image description here

Unlike the schematics in the link above, there is now a path from df to c (AR, the reset signal). I think this is from where the above clock interaction come, and I think technically it can't be told that these two clocks are physically exclusive, because a signal coming from a module (df) clocked with CLK100MHZ goes to a module (c) clocked by clk, which is a different clock. Is this correct?

\$\endgroup\$

3 Answers 3

2
\$\begingroup\$

I investigated more and it turns out that hold violations are only fixed in the place & route step. I have run implementation on Vivado and the problem disappears.

Although I would still like to understand why I get the hold violation and such a huge clock skew after synthesis.

In any case, the problem gets solved (in Xilinx Vivado) going from this clock divider:

// BAD CLOCK DIVIDER 

module clk_div #(parameter POL = 1'd0, parameter PWIDTH = 8'd4) (
    output  reg         div_clk,
    input   wire        clk,
    input   wire        rst
);
    reg [31:0] timer;

    always @(posedge clk or posedge rst) begin
        if (rst) begin
            div_clk <= POL;
            timer <= 0;
        end else begin
            if (timer < (PWIDTH - 1)) begin
                timer <= timer + 1;
            end else begin
                timer <= 0;
                div_clk = ~div_clk;
            end
        end
    end
endmodule

To this

// GOOD CLOCK DIVIDER

module clk_div #(parameter POL = 1'd0, parameter PWIDTH = 8'd4) (
    output  wire        div_clk,
    input   wire        clk,
    input   wire        rst
);
    reg [31:0] timer;
    reg div_clk_r;

    always @(posedge clk or posedge rst) begin
        if (rst) begin
            div_clk_r <= POL;
            timer <= 0;
        end else begin
            if (timer < (PWIDTH - 1)) begin
                timer <= timer + 1;
            end else begin
                timer <= 0;
                div_clk_r = ~div_clk_r;
            end
        end
    end

    BUFG bufg0(.O(div_clk), .I(div_clk_r));
endmodule

That BUFG is this. It seems it is a special flop that allows high fan-out with very low skew.

See also this for an alternative solution that consist in using only the Basys 3 main clock (100 MHz) and clock-enable pulses.

\$\endgroup\$
2
  • \$\begingroup\$ Did BUFG bufg0(.O(div_clk), .I(div_clk_r)); successfully route the divided clock to the global clock tree, without any extra XDC constraints? \$\endgroup\$
    – Mitu Raj
    Sep 23, 2022 at 10:28
  • \$\begingroup\$ @MituRaj you can find more details about that here: electronics.stackexchange.com/questions/635344/… But in summary, the clock interaction disappears, that is, with BUFG, the clock interaction diagram reveals only one clock. I guess that that means div_clk_r was indeed successfully routed to the global clock tree. \$\endgroup\$
    – Martel
    Sep 23, 2022 at 10:32
2
\$\begingroup\$

This is specifically a problem for the divider, because the hold time violation is between the launch clock of the reset signal being deasserted, and the latch clock of the FF that comes out of reset.

If these are the same clock, that isn't a problem: real-world FFs latch with the falling edge, so the constraint is between the rising edge at the source (plus safety margin) and the falling edge at the destination (minus safety margin). That is a lot of slack.

With a clock divider, now the rising edge of the fast clock combinatorially generates both rising and falling edges of the slow clock, and the latter is what timing analysis is concerned about.

To fix this, I'd bring the reset into the slow clock domain, and distribute it from there. This will be slightly delayed vs the fast clock, so there is also the possibility of a hold time violation if the reset deassertion doesn't reach the fast FFs before their window closes, especially if it gets shunted over to a high-fanout network, but timing analysis can see that all rising edges of the slow clock are related to a rising edge of the fast clock, and derive the timing between the rising edge of the slow clock and the falling edge of the fast clock from there.

If you have a PLL and the fast clock keeps running, you can also generate the slow clock there instead of combinatorially, which will also give better results.

As a further complication, this is something that often is safe in the context of the entire circuit despite technically being a timing violation, because the reset state for most circuits is some kind of idle state, and any control signals it generates will be inactive at first, so the circuits that consume these signals will not switch during the first clock anyway. For example, a peripheral to a processor will not be addressed on the first bus cycle after reset, because the processor itself is still initializing and does not generate bus requests yet.

So whether it's worth fixing these is an engineering trade-off: you would look into it for an IP component you sell, but for something that is used inside a controlled environment, it may be a secondary concern.

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

If there is a reset signal that is truly asynchronous then it is very likely that you will eventually see a real hold violation. The important question is how long is eventually. In your case, it will probably happen at the exact moment you have to demonstrate your circuit for the instructor.

You should synchronize the reset input signal, and pass it through a couple of flip-flops to reduce the risk of metastability to a very low level.

\$\endgroup\$
7
  • \$\begingroup\$ So you mean that even having all devices like @(posedge clk or posedge rst), rst should be synchronized with respect to clk? I don't see how this async. reset could cause a hold problem. In any case, if I put the rst signal through a sync. cell, will the hold time violation disappear, so I don't need the false path? \$\endgroup\$
    – Martel
    Sep 18, 2022 at 20:10
  • \$\begingroup\$ Now that I think about it, the debounce filter will necesarily make the signal synchronous with respect to sys_clk. Given that the other 2 clocks are sys_clk divided by something, and that they math its phase, I imagine it cannot be told this reset is asynchronous. Still I don't see the problem in having a truly asynchronous one. \$\endgroup\$
    – Martel
    Sep 18, 2022 at 20:20
  • \$\begingroup\$ I have added sync. cells (2 back-to-back ffs) to sync. the reset signal to each of the clocks and I get the exact same violation, this time, in the rst signals that go to the sync. cells' inputs respectively. \$\endgroup\$
    – Martel
    Sep 18, 2022 at 20:55
  • \$\begingroup\$ You basically have a race between the reset signal and the clock signal. You might be able to avoid this by moving the reset signal to the falling edge of the clock rather than the rising edge. \$\endgroup\$ Sep 18, 2022 at 22:54
  • 1
    \$\begingroup\$ You only have to synchronize the release of the reset signal. You really don't care when the assertion happens relative to the clock. Like this: electronics.stackexchange.com/questions/361850/… \$\endgroup\$
    – SteveSh
    Sep 19, 2022 at 0:11

Your Answer

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

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