AN 1014: Implementing Analog-to-Digital Converter Multilink Design with Agilex™ 7 FPGA F-Tile JESD204C RX IP

ID 857717
Date 11/24/2025
Public
Document Table of Contents

1.3.1.3. Editing Simulation Testbench for Synchronized ADC to Agilex™ 7 Dual Link

The simulation testbench, tb_top.sv, is located in the simulation/models folder. Follow these steps to edit the testbench.
  1. Open the testbench (tb_top.sv) in a text editor.
  2. Add the LINK parameter at the localparam declaration section. Example:
    localparam LINK = 2;     // Number of IP core in the dual link design
  3. In the instantiation of the F-Tile JESD204C example design modules, include the LINK parameter. Example:
    jesd204c_f_ed_rx #( 
    .LINK (LINK),
    
  4. Add the TX_REG and RX_REG text macros for each additional link. The additional IP instance in this example is intel_jesd204c_f_1 and intel_jesd204c_f_tx_1 and the text macro is TX_REG_1 and RX_REG_1. Example:
    `define TX_REG_1 tb_top.jesd204c_f_ed.u_j204c_f_ss.j204c_f_ip.intel_jesd204c_f_tx_1.intel_jesd204c_f_tx.j204c_f_sip_100_inst.j204c_gdr_tx_base_inst.j204c_gdr_tx_csr_inst.j204c_tx_regmap_inst
            `define RX_REG_1 tb_top.jesd204c_f_ed.u_j204c_f_ss.j204c_f_ip.intel_jesd204c_f_1.intel_jesd204c_f.j204c_f_sip_100_inst.j204c_f_rx_base_inst.j204c_f_rx_csr_inst.j204c_rx_regmap_inst
    
  5. Add the TX_RST_SEQ and RX_RST_SEQ text macros for each additional link. The text macro is TX_RST_SEQ_1 and RX_RST_SEQ_1. Example:
    `define TX_RST_SEQ_1 tb_top.jesd204c_f_ed.u_j204c_f_ss.j204c_f_ip.intel_jesd204c_f_tx_1.intel_jesd204c_f_tx.j204c_f_sip_100_inst.j204c_gdr_sip_rst_seq_tx_inst
            `define RX_RST_SEQ_1 tb_top.jesd204c_f_ed.u_j204c_f_ss.j204c_f_ip.intel_jesd204c_f_1.intel_jesd204c_f.j204c_f_sip_100_inst.j204c_f_sip_rst_seq_rx_inst 
    
  6. Add the TX_TOP and RX_TOP text macros for each additional link. The text macro is TX_TOP_1 and RX_TOP_1. Example:
    `define TX_TOP_1 tb_top.jesd204c_f_ed.u_j204c_f_ss.j204c_f_ip.intel_jesd204c_f_tx_1.intel_jesd204c_f_tx
            `define RX_TOP_1 tb_top.jesd204c_f_ed.u_j204c_f_ss.j204c_f_ip.intel_jesd204c_f_1.intel_jesd204c_f
    
  7. Comment out or delete the sysref_out port at the instantiation of the intel_j204c_f_ed subsystem.
    // Example in Verilog
            //.sysref_out (sysref),
  8. Change the dimension and assignment of the following wires and registers:
    reg [LINK-1:0]     tx_link_error_reg = 1'b0;
            reg [LINK-1:0]     rx_link_error_reg = 1'b0; 
            reg [LINK-1:0]     data_error_reg    = 1'b0;
            reg [LINK-1:0]     cmd_data_error_reg= 1'b0;
    
            wire [LINK*L-1:0]  tx_serial_data;
            wire [LINK*L-1:0]  rx_serial_data;   
            wire [LINK*L-1:0]  tx_serial_data_n;
            wire [LINK*L-1:0]  rx_serial_data_n;
    
            wire [LINK-1:0]    data_valid;       
            wire [LINK-1:0]    data_error;
            wire [LINK-1:0]    tx_link_error;
            wire [LINK-1:0]    rx_link_error;
    
            wire [LINK-1:0]    tx_rst_ack_n;
            wire [LINK-1:0]    rx_rsk_ack_n;
            wire [LINK-1:0]    rx_avst_ready;
            
            wire [LINK-1:0][(TOTAL_SAMPLE*N)-1:0]	rx_avst_data;
    
            wire [LINK-1:0]    cmd_data_valid;
            wire [LINK-1:0]    cmd_data_error;
            wire [LINK-1:0][L*18-1:0]  cmd_data;
            
            wire [LINK-1:0]    tx_err_sysref_lemc_err;
            wire [LINK-1:0]    tx_err_dll_data_invalid_err;
            wire [LINK-1:0]    tx_err_frame_data_invalid_err;
            wire [LINK-1:0]    tx_err_cmd_invalid_err;
            wire [LINK-1:0]    tx_err_tx_ready_err;
            wire [LINK-1:0]    tx_err_pcfifo_full_err;
            wire [LINK-1:0]    tx_err_tx_gb_underflow_err;
            wire [LINK-1:0]    tx_err_tx_gb_overflow_err;
            wire [LINK-1:0]    tx_err_efifo_overflow_err;
            wire [LINK-1:0]    tx_err_src_tx_alarm;
            wire [LINK-1:0]    tx_err_txpll_lock_err;
            wire [LINK-1:0]    tx_err_syspll_lock_err;
            
            wire [LINK-1:0]    rx_err_sysref_lemc_err;
            wire [LINK-1:0]    rx_err_dll_data_ready_err;
            wire [LINK-1:0]    rx_err_frame_data_ready_err;
            wire [LINK-1:0]    rx_err_cmd_ready_err;
            wire [LINK-1:0]    rx_err_cdr_locked_err;
            wire [LINK-1:0]    rx_err_pcfifo_full_err;
            wire [LINK-1:0]    rx_err_pcfifo_empty_err;
            wire [LINK-1:0]    rx_err_lane_deskew_err;
            wire [LINK-1:0]    rx_err_invalid_sync_header;
            wire [LINK-1:0]    rx_err_invalid_eomb;
            wire [LINK-1:0]    rx_err_invalid_eoemb;
            wire [LINK-1:0]    rx_err_cmd_par_err;
            wire [LINK-1:0]    rx_err_crc_err;
            wire [LINK-1:0]    rx_err_rx_gb_underflow_err;
            wire [LINK-1:0]    rx_err_rx_gb_overflow_err;
            wire [LINK-1:0]    rx_err_sh_unlock_err;
            wire [LINK-1:0]    rx_err_emb_unlock_err;
            wire [LINK-1:0]    rx_err_eb_full_err;
            wire [LINK-1:0]    rx_err_ecc_corrected_err;
            wire [LINK-1:0]    rx_err_ecc_fatal_err;
            wire [LINK-1:0]    rx_err_src_rx_alarm;
            wire [LINK-1:0]    rx_err_syspll_lock_err;
            wire [LINK-1:0]    rx_err_fec_uncorr_err;
            wire [LINK-1:0]    rx_err_fec_corr_err;
    
  9. Modify tx_ready and rx_ready so they include all IP’s transceiver channels.
    assign tx_ready  = (&`TX_RST_SEQ.lane_out_of_reset[L-1:0]) & (&`TX_RST_SEQ_1.lane_out_of_reset[L-1:0]);
            assign rx_ready = (&`RX_RST_SEQ.lane_out_of_reset[L-1:0]) & (&`RX_RST_SEQ_1.lane_out_of_reset[L-1:0]);
    
  10. Scale the dimensions of the rx_avst_ready, tx_rst_ack_n, rx_rst_ack_n, and rx_is_lockedtodata assignments according to the number of links. Example for LINK = 2:
    //Scale the dimension to [number of link-1:0]
    assign rx_avst_ready = tb_top.jesd204c_f_ed.rx_avst_ready[1:0];
    
    assign tx_rst_ack_n = tb_top.jesd204c_f_ed.tx_rst_ack_n[1:0];
    assign rx_rst_ack_n = tb_top.jesd204c_f_ed.rx_rst_ack_n[1:0];
    
    assign rx_is_lockedtodata     = 
    (&`RX_TOP.phy_rx_is_lockedtodata[L-1:0]) & 
    (&`RX_TOP_1.phy_rx_is_lockedtodata[L-1:0]);
      
    
  11. Scale the dimensions of the cmd_data_valid, cmd_data_error, and cmd_data assignments according to the number of links. Example for LINK = 2:
    assign cmd_data_valid [0] = `RX_TOP.j204c_rx_cmd_valid;
            assign cmd_data_valid [1] = `RX_TOP_1.j204c_rx_cmd_valid;
            
            assign cmd_data_error = tb_top.jesd204c_f_ed.o_cmd_ramp_chk_err[1:0];
            
            assign cmd_data [0]      = `RX_TOP.j204c_rx_cmd_data;
            assign cmd_data [1]      = `RX_TOP_1.j204c_rx_cmd_data;
    
  12. Add the LINK parameter to the assignment statements for rx_serial_data and rx_serial_data_n as shown below:
    //Internal Loopback
    assign rx_serial_data = INTERNAL_SERIAL_LB ? {LINK*L{1'b0}} : tx_serial_data;      
    assign rx_serial_data_n = INTERNAL_SERIAL_LB ? {LINK*L{1'b0}} : tx_serial_data_n;
    
  13. Add an index to each assignment of the TX and RX IP error. Assign the errors for each link according to the TX and RX IP text macro. Example:
    //TX Error LINK 0
    assign tx_err_sysref_lemc_err [0]       = `TX_REG.tx_err_sysref_lemc_err;
    assign tx_err_dll_data_invalid_err [0]  = `TX_REG.tx_err_dll_data_invalid_err;
    assign tx_err_frame_data_invalid_err[0] = `TX_REG.tx_err_frame_data_invalid_err;
    assign tx_err_cmd_invalid_err [0]       = `TX_REG.tx_err_cmd_invalid_err;
    assign tx_err_tx_gb_underflow_err[0]    = `TX_REG.tx_err_tx_gb_underflow_err;
    assign tx_err_tx_gb_overflow_err[0]     = `TX_REG.tx_err_tx_gb_overflow_err;
    assign tx_err_efifo_overflow_err[0]     = `TX_REG.tx_err_efifo_overflow_err;
    assign tx_err_src_tx_alarm[0]           = `TX_REG.tx_err_src_tx_alarm;
    assign tx_err_txpll_lock_err[0]         = `TX_REG.tx_err_txpll_lock_err;
    assign tx_err_syspll_lock_err[0]        = `TX_REG.tx_err_syspll_lock_err;
    	
    //TX Error LINK 1
    assign tx_err_sysref_lemc_err [1]       = `TX_REG_1.tx_err_sysref_lemc_err;
    assign tx_err_dll_data_invalid_err [1]  = `TX_REG_1.tx_err_dll_data_invalid_err;
    assign tx_err_frame_data_invalid_err[1] = `TX_REG_1.tx_err_frame_data_invalid_err;
    assign tx_err_cmd_invalid_err [1]       = `TX_REG_1.tx_err_cmd_invalid_err;
    assign tx_err_tx_gb_underflow_err[1]    = `TX_REG_1.tx_err_tx_gb_underflow_err;
    assign tx_err_tx_gb_overflow_err[1]     = `TX_REG_1.tx_err_tx_gb_overflow_err;
    assign tx_err_efifo_overflow_err[1]     = `TX_REG_1.tx_err_efifo_overflow_err;
    assign tx_err_src_tx_alarm[1]           = `TX_REG_1.tx_err_src_tx_alarm;
    assign tx_err_txpll_lock_err[1]         = `TX_REG_1.tx_err_txpll_lock_err;
    assign tx_err_syspll_lock_err[1]        = `TX_REG_1.tx_err_syspll_lock_err;
    
    //RX Error LINK 0
    assign rx_err_sysref_lemc_err[0]        = `RX_REG.rx_err_sysref_lemc_err;
    assign rx_err_dll_data_ready_err[0]     = `RX_REG.rx_err_dll_data_ready_err; 
    assign rx_err_frame_data_ready_err[0]   = `RX_REG.rx_err_frame_data_ready_err;
    assign rx_err_cmd_ready_err[0]          = `RX_REG.rx_err_cmd_ready_err;
    assign rx_err_cdr_locked_err[0]         = `RX_REG.rx_err_cdr_locked_err;
    assign rx_err_lane_deskew_err[0]        = `RX_REG.rx_err_lane_deskew_err;
    assign rx_err_invalid_sync_header[0]    = `RX_REG.rx_err_invalid_sync_header;
    assign rx_err_invalid_eomb[0]           = `RX_REG.rx_err_invalid_eomb;
    assign rx_err_invalid_eoemb [0]         = `RX_REG.rx_err_invalid_eoemb;
    assign rx_err_cmd_par_err[0]            = `RX_REG.rx_err_cmd_par_err;
    assign rx_err_crc_err[0]                = `RX_REG.rx_err_crc_err;
    assign rx_err_rx_gb_underflow_err[0]    = `RX_REG.rx_err_rx_gb_underflow_err;
    assign rx_err_rx_gb_overflow_err[0]     = `RX_REG.rx_err_rx_gb_overflow_err;
    assign rx_err_sh_unlock_err[0]          = `RX_REG.rx_err_sh_unlock_err;
    assign rx_err_emb_unlock_err[0]         = `RX_REG.rx_err_emb_unlock_err;
    assign rx_err_eb_full_err[0]            = `RX_REG.rx_err_eb_full_err;
    assign rx_err_ecc_corrected_err[0]      = `RX_REG.rx_err_ecc_corrected_err;
    assign rx_err_ecc_fatal_err [0]         = `RX_REG.rx_err_ecc_fatal_err;
    assign rx_err_src_rx_alarm [0]          = `RX_REG.rx_err_src_rx_alarm;
    assign rx_err_fec_corr_err  [0]         = `RX_REG.rx_err_fec_corr_err;
    assign rx_err_fec_uncorr_err [0]        = `RX_REG.rx_err_fec_uncorr_err;
    assign rx_err_syspll_lock_err [0]       = `RX_REG.rx_err_syspll_lock_err;
    	
    //RX Error LINK 1
    assign rx_err_sysref_lemc_err[1]        = `RX_REG_1.rx_err_sysref_lemc_err;
    assign rx_err_dll_data_ready_err[1]     = `RX_REG_1.rx_err_dll_data_ready_err; 
    assign rx_err_frame_data_ready_err[1]   = `RX_REG_1.rx_err_frame_data_ready_err;
    assign rx_err_cmd_ready_err[1]          = `RX_REG_1.rx_err_cmd_ready_err;
    assign rx_err_cdr_locked_err[1]         = `RX_REG_1.rx_err_cdr_locked_err;
    assign rx_err_lane_deskew_err[1]        = `RX_REG_1.rx_err_lane_deskew_err;
    assign rx_err_invalid_sync_header[1]    = `RX_REG_1.rx_err_invalid_sync_header;
    assign rx_err_invalid_eomb[1]           = `RX_REG_1.rx_err_invalid_eomb;
    assign rx_err_invalid_eoemb [1]         = `RX_REG_1.rx_err_invalid_eoemb;
    assign rx_err_cmd_par_err[1]            = `RX_REG_1.rx_err_cmd_par_err;
    assign rx_err_crc_err[1]                = `RX_REG_1.rx_err_crc_err;
    assign rx_err_rx_gb_underflow_err[1]    = `RX_REG_1.rx_err_rx_gb_underflow_err;
    assign rx_err_rx_gb_overflow_err[1]     = `RX_REG_1.rx_err_rx_gb_overflow_err;
    assign rx_err_sh_unlock_err[1]          = `RX_REG_1.rx_err_sh_unlock_err;
    assign rx_err_emb_unlock_err[1]         = `RX_REG_1.rx_err_emb_unlock_err;
    assign rx_err_eb_full_err[1]            = `RX_REG_1.rx_err_eb_full_err;
    assign rx_err_ecc_corrected_err[1]      = `RX_REG_1.rx_err_ecc_corrected_err;
    assign rx_err_ecc_fatal_err [1]         = `RX_REG_1.rx_err_ecc_fatal_err;
    assign rx_err_src_rx_alarm [1]          = `RX_REG_1.rx_err_src_rx_alarm;
    assign rx_err_fec_corr_err  [1]         = `RX_REG_1.rx_err_fec_corr_err;
    assign rx_err_fec_uncorr_err [1]        = `RX_REG_1.rx_err_fec_uncorr_err;
    assign rx_err_syspll_lock_err [1]       = `RX_REG_1.rx_err_syspll_lock_err;
    
    
  14. Create the generation loops for the data and link error signals:
    genvar i;
    
       // Pass/Fail Mechanism
       //
        generate
        for (i=0; i<LINK; i=i+1) begin: LINK_ERROR
          // Make sure interrupts do not assert
          always @(posedge mgmt_clk or negedge tx_rst_n) begin
             if(!tx_rst_n) 
                tx_link_error_reg[i] <= 1'b0;
             else if (tx_link_error[i] !== 0)
                tx_link_error_reg[i] <= 1'b1;
             else
                tx_link_error_reg[i] <= tx_link_error_reg[i]; 
          end
    
          always @(posedge mgmt_clk or negedge rx_rst_n) begin
             if(!rx_rst_n)
                rx_link_error_reg[i] <= 1'b0;
             else if (rx_link_error[i] !== 0)
                rx_link_error_reg[i] <= 1'b1;
             else
                rx_link_error_reg[i] <= rx_link_error_reg[i];
          end
    
          always @ (posedge data_error or negedge rx_rst_n) begin
             if (!rx_rst_n)
                data_error_reg[i] <= 1'b0;
             else if (data_valid[i] === 1'b1)
                data_error_reg[i] <= 1'b1;
          end
    
          always @ (posedge cmd_data_error or negedge rx_rst_n) begin
             if (!rx_rst_n)
                cmd_data_error_reg[i] <= 1'b0;
             else if (cmd_data_valid[i] === 1'b1)
                cmd_data_error_reg[i] <= 1'b1;
          end
       end
       endgenerate
    
  15. To monitor the combined simulation results of the dual link, modify the test_passed assignment statement so that, if the IP in any of the links has an interrupt or error, the simulation reports failure:
    assign test_passed = 
    (|data_error_reg===1'b0) & 
    (|cmd_data_error_reg===1'b0) & 
    (|tx_link_error_reg===1'b0) & 
    (|rx_link_error_reg===1'b0) & 
    (sh_lock_out===1'b1) & 
    (emb_lock_out===1'b1) & 
    (rx_is_lockedtodata===1'b1) & 
    (tx_ready===1'b1) & 
    (rx_ready===1'b1);
  16. Edit the criteria for displaying the link error message for data_error_reg, cmd_data_error_reg, tx_link_error_reg, and rx_link_error_reg signals so that, if the IP in any of the links has an interrupt, the simulation reports failure. Example:
    wait(&data_valid===1'b1); //AND the valid signals wait
            wait(&cmd_data_valid===1'b1); //AND the valid signals
    
             if (&data_valid===1'b1) begin                        
                if (|data_error_reg===1'b1) begin
                    $display("Pattern Checker(s): Data error(s) found!");
                end else begin
                    $display("Pattern Checker(s): OK!");
                end       
              end 
              else begin
                if (|rx_avst_data===0) begin
                    $display("Pattern Checker(s): No valid data found!");
                end else begin
                    if (|data_error_reg===1'b1) begin
                        $display("Pattern Checker(s): Data error(s) found!");
                    end else begin
                        $display("Pattern Checker(s): OK!");
                    end       
                end
              end
             
    
              if (&cmd_data_valid===1'b1) begin                        
                if (|cmd_data_error_reg===1'b1) begin
                    $display("Command Channel Pattern Checker(s): Data error(s) found!");
                end else begin
                    $display("Command Channel Pattern Checker(s): OK!");
                end       
              end else begin
               if (|cmd_data===0) begin
                    $display("Command Channel Pattern Checker(s): No valid data found!");
                end else begin
                    if (|cmd_data_error_reg===1'b1) begin
                        $display("Command Channel Pattern Checker(s): Data error(s) found!");
                    end else begin
                        $display("Command Channel Pattern Checker(s): OK!");
                    end       
                end
               end
    
                if (|tx_link_error_reg===1'b1) begin
                    $display("JESD204C Tx Core(s): Tx link error(s) found!");
                end else begin
                    $display("JESD204C Tx Core(s): OK!");
                end
                 
                if (|rx_link_error_reg===1'b1) begin
                    $display("JESD204C Rx Core(s): Rx link error(s) found!");
                end else begin
                    $display("JESD204C Rx Core(s): OK!");
                end