###### tags: `caraval-fpga` # add delay in verilog ## issue 1 (root cause is relative to inertial delay and update in below) I found the waveform in delay 13ns is incorrect. ``` assign #13 Serial_Data_Out_by_assign_13ns = Serial_Data_Out; ``` ## issue 2 Serial_Data_Out_delay with glitch I also implement a module name dly_line to simulation the behavior for delay. - I found the input source impact the result. - When I input ioclk then the result is ok. - When I input Serial_Data_Out then the result in Serial_Data_Out_delay with glitch. ![](https://hackmd.io/_uploads/r1xiqpsch.png) ## issue 3 (root cuase is the same as issue 1) There are another issue in assign with delay ``` assign #3 ioclk_by_assign_3ns = ioclk; assign #8 ioclk_by_assign_8ns = ioclk; assign #13 ioclk_by_assign_13ns = ioclk; ``` - ioclk_by_assign_3ns is ok - ioclk_by_assign_8ns is incorrect - ioclk_by_assign_13ns is incorrect ## result below net result is not meet my expectation. Why??? - Serial_Data_Out_by_assign_13ns - ioclk_by_assign_8ns - ioclk_by_assign_13ns - Serial_Data_Out_delay ![](https://hackmd.io/_uploads/SkTcCPTLn.png) ## code - fsic_io_serdes_m2.v ``` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 05/26/2023 05:10:17 PM // Design Name: // Module Name: sfic_io_serdes // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// //for ioserdes method 2 module fsic_io_serdes_tx_m2#( parameter TxFIFO_DEPTH = 4, parameter CLK_RATIO =4 ) ( input rst, output txclk, input ioclk, input coreclk, output Serial_Data_Out, input [CLK_RATIO-1:0] txdata_in ); reg tx_en; reg [7:0] tx_en_phase_cnt; always @(negedge ioclk) begin if (rst ) begin tx_en_phase_cnt <= 0; end else begin tx_en_phase_cnt <= tx_en_phase_cnt+1; end end always @(negedge ioclk) begin if (rst ) begin tx_en <= 0; end else begin if (tx_en_phase_cnt > 82) tx_en <= 1; else tx_en <= tx_en; end end reg [$clog2(CLK_RATIO)-1:0] tx_shift_phase_cnt; always @(posedge ioclk) begin if (rst ) begin tx_shift_phase_cnt <= 3; end else begin if (tx_en) tx_shift_phase_cnt <= tx_shift_phase_cnt + 1; else tx_shift_phase_cnt <= tx_shift_phase_cnt; end end assign Serial_Data_Out= txdata_in[tx_shift_phase_cnt] & tx_en ; assign txclk = ioclk&tx_en; //use negedge to avoid glitch in txclk. endmodule ``` ## code - delay_line.v ``` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 06/06/2023 03:37:37 PM // Design Name: // Module Name: delay_line // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module dly_line #( parameter SHIFT_DEPTH = 13 ) ( input dlyclk, input dly_in, input rst, output dly_out ); reg [SHIFT_DEPTH-1:0] ShiftReg; assign dly_out = ShiftReg[SHIFT_DEPTH-1]; always @(posedge dlyclk) begin if (rst) begin ShiftReg <= 0; end else begin ShiftReg[0] <= dly_in; ShiftReg[SHIFT_DEPTH-1:1] <= ShiftReg[SHIFT_DEPTH-2:0]; end end endmodule ``` ## testbench ``` `timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 06/06/2023 03:38:53 PM // Design Name: // Module Name: tb // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module tb#( parameter SHIFT_DEPTH = 13, parameter RxFIFO_DEPTH = 4, parameter CLK_RATIO = 4 ) ( ); reg rst; reg ioclk; reg dlyclk; reg coreclk_tx; reg [CLK_RATIO-1:0] txdata_in; assign #3 Serial_Data_Out_by_assign_3ns = Serial_Data_Out; assign #8 Serial_Data_Out_by_assign_8ns = Serial_Data_Out; assign #13 Serial_Data_Out_by_assign_13ns = Serial_Data_Out; assign #3 ioclk_by_assign_3ns = ioclk; assign #8 ioclk_by_assign_8ns = ioclk; assign #13 ioclk_by_assign_13ns = ioclk; fsic_io_serdes_tx_m2 #( .RxFIFO_DEPTH(RxFIFO_DEPTH), .CLK_RATIO(CLK_RATIO) ) fsic_io_serdes_tx_m2_1( .rst(rst), .txclk(txclk), .ioclk(ioclk), .coreclk(coreclk_tx), .Serial_Data_Out(Serial_Data_Out), .txdata_in(txdata_in) ); dly_line #( .SHIFT_DEPTH(10) ) dly_line_ioclk( .rst(rst), .dlyclk(dlyclk), .dly_in(ioclk), .dly_out(ioclk_delay) ); dly_line #( .SHIFT_DEPTH(10) ) dly_line_Serial_Data_Out( .rst(rst), .dlyclk(dlyclk), .dly_in(Serial_Data_Out), .dly_out(Serial_Data_Out_delay) ); reg[7:0]idx; initial begin rst = 1; dlyclk = 1; ioclk = 1; coreclk_tx = 1; #20; rst = 0; txdata_in = 0; #820; for(idx=0; idx<32; idx=idx+1)begin #40 txdata_in = idx; end #200; $finish; end always #20 coreclk_tx = ~coreclk_tx; always #5 ioclk = ~ioclk; always #0.5 dlyclk = ~dlyclk; endmodule ``` ## root cause ### issue 1: assign delay time issue - only delay 1ns to 5ns is correct, when delay time > 5ns then result is incorrect. ``` assign #1 ioclk_by_assign_1ns = ioclk; assign #2 ioclk_by_assign_2ns = ioclk; assign #3 ioclk_by_assign_3ns = ioclk; assign #4 ioclk_by_assign_4ns = ioclk; assign #5 ioclk_by_assign_5ns = ioclk; assign #6 ioclk_by_assign_6ns = ioclk; assign #7 ioclk_by_assign_7ns = ioclk; assign #8 ioclk_by_assign_8ns = ioclk; assign #9 ioclk_by_assign_9ns = ioclk; assign #10 ioclk_by_assign_10ns = ioclk; assign #11 ioclk_by_assign_11ns = ioclk; assign #12 ioclk_by_assign_12ns = ioclk; assign #13 ioclk_by_assign_13ns = ioclk; assign #14 ioclk_by_assign_14ns = ioclk; assign #15 ioclk_by_assign_15ns = ioclk; assign #16 ioclk_by_assign_16ns = ioclk; assign #17 ioclk_by_assign_17ns = ioclk; assign #18 ioclk_by_assign_18ns = ioclk; assign #19 ioclk_by_assign_19ns = ioclk; assign #20 ioclk_by_assign_20ns = ioclk; ``` ![](https://hackmd.io/_uploads/rkd_T7kPh.png) ### root cause of issue 1 - the ioclok pulse width is 5ns then verilog filter the pulse when in Inertial delay models(default) reference http://twins.ee.nctu.edu.tw/courses/ip_core_04/resource_pdf/cummings_final.pdf #### solution 1. use 2 or more stages to assign delay time. ``` assign #1 ioclk_by_assign_1ns = ioclk; assign #2 ioclk_by_assign_2ns = ioclk; assign #3 ioclk_by_assign_3ns = ioclk; assign #4 ioclk_by_assign_4ns = ioclk; assign #5 ioclk_by_assign_5ns = ioclk; assign #5 ioclk_by_assign_6ns = ioclk_by_assign_1ns; assign #5 ioclk_by_assign_7ns = ioclk_by_assign_2ns; assign #5 ioclk_by_assign_8ns = ioclk_by_assign_3ns; assign #5 ioclk_by_assign_9ns = ioclk_by_assign_4ns; assign #5 ioclk_by_assign_10ns = ioclk_by_assign_5ns; ``` ![](https://hackmd.io/_uploads/HJgoJSyv3.png) Or 2. use transport delay model(I don't know how to do in verilog), I do a lot of serach but not found example in vivado. reference https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug900-vivado-logic-simulation.pdf ![](https://hackmd.io/_uploads/SkXIMH1D2.png) ### root cause issue 2: Serial_Data_Out_delay with glitch update testbench code then pass #### code with issue ``` for(idx=0; idx<32; idx=idx+1)begin #40 txdata_in = idx; end ``` #### method 1 : using @(posedge coreclk_tx); ``` for(idx=0; idx<32; idx=idx+1)begin @(posedge coreclk_tx); //using @(posedge coreclk_tx) //#40; txdata_in = idx; end ``` #### method 2 : using Non-block assigment ``` for(idx=0; idx<32; idx=idx+1)begin #40; txdata_in <= idx; //using Non-block assigment end ``` #### method 3 : both method 1 and method 2 ``` for(idx=0; idx<32; idx=idx+1)begin @(posedge coreclk_tx); //using @(posedge coreclk_tx) //#40; txdata_in <= idx; //using Non-block assigment end ``` ![](https://hackmd.io/_uploads/S1EKj6j92.png)