Forum Discussion
Question 1) ~2):
Please refer to AN 433: Constraining and Analyzing Source-Synchronous Interfaces (intel.cn)
Page 41: It is not necessary to use a virtual clock to constrain the input delays. You can create
input delay constraints relative to the input clock instead of the virtual clock, but
using a virtual clock makes the constraining of the interface easier and more accurate.
So, the documents say it's not a must to use virtual clock. But you told set_input_delay must use virtual clock.
I am not sure when I need to use virtual clock, and when I don't need to create virtual clock.
what's the relationship between virtual clock and data input clock?
I also don't see virtual clock used for any set_output_delay.
Question 3):
Yes, derive_pll_clocks is another method should work.
But my question is if I use the method of the example, is create unshifted_clock a must? I don't see it use anywhere later.
Can I remove the create_generated_clock of unshifted_clock? Because we only care about the clk_out for set_output_delay.
I think we only need to tell fpga the external constraints.
Question 4):
You mean like this:
create_generated_clock -name out_clock -source [get_pins PLL|inclk[1]] -divide_by 8 [get_ports clk_out]
set_output_delay -add_delay -clock [get_clocks {clk_out}] -max 10.000 [get_ports {data_out}]
But such sdc will report error.
Node: nios:nios_0|mcu_uadc:mcu_uadc_0|read_cnt[2] was determined to be a clock but was found without an associated clock assignment.
No paths exist between clock target "uadc_sclk" of clock "uadc_sclk" and its clock source. Assuming zero source clock latency.
Here is the exact code in my project. uadc_sclk is the clk_out.
always @(negedge clk or negedge reset_n) begin
if(reset_n == 1'b0)
write_cnt <= 8'd0;
else if(spi_current_state == SPI_STATE_WRITE)
write_cnt <= write_cnt + 8'd1;
else
write_cnt <= 8'd0;
end
always @(negedge clk or negedge reset_n) begin
if(reset_n == 1'b0)
read_cnt <= 8'd0;
else if(spi_current_state == SPI_STATE_READ)
read_cnt <= read_cnt + 8'd1;
else
read_cnt <= 8'd0;
end
assign uadc_sclk = (write_cnt[7:3] >= 5'd4 && write_cnt[7:3] <= 5'd27 && write_cnt[2:0] <= 3'd3)? 1'b1 :
(read_cnt[7:3] >= 5'd4 && read_cnt[7:3] <= 5'd27 && read_cnt[2:0] <= 3'd3)? 1'b1 : 1'b0;
(1) For synchronous I/O, there's always a virtual clock and it should always be referenced for set_input_delay and set_output_delay. For source synchronous I/O, there's only a virtual clock for inputs since the FPGA generates the output clock that will latch the data. So set_input_delay references the virtual clock that drives the "upstream" device driving into the FPGA while set_output_delay for source synch always references the output generated clock coming from the FPGA itself.
(3) Again, it's just an example. You use the clocks you need. The easiest thing to do is what I said: use derive_pll_clocks and then create_generated_clock sourced from the appropriate output pin of the PLL.
(4) No. The -source for create_generated_clock should be the output pin of the PLL, not the input pin. And your set_output_delay is wrong because the -clock is referencing "clk_out" when you named the output clock "out_clock". So this should be:
create_generated_clock -name out_clock -source [get_pins PLL|clk[<output clock pin>]] -divide_by 8 [get_ports clk_out]
set_output_delay -add_delay -clock [get_clocks {out_clock}] -max 10.000 [get_ports {data_out}]
As for your error, I've never seen double "?" checks for a single assignment. I'm not sure what you're trying to do with this so it's not clear why read_cnt[2] is being seen as a clock. But that's not related to the constraints you've shown.