Простая задача: ввод данных с АЦП в MachXO2. АЦП тактируется от PLL ПЛИС:
Код
module top (input clk, output adc_clk, input [7:0] adc_data);
PLL _pll (.CLKI(clk), .CLKOP(adc_clk));
reg [7:0] rdata;
always @ (posedge adc_clk) begin
rdata <= adc_data;
// Дальше работаем с rdata...
end
endmodule
PLL _pll (.CLKI(clk), .CLKOP(adc_clk));
reg [7:0] rdata;
always @ (posedge adc_clk) begin
rdata <= adc_data;
// Дальше работаем с rdata...
end
endmodule
В Quartus/TimeQuest временные ограничения для шины данных можно было бы задать так:
Код
create_generated_clock -name {adc_clk} -source [get_pins {_pll/PLLInst_0/CLKOP}] [get_ports {adc_clk}]
set_input_delay -clock {adc_clk} -max [...] [get_ports {adc_data[*]}]
set_input_delay -clock {adc_clk} -min [...] [get_ports {adc_data[*]}]
set_input_delay -clock {adc_clk} -max [...] [get_ports {adc_data[*]}]
set_input_delay -clock {adc_clk} -min [...] [get_ports {adc_data[*]}]
При этом учитывается как задержка данных на входных буферах ПЛИС, так и разность времен распространения клока от выхода PLL через кристалл наружу и от выхода PLL до регистров внутри ПЛИС.
В Lattice Diamond SDC не поддерживается (во всяком случае, в Place & Route и I/O Timing Analysis). Задавать временные ограничения нужно в LPF. В LPF ничего похожего на create_generated_clock нет. Аналогом set_input_delay является INPUT_SETUP. Вроде бы естественно написать:
Код
INPUT_SETUP PORT "adc_data*" ... ns HOLD ... ns CLKPORT "adc_clk";
Однако при этом, судя по отчету, в расчет берется только PADI_DEL + ROUTE данных минус ROUTE клока от PLL к регистру. Задержка вывода клока от PLL наружу не учитывается, что делает такой анализ бессмысленным.
Вопрос: как правильно задать временные ограничения для этого интерфейса в Diamond?