cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
kakaluoteasd
Visitor
Visitor
3,392 Views
Registered: ‎11-02-2017

Confusion about timing constraints

Jump to solution

Hi everyone,

I'm a beginner of learning FPGA. Now I'm learning how to add time constraints. I wrote a verilog code to practice it. I used to clocks,‘sclk’was used to drive some simple logic and ‘clk1’was used to produce a new clock ‘clock_out'. I used vivado to add some constraints. However, when i saw the report, i was confused about something.

First, clock_interaction report showed that‘From clock div_clock_out'‘To clock div_clock’, in my opinion, it should be‘from div_clock to div_clock_out'.

Second, i have used 'set_clock_groups' to seperate the two clocks,why the ‘common primay clock’showed ‘yes’. 

Third, when i saw the time_report_summary,it used ‘div_clock_out’ as the source clock, it should be 'div_clock'. And when vivado did path analysis, it add 20ns to the arrival time at first,why vivado did that?.

 

I felt i did something wrong. Anybody can  give me some suggestions? Thanks a lot!

 

 

always @(posedge sclk or negedge rst_n)
begin
if(~rst_n)
b_r<=1'b0;
else
b_r<=b;
end

always @(posedge sclk or negedge rst_n)
begin
if(~rst_n)
d_r<=1'b0;
else
d_r<=out;
end

assign out=(~c)^(b_r && a);

assign y=(~c)&&d_r;


always @(posedge clk1 or negedge rst_n)
begin
if(~rst_n)
div<=1'b0;
else
div<=~div;
end
assign clk_out=div;

 

added constraints

constraint.jpg

 

report_clock_interaction

reprot1.jpg

 

 

report_timing_summary

QQ截图20171117173539.jpg

QQ截图20171117173556.jpg

 

0 Kudos
1 Solution

Accepted Solutions
avrumw
Expert
Expert
4,807 Views
Registered: ‎01-23-2009

First, clock_interaction report showed that‘From clock div_clock_out'‘To clock div_clock’, in my opinion, it should be‘from div_clock to div_clock_out'.

 

There is no path from div_clock to div_clock_out. A path needs a startpoint and and endpoint. As defined there is only one flip-flop on the combination of these two domains, which is div_reg.

 

As defined, div_reg/C is on div_clock. However, your create_generated_clock changes the clock on everything including and downstream of div_reg/Q. Since the only path here is from div_reg/Q (which is, as you defined it on div_clock_out) to div_reg/C (which is on div_clock), the path is shown as such.

 

