From cc1687104fb9be739b3e96e78614890aae2e8174 Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Wed, 3 Dec 2025 11:22:08 +0200 Subject: [PATCH 01/10] project/ada4355: Testbench --- testbenches/project/ada4355/Makefile | 41 +++ testbenches/project/ada4355/README.md | 26 ++ testbenches/project/ada4355/cfgs/cfg1.tcl | 3 + testbenches/project/ada4355/cfgs/cfg2.tcl | 3 + testbenches/project/ada4355/system_bd.tcl | 60 ++++ .../project/ada4355/system_project.tcl | 35 ++ testbenches/project/ada4355/system_tb.sv | 169 +++++++++ .../project/ada4355/tests/test_program.sv | 311 ++++++++++++++++ testbenches/project/ada4355/waves/cfg1.wcfg | 337 ++++++++++++++++++ testbenches/project/ada4355/waves/cfg2.wcfg | 50 +++ 10 files changed, 1035 insertions(+) create mode 100644 testbenches/project/ada4355/Makefile create mode 100644 testbenches/project/ada4355/README.md create mode 100644 testbenches/project/ada4355/cfgs/cfg1.tcl create mode 100644 testbenches/project/ada4355/cfgs/cfg2.tcl create mode 100644 testbenches/project/ada4355/system_bd.tcl create mode 100644 testbenches/project/ada4355/system_project.tcl create mode 100644 testbenches/project/ada4355/system_tb.sv create mode 100644 testbenches/project/ada4355/tests/test_program.sv create mode 100644 testbenches/project/ada4355/waves/cfg1.wcfg create mode 100644 testbenches/project/ada4355/waves/cfg2.wcfg diff --git a/testbenches/project/ada4355/Makefile b/testbenches/project/ada4355/Makefile new file mode 100644 index 000000000..53b571536 --- /dev/null +++ b/testbenches/project/ada4355/Makefile @@ -0,0 +1,41 @@ +#################################################################################### +#################################################################################### +## Copyright 2025 (c) Analog Devices, Inc. +#################################################################################### +#################################################################################### + +# Makeincludes +include ../../../scripts/make_tb_path.mk +include $(ADI_TB_DIR)/library/includes/Makeinclude_common.mk +include $(ADI_TB_DIR)/library/includes/Makeinclude_dmac.mk +include $(ADI_TB_DIR)/library/includes/Makeinclude_converter.mk + +LIB_DEPS += axi_ada4355 +LIB_DEPS += axi_dmac +LIB_DEPS += axi_sysid +LIB_DEPS += sysid_rom + +# default test programs +# Format is: +TP := $(notdir $(basename $(wildcard tests/*.sv))) + +# config files should have the following format +# cfg__.tcl +CFG_FILES := $(notdir $(wildcard cfgs/cfg*.tcl)) + +# List of tests and configuration combinations that has to be run +# Format is: : +TESTS := $(foreach cfg, $(basename $(CFG_FILES)), $(addprefix $(cfg):, $(TP))) + +include $(ADI_TB_DIR)/scripts/project-sim.mk + +# usage : +# +# run specific test on a specific configuration in gui mode +# make CFG= TST= MODE=gui +# +# run all test from a configuration +# make + +#################################################################################### +#################################################################################### diff --git a/testbenches/project/ada4355/README.md b/testbenches/project/ada4355/README.md new file mode 100644 index 000000000..c84107f5a --- /dev/null +++ b/testbenches/project/ada4355/README.md @@ -0,0 +1,26 @@ +Usage : + +Run all tests in batch mode: + + make + + +Run all tests in GUI mode: + + make MODE=gui + + +Run specific test on a specific configuration in gui mode: + + make CFG= TST= MODE=gui + + +Run all test from a configuration: + + make + + +Where: + + * is a file from the cfgs directory without the tcl extension of format cfg\* + * is a file from the tests directory without the tcl extension diff --git a/testbenches/project/ada4355/cfgs/cfg1.tcl b/testbenches/project/ada4355/cfgs/cfg1.tcl new file mode 100644 index 000000000..a5fc9616d --- /dev/null +++ b/testbenches/project/ada4355/cfgs/cfg1.tcl @@ -0,0 +1,3 @@ +global ad_project_params + +set ad_project_params(BUFMRCE_EN) 1 diff --git a/testbenches/project/ada4355/cfgs/cfg2.tcl b/testbenches/project/ada4355/cfgs/cfg2.tcl new file mode 100644 index 000000000..cc21b7c06 --- /dev/null +++ b/testbenches/project/ada4355/cfgs/cfg2.tcl @@ -0,0 +1,3 @@ +global ad_project_params + +set ad_project_params(BUFMRCE_EN) 0 diff --git a/testbenches/project/ada4355/system_bd.tcl b/testbenches/project/ada4355/system_bd.tcl new file mode 100644 index 000000000..741261454 --- /dev/null +++ b/testbenches/project/ada4355/system_bd.tcl @@ -0,0 +1,60 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright 2025 (c) Analog Devices, Inc. All rights reserved. +# +# In this HDL repository, there are many different and unique modules, consisting +# of various HDL (Verilog or VHDL) components. The individual modules are +# developed independently, and may be accompanied by separate and unique license +# terms. +# +# The user should read each of these license terms, and understand the +# freedoms and responsibilities that he or she has by using this source/core. +# +# This core is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. +# +# Redistribution and use of source or resulting binaries, with or without modification +# of this file, are permitted under one of the following two license terms: +# +# 1. The GNU General Public License version 2 as published by the +# Free Software Foundation, which can be found in the top level directory +# of this repository (LICENSE_GPL2), and also online at: +# +# +# OR +# +# 2. An ADI specific BSD license, which can be found in the top level directory +# of this repository (LICENSE_ADIBSD), and also on-line at: +# https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +# This will allow to generate bit files and not release the source code, +# as long as it attaches to an ADI device. +# +# *************************************************************************** +# *************************************************************************** + +source ../../../../scripts/adi_env.tcl + +# system level parameters +set BUFMRCE_EN $ad_project_params(BUFMRCE_EN) + +global ad_project_params + +# +# Block design under test +# +# +source $ad_hdl_dir/projects/ada4355_fmc/common/ada4355_fmc_bd.tcl + +# Define and verify base addresses from the block design +set BA_ADA4355_ADC 0x44A00000 +set_property offset $BA_ADA4355_ADC [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_data_axi_ada4355_adc}] +adi_sim_add_define "ADA4355_ADC_BA=[format "%d" ${BA_ADA4355_ADC}]" + +set BA_ADA4355_DMA 0x44A30000 +set_property offset $BA_ADA4355_DMA [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_data_axi_ada4355_dma}] +adi_sim_add_define "ADA4355_DMA_BA=[format "%d" ${BA_ADA4355_DMA}]" + +set BA_DDR 0x80000000 +set_property offset $BA_DDR [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_mng_ddr_cntlr}] +adi_sim_add_define "DDR_BA=[format "%d" ${BA_DDR}]" diff --git a/testbenches/project/ada4355/system_project.tcl b/testbenches/project/ada4355/system_project.tcl new file mode 100644 index 000000000..0cf17271d --- /dev/null +++ b/testbenches/project/ada4355/system_project.tcl @@ -0,0 +1,35 @@ +source ../../../scripts/adi_sim.tcl +source ../../../../scripts/adi_env.tcl +source $ad_hdl_dir/projects/scripts/adi_board.tcl + +if {$argc < 1} { + puts "Expecting at least one argument that specifies the test configuration" + exit 1 +} else { + set cfg_file [lindex $argv 0] +} + +# Read common config file +source "cfgs/${cfg_file}" + +# Set the project name +set project_name [file rootname $cfg_file] + +#set a default test program +adi_sim_add_define "TEST_PROGRAM=test_program" + +# Create the project +adi_sim_project_xilinx $project_name "xc7z020clg484-1" ; + +# Source the include files for package dependencies +source $ad_tb_dir/library/includes/sp_include_common.tcl +source $ad_tb_dir/library/includes/sp_include_dmac.tcl +source $ad_tb_dir/library/includes/sp_include_converter.tcl + +# Add test files to the project +adi_sim_project_files [list \ + "tests/test_program.sv" \ + "system_tb.sv" \ + ] + +adi_sim_generate $project_name diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv new file mode 100644 index 000000000..0640b1672 --- /dev/null +++ b/testbenches/project/ada4355/system_tb.sv @@ -0,0 +1,169 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2025 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/1ps + +`include "utils.svh" + +module system_tb #( +) (); + + localparam DCO_HALF_PERIOD = 1; // Period 2 ns -> 500 MHz DCO + localparam FRAME_HALF_PERIOD = 4; // Period 8 ns -> 125 MHz Frame + localparam BITS_PER_CYCLE = 2 * 2; + localparam LATENCY = 3; + + reg sync_n = 1'b0; + reg ssi_clk = 1'b0; + reg frame_clk = 1'b0; + reg div_clock = 1'b0; + reg enable_pattern = 1'b0; + reg dco_p = 1'b0; + reg dco_n = 1'b1; + reg frame_clock_p = 1'b0; + reg frame_clock_n = 1'b0; + reg late_signal_p = 1'b0; + reg late_signal_n = 1'b0; + + `TEST_PROGRAM test(); + + test_harness `TH ( + + .dco_p (dco_p), + .dco_n (dco_n), + .d0a_p (da_p), + .d0a_n (da_n), + .d1a_p (db_p), + .d1a_n (db_n), + .sync_n (sync_n), + .frame_p (frame_clock_p), + .frame_n (frame_clock_n) + ); + + reg sync_n_d = 1'b0; + // Add some transport delay to simulate PCB and clock chip propagation delay + always @(*) sync_n_d <= #25 sync_n; + + // Add transport delay to the DCO clock to simulate longer internal delay of + // the clock path inside the FPGA + always @(*) dco_p <= #3 ssi_clk; + always @(*) dco_n <= #3 ~ssi_clk; + + always @(*) frame_clock_p <= frame_clk; + always @(*) frame_clock_n <= ~frame_clk; + + // + // Clock generation + // + // Start clocks with rising edge once sync_n_d deasserts + initial begin + #1; + @(posedge sync_n_d); + while (sync_n_d) begin + ssi_clk <= ~ssi_clk; + #DCO_HALF_PERIOD; + end + ssi_clk <= 1'b0; + end + + // Starts frame clock + + initial begin + #1; + @(posedge sync_n_d); + while (sync_n_d) begin + frame_clk <= ~frame_clk; + #FRAME_HALF_PERIOD; + end + end + + initial begin + #1; + @(posedge sync_n_d); + while (sync_n_d) begin + div_clock <= ~div_clock; + #FRAME_HALF_PERIOD; + end + end + + always @(*) late_signal_p <= #3 div_clock; + always @(*) late_signal_n <= #3 ~div_clock; + + // Data generation + + reg [15:0] sample = 16'h0; + + reg da_p = 1'b0; + reg da_n = 1'b1; + reg db_p = 1'b0; + reg db_n = 1'b1; + wire [15:0] final_sample; + assign final_sample = sample; + always @(posedge frame_clock_p) begin + repeat (LATENCY) @(posedge ssi_clk); + fork + begin + drive_sample(final_sample); + end + join_none + #1; + + if (sample == 16'hFFFF) begin + sample = 0; + end else begin + sample = sample + 2; + end + end + + task automatic drive_sample(bit [15:0] sample_t); + int num_lanes = 2; + int bits_per_cycle = num_lanes * 2; + for (int i = 15; i >= 0; i=i-bits_per_cycle) begin + @(negedge ssi_clk); + #1; + da_p <= sample_t[i]; + da_n <= ~sample_t[i]; + db_p <= sample_t[i-1]; + db_n <= ~sample_t[i-1]; + @(posedge ssi_clk); + #1; + da_p <= sample_t[i-2]; + da_n <= ~sample_t[i-2]; + db_p <= sample_t[i-3]; + db_n <= ~sample_t[i-3]; + end + endtask + +endmodule diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv new file mode 100644 index 000000000..4368eb9f3 --- /dev/null +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -0,0 +1,311 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2025 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** +// +// + +`include "utils.svh" + +import axi_vip_pkg::*; +import axi4stream_vip_pkg::*; +import adi_regmap_pkg::*; +import adi_regmap_dmac_pkg::*; +import adi_regmap_adc_pkg::*; +import adi_regmap_common_pkg::*; +import logger_pkg::*; +import test_harness_env_pkg::*; +import adi_axi_agent_pkg::*; +import dmac_api_pkg::*; +import adc_api_pkg::*; +import common_api_pkg::*; + +import `PKGIFY(test_harness, mng_axi_vip)::*; +import `PKGIFY(test_harness, ddr_axi_vip)::*; + +program test_program; + + // Base address from block design + parameter BASE = `ADA4355_ADC_BA; + + // Delay control registers offset + parameter RX_DELAY_BASE = BASE + 'h02_00 * 4; + + // ADA4355 specific register + parameter REGMAP_ENABLE = BASE + 'h00C8; + + // Module-level variables used in tasks + int num_lanes = 2; + int sdr_ddr_n = 0; + + test_harness_env env; + adi_axi_master_agent #(`AXI_VIP_PARAMS(test_harness, mng_axi_vip)) mng; + adi_axi_slave_mem_agent #(`AXI_VIP_PARAMS(test_harness, ddr_axi_vip)) ddr; + + // API instances + dmac_api rx_dma_api; + adc_api rx_adc_api; + common_api rx_common_api; + + bit [31:0] val; + + +// -------------------------- +// Main procedure +// -------------------------- + +initial begin + + //creating environment + env = new( + .name("Test Environment"), + .sys_clk_vip_if(`TH.`SYS_CLK.inst.IF), + .dma_clk_vip_if(`TH.`DMA_CLK.inst.IF), + .ddr_clk_vip_if(`TH.`DDR_CLK.inst.IF), + .sys_rst_vip_if(`TH.`SYS_RST.inst.IF), + .irq_base_address(`IRQ_C_BA), + .irq_vip_if(`TH.`IRQ.inst.inst.IF.vif)); + + mng = new(.name(""), .master_vip_if(`TH.`MNG_AXI.inst.IF)); + ddr = new(.name(""), .slave_vip_if(`TH.`DDR_AXI.inst.IF)); + + `LINK(mng, env, mng) + `LINK(ddr, env, ddr) + + // Initialize API instances + rx_dma_api = new(.name("RX DMA API"), + .bus(env.mng.master_sequencer), + .base_address(`ADA4355_DMA_BA)); + + rx_adc_api = new(.name("RX ADC API"), + .bus(env.mng.master_sequencer), + .base_address(BASE)); + + rx_common_api = new(.name("RX Common API"), + .bus(env.mng.master_sequencer), + .base_address(BASE)); + + setLoggerVerbosity(ADI_VERBOSITY_NONE); + env.start(); + + // System reset + env.sys_reset(); + + sanity_test; + + dma_test; + + #1000ns; + ada4355_regmap; + + #7000ns; + misaligned_frame; + + #7000ns; + resync; + + // Tap value for lane 0 + env.mng.master_sequencer.RegWrite32(RX_DELAY_BASE + 'h0, 15); + env.mng.master_sequencer.RegWrite32(RX_DELAY_BASE + 'h4, 10); + + `INFO(("Test Done"), ADI_VERBOSITY_NONE); + +end + +// -------------------------- +// Sanity test reg interface +// -------------------------- + +task sanity_test; +begin + // Run sanity tests for all APIs + rx_common_api.sanity_test(); + rx_dma_api.sanity_test(); + + `INFO(("Sanity Test Done"), ADI_VERBOSITY_LOW); +end +endtask + +// -------------------------- +// Setup link +// -------------------------- + +task link_setup; +begin + + // Configure Rx interface + rx_adc_api.set_common_control( + .pin_mode(1'b0), + .ddr_edgesel(1'b0), + .r1_mode(1'b0), + .sync(1'b0), + .num_lanes(num_lanes), + .symb_8_16b(1'b0), + .symb_op(1'b0), + .sdr_ddr_n(sdr_ddr_n)); + + // pull out RX of reset + rx_adc_api.reset(.ce_n(1'b1), .mmcm_rstn(1'b1), .rstn(1'b1)); + + force system_tb.sync_n = 1'b1; + #10ns; + +end +endtask + +task resync; +begin + bit [31:0] current_val; + + rx_adc_api.axi_read(GetAddrs(ADC_COMMON_REG_CNTRL), current_val); + rx_adc_api.axi_write(GetAddrs(ADC_COMMON_REG_CNTRL), current_val | 32'h8); + +end +endtask + +task misaligned_frame; +begin + + rx_adc_api.set_common_control_3(.crc_en(1'b0), .custom_control(8'h1)); + +end +endtask + +task ada4355_regmap; +begin + bit [31:0] regmap_val; + + `INFO(("Inside ada4355_regmap task"), ADI_VERBOSITY_LOW); + env.mng.master_sequencer.RegWrite32(REGMAP_ENABLE, 4); + `INFO(("After write ada4355_regmap task"), ADI_VERBOSITY_LOW); + env.mng.master_sequencer.RegRead32(REGMAP_ENABLE, regmap_val); + `INFO(("Regmap Value 0x%h", regmap_val), ADI_VERBOSITY_LOW); +end +endtask + +// -------------------------- +// Enable pattern +// -------------------------- + +task enable_pattern; +begin + logic sync_stat; + + force system_tb.enable_pattern = 1'b1; + `INFO(("Force enable_pattern = 1"), ADI_VERBOSITY_LOW); + + rx_adc_api.set_common_control_3(.crc_en(1'b0), .custom_control(8'h2)); + + rx_adc_api.set_common_control( + .pin_mode(1'b0), + .ddr_edgesel(1'b0), + .r1_mode(1'b0), + .sync(1'b1), // sync enabled + .num_lanes(num_lanes), + .symb_8_16b(1'b0), + .symb_op(1'b0), + .sdr_ddr_n(sdr_ddr_n)); + + rx_adc_api.get_sync_status(sync_stat); + `INFO(("Sync status = %0d", sync_stat), ADI_VERBOSITY_LOW); + + force system_tb.enable_pattern = 1'b0; + `INFO(("Force enable_pattern = 0"), ADI_VERBOSITY_LOW); + +end +endtask + +// -------------------------- +// DMA test procedure +// -------------------------- + +task dma_test; +begin + + link_setup; + + `INFO(("Link Setup Done"), ADI_VERBOSITY_LOW); + + #1us; + + // Configure RX DMA + rx_dma_api.enable_dma(); + rx_dma_api.set_flags( + .cyclic(1'b0), + .tlast(1'b1), + .partial_reporting_en(1'b0)); + rx_dma_api.set_lengths(.xfer_length_x(64*4-1), .xfer_length_y(0)); + rx_dma_api.set_dest_addr(.xfer_addr(`DDR_BA+32'h00002000)); + rx_dma_api.transfer_start(); + + `INFO(("Configure RX DMA Done"), ADI_VERBOSITY_LOW); + + enable_pattern; + + `INFO(("Enable Pattern Done"), ADI_VERBOSITY_LOW); + +end +endtask + +// Check captured data against incremental pattern based on first sample +// Pattern should be contiguous +task check_captured_data(bit [31:0] address, + int length = 1024, + int step = 1, + int max_sample = 2048 + ); + + bit [31:0] current_address; + bit [31:0] captured_word; + bit [31:0] reference_word; + bit [19:0] first; + + for (int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sync_n + sync_n + + + sync_n_d + sync_n_d + + + ssi_clk + ssi_clk + + + serdes_reset_s + serdes_reset_s + + + serdes_reset_d + serdes_reset_d + + + bitslip_enable + bitslip_enable + + + pattern_value[7:0] + pattern_value[7:0] + + + sync_status_int + sync_status_int + + + Signals + label + + + frame_clk + frame_clk + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + STYLE_DIGITAL + + + frame_clock_p + frame_clock_p + + + serdes_data_frame[7:0] + serdes_data_frame[7:0] + + + serdes_data_frame_d[7:0] + serdes_data_frame_d[7:0] + + + data_frame_shifted[7:0] + data_frame_shifted[7:0] + + + adc_clk_div + adc_clk_div + + + serdes_frame[7:0] + serdes_frame[7:0] + + + data_frame_shifted[7:0] + data_frame_shifted[7:0] + + + shift_cnt[2:0] + shift_cnt[2:0] + #FFA500 + true + + + state[2:0] + state[2:0] + + + da_p + da_p + + + db_p + db_p + + + frame_clock_p + frame_clock_p + + + Q1 + Q1 + + + Q2 + Q2 + + + Q3 + Q3 + + + Q4 + Q4 + + + Q5 + Q5 + + + Q6 + Q6 + + + Q7 + Q7 + + + Q8 + Q8 + + + adc_data[15:0] + adc_data[15:0] + STYLE_ANALOG + 100 + + + serdes_valid[1:0] + serdes_valid[1:0] + + + serdes_valid_d[1:0] + serdes_valid_d[1:0] + + + serdes_data_16[15:0] + serdes_data_16[15:0] + + + serdes_data_16_d[15:0] + serdes_data_16_d[15:0] + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + + + + + O + O + + + Q1 + Q1 + + + Q2 + Q2 + + + Q3 + Q3 + + + Q4 + Q4 + + + Q5 + Q5 + + + Q6 + Q6 + + + Q7 + Q7 + + + Q8 + Q8 + + + SHIFTOUT1 + SHIFTOUT1 + + + SHIFTOUT2 + SHIFTOUT2 + + + BITSLIP + BITSLIP + + + SHIFTOUT1 + SHIFTOUT1 + + + SHIFTOUT2 + SHIFTOUT2 + + + state[2:0] + state[2:0] + + + serdes_reset_s + serdes_reset_s + + + serdes_reset_d + serdes_reset_d + + + adc_clk_div + adc_clk_div + + + serdes_data_frame_d[7:0] + serdes_data_frame_d[7:0] + + + serdes_data_frame[7:0] + serdes_data_frame[7:0] + + + data_frame_shifted[7:0] + data_frame_shifted[7:0] + + + shift_cnt[2:0] + shift_cnt[2:0] + + + final_sample[15:0] + final_sample[15:0] + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + + + da_p + da_p + + + db_p + db_p + + + serdes_valid[1:0] + serdes_valid[1:0] + + + serdes_valid_d[1:0] + serdes_valid_d[1:0] + + + serdes_data_0[7:0] + serdes_data_0[7:0] + + + + serdes_data_1[7:0] + serdes_data_1[7:0] + + + serdes_data[15:0] + serdes_data[15:0] + + + serdes_data_16[15:0] + serdes_data_16[15:0] + + + serdes_data_16_d[15:0] + serdes_data_16_d[15:0] + + + da_p + da_p + + + db_p + db_p + + diff --git a/testbenches/project/ada4355/waves/cfg2.wcfg b/testbenches/project/ada4355/waves/cfg2.wcfg new file mode 100644 index 000000000..192b2a2b4 --- /dev/null +++ b/testbenches/project/ada4355/waves/cfg2.wcfg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 43c9e1b1ad1fc1d1cfe0e39a6f0b30b7d17956ca Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Wed, 3 Dec 2025 17:13:51 +0200 Subject: [PATCH 02/10] ada4355: Fix sanity_test_error Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/tests/test_program.sv | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index 4368eb9f3..407b46a03 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -148,8 +148,11 @@ end task sanity_test; begin - // Run sanity tests for all APIs - rx_common_api.sanity_test(); + // check ADC VERSION + env.mng.master_sequencer.RegReadVerify32(BASE + GetAddrs(COMMON_REG_VERSION), + `SET_COMMON_REG_VERSION_VERSION('h000a0300)); + + // Run DMA sanity test rx_dma_api.sanity_test(); `INFO(("Sanity Test Done"), ADI_VERBOSITY_LOW); From 63eef4daae35b5450e69886cbaee13f363e5c06d Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Wed, 3 Dec 2025 17:22:35 +0200 Subject: [PATCH 03/10] ada4355: Avoid frame transitions coinciding with DCO edges Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/system_tb.sv | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index 0640b1672..b4be69ccc 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -81,8 +81,9 @@ module system_tb #( always @(*) dco_p <= #3 ssi_clk; always @(*) dco_n <= #3 ~ssi_clk; - always @(*) frame_clock_p <= frame_clk; - always @(*) frame_clock_n <= ~frame_clk; + // Add same transport delay as DCO to maintain phase alignment + always @(*) frame_clock_p <= #3 frame_clk; + always @(*) frame_clock_n <= #3 ~frame_clk; // // Clock generation @@ -99,10 +100,11 @@ module system_tb #( end // Starts frame clock - + // Offset by 0.5ns to avoid frame transitions coinciding with DCO edges initial begin #1; @(posedge sync_n_d); + #0.5; // Phase offset to center frame transitions between DCO edges while (sync_n_d) begin frame_clk <= ~frame_clk; #FRAME_HALF_PERIOD; From e819d3db58c7c155b674a2dc41e99cde5ef857a9 Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Thu, 4 Dec 2025 16:32:04 +0200 Subject: [PATCH 04/10] ada4355: Check captured data developing Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/system_tb.sv | 91 ++++++++------ .../project/ada4355/tests/test_program.sv | 117 ++++++++++++++---- 2 files changed, 152 insertions(+), 56 deletions(-) diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index b4be69ccc..2fc5df52d 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -43,7 +43,7 @@ module system_tb #( localparam DCO_HALF_PERIOD = 1; // Period 2 ns -> 500 MHz DCO localparam FRAME_HALF_PERIOD = 4; // Period 8 ns -> 125 MHz Frame localparam BITS_PER_CYCLE = 2 * 2; - localparam LATENCY = 3; + localparam LATENCY = 3; // Gives correct step=2 increment reg sync_n = 1'b0; reg ssi_clk = 1'b0; @@ -99,16 +99,17 @@ module system_tb #( ssi_clk <= 1'b0; end - // Starts frame clock - // Offset by 0.5ns to avoid frame transitions coinciding with DCO edges + // Generate frame clock with phase offset (independent) + // Testing different offsets to find optimal alignment initial begin #1; @(posedge sync_n_d); - #0.5; // Phase offset to center frame transitions between DCO edges + #0.5; // Best case: 0.5ns offset - samples 0-6 correct, every 8th has error while (sync_n_d) begin frame_clk <= ~frame_clk; #FRAME_HALF_PERIOD; end + frame_clk <= 1'b0; end initial begin @@ -123,49 +124,69 @@ module system_tb #( always @(*) late_signal_p <= #3 div_clock; always @(*) late_signal_n <= #3 ~div_clock; - // Data generation + // Data generation - continuous DCO-synchronized approach + // Drive data continuously in sync with DCO, one 16-bit sample per 4 DCO cycles reg [15:0] sample = 16'h0; - reg da_p = 1'b0; reg da_n = 1'b1; reg db_p = 1'b0; reg db_n = 1'b1; - wire [15:0] final_sample; - assign final_sample = sample; - always @(posedge frame_clock_p) begin - repeat (LATENCY) @(posedge ssi_clk); - fork - begin - drive_sample(final_sample); - end - join_none - #1; - if (sample == 16'hFFFF) begin - sample = 0; - end else begin - sample = sample + 2; - end - end + // Continuous data driving loop - drives one sample every 4 DCO cycles + // HDL interleaving: db carries ODD bit positions, da carries EVEN bit positions + // Drive LSB first to match ISERDES capture order + initial begin + @(posedge sync_n_d); + + forever begin + // Drive 16 bits over 4 DCO cycles (4 bits per cycle, 2 per lane, DDR) + // Cycle 0: bits 3,2 (negedge), bits 1,0 (posedge) + @(negedge ssi_clk); + #1; + db_p <= sample[3]; db_n <= ~sample[3]; + da_p <= sample[2]; da_n <= ~sample[2]; + @(posedge ssi_clk); + #1; + db_p <= sample[1]; db_n <= ~sample[1]; + da_p <= sample[0]; da_n <= ~sample[0]; - task automatic drive_sample(bit [15:0] sample_t); - int num_lanes = 2; - int bits_per_cycle = num_lanes * 2; - for (int i = 15; i >= 0; i=i-bits_per_cycle) begin + // Cycle 1: bits 7,6 (negedge), bits 5,4 (posedge) @(negedge ssi_clk); #1; - da_p <= sample_t[i]; - da_n <= ~sample_t[i]; - db_p <= sample_t[i-1]; - db_n <= ~sample_t[i-1]; + db_p <= sample[7]; db_n <= ~sample[7]; + da_p <= sample[6]; da_n <= ~sample[6]; @(posedge ssi_clk); #1; - da_p <= sample_t[i-2]; - da_n <= ~sample_t[i-2]; - db_p <= sample_t[i-3]; - db_n <= ~sample_t[i-3]; + db_p <= sample[5]; db_n <= ~sample[5]; + da_p <= sample[4]; da_n <= ~sample[4]; + + // Cycle 2: bits 11,10 (negedge), bits 9,8 (posedge) + @(negedge ssi_clk); + #1; + db_p <= sample[11]; db_n <= ~sample[11]; + da_p <= sample[10]; da_n <= ~sample[10]; + @(posedge ssi_clk); + #1; + db_p <= sample[9]; db_n <= ~sample[9]; + da_p <= sample[8]; da_n <= ~sample[8]; + + // Cycle 3: bits 15,14 (negedge), bits 13,12 (posedge) + @(negedge ssi_clk); + #1; + db_p <= sample[15]; db_n <= ~sample[15]; + da_p <= sample[14]; da_n <= ~sample[14]; + @(posedge ssi_clk); + #1; + db_p <= sample[13]; db_n <= ~sample[13]; + da_p <= sample[12]; da_n <= ~sample[12]; + + // Increment sample for next 4-cycle period + if (sample == 16'hFFFF) + sample <= 16'h0; + else + sample <= sample + 16'd2; end - endtask + end endmodule diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index 407b46a03..1463b5fea 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -253,6 +253,9 @@ endtask // -------------------------- task dma_test; + logic [3:0] transfer_id; + localparam TRANSFER_LENGTH = 64*4; // 64 samples * 4 bytes + localparam DMA_DEST_ADDR = `DDR_BA + 32'h00002000; begin link_setup; @@ -267,48 +270,120 @@ begin .cyclic(1'b0), .tlast(1'b1), .partial_reporting_en(1'b0)); - rx_dma_api.set_lengths(.xfer_length_x(64*4-1), .xfer_length_y(0)); - rx_dma_api.set_dest_addr(.xfer_addr(`DDR_BA+32'h00002000)); + rx_dma_api.set_lengths(.xfer_length_x(TRANSFER_LENGTH-1), .xfer_length_y(0)); + rx_dma_api.set_dest_addr(.xfer_addr(DMA_DEST_ADDR)); + + // Get transfer ID and start + rx_dma_api.transfer_id_get(transfer_id); rx_dma_api.transfer_start(); - `INFO(("Configure RX DMA Done"), ADI_VERBOSITY_LOW); + `INFO(("Configure RX DMA Done, transfer_id=%0d", transfer_id), ADI_VERBOSITY_LOW); enable_pattern; `INFO(("Enable Pattern Done"), ADI_VERBOSITY_LOW); + // Wait for DMA transfer to complete + rx_dma_api.wait_transfer_done(.transfer_id(transfer_id), .timeut_in_us(5000)); + + `INFO(("DMA Transfer Complete"), ADI_VERBOSITY_LOW); + + // Debug: dump first 16 words of raw data to analyze pattern + dump_raw_data(.address(DMA_DEST_ADDR), .length(16)); + + // Verify captured data + // 64 samples of 16-bit = 32 words of 32-bit (2 samples per word) + // Sample pattern from system_tb: 0, 2, 4, 6, ... (step=2) + check_captured_data( + .address(DMA_DEST_ADDR), + .length(TRANSFER_LENGTH/4), // number of 32-bit words + .step(2) // sample increment step + ); + end endtask // Check captured data against incremental pattern based on first sample -// Pattern should be contiguous +// Data format: Each 32-bit word contains 2 x 16-bit samples +// Word[31:16] = sample[2*i+1], Word[15:0] = sample[2*i] +// Pattern from system_tb: sample increments by 'step' each clock (default step=2) task check_captured_data(bit [31:0] address, - int length = 1024, - int step = 1, - int max_sample = 2048 + int length = 64, + int step = 2 ); bit [31:0] current_address; bit [31:0] captured_word; - bit [31:0] reference_word; - bit [19:0] first; + bit [15:0] sample_lo, sample_hi; + bit [15:0] expected_lo, expected_hi; + bit [15:0] first_sample; + int errors = 0; + + `INFO(("Checking captured data at address 0x%h, length=%0d words, step=%0d", address, length, step), ADI_VERBOSITY_LOW); - for (int i=0;i Date: Fri, 5 Dec 2025 16:49:49 +0200 Subject: [PATCH 05/10] ada4355: Debug/align frame and data timing Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/system_tb.sv | 147 +++++++++---- .../project/ada4355/tests/test_program.sv | 19 +- testbenches/project/ada4355/waves/cfg2.wcfg | 203 +++++++++++++++++- 3 files changed, 316 insertions(+), 53 deletions(-) diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index 2fc5df52d..27e5c5a9f 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -47,7 +47,7 @@ module system_tb #( reg sync_n = 1'b0; reg ssi_clk = 1'b0; - reg frame_clk = 1'b0; + reg frame_clk = 1'b1; // Start HIGH for 0xF0 pattern reg div_clock = 1'b0; reg enable_pattern = 1'b0; reg dco_p = 1'b0; @@ -99,12 +99,13 @@ module system_tb #( ssi_clk <= 1'b0; end - // Generate frame clock with phase offset (independent) - // Testing different offsets to find optimal alignment + // Generate frame clock aligned with data + // Adjust timing so serdes_frame=0xF0 directly (shift_cnt=0) + // Add 3*DCO_HALF_PERIOD to align frame with ISERDESE capture window initial begin #1; @(posedge sync_n_d); - #0.5; // Best case: 0.5ns offset - samples 0-6 correct, every 8th has error + #(FRAME_HALF_PERIOD + 3*DCO_HALF_PERIOD); // Align for shift_cnt=0 while (sync_n_d) begin frame_clk <= ~frame_clk; #FRAME_HALF_PERIOD; @@ -127,65 +128,125 @@ module system_tb #( // Data generation - continuous DCO-synchronized approach // Drive data continuously in sync with DCO, one 16-bit sample per 4 DCO cycles - reg [15:0] sample = 16'h0; + reg [15:0] sample = 16'h1234; + reg da_p_int = 1'b0; + reg db_p_int = 1'b0; reg da_p = 1'b0; reg da_n = 1'b1; reg db_p = 1'b0; reg db_n = 1'b1; + // Use transport delay (not inertial) to match DCO timing + // always @(*) with <= #delay provides transport delay behavior + always @(*) da_p <= #3 da_p_int; + always @(*) da_n <= #3 ~da_p_int; + always @(*) db_p <= #3 db_p_int; + always @(*) db_n <= #3 ~db_p_int; + // Continuous data driving loop - drives one sample every 4 DCO cycles - // HDL interleaving: db carries ODD bit positions, da carries EVEN bit positions - // Drive LSB first to match ISERDES capture order + // As per ADA4355/4356 timing diagram (BITWISE MODE): + // - Lane D0A (da): EVEN bits (14, 12, 10, 8, 6, 4, 2, 0) + // - Lane D1A (db): ODD bits (15, 13, 11, 9, 7, 5, 3, 1) + // Bits sent MSB first over 8 DDR edges (4 clock cycles) + // + // The ISERDESE2 in DDR 8:1 mode with NETWORKING interface captures: + // Q8 (data_s7) = rising edge first sample (oldest) + // Q7 (data_s6) = falling edge + // Q6 (data_s5) = rising edge + // Q5 (data_s4) = falling edge + // Q4 (data_s3) = rising edge + // Q3 (data_s2) = falling edge + // Q2 (data_s1) = rising edge + // Q1 (data_s0) = falling edge last sample (newest) + // + // HDL interleaving: serdes_data = {data_1[7], data_0[7], ..., data_1[0], data_0[0]} + // where data_1[i] = data_si[1] (d1a/db) and data_0[i] = data_si[0] (d0a/da) + // + // IMPORTANT: Data must be stable BEFORE the clock edge for proper capture. + + reg [31:0] sample_count = 0; + reg [7:0] da_bits_sent; // Track bits sent on da lane + reg [7:0] db_bits_sent; // Track bits sent on db lane + initial begin @(posedge sync_n_d); + $display("[TB] @%0t: Starting data generation, sample=0x%04h", $time, sample); + $display("[TB] 14-bit ADC format: MSB=D13, LSB=D00, last edge=padding zero"); + $display("[TB] D0A(da): D12,D10,D08,D06,D04,D02,D00,0"); + $display("[TB] D1A(db): D13,D11,D09,D07,D05,D03,D01,0"); + + // ADA4355/4356 is 14-bit ADC. From timing.png: + // - D0A sends: D12, D10, D08, D06, D04, D02, D00(LSB), 0(pad) + // - D1A sends: D13(MSB), D11, D09, D07, D05, D03, D01, 0(pad) + // MSB = bit 13, LSB = bit 0, bits 15:14 unused + + // Pre-setup padding zeros before first rising edge + // Padding at BEGINNING gives right-justified output: {2'b00, sample[13:0]} = sample + // Delay by 4 DDR edges (FRAME_HALF_PERIOD) to get serdes_data=0x1234 + #FRAME_HALF_PERIOD; + da_p_int <= 1'b0; // Padding zero first + db_p_int <= 1'b0; // Padding zero first + forever begin - // Drive 16 bits over 4 DCO cycles (4 bits per cycle, 2 per lane, DDR) - // Cycle 0: bits 3,2 (negedge), bits 1,0 (posedge) - @(negedge ssi_clk); - #1; - db_p <= sample[3]; db_n <= ~sample[3]; - da_p <= sample[2]; da_n <= ~sample[2]; + // Track what we're sending for debug (pad first, then 14-bit data) + da_bits_sent = {1'b0, sample[12], sample[10], sample[8], + sample[6], sample[4], sample[2], sample[0]}; // pad,D12,D10,D08,D06,D04,D02,D00 + db_bits_sent = {1'b0, sample[13], sample[11], sample[9], + sample[7], sample[5], sample[3], sample[1]}; // pad,D13,D11,D09,D07,D05,D03,D01 + + // Edge 0 (rising) captures padding zeros (already setup) @(posedge ssi_clk); - #1; - db_p <= sample[1]; db_n <= ~sample[1]; - da_p <= sample[0]; da_n <= ~sample[0]; + da_p_int <= sample[12]; // D12 + db_p_int <= sample[13]; // D13 (MSB) - // Cycle 1: bits 7,6 (negedge), bits 5,4 (posedge) + // Edge 1 (falling) captures D12,D13 @(negedge ssi_clk); - #1; - db_p <= sample[7]; db_n <= ~sample[7]; - da_p <= sample[6]; da_n <= ~sample[6]; + da_p_int <= sample[10]; // D10 + db_p_int <= sample[11]; // D11 + + // Edge 2 (rising) captures D10,D11 @(posedge ssi_clk); - #1; - db_p <= sample[5]; db_n <= ~sample[5]; - da_p <= sample[4]; da_n <= ~sample[4]; + da_p_int <= sample[8]; // D08 + db_p_int <= sample[9]; // D09 - // Cycle 2: bits 11,10 (negedge), bits 9,8 (posedge) + // Edge 3 (falling) captures D08,D09 @(negedge ssi_clk); - #1; - db_p <= sample[11]; db_n <= ~sample[11]; - da_p <= sample[10]; da_n <= ~sample[10]; + da_p_int <= sample[6]; // D06 + db_p_int <= sample[7]; // D07 + + // Edge 4 (rising) captures D06,D07 @(posedge ssi_clk); - #1; - db_p <= sample[9]; db_n <= ~sample[9]; - da_p <= sample[8]; da_n <= ~sample[8]; + da_p_int <= sample[4]; // D04 + db_p_int <= sample[5]; // D05 - // Cycle 3: bits 15,14 (negedge), bits 13,12 (posedge) + // Edge 5 (falling) captures D04,D05 @(negedge ssi_clk); - #1; - db_p <= sample[15]; db_n <= ~sample[15]; - da_p <= sample[14]; da_n <= ~sample[14]; + da_p_int <= sample[2]; // D02 + db_p_int <= sample[3]; // D03 + + // Edge 6 (rising) captures D02,D03 @(posedge ssi_clk); - #1; - db_p <= sample[13]; db_n <= ~sample[13]; - da_p <= sample[12]; da_n <= ~sample[12]; - - // Increment sample for next 4-cycle period - if (sample == 16'hFFFF) - sample <= 16'h0; - else - sample <= sample + 16'd2; + da_p_int <= sample[0]; // D00 (LSB) + db_p_int <= sample[1]; // D01 + + // Edge 7 (falling) captures D00,D01 + @(negedge ssi_clk); + // Print first few samples with detailed bit info + if (sample_count < 5) begin + $display("[TB] @%0t: Sample[%0d] = 0x%04h (14-bit: 0x%04h)", + $time, sample_count, sample, sample & 14'h3FFF); + $display("[TB] da(D0A): 0x%02h (pad,D12,D10,D08,D06,D04,D02,D00)", da_bits_sent); + $display("[TB] db(D1A): 0x%02h (pad,D13,D11,D09,D07,D05,D03,D01)", db_bits_sent); + end + sample_count <= sample_count + 1; + + // Setup padding for next sample + da_p_int <= 1'b0; // Padding zero + db_p_int <= 1'b0; // Padding zero + + // Use constant 0x1234 pattern to verify bit ordering + sample <= 16'h1234; end end diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index 1463b5fea..fdf804665 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -242,6 +242,21 @@ begin rx_adc_api.get_sync_status(sync_stat); `INFO(("Sync status = %0d", sync_stat), ADI_VERBOSITY_LOW); + // Debug: Monitor serdes values for a few cycles + repeat(10) begin + @(posedge system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_clk_div); + `INFO(("SERDES DEBUG: serdes_data=0x%04h, serdes_data_d=0x%04h, serdes_frame=0x%02h, serdes_frame_d=0x%02h", + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_data, + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_data_d, + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_frame, + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_frame_d), ADI_VERBOSITY_NONE); + `INFO((" shift_cnt=%0d, frame_shifted=0x%02h, adc_data_shifted=0x%04h, state=%0d", + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.shift_cnt, + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.frame_shifted, + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_data_shifted, + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.state), ADI_VERBOSITY_NONE); + end + force system_tb.enable_pattern = 1'b0; `INFO(("Force enable_pattern = 0"), ADI_VERBOSITY_LOW); @@ -293,11 +308,11 @@ begin // Verify captured data // 64 samples of 16-bit = 32 words of 32-bit (2 samples per word) - // Sample pattern from system_tb: 0, 2, 4, 6, ... (step=2) + // Sample pattern from system_tb: constant 0x1234 check_captured_data( .address(DMA_DEST_ADDR), .length(TRANSFER_LENGTH/4), // number of 32-bit words - .step(2) // sample increment step + .step(0) // constant pattern (all samples = first_sample) ); end diff --git a/testbenches/project/ada4355/waves/cfg2.wcfg b/testbenches/project/ada4355/waves/cfg2.wcfg index 192b2a2b4..1ad06190a 100644 --- a/testbenches/project/ada4355/waves/cfg2.wcfg +++ b/testbenches/project/ada4355/waves/cfg2.wcfg @@ -5,20 +5,31 @@ + + + + + + + - + + + + + - + @@ -27,24 +38,200 @@ - - + + - - - + + + + + - + + + dco_p + dco_p + + + dco_n + dco_n + + + d0a_p + d0a_p + + + d0a_n + d0a_n + + + d1a_p + d1a_p + + + d1a_n + d1a_n + + + fco_p + fco_p + + + fco_n + fco_n + + + sync_n + sync_n + + + state[2:0] + state[2:0] + + + shift_cnt[2:0] + shift_cnt[2:0] + + + serdes_data[15:0] + serdes_data[15:0] + + + serdes_data_d[15:0] + serdes_data_d[15:0] + + + pattern_value[7:0] + pattern_value[7:0] + + + frame_shifted[7:0] + frame_shifted[7:0] + + + serdes_frame[7:0] + serdes_frame[7:0] + + + serdes_frame_d[7:0] + serdes_frame_d[7:0] + + + test_pattern[15:0] + test_pattern[15:0] + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + #D2691E + true + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + frame_s7 + frame_s7 + + + frame_s6 + frame_s6 + + + frame_s5 + frame_s5 + + + frame_s4 + frame_s4 + + + frame_s3 + frame_s3 + + + frame_s2 + frame_s2 + + + frame_s1 + frame_s1 + + + frame_s0 + frame_s0 + From 7c8c13b73d6eac00937cf34d6f409df9bf4f43e5 Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Mon, 8 Dec 2025 14:29:50 +0200 Subject: [PATCH 06/10] ada4355: Incrementing pattern at input Signed-off-by: Pop Ioan Daniel --- .../project/ada4355/cfgs/cfg_shift0.tcl | 8 +++ testbenches/project/ada4355/system_bd.tcl | 11 ++++ testbenches/project/ada4355/system_tb.sv | 66 +++++++++++++------ .../project/ada4355/tests/test_program.sv | 51 +++++++++++--- testbenches/project/ada4355/waves/cfg2.wcfg | 10 +-- 5 files changed, 112 insertions(+), 34 deletions(-) create mode 100644 testbenches/project/ada4355/cfgs/cfg_shift0.tcl diff --git a/testbenches/project/ada4355/cfgs/cfg_shift0.tcl b/testbenches/project/ada4355/cfgs/cfg_shift0.tcl new file mode 100644 index 000000000..b02617fbd --- /dev/null +++ b/testbenches/project/ada4355/cfgs/cfg_shift0.tcl @@ -0,0 +1,8 @@ +global ad_project_params + +# ADA4356 configuration (no BUFMRCE) +set ad_project_params(BUFMRCE_EN) 0 + +# Frame timing: aligned (shift_cnt=0) +# FSM should detect frame_shifted=0xF0 without correction +set ad_project_params(FRAME_SHIFT_CNT) 0 diff --git a/testbenches/project/ada4355/system_bd.tcl b/testbenches/project/ada4355/system_bd.tcl index 741261454..c764f6692 100644 --- a/testbenches/project/ada4355/system_bd.tcl +++ b/testbenches/project/ada4355/system_bd.tcl @@ -38,6 +38,14 @@ source ../../../../scripts/adi_env.tcl # system level parameters set BUFMRCE_EN $ad_project_params(BUFMRCE_EN) +# FRAME_SHIFT_CNT for testbench - controls frame timing offset +# Default to 0 if not specified in config +if {[info exists ad_project_params(FRAME_SHIFT_CNT)]} { + set FRAME_SHIFT_CNT $ad_project_params(FRAME_SHIFT_CNT) +} else { + set FRAME_SHIFT_CNT 0 +} + global ad_project_params # @@ -58,3 +66,6 @@ adi_sim_add_define "ADA4355_DMA_BA=[format "%d" ${BA_ADA4355_DMA}]" set BA_DDR 0x80000000 set_property offset $BA_DDR [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_mng_ddr_cntlr}] adi_sim_add_define "DDR_BA=[format "%d" ${BA_DDR}]" + +# Testbench configuration for frame timing offset +adi_sim_add_define "FRAME_SHIFT_CNT=${FRAME_SHIFT_CNT}" diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index 27e5c5a9f..a279bc5d9 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -37,6 +37,15 @@ `include "utils.svh" +// FRAME_SHIFT_CNT: Controls frame timing offset to test FSM alignment +// - 0: Frame arrives aligned (serdes_frame=0xF0, shift_cnt=0) +// - 1-7: Frame arrives misaligned by N DDR edges (FSM must correct) +// Each increment reduces delay by 1 DCO_HALF_PERIOD, increasing shift_cnt by 1 +// Can be overridden via define: +define+FRAME_SHIFT_CNT=3 +`ifndef FRAME_SHIFT_CNT + `define FRAME_SHIFT_CNT 0 +`endif + module system_tb #( ) (); @@ -45,6 +54,15 @@ module system_tb #( localparam BITS_PER_CYCLE = 2 * 2; localparam LATENCY = 3; // Gives correct step=2 increment + // Calculate frame and data delays based on desired shift_cnt + // Base delay for shift_cnt=0 is FRAME_HALF_PERIOD + 3*DCO_HALF_PERIOD + // Each additional shift_cnt reduces the delay by 1 DCO_HALF_PERIOD + localparam FRAME_SHIFT_CNT = `FRAME_SHIFT_CNT; + localparam FRAME_DELAY = FRAME_HALF_PERIOD + (3 - FRAME_SHIFT_CNT) * DCO_HALF_PERIOD; + // Data delay is FRAME_DELAY minus 3*DCO_HALF_PERIOD (empirically tuned offset) + // This maintains fixed frame-data phase relationship from ADC + localparam DATA_DELAY = FRAME_HALF_PERIOD - FRAME_SHIFT_CNT * DCO_HALF_PERIOD; + reg sync_n = 1'b0; reg ssi_clk = 1'b0; reg frame_clk = 1'b1; // Start HIGH for 0xF0 pattern @@ -81,9 +99,11 @@ module system_tb #( always @(*) dco_p <= #3 ssi_clk; always @(*) dco_n <= #3 ~ssi_clk; - // Add same transport delay as DCO to maintain phase alignment - always @(*) frame_clock_p <= #3 frame_clk; - always @(*) frame_clock_n <= #3 ~frame_clk; + // Add transport delay with 0.5ns offset from DCO to avoid frame transitions + // coinciding with DCO edges (prevents ISERDESE2 metastability) + // Using 2.5ns (0.5ns before DCO edges) to maintain frame-data alignment + always @(*) frame_clock_p <= #2.5 frame_clk; + always @(*) frame_clock_n <= #2.5 ~frame_clk; // // Clock generation @@ -99,13 +119,16 @@ module system_tb #( ssi_clk <= 1'b0; end - // Generate frame clock aligned with data - // Adjust timing so serdes_frame=0xF0 directly (shift_cnt=0) - // Add 3*DCO_HALF_PERIOD to align frame with ISERDESE capture window + // Generate frame clock with configurable timing offset + // FRAME_DELAY controls the initial delay to produce different shift_cnt values + // shift_cnt=0: FRAME_DELAY = 7ns (aligned) + // shift_cnt=N: FRAME_DELAY = 7-N ns (misaligned by N DDR edges) initial begin #1; @(posedge sync_n_d); - #(FRAME_HALF_PERIOD + 3*DCO_HALF_PERIOD); // Align for shift_cnt=0 + $display("[TB] FRAME_SHIFT_CNT=%0d, FRAME_DELAY=%0d ns (expected shift_cnt=%0d)", + FRAME_SHIFT_CNT, FRAME_DELAY, FRAME_SHIFT_CNT); + #(FRAME_DELAY); while (sync_n_d) begin frame_clk <= ~frame_clk; #FRAME_HALF_PERIOD; @@ -136,12 +159,13 @@ module system_tb #( reg db_p = 1'b0; reg db_n = 1'b1; - // Use transport delay (not inertial) to match DCO timing - // always @(*) with <= #delay provides transport delay behavior - always @(*) da_p <= #3 da_p_int; - always @(*) da_n <= #3 ~da_p_int; - always @(*) db_p <= #3 db_p_int; - always @(*) db_n <= #3 ~db_p_int; + // Use transport delay with 0.5ns offset from DCO to avoid data transitions + // coinciding with DCO edges (prevents ISERDESE2 metastability) + // Using 2.5ns (0.5ns before DCO edges) same as frame + always @(*) da_p <= #2.5 da_p_int; + always @(*) da_n <= #2.5 ~da_p_int; + always @(*) db_p <= #2.5 db_p_int; + always @(*) db_n <= #2.5 ~db_p_int; // Continuous data driving loop - drives one sample every 4 DCO cycles // As per ADA4355/4356 timing diagram (BITWISE MODE): @@ -172,6 +196,7 @@ module system_tb #( @(posedge sync_n_d); $display("[TB] @%0t: Starting data generation, sample=0x%04h", $time, sample); + $display("[TB] DATA_DELAY=%0d ns (FRAME_SHIFT_CNT=%0d)", DATA_DELAY, FRAME_SHIFT_CNT); $display("[TB] 14-bit ADC format: MSB=D13, LSB=D00, last edge=padding zero"); $display("[TB] D0A(da): D12,D10,D08,D06,D04,D02,D00,0"); $display("[TB] D1A(db): D13,D11,D09,D07,D05,D03,D01,0"); @@ -181,10 +206,10 @@ module system_tb #( // - D1A sends: D13(MSB), D11, D09, D07, D05, D03, D01, 0(pad) // MSB = bit 13, LSB = bit 0, bits 15:14 unused - // Pre-setup padding zeros before first rising edge - // Padding at BEGINNING gives right-justified output: {2'b00, sample[13:0]} = sample - // Delay by 4 DDR edges (FRAME_HALF_PERIOD) to get serdes_data=0x1234 - #FRAME_HALF_PERIOD; + // Use DATA_DELAY to maintain fixed phase relationship with frame + // DATA_DELAY shifts with FRAME_SHIFT_CNT to keep frame-data alignment + #DATA_DELAY; + da_p_int <= 1'b0; // Padding zero first db_p_int <= 1'b0; // Padding zero first @@ -241,12 +266,13 @@ module system_tb #( end sample_count <= sample_count + 1; - // Setup padding for next sample + // Setup padding for next sample (will be captured on next Edge 0) da_p_int <= 1'b0; // Padding zero db_p_int <= 1'b0; // Padding zero - // Use constant 0x1234 pattern to verify bit ordering - sample <= 16'h1234; + // Use incrementing pattern (step=1) to verify data flow + // Each sample increments by 1, allowing verification of sequential capture + sample <= sample + 1; end end diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index fdf804665..3be65607f 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -223,6 +223,10 @@ endtask task enable_pattern; begin logic sync_stat; + logic [7:0] frame_shifted_val; + logic [15:0] adc_data_shifted_val; + logic [2:0] shift_cnt_val; + int alignment_errors = 0; force system_tb.enable_pattern = 1'b1; `INFO(("Force enable_pattern = 1"), ADI_VERBOSITY_LOW); @@ -242,19 +246,46 @@ begin rx_adc_api.get_sync_status(sync_stat); `INFO(("Sync status = %0d", sync_stat), ADI_VERBOSITY_LOW); - // Debug: Monitor serdes values for a few cycles - repeat(10) begin + // Wait for FSM to stabilize and verify alignment + // FSM takes ~3 cycles per shift value, 8 values max = 24 cycles minimum + // Add extra margin for stabilization + repeat(50) @(posedge system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_clk_div); + + // Capture FSM alignment results + shift_cnt_val = system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.shift_cnt; + frame_shifted_val = system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.frame_shifted; + adc_data_shifted_val = system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_data_shifted; + + `INFO(("FSM Alignment Results: shift_cnt=%0d, frame_shifted=0x%02h, adc_data_shifted=0x%04h", + shift_cnt_val, frame_shifted_val, adc_data_shifted_val), ADI_VERBOSITY_NONE); + + // Verify FSM achieved correct alignment + if (frame_shifted_val !== 8'hF0) begin + `ERROR(("ALIGNMENT FAIL: frame_shifted=0x%02h, expected 0xF0", frame_shifted_val)); + alignment_errors++; + end else begin + `INFO(("ALIGNMENT OK: frame_shifted=0xF0 (FSM found correct shift_cnt=%0d)", shift_cnt_val), ADI_VERBOSITY_NONE); + end + + // With incrementing pattern, just log the current data value (don't check specific value) + // The actual data verification is done by check_captured_data with step=1 + `INFO(("ADC data at alignment check: adc_data_shifted=0x%04h", adc_data_shifted_val), ADI_VERBOSITY_NONE); + + // Debug: Monitor serdes values for a few more cycles + repeat(5) begin @(posedge system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_clk_div); - `INFO(("SERDES DEBUG: serdes_data=0x%04h, serdes_data_d=0x%04h, serdes_frame=0x%02h, serdes_frame_d=0x%02h", + `INFO(("SERDES DEBUG: serdes_data=0x%04h, serdes_frame=0x%02h, shift_cnt=%0d, frame_shifted=0x%02h, adc_data_shifted=0x%04h", system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_data, - system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_data_d, system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_frame, - system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.serdes_frame_d), ADI_VERBOSITY_NONE); - `INFO((" shift_cnt=%0d, frame_shifted=0x%02h, adc_data_shifted=0x%04h, state=%0d", system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.shift_cnt, system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.frame_shifted, - system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_data_shifted, - system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.state), ADI_VERBOSITY_NONE); + system_tb.test_harness.axi_ada4355_adc.inst.i_ada4355_interface.adc_data_shifted), ADI_VERBOSITY_LOW); + end + + if (alignment_errors == 0) begin + `INFO(("FSM Alignment Test: PASSED"), ADI_VERBOSITY_NONE); + end else begin + `ERROR(("FSM Alignment Test: FAILED - %0d errors", alignment_errors)); end force system_tb.enable_pattern = 1'b0; @@ -308,11 +339,11 @@ begin // Verify captured data // 64 samples of 16-bit = 32 words of 32-bit (2 samples per word) - // Sample pattern from system_tb: constant 0x1234 + // Sample pattern from system_tb: incrementing by 1 each sample check_captured_data( .address(DMA_DEST_ADDR), .length(TRANSFER_LENGTH/4), // number of 32-bit words - .step(0) // constant pattern (all samples = first_sample) + .step(1) // incrementing pattern (sample[n+1] = sample[n] + 1) ); end diff --git a/testbenches/project/ada4355/waves/cfg2.wcfg b/testbenches/project/ada4355/waves/cfg2.wcfg index 1ad06190a..f96d54b2a 100644 --- a/testbenches/project/ada4355/waves/cfg2.wcfg +++ b/testbenches/project/ada4355/waves/cfg2.wcfg @@ -51,13 +51,13 @@ - - - + + + - + @@ -137,6 +137,8 @@ adc_data_shifted[15:0] #D2691E true + STYLE_ANALOG + 100 data_1[7:0] From d6154a6da1fca47665ba3dfbc659a35693796bd6 Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Mon, 8 Dec 2025 15:29:23 +0200 Subject: [PATCH 07/10] ada4355: Sine wave at input Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/system_tb.sv | 39 +++++++++++-- .../project/ada4355/tests/test_program.sv | 56 ++++++++++--------- testbenches/project/ada4355/waves/cfg2.wcfg | 8 +-- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index a279bc5d9..aaf2937ac 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -159,6 +159,30 @@ module system_tb #( reg db_p = 1'b0; reg db_n = 1'b1; + // Sine wave generation parameters + // 14-bit ADC: values 0 to 16383, mid-point at 8192 + localparam real PI = 3.14159265358979; + localparam SINE_AMPLITUDE = 7000; // Amplitude (half peak-to-peak) + localparam SINE_OFFSET = 8192; // DC offset (mid-scale for 14-bit) + localparam SINE_PERIOD = 64; // Samples per sine period + + // Function to calculate sine sample value + function [15:0] calc_sine_sample; + input [31:0] idx; + real angle; + real sine_val; + integer result; + begin + angle = 2.0 * PI * $itor(idx) / $itor(SINE_PERIOD); + sine_val = $sin(angle); + result = SINE_OFFSET + $rtoi(sine_val * $itor(SINE_AMPLITUDE)); + // Clamp to 14-bit range + if (result < 0) result = 0; + if (result > 16383) result = 16383; + calc_sine_sample = result[15:0]; + end + endfunction + // Use transport delay with 0.5ns offset from DCO to avoid data transitions // coinciding with DCO edges (prevents ISERDESE2 metastability) // Using 2.5ns (0.5ns before DCO edges) same as frame @@ -195,7 +219,14 @@ module system_tb #( initial begin @(posedge sync_n_d); - $display("[TB] @%0t: Starting data generation, sample=0x%04h", $time, sample); + // Initialize first sample to sine wave start (index 0) + sample = calc_sine_sample(0); + + $display("[TB] @%0t: Starting SINE WAVE data generation", $time); + $display("[TB] Sine params: amplitude=%0d, offset=%0d, period=%0d samples", + SINE_AMPLITUDE, SINE_OFFSET, SINE_PERIOD); + $display("[TB] First sample=0x%04h (should be ~0x%04h = mid-scale)", + sample, SINE_OFFSET); $display("[TB] DATA_DELAY=%0d ns (FRAME_SHIFT_CNT=%0d)", DATA_DELAY, FRAME_SHIFT_CNT); $display("[TB] 14-bit ADC format: MSB=D13, LSB=D00, last edge=padding zero"); $display("[TB] D0A(da): D12,D10,D08,D06,D04,D02,D00,0"); @@ -270,9 +301,9 @@ module system_tb #( da_p_int <= 1'b0; // Padding zero db_p_int <= 1'b0; // Padding zero - // Use incrementing pattern (step=1) to verify data flow - // Each sample increments by 1, allowing verification of sequential capture - sample <= sample + 1; + // Generate sine wave pattern for realistic ADC waveform display + // Sine period = 64 samples = 512ns at 125 MSPS (~1.95 MHz sine) + sample <= calc_sine_sample(sample_count + 1); end end diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index 3be65607f..eb6557123 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -349,23 +349,31 @@ begin end endtask -// Check captured data against incremental pattern based on first sample +// Check captured data - verify sine wave is in valid range // Data format: Each 32-bit word contains 2 x 16-bit samples // Word[31:16] = sample[2*i+1], Word[15:0] = sample[2*i] -// Pattern from system_tb: sample increments by 'step' each clock (default step=2) +// Pattern from system_tb: sine wave with 64 sample period task check_captured_data(bit [31:0] address, int length = 64, - int step = 2 + int step = 2 // Unused for sine, kept for compatibility ); + // Sine wave parameters (must match system_tb.sv) + localparam int SINE_AMPLITUDE = 7000; + localparam int SINE_OFFSET = 8192; + localparam int SINE_MIN = SINE_OFFSET - SINE_AMPLITUDE; // 1192 + localparam int SINE_MAX = SINE_OFFSET + SINE_AMPLITUDE; // 15192 + bit [31:0] current_address; bit [31:0] captured_word; bit [15:0] sample_lo, sample_hi; - bit [15:0] expected_lo, expected_hi; - bit [15:0] first_sample; int errors = 0; + int min_val = 16'hFFFF; + int max_val = 0; - `INFO(("Checking captured data at address 0x%h, length=%0d words, step=%0d", address, length, step), ADI_VERBOSITY_LOW); + `INFO(("Checking captured SINE WAVE data at address 0x%h, length=%0d words", address, length), ADI_VERBOSITY_LOW); + `INFO(("Expected range: 0x%h to 0x%h (amplitude=%0d, offset=%0d)", + SINE_MIN, SINE_MAX, SINE_AMPLITUDE, SINE_OFFSET), ADI_VERBOSITY_LOW); for (int i = 0; i < length; i = i + 1) begin current_address = address + (i * 4); @@ -375,35 +383,31 @@ task check_captured_data(bit [31:0] address, sample_lo = captured_word[15:0]; sample_hi = captured_word[31:16]; - if (i == 0) begin - // Use first sample as reference base - first_sample = sample_lo; - `INFO(("First sample = 0x%h", first_sample), ADI_VERBOSITY_LOW); - end - - // Calculate expected samples - // Sample index: word i contains samples 2*i and 2*i+1 - expected_lo = (first_sample + (2 * i) * step) & 16'hFFFF; - expected_hi = (first_sample + (2 * i + 1) * step) & 16'hFFFF; + // Track min/max for sine wave verification + if (sample_lo < min_val) min_val = sample_lo; + if (sample_hi < min_val) min_val = sample_hi; + if (sample_lo > max_val) max_val = sample_lo; + if (sample_hi > max_val) max_val = sample_hi; - // Verify both samples in the word - if (sample_lo !== expected_lo) begin - `ERROR(("Word %0d [15:0]: Address 0x%h Expected 0x%h found 0x%h", i, current_address, expected_lo, sample_lo)); + // Verify samples are within expected sine range (with 5% margin) + if (sample_lo < (SINE_MIN - 500) || sample_lo > (SINE_MAX + 500)) begin + `ERROR(("Word %0d [15:0]: Address 0x%h Value 0x%h out of sine range", i, current_address, sample_lo)); errors++; end - if (sample_hi !== expected_hi) begin - `ERROR(("Word %0d [31:16]: Address 0x%h Expected 0x%h found 0x%h", i, current_address, expected_hi, sample_hi)); + if (sample_hi < (SINE_MIN - 500) || sample_hi > (SINE_MAX + 500)) begin + `ERROR(("Word %0d [31:16]: Address 0x%h Value 0x%h out of sine range", i, current_address, sample_hi)); errors++; end - // Log successful reads at higher verbosity - if (sample_lo === expected_lo && sample_hi === expected_hi) begin - `INFO(("Word %0d: 0x%h OK (samples: 0x%h, 0x%h)", i, captured_word, sample_lo, sample_hi), ADI_VERBOSITY_MEDIUM); - end + // Log samples at higher verbosity + `INFO(("Word %0d: 0x%h (samples: 0x%h, 0x%h)", i, captured_word, sample_lo, sample_hi), ADI_VERBOSITY_MEDIUM); end + `INFO(("Captured sine wave: min=0x%h (%0d), max=0x%h (%0d)", min_val, min_val, max_val, max_val), ADI_VERBOSITY_NONE); + `INFO(("Expected sine wave: min=0x%h (%0d), max=0x%h (%0d)", SINE_MIN, SINE_MIN, SINE_MAX, SINE_MAX), ADI_VERBOSITY_NONE); + if (errors == 0) begin - `INFO(("check_captured_data: PASSED - All %0d words verified correctly", length), ADI_VERBOSITY_NONE); + `INFO(("check_captured_data: PASSED - All %0d words within sine range", length), ADI_VERBOSITY_NONE); end else begin `ERROR(("check_captured_data: FAILED - %0d errors found", errors)); end diff --git a/testbenches/project/ada4355/waves/cfg2.wcfg b/testbenches/project/ada4355/waves/cfg2.wcfg index f96d54b2a..a7762a495 100644 --- a/testbenches/project/ada4355/waves/cfg2.wcfg +++ b/testbenches/project/ada4355/waves/cfg2.wcfg @@ -51,13 +51,13 @@ - - - + + + - + From a19e7d33f62bca3dd5111e92da535817f70fcd1b Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Tue, 9 Dec 2025 10:47:11 +0200 Subject: [PATCH 08/10] ada4355: Add cfg_shift3 Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/cfgs/cfg_shift3.tcl | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 testbenches/project/ada4355/cfgs/cfg_shift3.tcl diff --git a/testbenches/project/ada4355/cfgs/cfg_shift3.tcl b/testbenches/project/ada4355/cfgs/cfg_shift3.tcl new file mode 100644 index 000000000..9cfd2f96a --- /dev/null +++ b/testbenches/project/ada4355/cfgs/cfg_shift3.tcl @@ -0,0 +1,9 @@ +global ad_project_params + +# ADA4356 configuration (no BUFMRCE) +set ad_project_params(BUFMRCE_EN) 0 + +# Frame timing: misaligned by 3 DDR edges (shift_cnt=3) +# FSM should detect misalignment and apply shift_cnt=3 correction +# frame >> 3 and data >> 6 to align +set ad_project_params(FRAME_SHIFT_CNT) 3 From 28132d43d1aa79ec5674622299530e697a156276 Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Tue, 9 Dec 2025 12:04:16 +0200 Subject: [PATCH 09/10] ada4355: Resync Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/system_tb.sv | 80 ++++++++++++++----- .../project/ada4355/tests/test_program.sv | 62 +++++++++++--- 2 files changed, 110 insertions(+), 32 deletions(-) diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index aaf2937ac..1f3eade90 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -55,10 +55,11 @@ module system_tb #( localparam LATENCY = 3; // Gives correct step=2 increment // Calculate frame and data delays based on desired shift_cnt - // Base delay for shift_cnt=0 is FRAME_HALF_PERIOD + 3*DCO_HALF_PERIOD + // Base delay calibrated for shift_cnt=0 (empirically tuned) // Each additional shift_cnt reduces the delay by 1 DCO_HALF_PERIOD localparam FRAME_SHIFT_CNT = `FRAME_SHIFT_CNT; - localparam FRAME_DELAY = FRAME_HALF_PERIOD + (3 - FRAME_SHIFT_CNT) * DCO_HALF_PERIOD; + // Adjusted: +5 to compensate for observed shift_cnt=5 offset + localparam FRAME_DELAY = FRAME_HALF_PERIOD + (8 - FRAME_SHIFT_CNT) * DCO_HALF_PERIOD; // Data delay is FRAME_DELAY minus 3*DCO_HALF_PERIOD (empirically tuned offset) // This maintains fixed frame-data phase relationship from ADC localparam DATA_DELAY = FRAME_HALF_PERIOD - FRAME_SHIFT_CNT * DCO_HALF_PERIOD; @@ -75,6 +76,17 @@ module system_tb #( reg late_signal_p = 1'b0; reg late_signal_n = 1'b0; + // Phase shift control - can be modified mid-simulation to test FSM realignment + // This value shifts BOTH frame AND data together (maintaining their relationship) + // Units: DDR edges (0.5ns each at 500MHz DCO). Range: 0-7 + // When changed, FSM must search for new shift_cnt value to achieve frame_shifted=0xF0 + reg [2:0] phase_shift_edges = 3'd0; + + // Shift registers to delay frame and data by phase_shift_edges + reg [7:0] frame_shift_reg = 8'hF0; // 8-bit shift register for frame + reg [7:0] da_shift_reg = 8'h00; // 8-bit shift register for data lane A + reg [7:0] db_shift_reg = 8'h00; // 8-bit shift register for data lane B + `TEST_PROGRAM test(); test_harness `TH ( @@ -106,34 +118,58 @@ module system_tb #( always @(*) frame_clock_n <= #2.5 ~frame_clk; // - // Clock generation + // Clock generation - Synchronized to prevent long-simulation drift // - // Start clocks with rising edge once sync_n_d deasserts - initial begin - #1; - @(posedge sync_n_d); - while (sync_n_d) begin - ssi_clk <= ~ssi_clk; - #DCO_HALF_PERIOD; - end - ssi_clk <= 1'b0; - end + // Frame clock is derived from SSI edge counting to prevent drift. + // SSI clock: 500 MHz (1ns half-period) - master clock + // Frame clock: 125 MHz (4ns half-period) - derived from SSI + // + // The frame clock toggles every 4 SSI edges (= 4ns = FRAME_HALF_PERIOD) + // Initial phase is set by FRAME_DELAY before starting edge counting. + // + + // Edge counter for frame derivation + reg [2:0] ssi_edge_cnt = 3'd0; + reg frame_sync_active = 1'b0; - // Generate frame clock with configurable timing offset - // FRAME_DELAY controls the initial delay to produce different shift_cnt values - // shift_cnt=0: FRAME_DELAY = 7ns (aligned) - // shift_cnt=N: FRAME_DELAY = 7-N ns (misaligned by N DDR edges) + // SSI clock generator (master) - also drives frame via edge counting initial begin #1; @(posedge sync_n_d); $display("[TB] FRAME_SHIFT_CNT=%0d, FRAME_DELAY=%0d ns (expected shift_cnt=%0d)", FRAME_SHIFT_CNT, FRAME_DELAY, FRAME_SHIFT_CNT); - #(FRAME_DELAY); - while (sync_n_d) begin - frame_clk <= ~frame_clk; - #FRAME_HALF_PERIOD; + $display("[TB] Frame derived from SSI: toggle every 4 SSI edges after FRAME_DELAY"); + + // Phase 1: Run SSI clock during FRAME_DELAY period (frame stays HIGH) + repeat(FRAME_DELAY) begin + #DCO_HALF_PERIOD; + ssi_clk = ~ssi_clk; + end + + // Phase 2: Run SSI clock during first FRAME_HALF_PERIOD (frame still HIGH) + repeat(FRAME_HALF_PERIOD) begin + #DCO_HALF_PERIOD; + ssi_clk = ~ssi_clk; + end + + // Now toggle frame for the first time (matches original timing) + frame_clk = ~frame_clk; + ssi_edge_cnt = 3'd0; + + // Phase 3: Forever loop - toggle SSI every #1, toggle frame every 4 SSI edges + forever begin + #DCO_HALF_PERIOD; + ssi_clk = ~ssi_clk; + + // Count SSI edges and toggle frame every 4 + if (ssi_edge_cnt == 3'd3) begin + ssi_edge_cnt = 3'd0; + #0; // Delta delay to put frame toggle in next delta cycle + frame_clk = ~frame_clk; + end else begin + ssi_edge_cnt = ssi_edge_cnt + 1; + end end - frame_clk <= 1'b0; end initial begin diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index eb6557123..4560e7043 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -128,12 +128,32 @@ initial begin #1000ns; ada4355_regmap; - #7000ns; - misaligned_frame; - + // Test resync functionality - now using direct sync_n control #7000ns; resync; + // ========================================================================= + // FSM ALIGNMENT TEST + // ========================================================================= + // To test FSM alignment with different initial phase offsets, run: + // + // make CFG=cfg2 TST=test_program EXTRA_VFLAGS="+define+FRAME_SHIFT_CNT=4" + // + // This starts the simulation with frame/data shifted by 4 DCO half-periods. + // The FSM will search and find shift_cnt=4 to achieve frame_shifted=0xF0. + // + // Test matrix: + // FRAME_SHIFT_CNT=0 -> shift_cnt=0 (default, aligned) + // FRAME_SHIFT_CNT=2 -> shift_cnt=2 (small misalignment) + // FRAME_SHIFT_CNT=4 -> shift_cnt=4 (180-degree phase shift) + // FRAME_SHIFT_CNT=6 -> shift_cnt=6 (large misalignment) + // + // All cases should result in frame_shifted=0xF0 after FSM alignment. + // ========================================================================= + + // Extended delay to verify long-term stability + #50000ns; + // Tap value for lane 0 env.mng.master_sequencer.RegWrite32(RX_DELAY_BASE + 'h0, 15); env.mng.master_sequencer.RegWrite32(RX_DELAY_BASE + 'h4, 10); @@ -190,20 +210,42 @@ task resync; begin bit [31:0] current_val; - rx_adc_api.axi_read(GetAddrs(ADC_COMMON_REG_CNTRL), current_val); - rx_adc_api.axi_write(GetAddrs(ADC_COMMON_REG_CNTRL), current_val | 32'h8); + `INFO(("Triggering resync via sync_n pulse"), ADI_VERBOSITY_LOW); -end -endtask + // Directly control sync_n via testbench to trigger FSM reset + // The RTL FSM resets on negedge sync_n (axi_ada4355_if.v:273-279) + force system_tb.sync_n = 1'b0; -task misaligned_frame; -begin + // Hold sync_n low for enough time for the FSM to reset + // serdes_reset shift register needs 10 clock cycles (adc_clk_div = 125MHz = 8ns) + #100ns; + + // Release sync_n to allow FSM to re-align + force system_tb.sync_n = 1'b1; + + // Wait for FSM to complete alignment search + // FSM takes ~3 cycles per shift value, 8 values max = 24 cycles = ~200ns + #300ns; + + `INFO(("Resync complete - FSM should have re-aligned"), ADI_VERBOSITY_LOW); - rx_adc_api.set_common_control_3(.crc_en(1'b0), .custom_control(8'h1)); + // Optionally also write to the register for consistency with real HW flow + rx_adc_api.axi_read(GetAddrs(ADC_COMMON_REG_CNTRL), current_val); + rx_adc_api.axi_write(GetAddrs(ADC_COMMON_REG_CNTRL), current_val | 32'h8); end endtask +// -------------------------- +// FSM Alignment Testing +// -------------------------- +// To test FSM alignment with different initial phase offsets, use: +// make CFG=cfg2 TST=test_program EXTRA_VFLAGS="+define+FRAME_SHIFT_CNT=4" +// +// FRAME_SHIFT_CNT controls how many DCO half-periods the frame/data are +// delayed at simulation start. The FSM must search for the correct shift_cnt +// to achieve frame_shifted=0xF0. + task ada4355_regmap; begin bit [31:0] regmap_val; From 94cb09a37ee8b0b896660bbd08bd3731f45629f4 Mon Sep 17 00:00:00 2001 From: Pop Ioan Daniel Date: Thu, 11 Dec 2025 12:05:45 +0200 Subject: [PATCH 10/10] testbenches/ada4355: Correct SERDES capture timing for odd FRAME_SHIFT_CNT Signed-off-by: Pop Ioan Daniel --- testbenches/project/ada4355/system_tb.sv | 128 +++--- .../project/ada4355/tests/test_program.sv | 41 +- .../project/ada4355/waves/cfg_shift3.wcfg | 405 ++++++++++++++++++ 3 files changed, 484 insertions(+), 90 deletions(-) create mode 100644 testbenches/project/ada4355/waves/cfg_shift3.wcfg diff --git a/testbenches/project/ada4355/system_tb.sv b/testbenches/project/ada4355/system_tb.sv index 1f3eade90..49a76a8ac 100644 --- a/testbenches/project/ada4355/system_tb.sv +++ b/testbenches/project/ada4355/system_tb.sv @@ -54,15 +54,17 @@ module system_tb #( localparam BITS_PER_CYCLE = 2 * 2; localparam LATENCY = 3; // Gives correct step=2 increment - // Calculate frame and data delays based on desired shift_cnt - // Base delay calibrated for shift_cnt=0 (empirically tuned) - // Each additional shift_cnt reduces the delay by 1 DCO_HALF_PERIOD + // FRAME_SHIFT_CNT: Simulates starting SERDES capture at wrong position in frame pattern + // Frame and data arrive together (same timing), but SERDES captures at wrong phase + // FSM must detect misalignment and correct via shift_cnt register localparam FRAME_SHIFT_CNT = `FRAME_SHIFT_CNT; - // Adjusted: +5 to compensate for observed shift_cnt=5 offset - localparam FRAME_DELAY = FRAME_HALF_PERIOD + (8 - FRAME_SHIFT_CNT) * DCO_HALF_PERIOD; - // Data delay is FRAME_DELAY minus 3*DCO_HALF_PERIOD (empirically tuned offset) - // This maintains fixed frame-data phase relationship from ADC - localparam DATA_DELAY = FRAME_HALF_PERIOD - FRAME_SHIFT_CNT * DCO_HALF_PERIOD; + // CRITICAL FIX: For odd FRAME_SHIFT_CNT, add +1 DCO edge to ensure SERDES + // captures at the correct edge position (not same as adjacent even shift_cnt) + // This prevents cfg_shift3 and cfg_shift4 from capturing the same serdes_data + localparam FRAME_DELAY = FRAME_HALF_PERIOD + (8 - FRAME_SHIFT_CNT) * DCO_HALF_PERIOD + + ((FRAME_SHIFT_CNT % 2) * DCO_HALF_PERIOD); + // Frame and data arrive synchronized (as from real ADC) + localparam DATA_DELAY = FRAME_DELAY; reg sync_n = 1'b0; reg ssi_clk = 1'b0; @@ -255,91 +257,93 @@ module system_tb #( initial begin @(posedge sync_n_d); - // Initialize first sample to sine wave start (index 0) - sample = calc_sine_sample(0); + // Initialize first sample to constant value for debugging + sample = 16'h1234; // Constant value = 4660 (easy to recognize pattern) - $display("[TB] @%0t: Starting SINE WAVE data generation", $time); - $display("[TB] Sine params: amplitude=%0d, offset=%0d, period=%0d samples", - SINE_AMPLITUDE, SINE_OFFSET, SINE_PERIOD); - $display("[TB] First sample=0x%04h (should be ~0x%04h = mid-scale)", - sample, SINE_OFFSET); + $display("[TB] @%0t: Starting CONSTANT VALUE data generation", $time); + $display("[TB] Constant value: 0x%04h (%0d decimal)", sample, sample); + $display("[TB] First sample=0x%04h", sample); $display("[TB] DATA_DELAY=%0d ns (FRAME_SHIFT_CNT=%0d)", DATA_DELAY, FRAME_SHIFT_CNT); - $display("[TB] 14-bit ADC format: MSB=D13, LSB=D00, last edge=padding zero"); - $display("[TB] D0A(da): D12,D10,D08,D06,D04,D02,D00,0"); - $display("[TB] D1A(db): D13,D11,D09,D07,D05,D03,D01,0"); + $display("[TB] Full 16-bit transmission (HDL handles all 16 bits)"); + $display("[TB] D0A(da): sample[14,12,10,8,6,4,2,0] - even-indexed bits"); + $display("[TB] D1A(db): sample[15,13,11,9,7,5,3,1] - odd-indexed bits"); - // ADA4355/4356 is 14-bit ADC. From timing.png: - // - D0A sends: D12, D10, D08, D06, D04, D02, D00(LSB), 0(pad) - // - D1A sends: D13(MSB), D11, D09, D07, D05, D03, D01, 0(pad) - // MSB = bit 13, LSB = bit 0, bits 15:14 unused + // Transmit full 16-bit sample value + // The lanes transmit even/odd indexed bits of the 16-bit word + // - D0A sends: sample[14], sample[12], sample[10], sample[8], sample[6], sample[4], sample[2], sample[0] + // - D1A sends: sample[15], sample[13], sample[11], sample[9], sample[7], sample[5], sample[3], sample[1] // Use DATA_DELAY to maintain fixed phase relationship with frame // DATA_DELAY shifts with FRAME_SHIFT_CNT to keep frame-data alignment #DATA_DELAY; - da_p_int <= 1'b0; // Padding zero first - db_p_int <= 1'b0; // Padding zero first + da_p_int <= sample[14]; // Bit 14 - transmitted first (MSB-first order) + db_p_int <= sample[15]; // Bit 15 (MSB) forever begin - // Track what we're sending for debug (pad first, then 14-bit data) - da_bits_sent = {1'b0, sample[12], sample[10], sample[8], - sample[6], sample[4], sample[2], sample[0]}; // pad,D12,D10,D08,D06,D04,D02,D00 - db_bits_sent = {1'b0, sample[13], sample[11], sample[9], - sample[7], sample[5], sample[3], sample[1]}; // pad,D13,D11,D09,D07,D05,D03,D01 - - // Edge 0 (rising) captures padding zeros (already setup) + // Track what we're sending for debug + // Transmission order: MSB-first, even bits on D0A, odd bits on D1A + // Edge 0 → data_s7 → serdes_data[15:14] - bits [15:14] + // Edge 1 → data_s6 → serdes_data[13:12] - bits [13:12] + // ... + // Edge 7 → data_s0 → serdes_data[1:0] - bits [1:0] + da_bits_sent = {sample[14], sample[12], sample[10], sample[8], + sample[6], sample[4], sample[2], sample[0]}; // Even bits, MSB to LSB + db_bits_sent = {sample[15], sample[13], sample[11], sample[9], + sample[7], sample[5], sample[3], sample[1]}; // Odd bits, MSB to LSB + + // Edge 0 (rising) captures bits [15:14] → data_s7 → serdes_data[15:14] @(posedge ssi_clk); - da_p_int <= sample[12]; // D12 - db_p_int <= sample[13]; // D13 (MSB) + da_p_int <= sample[12]; // Bit 12 + db_p_int <= sample[13]; // Bit 13 - // Edge 1 (falling) captures D12,D13 + // Edge 1 (falling) captures bits [13:12] → data_s6 → serdes_data[13:12] @(negedge ssi_clk); - da_p_int <= sample[10]; // D10 - db_p_int <= sample[11]; // D11 + da_p_int <= sample[10]; // Bit 10 + db_p_int <= sample[11]; // Bit 11 - // Edge 2 (rising) captures D10,D11 + // Edge 2 (rising) captures bits [11:10] → data_s5 → serdes_data[11:10] @(posedge ssi_clk); - da_p_int <= sample[8]; // D08 - db_p_int <= sample[9]; // D09 + da_p_int <= sample[8]; // Bit 8 + db_p_int <= sample[9]; // Bit 9 - // Edge 3 (falling) captures D08,D09 + // Edge 3 (falling) captures bits [9:8] → data_s4 → serdes_data[9:8] @(negedge ssi_clk); - da_p_int <= sample[6]; // D06 - db_p_int <= sample[7]; // D07 + da_p_int <= sample[6]; // Bit 6 + db_p_int <= sample[7]; // Bit 7 - // Edge 4 (rising) captures D06,D07 + // Edge 4 (rising) captures bits [7:6] → data_s3 → serdes_data[7:6] @(posedge ssi_clk); - da_p_int <= sample[4]; // D04 - db_p_int <= sample[5]; // D05 + da_p_int <= sample[4]; // Bit 4 + db_p_int <= sample[5]; // Bit 5 - // Edge 5 (falling) captures D04,D05 + // Edge 5 (falling) captures bits [5:4] → data_s2 → serdes_data[5:4] @(negedge ssi_clk); - da_p_int <= sample[2]; // D02 - db_p_int <= sample[3]; // D03 + da_p_int <= sample[2]; // Bit 2 + db_p_int <= sample[3]; // Bit 3 - // Edge 6 (rising) captures D02,D03 + // Edge 6 (rising) captures bits [3:2] → data_s1 → serdes_data[3:2] @(posedge ssi_clk); - da_p_int <= sample[0]; // D00 (LSB) - db_p_int <= sample[1]; // D01 + da_p_int <= sample[0]; // Bit 0 (LSB) + db_p_int <= sample[1]; // Bit 1 - // Edge 7 (falling) captures D00,D01 + // Edge 7 (falling) captures bits [1:0] → data_s0 → serdes_data[1:0] @(negedge ssi_clk); // Print first few samples with detailed bit info if (sample_count < 5) begin - $display("[TB] @%0t: Sample[%0d] = 0x%04h (14-bit: 0x%04h)", - $time, sample_count, sample, sample & 14'h3FFF); - $display("[TB] da(D0A): 0x%02h (pad,D12,D10,D08,D06,D04,D02,D00)", da_bits_sent); - $display("[TB] db(D1A): 0x%02h (pad,D13,D11,D09,D07,D05,D03,D01)", db_bits_sent); + $display("[TB] @%0t: Sample[%0d] = 0x%04h (full 16-bit word)", + $time, sample_count, sample); + $display("[TB] da(D0A): 0x%02h (even bits [14,12,10,8,6,4,2,0] MSB-first)", da_bits_sent); + $display("[TB] db(D1A): 0x%02h (odd bits [15,13,11,9,7,5,3,1] MSB-first)", db_bits_sent); end sample_count <= sample_count + 1; - // Setup padding for next sample (will be captured on next Edge 0) - da_p_int <= 1'b0; // Padding zero - db_p_int <= 1'b0; // Padding zero + // Setup MSB bits for next sample's Edge 0 + da_p_int <= sample[14]; // Bit 14 + db_p_int <= sample[15]; // Bit 15 (MSB) - // Generate sine wave pattern for realistic ADC waveform display - // Sine period = 64 samples = 512ns at 125 MSPS (~1.95 MHz sine) - sample <= calc_sine_sample(sample_count + 1); + // Keep constant value for debugging (easier to trace than sine wave) + sample <= 16'h1234; // Constant value = 4660 end end diff --git a/testbenches/project/ada4355/tests/test_program.sv b/testbenches/project/ada4355/tests/test_program.sv index 4560e7043..63d501645 100644 --- a/testbenches/project/ada4355/tests/test_program.sv +++ b/testbenches/project/ada4355/tests/test_program.sv @@ -391,31 +391,25 @@ begin end endtask -// Check captured data - verify sine wave is in valid range +// Check captured data - verify constant value // Data format: Each 32-bit word contains 2 x 16-bit samples // Word[31:16] = sample[2*i+1], Word[15:0] = sample[2*i] -// Pattern from system_tb: sine wave with 64 sample period +// Pattern from system_tb: constant value for debugging task check_captured_data(bit [31:0] address, int length = 64, - int step = 2 // Unused for sine, kept for compatibility + int step = 2 // Unused, kept for compatibility ); - // Sine wave parameters (must match system_tb.sv) - localparam int SINE_AMPLITUDE = 7000; - localparam int SINE_OFFSET = 8192; - localparam int SINE_MIN = SINE_OFFSET - SINE_AMPLITUDE; // 1192 - localparam int SINE_MAX = SINE_OFFSET + SINE_AMPLITUDE; // 15192 + // Constant value parameters (must match system_tb.sv) + localparam int EXPECTED_VALUE = 16'h1234; // 4660 decimal bit [31:0] current_address; bit [31:0] captured_word; bit [15:0] sample_lo, sample_hi; int errors = 0; - int min_val = 16'hFFFF; - int max_val = 0; - `INFO(("Checking captured SINE WAVE data at address 0x%h, length=%0d words", address, length), ADI_VERBOSITY_LOW); - `INFO(("Expected range: 0x%h to 0x%h (amplitude=%0d, offset=%0d)", - SINE_MIN, SINE_MAX, SINE_AMPLITUDE, SINE_OFFSET), ADI_VERBOSITY_LOW); + `INFO(("Checking captured CONSTANT VALUE data at address 0x%h, length=%0d words", address, length), ADI_VERBOSITY_LOW); + `INFO(("Expected value: 0x%h (%0d decimal)", EXPECTED_VALUE, EXPECTED_VALUE), ADI_VERBOSITY_LOW); for (int i = 0; i < length; i = i + 1) begin current_address = address + (i * 4); @@ -425,19 +419,13 @@ task check_captured_data(bit [31:0] address, sample_lo = captured_word[15:0]; sample_hi = captured_word[31:16]; - // Track min/max for sine wave verification - if (sample_lo < min_val) min_val = sample_lo; - if (sample_hi < min_val) min_val = sample_hi; - if (sample_lo > max_val) max_val = sample_lo; - if (sample_hi > max_val) max_val = sample_hi; - - // Verify samples are within expected sine range (with 5% margin) - if (sample_lo < (SINE_MIN - 500) || sample_lo > (SINE_MAX + 500)) begin - `ERROR(("Word %0d [15:0]: Address 0x%h Value 0x%h out of sine range", i, current_address, sample_lo)); + // Verify samples match expected constant value + if (sample_lo !== EXPECTED_VALUE) begin + `ERROR(("Word %0d [15:0]: Address 0x%h Value 0x%h, expected 0x%h", i, current_address, sample_lo, EXPECTED_VALUE)); errors++; end - if (sample_hi < (SINE_MIN - 500) || sample_hi > (SINE_MAX + 500)) begin - `ERROR(("Word %0d [31:16]: Address 0x%h Value 0x%h out of sine range", i, current_address, sample_hi)); + if (sample_hi !== EXPECTED_VALUE) begin + `ERROR(("Word %0d [31:16]: Address 0x%h Value 0x%h, expected 0x%h", i, current_address, sample_hi, EXPECTED_VALUE)); errors++; end @@ -445,11 +433,8 @@ task check_captured_data(bit [31:0] address, `INFO(("Word %0d: 0x%h (samples: 0x%h, 0x%h)", i, captured_word, sample_lo, sample_hi), ADI_VERBOSITY_MEDIUM); end - `INFO(("Captured sine wave: min=0x%h (%0d), max=0x%h (%0d)", min_val, min_val, max_val, max_val), ADI_VERBOSITY_NONE); - `INFO(("Expected sine wave: min=0x%h (%0d), max=0x%h (%0d)", SINE_MIN, SINE_MIN, SINE_MAX, SINE_MAX), ADI_VERBOSITY_NONE); - if (errors == 0) begin - `INFO(("check_captured_data: PASSED - All %0d words within sine range", length), ADI_VERBOSITY_NONE); + `INFO(("check_captured_data: PASSED - All %0d words match constant value 0x%h", length, EXPECTED_VALUE), ADI_VERBOSITY_NONE); end else begin `ERROR(("check_captured_data: FAILED - %0d errors found", errors)); end diff --git a/testbenches/project/ada4355/waves/cfg_shift3.wcfg b/testbenches/project/ada4355/waves/cfg_shift3.wcfg new file mode 100644 index 000000000..f8a5bf261 --- /dev/null +++ b/testbenches/project/ada4355/waves/cfg_shift3.wcfg @@ -0,0 +1,405 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dco_p + dco_p + + + dco_n + dco_n + + + d0a_p + d0a_p + + + d0a_n + d0a_n + + + d1a_p + d1a_p + + + d1a_n + d1a_n + + + fco_p + fco_p + + + fco_n + fco_n + + + sync_n + sync_n + + + state[2:0] + state[2:0] + + + shift_cnt[2:0] + shift_cnt[2:0] + + + serdes_data[15:0] + serdes_data[15:0] + + + + serdes_data_d[15:0] + serdes_data_d[15:0] + + + pattern_value[7:0] + pattern_value[7:0] + + + frame_shifted[7:0] + frame_shifted[7:0] + + + + serdes_frame[7:0] + serdes_frame[7:0] + + + serdes_frame_d[7:0] + serdes_frame_d[7:0] + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + #D2691E + true + STYLE_DIGITAL + ANALOG_YRANGETYPE_FIXED + 1.84467e+19 + 18067 + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + #D2691E + true + STYLE_ANALOG + 100 + ANALOG_YRANGETYPE_FIXED + 1.84467e+19 + 18067 + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + data_1[7:0] + data_1[7:0] + + + data_0[7:0] + data_0[7:0] + + + frame_s7 + frame_s7 + + + frame_s6 + frame_s6 + + + frame_s5 + frame_s5 + + + frame_s4 + frame_s4 + + + frame_s3 + frame_s3 + + + frame_s2 + frame_s2 + + + frame_s1 + frame_s1 + + + frame_s0 + frame_s0 + + + adc_pn_err + adc_pn_err + + + serdes data + label + + + data_s1[1:0] + data_s1[1:0] + + + data_s2[1:0] + data_s2[1:0] + + + data_s3[1:0] + data_s3[1:0] + + + data_s4[1:0] + data_s4[1:0] + + + data_s5[1:0] + data_s5[1:0] + + + data_s6[1:0] + data_s6[1:0] + + + data_s7[1:0] + data_s7[1:0] + + + data_in_p[1:0] + data_in_p[1:0] + + + data_in_n[1:0] + data_in_n[1:0] + + + serdes frame + label + + + data_s1[0:0] + data_s1[0:0] + + + data_s2[0:0] + data_s2[0:0] + + + data_s3[0:0] + data_s3[0:0] + + + data_s4[0:0] + data_s4[0:0] + + + data_s5[0:0] + data_s5[0:0] + + + data_s6[0:0] + data_s6[0:0] + + + data_s7[0:0] + data_s7[0:0] + + + data_in_p[0:0] + data_in_p[0:0] + + + data_in_n[0:0] + data_in_n[0:0] + + + serdes_data[15:0] + serdes_data[15:0] + + + serdes_data_d[15:0] + serdes_data_d[15:0] + + + serdes_frame[7:0] + serdes_frame[7:0] + + + serdes_frame_d[7:0] + serdes_frame_d[7:0] + + + frame_shifted[7:0] + frame_shifted[7:0] + + + shift_cnt[2:0] + shift_cnt[2:0] + + + state[2:0] + state[2:0] + + + dco_p + dco_p + + + dco_n + dco_n + + + d0a_p + d0a_p + + + d0a_n + d0a_n + + + d1a_p + d1a_p + + + d1a_n + d1a_n + + + fco_p + fco_p + + + fco_n + fco_n + + + adc_data_shifted[15:0] + adc_data_shifted[15:0] + #D2691E + true + STYLE_DIGITAL + ANALOG_YRANGETYPE_FIXED + 1.84467e+19 + 18067 + HEXRADIX + +