How SDC definition affects synthesis result? - Page 1
Forum section: electronics / general

author: radiolistener
author_rank: Super Contributor
timestamp: April 01, 2021, 10:58:47 am
content: I'm not familiar with Synopsis Design Constraints file, usually I'm just put some base clock definition and standard stuff like that:Code:set_time_format -unit ns -decimal_places 3derive_pll_clocksderive_clock_uncertainty# set false pathset_false_path -from [get_ports {key0}]set_false_path -from * -to [get_ports {led*}]set_false_path -from * -to [get_ports {phy_reset_n phy_col phy_crs}]# input XTAL clock 50MHz / 20nscreate_clock -name clk50mhz -period 20 [get_ports {clk50mhz}]# clk2500create_generated_clock -name clk_2500 -source [get_ports {phy_rxclk}] -divide_by 50 -multiply_by 1 gmii_phy:gmii_phy_i|clk_div:div50|clk_track# set Clock Groupsset_clock_groups -asynchronous \-group { clk50mhz } \-group { phy_rxclk }and it works.But now I'm implementing circuit with gigabit ethernet, and catch some strange behavior. I implemented example based on GMII interface by analogy with another verilog code found on internet. And it don't works...I investigated the issue and found that there is some problem with GMII RX, it doesn't works for some unknown reason. My code just don't see what my gigabit router sends to the fpga. I found that there is something bad with phy_rxclk, because when I tried to invert it, it started to work, but very unstable.Then I found that the root of cause which affects this issue is SDC file definition. I copied SDC content from another verilog project with working GMII interface (actually it uses different PHY chipset). Very strange, but adding a couple of lines into SDC file resolve the problem and GMII RX starts to work as expected.With exclude method I found that the issue depends on these SDC definitions which define constraints for the PHY RX signals (4 lines that fix the issue starts afer comment "Ethernet PHY RX per AN477, with PHY delay for RX enabled"):Code:## Clocks in Eth RX Domaincreate_clock -name virt_phy_rx_clk_fast-period 8.000create_clock -name virt_phy_rx_clk_slow-period 40.000set_clock_groups -exclusive -group {virt_phy_rx_clk_fast} -group {virt_phy_rx_clk_slow}# input PHY GMII clock 125MHz / 8nscreate_clock -name phy_rxclk -period 8 -waveform {2.0 6.0} [get_ports {phy_rxclk}]## Ethernet PHY RX per AN477, with PHY delay for RX enabled## Clock delay added by KSZ9031 is 1.0 to 2.6 per datasheet table 7-1## Clock is 90deg shifted, 2ns## Max delay is 2.6-2.0 = 0.6## Min delay is 1.0-2.0 = -1.0set_input_delay -max 0.6 -clock virt_phy_rx_clk_fast [get_ports {phy_rxd[*]}]set_input_delay -min -1.0 -clock virt_phy_rx_clk_fast -add_delay [get_ports {phy_rxd[*]}]set_input_delay -max 0.6 -clock virt_phy_rx_clk_fast -clock_fall -add_delay [get_ports {phy_rxd[*]}]set_input_delay -min -1.0 -clock virt_phy_rx_clk_fast -clock_fall -add_delay [get_ports {phy_rxd[*]}]I'm confused, because I thought these lines and especially virtual clock definitions are used for timing analysis only and don't affects the synthesis result.Could someone help to clarify why these time constraints in SDC file affects synthesis result?Here is my top level verilog code (I cut unrelated parts):Code:module TEST(input clk50mhz,// PHY RTL8211EGoutput phy_reset_n, // Hardware Reset. Active low.output phy_mdc,inout phy_mdio,input phy_col, // Collision In Half Duplex Mode/Mode configuration (pull up=RGMII, pull down=GMII)input phy_crs, // Carrier Senseinput phy_rxclk, // The continuous receive reference clock will be 125/25/2.5 MHz. Derived from the received data stream.input phy_txclk, // The transmit reference clock will be 25MHz, or 2.5MHz depending on speed.output phy_gtxclk, // The transmit reference clock is 125 MHz(* useioff = 1 *) output [7:0] phy_txd, // Transmit Data(* useioff = 1 *) output phy_txen, // Transmit Enableoutput phy_txer, // Transmit Error (Connect to GND if MAC does not have a TXER pin)(* useioff = 1 *) input [7:0] phy_rxd, // Receive Data(* useioff = 1 *) input phy_rxdv, // Receive Data Validinput phy_rxer // Receive Error);logic speed_1gb;logic clk_2500;logic eth_txclk;logic eth_rxclk;logic [7:0] phy_tx_data;logic phy_tx_valid;logic [7:0] phy_rx_data;logic phy_rx_valid;gmii_phy gmii_phy_i(.phy_reset_n(phy_reset_n),.phy_rxclk(phy_rxclk),.phy_txclk(phy_txclk),.phy_gtxclk(phy_gtxclk),.phy_txd(phy_txd),.phy_txen(phy_txen),.phy_txer(phy_txer),.phy_rxd(phy_rxd),.phy_rxdv(phy_rxdv),.phy_rxer(phy_rxer),.speed_1gb(speed_1gb),.clk_2500(clk_2500),.eth_txclk(eth_txclk),.eth_rxclk(eth_rxclk),.phy_tx_data(phy_tx_data),.phy_tx_valid(phy_tx_valid),.phy_rx_data(phy_rx_data),.phy_rx_valid(phy_rx_valid));// ... using phy_tx_data / phy_tx_valid and phy_rx_data / phy_rx_valid...endmodulemodule gmii_phy(// PHY hardware pinsoutput phy_reset_n,input phy_rxclk,input phy_txclk,output phy_gtxclk,output [7:0] phy_txd,output phy_txen,output phy_txer,input [7:0] phy_rxd,input phy_rxdv,input phy_rxer,input speed_1gb,output clk_2500,output eth_txclk,output eth_rxclk,input [7:0] phy_tx_data,input phy_tx_valid,output [7:0] phy_rx_data,output phy_rx_valid);assign phy_reset_n = 1'b1;assign phy_gtxclk = phy_rxclk;logic phy_rx_clk_div2 = 1'b0;logic speed_1gb_clksel = 1'b0;// clk_ctrl = 125 / 50 = 2.5 MHzclk_div #(7, 25)div50(phy_rxclk, 0, clk_2500);always @(posedge phy_rxclk) beginphy_rx_clk_div2 <= ~phy_rx_clk_div2;endalways @(posedge clk_2500) beginspeed_1gb_clksel <= speed_1gb;endassign eth_txclk = phy_gtxclk;assign eth_rxclk = speed_1gb_clksel ? phy_rxclk : phy_rx_clk_div2;gmii_send gmii_send_i (.clk(eth_txclk),.phy_tx_data(phy_tx_data),.phy_tx_valid(phy_tx_valid),.phy_txd(phy_txd),.phy_txen(phy_txen),.phy_txer(phy_txer));gmii_recv gmii_recv_i (.clk(eth_rxclk),.phy_rx_data(phy_rx_data),.phy_rx_valid(phy_rx_valid),.phy_rxd(phy_rxd),.phy_rxdv(phy_rxdv),.phy_rxer(phy_rxer));endmodulemodule gmii_send(input clk,input [7:0] phy_tx_data,input phy_tx_valid,//hardware pinsoutput reg [7:0] phy_txd = 8'h00, // Transmit Dataoutput reg phy_txen = 1'b0, // Transmit Enableoutput reg phy_txer = 1'b0 // Transmit Error (Connect to GND if MAC does not have a TXER pin));always@(negedge clk) beginphy_txd <= phy_tx_data;phy_txen <= phy_tx_valid;phy_txer <= 1'b0;endendmodulemodule gmii_recv(input clk,output reg [7:0] phy_rx_data,output reg phy_rx_valid,//hardware pinsinput [7:0] phy_rxd, // Receive Datainput phy_rxdv, // Receive Data Validinput phy_rxer // Receive Error);always @(posedge clk) beginphy_rx_data <= phy_rxd;phy_rx_valid <= phy_rxdv;endendmodulemodule clk_div#(parameter WIDTH = 3, // Width of the register requiredparameter N = 6 // We will divide by 12 for example in this case)(input clk,input reset,output clk_out);reg [WIDTH-1:0] r_reg;wire [WIDTH-1:0] r_nxt;reg clk_track;always @(posedge clk or posedge reset)beginif (reset)beginr_reg <= 0;clk_track <= 1'b0;endelse if (r_nxt == N)beginr_reg <= 0;clk_track <= ~clk_track;endelser_reg <= r_nxt;endassign r_nxt = r_reg+1;assign clk_out = clk_track;endmoduleYou may note that I'm generate low speed 2.5 MHz clock from the external 125 MHz PHY clock with a clk_div divider instead of using PLL. I know this is bad, but for some reason my starter kit fpga board uses phy_rxclk on a regular pin, so I cannot use PLL for that. If you can help with better solution to bypass this hardware limitation it it would be great.

