Timing failure with external synchronous SRAM
I have a Cyclone V FPGA interfaced with an external synchronous (ZBT) SRAM. The FPGA is clocked with a 100 MHz XO, which is passed through the FPGA and forwarded/outputted to my SRAM as its clock. Obviously the FPGA has an address-bus connected (output) to the SRAM and a bidirectional data-bus from/to the SRAM.
The relevant constraints I've used are:
create_clock -name "clk_100_in" -period 10.000ns -waveform { 0.000 5.000 } [get_ports {clk_100_in}] create_generated_clock -name {sram_clk_out} -source [get_ports {clk_100_in}] [get_ports {sram_clk_out}] # SRAM input minimum delay in ns set_input_delay -clock sram_clk_out -min 1.3 [get_ports {sram_data36_inout*}] # SRAM input maximum delay in ns set_input_delay -clock sram_clk_out -max 3 [get_ports {sram_data36_inout*}] # SRAM output minimum delay (=hold time) in ns set_output_delay -clock sram_clk_out -min -0.5 [get_ports {sram_address21_out*}] set_output_delay -clock sram_clk_out -min -0.5 [get_ports {sram_data36_inout*}] # SRAM output maximum delay (=setup time) in ns set_output_delay -clock sram_clk_out -max 1.5 [get_ports {sram_address21_out*}] set_output_delay -clock sram_clk_out -max 1.5 [get_ports {sram_data36_inout*}]
The problem is that I get consistent timing failures with the inputs for my SRAM->FPGA data-bus like this:
When I report the timing for eg. data[31] I get:
I think one of the issues I'm facing is the negative clock skew but I have no idea how to fix that. I've tried about a ton of things for several days now to get timing closure but I'm at a complete loss since I'm out of ideas. Any help would be greatly appreciated.
Sorry for the delay in response. Been taking some time to solve the timing violation.
For bidirectional I/O, they are analyzed as inputs and outputs, so they usually have both set_input_delay and set_output_delay assignments.
These sdc below in the project could be reason we got the huge negative slack. The tool analyze that the Data Arrival Path goes from clk_100_in -> sram_clk_out -> sram_clk_inout (o) -> external device -> sram_clk_inout (i) and then back to RAM block. This make it a very long timing path.
set_input_delay -clock sram_clk_out -min 1.3 [get_ports {sram_data36_inout*}]
set_input_delay -clock sram_clk_out -max 3 [get_ports {sram_data36_inout*}]With that, I create a virtual clock and add the input and output delay constraint to the sram_data36_inout*:
create_clock -name {sram_clk_ext} -period 10.000ns
set_input_delay -clock sram_clk_ext -min 1.3 [get_ports {sram_data36_inout*}]
set_input_delay -clock sram_clk_ext -max 3 [get_ports {sram_data36_inout*}]
set_output_delay -clock sram_clk_out -min 1.3 [get_ports {sram_data36_inout*}]
set_output_delay -clock sram_clk_out -max 3 [get_ports {sram_data36_inout*}]I also disable all the location assignment so that the fitter can place and route without being constraint, to meet the timing.
Attached the modified project. Though there is a timing violation of sram_address21_out and I believe it can be solved by tweaking the -max value to 1.0.
set_output_delay -clock sram_clk_out -max 1.0 [get_ports {sram_*_out*}]Best Regards,
Richard Tan