# Lattice FPGA problems with built-in DELAY module

I'm trying to delay an input data coming from ADC component in DDR to my FPGA, afterwards output it in the clock rising edge. The ADC Im using: ADS5463:

Im using Lattice ECP3 FPGA, based on the fpga datasheet this fpga have delay module built in called DELAYB:

The reason why Im trying to delay the inputs is to maximize the setup time and hold time as the ADS5463 recommends to do.

My code for trying to use this delay module and output the delayed data in rising edge clock:

module top(
input rstn,
input dry,               //DRY=fs/2 -> fs=300Mhz -> DRY=150MHz
input [11:0] data_input,
output clk2,
output [11:0] data_output
);

wire clk2;
wire rst;
wire [11:0] data_input_delay;
reg [11:0] posedge_data;
reg [11:0] negedge_data;
reg [23:0] data_output;

assign rst = ~rstn;

//divide clk. clk2=dry_i/2=75MHz.
CLKDIVB div2 (
.CLKI   (dry),
.RST    (rst),
.RELEASE(1'b1),
.CDIV1  (),
.CDIV2  (clk2),
.CDIV4  (),
.CDIV8  ()
);

//delay data => 35ps steps.
genvar i;
generate
for (i = 0; i < 12; i = i + 1) begin
DELAYB delay (
.A(data_input[i]),
.DEL0(1'b1),
.DEL1(1'b1),
.DEL2(1'b0),
.DEL3(1'b0),
.Z(data_input_delay[i])
);
end
endgenerate

always @(posedge dry, posedge rst)
begin
if (rst) begin
posedge_data   <= 12'b100000000000;
end else begin
posedge_data   <= data_input_delay;
end
end

always @(negedge dry, posedge rst)
begin
if (rst) begin
negedge_data   <= 12'b100000000000;
end else begin
negedge_data   <= data_input_delay;
end
end

always @(posedge clk2, posedge rst)
begin
if (rst) begin
data_output   <= 24'b100000000000100000000000;
end else begin
data_output  <= {posedge_data, negedge_data};
end
end

endmodule


When Im trying to synthesize this code, I'm getting this error message from Diamond Lattice:

ERROR - Dynamic delay cell 'genblk1[0].delay' cannot drive component 'negedge_data[0]'.

ERROR - Dynamic delay cell 'genblk1[11].delay' cannot drive component 'negedge_data[11]'.

ERROR - Dynamic delay cell 'genblk1[10].delay' cannot drive component 'negedge_data[10]'.

ERROR - Dynamic delay cell 'genblk1[9].delay' cannot drive component 'negedge_data[9]'.

ERROR - Dynamic delay cell 'genblk1[8].delay' cannot drive component 'negedge_data[8]'.

ERROR - Dynamic delay cell 'genblk1[7].delay' cannot drive component 'negedge_data[7]'.

ERROR - Dynamic delay cell 'genblk1[6].delay' cannot drive component 'negedge_data[6]'.

ERROR - Dynamic delay cell 'genblk1[5].delay' cannot drive component 'negedge_data[5]'.

ERROR - Dynamic delay cell 'genblk1[4].delay' cannot drive component 'negedge_data[4]'.

ERROR - Dynamic delay cell 'genblk1[3].delay' cannot drive component 'negedge_data[3]'.

ERROR - Dynamic delay cell 'genblk12.delay' cannot drive component 'negedge_data2'.

ERROR - Dynamic delay cell 'genblk11.delay' cannot drive component 'negedge_data1'.

INFO - Errors found in user's design. Output files not written. Check map report for more details.

Someone please can help me see my thats happening? I have ref design which using this components and there its working fine, whats wrong?

Edit After Rakend comment:

okay after adding IFS1P3IX instances to the output registers of DELAYB module like the ref advised. It did fix the errors mentioned above, but now my design putting the data_input's in High-Z mode, its still not working, the design is pass the synthesises but giving me this warning which makes the design now working.

the new code:

module top (rstn,dry,data_input,clk2,led_clk,led_rst,data_output);

input rstn;
input dry;               //DRY=fs/2 -> fs=300Mhz -> DRY=150MHz
input [11:0] data_input;
output wire clk2;
output  led_clk;
output reg  led_rst;
output reg [23:0] data_output;

wire rst;
wire [11:0] data_input_temp;
wire [11:0] data_input_delay;
reg [25:0] adc_clk_count = 26'b0;

assign rst = ~rstn;

//divide clk. clk2=dry_i/2=75MHz.
CLKDIVB div2 (
.CLKI   (dry),
.RST    (rst),
.RELEASE(1'b1),
.CDIV1  (),
.CDIV2  (clk2),
.CDIV4  (),
.CDIV8  ()
);

genvar i;
generate
for (i = 0; i < 12; i = i + 1) begin
DELAYB delay (
.A(data_input[i]),
.DEL0(1'b1),
.DEL1(1'b1),
.DEL2(1'b0),
.DEL3(1'b0),
.Z(data_input_temp[i])
);
end
endgenerate

genvar j;
generate
for (j = 0; j < 12; j = j + 1) begin
IFS1P3IX data_reg (
.Q(data_input_delay[j]),
.SP(1'b1),
.CD(rst),
.SCLK(dry),
.D(data_input_temp[j])
);
end
endgenerate

endmodule


the critical warning Diamond drop on me:

2019991 WARNING - CL168 :"C:\----\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[11].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[10].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[9].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\----------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[8].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[7].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[6].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[5].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[4].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[3].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[2].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\---------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[1].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\---------\ADC_Interface\src\top.v":51:12:51:19|Removing instance genblk2[0].data_reg because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\-------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[11].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[10].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\----------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[9].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[8].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\---------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[7].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[6].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\---------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[5].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\---------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[4].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\----------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[3].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\--------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[2].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\----------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[1].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.
2019991 WARNING - CL168 :"C:\-----------\ADC_Interface\src\top.v":37:10:37:14|Removing instance genblk1[0].delay because it does not drive other instances. To preserve this instance, use the syn_noprune synthesis directive.

2019993 WARNING - MT420 |Found inferred clock top|dry with period 5.00ns. Please declare a user-defined clock on port dry.
1166052 WARNING - logical net 'CDIV1' has no load.
1166052 WARNING - logical net 'CDIV4' has no load.
1166052 WARNING - logical net 'CDIV8' has no load.
1166052 WARNING - logical net 'data_input_c[0]' has no load.
1166052 WARNING - logical net 'data_input_c[1]' has no load.
1166052 WARNING - logical net 'data_input_c[2]' has no load.
1166052 WARNING - logical net 'data_input_c[3]' has no load.
1166052 WARNING - logical net 'data_input_c[4]' has no load.
1166052 WARNING - logical net 'data_input_c[5]' has no load.
1166052 WARNING - logical net 'data_input_c[6]' has no load.
1166052 WARNING - logical net 'data_input_c[7]' has no load.
1166052 WARNING - logical net 'data_input_c[8]' has no load.
1166052 WARNING - logical net 'data_input_c[9]' has no load.
1166052 WARNING - logical net 'data_input_c[10]' has no load.
1166052 WARNING - logical net 'data_input_c[11]' has no load.
1163101 WARNING - DRC complete with 15 warnings.
1100523 WARNING - C:/--------/ADC_Interface
51001030    WARNING - Using local reset signal 'rstn_c' to infer global GSR net.


Any Idea why it happening?

• 1) the delay modules are normally not instanced by hand afaik but are part of the automatic DDR instantiation process via IPExpress. 2) over the course of your questions I get the feeling that you try to implement a DDR interface "by hand". The intended way is described here: latticesemi.com/~/media/LatticeSemi/Documents/ApplicationNotes/… - look for ddr generic. – Christian B. Feb 26 '20 at 7:24
• @ChristianB. thanks for the comment. I familiar with this PDF, I did tried to create Generic DDR with LVDS inputs and when its created its became my top module of the project without any success to assign anyother file as top module. Should I keep it as top module and assign the FPGA pins to the signals this IP created? I created: "GDDRX1_RX.SCLK.Aligned" – Michael Astahov Feb 26 '20 at 7:48
• I tried to (ab)use the delay instances as well for a delay line but it turns out that lattice diamond/technology lib is rather rigid if it comes to constraints. So did you manage to use the IPExpress generated DDR by now? Sometimes one has to manually change the main module via the project settings. – Christian B. Feb 26 '20 at 19:49
• @ChristianB. Thanks for the effort and the concern man. I also did understand that using these lattice modules manually its just a big headache. I did had sucess using the IPexpress, I generated the file for this interface and changed it a bit and copy it to another project and in this way overcome the problem that it became top module. Tomorrow I want to try again and open a new project using the IPexpress without any tricks. I think the problem maybe because Im choosing LVDS inputs for the interface so it has to be top module? what you think? – Michael Astahov Feb 26 '20 at 20:08
• anyway ill try tomorrow and open new question if ill had another problem. – Michael Astahov Feb 26 '20 at 20:09

Based on the error and the description "Data going to DDR registers", the DELAYB modules can only be used before PIO register. This may not be able to drive the other registers.

This example is also showing that the DELAYB driving IO register.

Edited :

Further check at the FPGA ref guide shows:

The DELAYB block can also be used to delay non-DDR inputs that use the input PIO register.

This means that the DELAYB block can be used for DDR (probably the IDDR and ODDR components) and PIO registers.

Each PIO includes a sysIO buffer and I/O logic (IOLOGIC). The I/O logic includes input, output and tri-state registers that implement both single data rate (SDR) and double data rate (DDR) applications along with the necessary clock and data selection logic.

• @Rakned Thanks! its helped with the errors but now Im facing new warning which makes the design not to work, can you look on the edited post? – Michael Astahov Feb 26 '20 at 11:31
• @MichaelAstahov May be something wrong with the connections or reset caused the tool to optimize the signals. But I believe it's better to put it as a different question since it may not be due to DELAYB module and some other persons can help. Also, what happened to the adc codes? I hope it's not an xy problem – Rakend Feb 26 '20 at 12:02
• ok ill take your advice and open another question. I commented for now the ADC code (the 3 alwyas block which put rising/falling delayed data in the output register) because for now all I want to see is that the DELAY module works and transfer the data to the 'data_input_delay' register. – Michael Astahov Feb 26 '20 at 13:02
• @MichaelAstahov why don't you try using IDDR for latching ADC data instead of using normal flip flops? This is what we usually do. – Rakend Feb 26 '20 at 13:36
• ok thanks, I had problems with it but I overcome them now in the second try when using the generic DDR lattice provide in IPexpress. So I have some valid data to work with now. Anyways its still intresting why its not working manually :( – Michael Astahov Feb 26 '20 at 13:51