content
How to design constraints for analyzing input delay
PLL IP configuration parameters
Change Phase Shift Parameters in PLL IP
Timing Analysis Practice
In this experiment, according to the analysis of the data sheet, the timing is constrained, and it is divided into two cases: data intermediate sampling and data edge sampling, and in the case of edge sampling, the PLL is also used to optimize the timing.
Analysis Data Book
The information in the analysis diagram is data center sampling and data edge sampling. In the case of edge sampling, for clock-to-data sampling, the maximum deviation between the clock edge and the data arrival is 2ns, and the minimum is -2ns.
The frequency of the clock is 54Mhz, which means the period is 18.519ns.
Experimental Engineering
This time, I still use the project that analyzed the input delay last time. The code is as follows
input section
`timescale 1ns / 1ps
module iddr_ctrl(
(* clock_buffer_type = "none" *) input wire rx_clk_90,
input wire rst,
input wire [3:0] rx_dat,
input wire rx_ctrl,
output wire rx_en,
output wire [7:0] rx_data
);
wire [7:0] rxd;
wire rxdv,rxerr;
reg rxdv_r;
reg rxerr_r;
reg [7:0] rxd_r;
assign rx_en = rxdv_r;
assign rx_data =rxd_r ;
always @(posedge rx_clk_90) begin
if (rst == 1'b1) begin
rxdv_r <= 1'b0;
rxerr_r <= 1'b0;
rxd_r <= 'd0;
end
else begin
rxdv_r <= rxdv;
rxerr_r <= rxerr;
rxd_r <= rxd;
end
end
generate
genvar i;
for(i=0;i<4;i=i+1) begin
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) IDDR_rxd_inst (
.Q1(rxd[i]), // 1-bit output for positive edge of clock
.Q2(rxd[i+4]), // 1-bit output for negative edge of clock
.C(rx_clk_90), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D(rx_dat[i]), // 1-bit DDR data input
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
end
endgenerate
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) IDDR_rxctrl_inst (
.Q1(rxdv), // 1-bit output for positive edge of clock
.Q2(rxerr), // 1-bit output for negative edge of clock
.C(rx_clk_90), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D(rx_ctrl), // 1-bit DDR data input
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
endmodule
output section
module oddr_ctrl(
input wire sclk,
input wire [7:0] tx_dat,
input wire tx_en,
input wire tx_c,//相移时钟
output wire [3:0] tx_data,
output wire tx_dv,
output wire tx_clk
);
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
.SRTYPE("ASYNC") // Set/Reset type: "SYNC" or "ASYNC"
) ODDR_DV_inst (
.Q(tx_dv), // 1-bit DDR output
.C(sclk), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D1(tx_en), // 1-bit data input (positive edge)
.D2(tx_en), // 1-bit data input (negative edge)
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
.SRTYPE("ASYNC") // Set/Reset type: "SYNC" or "ASYNC"
) ODDR_CLK_inst (
.Q(tx_clk), // 1-bit DDR output
.C(tx_c), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D1(1'b1), // 1-bit data input (positive edge)
.D2(1'b0), // 1-bit data input (negative edge)
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
genvar j;
generate
for(j=0;j<4;j=j+1)
begin
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
.SRTYPE("ASYNC") // Set/Reset type: "SYNC" or "ASYNC"
) ODDR_DATA_inst (
.Q(tx_data[j]), // 1-bit DDR output
.C(sclk), // 1-bit clock input
.CE(1'b1), // 1-bit clock enable input
.D1(tx_dat[j]), // 1-bit data input (positive edge)
.D2(tx_dat[j+4]), // 1-bit data input (negative edge)
.R(1'b0), // 1-bit reset
.S(1'b0) // 1-bit set
);
end
endgenerate
endmodule
top section
module top_ioddr(
input wire rx_clk,
input wire rx_ctrl,
input wire [3:0] rx_dat,
//tx
output wire tx_clk,
output wire [3:0] tx_d,
output wire tx_dv,
input wire sdrclk,
input wire [3:0] sdrdata,
input wire sdrden,
output reg tout
);
wire rst;
wire rx_clk_90;
wire rx_en;
wire [7:0] rx_data;
reg tx_en1,tx_en2;
reg [7:0] tx_data1,tx_data2;
assign rst =0;
assign rx_clk_90 = rx_clk;
/*
clk_wiz_0 clk_gen0
(
// Clock out ports
.clk_out1(rx_clk_90), // output clk_out1
// Clock in ports
.clk_in1(rx_clk)); // input clk_in1
*/
always @(posedge rx_clk_90 or posedge rst) begin
if (rst == 1'b1) begin
tx_data1 <= 'd0;
end
else if (rx_en == 1'b1) begin
tx_data1 <= rx_data+ rx_data -1;
end
end
always @(posedge rx_clk_90 or posedge rst) begin
if (rst == 1'b1) begin
tx_data2 <= 'd0;
end
else if (tx_en1 == 1'b1) begin
tx_data2 <= tx_data1+ tx_data1 -5;
end
end
always @(posedge rx_clk_90 ) begin
tx_en1 <= rx_en;
end
always @(posedge rx_clk_90 ) begin
tx_en2 <= tx_en1;
end
iddr_ctrl inst_iddr_ctrl
(
.rx_clk_90 (rx_clk_90),
.rst (rst),
.rx_dat (rx_dat),
.rx_ctrl (rx_ctrl),
.rx_en (rx_en),
.rx_data (rx_data)
);
oddr_ctrl inst_oddr_ctrl
(
.sclk (rx_clk_90),
.tx_dat (tx_data2),
.tx_en (tx_en2),
.tx_c (rx_clk_90),
.tx_data (tx_d),
.tx_dv (tx_dv),
.tx_clk (tx_clk)
);
//sdr clock domain
reg [3:0] sdrdata_r1,sdrdata_r2;
reg sdrden_r1,sdrden_r2;
always @(posedge sdrclk ) begin
{sdrdata_r2,sdrdata_r1} <= {sdrdata_r1,sdrdata};
end
always @(posedge sdrclk ) begin
{sdrden_r2,sdrden_r1} <= {sdrden_r1,sdrden};
end
always @(posedge sdrclk) begin
if(sdrden_r2 == 1'b1) begin
tout <= (&sdrdata_r1)|(&sdrdata_r2);
end
else begin
tout <= (^sdrdata_r2);
end
end
endmodule
design hierarchy
Integrated wiring
After the integrated routing is completed, click edit timing constraints in the open implemented design of the routing to edit the timing constraints
timing constraints
clock constraints
Click the + sign in the creat clock to create the following clock constraints. Constrain the clock in the manual. The frequency is 54Mhz, that is, the period is 18.519ns. The clock constraint name is set to sdrclk, which corresponds to the name of the unilateral sampling clock. Let it be correspond. Finally click ok.
This creates the clock constraint
Input Delay Constraints
Then add the input delay constraint. Similarly, click the + sign in the input delay selection column on the left column to add constraints.
How to design constraints for analyzing input delay
Intermediate sampling of data
Since it is an intermediate sampling, the sampling clock is located in the middle of the data, and the entire data can be regarded as a clock cycle. In the middle, it should be a general clock cycle, that is, 9.259ns. A schematic diagram is simply drawn with Visio to facilitate understanding. In addition, there are also the maximum and minimum delays, which are max=2ns and min=-2ns, respectively. Therefore, the minimum delay constraint and the maximum delay constraint should be added respectively.
Minimum Delay Constraint
Minimum delay constraint = half cycle + minimum delay = 9.259ns-2ns = 7.259ns
Select as rising edge, set the delay value to 7.259ns
object corresponding, and then click ok
Maximum Delay Constraint
It is roughly the same as the one with the minimum delay constraint, just set the delay value to 11.259ns and change it to max, and click ok for the rest.
In this way, you can see the input delay constraint just added in the input delay
At this time, click apply to save, and open the timing report, report timing
Result analysis
At this time, it can be seen that the margins of setup time and hold time are very sufficient, indicating that there is no problem with timing constraints.
Just click on a path, you can calculate and verify the following
According to the previous introduction, setup time margin = time required for data to arrive - time for data to actually arrive
Substitute into calculation: setup slack = 20.048ns - 12.183ns = 7.865ns
results in accordance with the design.
Due to the use of data intermediate sampling, this sampling method can generally meet the establishment time and hold time, but whether the data edge sampling method can meet the requirements.
Data edge sampling
The second method uses data edge sampling to implement input delay constraints, as shown in the figure below, this time is different from the previous one, this time the rising edge of the sampling clock is on the edge of the end of the data, pay attention! The clock edge is collected when the data ends!
Add input delay constraint
Just change the delay value in the constraints just now, max = 2ns, min = -2ns
After setting, click save
Timing report
report timing, the setup time margin is OK
A hold time margin error is reported, and the presence of red indicates a hold time violation.
It can be seen that the setup time margin is very abundant, but the hold time margin has a negative value, which means that the data ends earlier than the clock arrival time, which causes the clock to not pick up data, so it must be constrained.
Solution
There are two solutions:
- Increase the latency of data
- Reduce clock delay
Obviously, it is easier to reduce the delay of the clock. You can use PLL to change the clock delay. Add a PLL with zero phase shift. The input and output clock frequencies are both 54Mhz. In addition to the phase offset and the function of changing the clock frequency, the PLL , and another function is to eliminate the delay before the clock arrives, that is, there is a delay before the input clock reaches the PLL. This delay can be eliminated by the PLL. As mentioned earlier, the reason for the violation of the hold time margin is that The delay of the sampling clock is greater than the time when the data ends, and adding a PLL can reduce the clock delay to a certain extent.
First add the PLL IP in the ip catalog and instantiate it into the top layer.
specific code instantiation
module top_ioddr(
input wire rx_clk,
input wire rx_ctrl,
input wire [3:0] rx_dat,
//tx
output wire tx_clk,
output wire [3:0] tx_d,
output wire tx_dv,
input wire sdrclk,
input wire [3:0] sdrdata,
input wire sdrden,
output reg tout
);
wire rst;
wire rx_clk_90;
wire rx_en;
wire [7:0] rx_data;
reg tx_en1,tx_en2;
reg [7:0] tx_data1,tx_data2;
wire sdrclk1;
assign rst =0;
assign rx_clk_90 = rx_clk;
/*
clk_wiz_0 clk_gen0
(
// Clock out ports
.clk_out1(rx_clk_90), // output clk_out1
// Clock in ports
.clk_in1(rx_clk)); // input clk_in1
*/
always @(posedge rx_clk_90 or posedge rst) begin
if (rst == 1'b1) begin
tx_data1 <= 'd0;
end
else if (rx_en == 1'b1) begin
tx_data1 <= rx_data+ rx_data -1;
end
end
always @(posedge rx_clk_90 or posedge rst) begin
if (rst == 1'b1) begin
tx_data2 <= 'd0;
end
else if (tx_en1 == 1'b1) begin
tx_data2 <= tx_data1+ tx_data1 -5;
end
end
always @(posedge rx_clk_90 ) begin
tx_en1 <= rx_en;
end
always @(posedge rx_clk_90 ) begin
tx_en2 <= tx_en1;
end
iddr_ctrl inst_iddr_ctrl
(
.rx_clk_90 (rx_clk_90),
.rst (rst),
.rx_dat (rx_dat),
.rx_ctrl (rx_ctrl),
.rx_en (rx_en),
.rx_data (rx_data)
);
oddr_ctrl inst_oddr_ctrl
(
.sclk (rx_clk_90),
.tx_dat (tx_data2),
.tx_en (tx_en2),
.tx_c (rx_clk_90),
.tx_data (tx_d),
.tx_dv (tx_dv),
.tx_clk (tx_clk)
);
clk_wiz_0 pll_inst
(
// Clock out ports
.clk_out1(sdrclk1), // output clk_out1
// Clock in ports
.clk_in1(sdrclk)); // input clk_in1
//sdr clock domain
reg [3:0] sdrdata_r1,sdrdata_r2;
reg sdrden_r1,sdrden_r2;
always @(posedge sdrclk1 ) begin
{sdrdata_r2,sdrdata_r1} <= {sdrdata_r1,sdrdata};
end
always @(posedge sdrclk1 ) begin
{sdrden_r2,sdrden_r1} <= {sdrden_r1,sdrden};
end
always @(posedge sdrclk1) begin
if(sdrden_r2 == 1'b1) begin
tout <= (&sdrdata_r1)|(&sdrdata_r2);
end
else begin
tout <= (^sdrdata_r2);
end
end
endmodule
PLL IP configuration parameters
The input clock and output clock frequency are set to 54Mhz, which is consistent with the data sheet, the phase shift is 0°, and the rest can be kept as default.
Since the PLL is used to constrain the clock, the clock constraint just added should be deleted in the XDC file, and the clock is provided by the PLL.
set_property IOSTANDARD LVCMOS33 [get_ports rx_clk]
set_property PACKAGE_PIN J19 [get_ports rx_clk]
set_property PACKAGE_PIN H22 [get_ports rx_ctrl]
set_property IOSTANDARD LVCMOS33 [get_ports rx_ctrl]
set_property PACKAGE_PIN K22 [get_ports {rx_dat[0]}]
set_property PACKAGE_PIN K21 [get_ports {rx_dat[1]}]
set_property PACKAGE_PIN J22 [get_ports {rx_dat[2]}]
set_property PACKAGE_PIN J20 [get_ports {rx_dat[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {rx_dat[0]}]
set_property PACKAGE_PIN M18 [get_ports tx_dv]
set_property IOSTANDARD LVCMOS33 [get_ports tx_dv]
set_property PACKAGE_PIN K18 [get_ports tx_clk]
set_property IOSTANDARD LVCMOS33 [get_ports tx_clk]
set_property PACKAGE_PIN M22 [get_ports {tx_d[0]}]
set_property PACKAGE_PIN L18 [get_ports {tx_d[1]}]
set_property PACKAGE_PIN L19 [get_ports {tx_d[2]}]
set_property PACKAGE_PIN L20 [get_ports {tx_d[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {tx_d[0]}]
set_property PACKAGE_PIN W19 [get_ports sdrclk]
set_property PACKAGE_PIN Y22 [get_ports sdrden]
set_property PACKAGE_PIN V20 [get_ports {sdrdata[0]}]
set_property PACKAGE_PIN U20 [get_ports {sdrdata[1]}]
set_property PACKAGE_PIN AB22 [get_ports {sdrdata[2]}]
set_property PACKAGE_PIN AB21 [get_ports {sdrdata[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports sdrclk]
set_property IOSTANDARD LVCMOS33 [get_ports {sdrdata[*]}]
set_property IOSTANDARD LVCMOS33 [get_ports sdrden]
set_property PACKAGE_PIN Y21 [get_ports tout]
set_property IOSTANDARD LVCMOS33 [get_ports tout]
Integrated wiring
The operation after the general wiring is consistent with the intermediate sampling of the data just done.
Open editing timing constraints and report timing
It can be seen that the setup time margin is in a normal state
There is still a violation of the hold time margin, but it can be found that the hold time margin after adding the PLL has been improved compared to when the PLL was not added just now.
This shows that the delay of the sampling clock is still too large, and it is necessary to further reduce the delay. Using the phase-shift feature of the PLL, the clock is phase-shifted to the left by 60°, and one cycle is 360°, which is equivalent to a 1/6 shift to the left. A clock cycle is 18.519ns, which is equivalent to reducing the clock delay by 3.0865ns, so that the margin of the hold time can be increased.
Change Phase Shift Parameters in PLL IP
Integrated wiring
After reload is complete, re-report timing to view the timing report.
It can be seen that the setup time slack and hold time slack are both back to normal.
Result analysis
Simply click on a path for analysis, and the hold time margin obtained meets the design requirements, so that the establishment time margin and the hold time margin are both returned to normal.
Past series of blogs