Technically your create_generated_clock command is incorrect - the attach point should be [get_ports clk_out] (I presume that is the name - you don't show the port list).

 

As a minor point, it is generally preferred to choose the -source as close to the clock modifying cell as possible - in this case, I would choose the C pin of div_reg, so I would use the command

 

create_generated_clock -name div_clk_out -source [get_pins div_reg/C] -divide_by 2 [get_ports div_clk_out]

 

This will return div_reg/Q to the div_clock domain

 

Structurally, this is also not "good" coding style. By having the div_reg register be both the source of its own feedback and the output going out of the chip, you prevent the tool from packing div_reg into the IOB - the IOB flip-flop can only drive the output of the chip, it can't go "back" into the the FPGA fabric. Your assign doesn't change this - that is merely a renaming.

 

To do this and use the IOB flip-flop (which would also fix your problem above) you could split the div_reg flip-flop

 

(* DONT_TOUCH = TRUE *) reg div, clock_out;

 

always @(posedge clk1 or negedge rst_n)
begin
   if(~rst_n)

  begin
    div<=1'b0;

    clock_out <= 1'b0;

  end
  else

  begin
    div<=~div;

    clock_out <= ~div;
  end

end

 

Finally using asynchronous resets is not the preferred mechanism in Xilinx FPGAs. If you need to use resets, synchronous ones are preferred.

 

Avrum

View solution in original post

0 Kudos
6 Replies
avrumw
Expert
Expert
4,808 Views
Registered: ‎01-23-2009

First, clock_interaction report showed that‘From clock div_clock_out'‘To clock div_clock’, in my opinion, it should be‘from div_clock to div_clock_out'.

 

There is no path from div_clock to div_clock_out. A path needs a startpoint and and endpoint. As defined there is only one flip-flop on the combination of these two domains, which is div_reg.

 

As defined, div_reg/C is on div_clock. However, your create_generated_clock changes the clock on everything including and downstream of div_reg/Q. Since the only path here is from div_reg/Q (which is, as you defined it on div_clock_out) to div_reg/C (which is on div_clock), the path is shown as such.

 

Technically your create_generated_clock command is incorrect - the attach point should be [get_ports clk_out] (I presume that is the name - you don't show the port list).

 

As a minor point, it is generally preferred to choose the -source as close to the clock modifying cell as possible - in this case, I would choose the C pin of div_reg, so I would use the command

 

create_generated_clock -name div_clk_out -source [get_pins div_reg/C] -divide_by 2 [get_ports div_clk_out]

 

This will return div_reg/Q to the div_clock domain

 

Structurally, this is also not "good" coding style. By having the div_reg register be both the source of its own feedback and the output going out of the chip, you prevent the tool from packing div_reg into the IOB - the IOB flip-flop can only drive the output of the chip, it can't go "back" into the the FPGA fabric. Your assign doesn't change this - that is merely a renaming.

 

To do this and use the IOB flip-flop (which would also fix your problem above) you could split the div_reg flip-flop

 

(* DONT_TOUCH = TRUE *) reg div, clock_out;

 

always @(posedge clk1 or negedge rst_n)
begin
   if(~rst_n)

  begin
    div<=1'b0;

    clock_out <= 1'b0;

  end
  else

  begin
    div<=~div;

    clock_out <= ~div;
  end

end

 

Finally using asynchronous resets is not the preferred mechanism in Xilinx FPGAs. If you need to use resets, synchronous ones are preferred.

 

Avrum

View solution in original post

0 Kudos
avrumw
Expert
Expert
3,350 Views
Registered: ‎01-23-2009

Second, i have used 'set_clock_groups' to seperate the two clocks,why the ‘common primay clock’showed ‘yes’. 

 

First of all - your set_clock_groups only affects paths between clk_div_out and sys_clk (in either direction). No such paths exists. Since there are no paths, there are already no clock interactions, and this command doesn't do anything (and is unnecessary).

 

Furthermore, using the set_clock_groups command should only be done if there is a clearly understood reason why this is the right thing to do. In many (most?) cases, it is not.

 

Finally, the clock interaction report is showing only two pairs of interactions:

  - between div_clock and div_clock_out: These two clocks do share a common primary clock with each other

  - between sys_clock and sys_clock: This is the same clock, so clearly shares a primary clock with itself

 

Nothing in this report shows any relationships between sys_clock and either of the div_clock clocks (since no paths exist).

 

Avrum

0 Kudos
avrumw
Expert
Expert
3,347 Views
Registered: ‎01-23-2009

Third, when i saw the time_report_summary,it used ‘div_clock_out’ as the source clock, it should be 'div_clock'. And when vivado did path analysis, it add 20ns to the arrival time at first,why vivado did that?.

 

This is related to your first problem.

 

The startpoint of the path i (div_reg/Q) is also the attach point of the generated clock. As such, the tools don't really understand how to time this. In this case, it is considering the falling edge of div_clk_out, which really shouldn't play a role since div_reg is a rising edge flip-flop. But the flip-flop isn't clocked with the same clock as the startpoint, so it is basically confused.

 

Fix the create generated clock and/or duplicate the div_reg as I described above, and this will become a more normal path report.

 

Avrum

0 Kudos
kakaluoteasd
Visitor
Visitor
3,316 Views
Registered: ‎11-02-2017

Thanks a lot! I have tried what you said and everthing is working correctly!

I changed [get_ports clk_out] to [get_pins div_reg/Q], then the report became the original report again. Are there any difference between them?

And in your verilog code 'clock_out <= ~div;' , maybe it should be 'clock_out <=div;' , i'm not sure about that.....

Thanks again for your reply!

 

WNS TNS Failing TNS Total WNS Path Common Inter-Clock
From Clock To Clock Clock Edges WNS(ns) TNS(ns) Endpoints Endpoints Requirement(ns) Primary Clock Constraints
------------- ------------- ----------- ------- ------- ----------- ----------- --------------- ------------- -----------
div_clock_out div_clock rise - rise 19.09 0.00 0 2 20.00 Yes Timed
sys_clock sys_clock rise - rise 8.98 0.00 0 1 10.00 Yes Timed

0 Kudos
avrumw
Expert
Expert
3,288 Views
Registered: ‎01-23-2009

Are there any difference between them?

 

As I explained above, the difference is where the divided clock starts. If you put it on div_reg/Q, then div_reg/Q is considered to be on the new clock domain rather than the old one (which is what it should be). Putting it "farther down" leaves div_reg/Q on the original clock domain.

 

And in your verilog code 'clock_out <= ~div;' , maybe it should be 'clock_out <=div;' 

 

You wanted your output to be div. On each clock, div is loaded with ~div. If you want a second flip-flop (clock_out) to always have the same value as div, then you need to load it with the same thing that div is loaded with, which is ~div.

 

Avrum

0 Kudos
kakaluoteasd
Visitor
Visitor
3,272 Views
Registered: ‎11-02-2017

Thanks for your detailed explanation!

0 Kudos