author: Bassman59
author_rank: Super Contributor
timestamp: April 01, 2021, 03:33:44 pm
content: The SDC constraints are also used for place and route.

author: SiliconWizard
author_rank: Super Contributor
timestamp: April 01, 2021, 04:15:02 pm
content: From what I saw, the second SDC file contains 'set_input_delay' constraints - this kind of constraints is hard to avoid when dealing with IOs that have strict timing requirements. I wrote a SDRAM controller and had to set up a number of such constraints in order to get proper placement and get reliable operation.You must use accurate terms though; they won't affect "synthesis" per se (as far as I know anyway - the synthesis tool itself has no means of checking, even less so trying to enforce, this kind of constraints), but will affect place-and-route (PAR), as Bassman59 said, and possibly map as well in some cases.And generally speaking, most timing constraints *can* affect PAR. They aren't just used for timing analysis. Even a clock constraint usually affects PAR. Just try for yourself. You'll get different results depending on the required clock period.

author: Bassman59
author_rank: Super Contributor
timestamp: April 02, 2021, 05:10:58 pm
content: Quote from: SiliconWizard on April 01, 2021, 04:15:02 pmMany newer FPGA families have configurable delays on input pins. If you create the proper set_input_delay constraint, the tools will actually set that hardware input delay to ensure that you meet timing. Look in the reports -- it should be called out as such.