diff --git a/library/vip/amd/s_axis_sequencer.sv b/library/vip/amd/s_axis_sequencer.sv index eede6bac..77d42582 100644 --- a/library/vip/amd/s_axis_sequencer.sv +++ b/library/vip/amd/s_axis_sequencer.sv @@ -135,6 +135,16 @@ package s_axis_sequencer_pkg; end endtask + // function for popping bytes that the test doesn't care about + task get_byte( + output bit [7:0] data); + if (byte_stream.size() == 0) begin + `ERROR(("Byte steam empty !!!")); + end else begin + data = byte_stream.pop_front(); + end + endtask + // call ready generation function task run(); user_gen_tready(); diff --git a/testbenches/ip/spi_engine_execution/Makefile b/testbenches/ip/spi_engine_execution/Makefile new file mode 100644 index 00000000..aea5c0f7 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/Makefile @@ -0,0 +1,68 @@ +#################################################################################### +#################################################################################### +## Copyright 2024(c) Analog Devices, Inc. +#################################################################################### +#################################################################################### + +# All test-bench dependencies except test programs +SV_DEPS += ../../../library/utilities/utils.svh +SV_DEPS += ../../../library/utilities/logger_pkg.sv +SV_DEPS += ../../../library/regmaps/reg_accessor.sv +SV_DEPS += ../../../library/vip/amd/m_axis_sequencer.sv +SV_DEPS += ../../../library/vip/amd/s_axis_sequencer.sv +SV_DEPS += ../../../library/vip/amd/m_axi_sequencer.sv +SV_DEPS += ../../../library/vip/amd/s_axi_sequencer.sv +SV_DEPS += ../../../library/vip/adi/spi_vip/s_spi_sequencer.sv +SV_DEPS += ../../../library/vip/adi/spi_vip/adi_spi_vip_pkg.sv +SV_DEPS += ../../../library/drivers/dmac/dmac_api.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_pkg.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_clkgen_pkg.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_dmac_pkg.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_spi_engine_pkg.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_pwm_gen_pkg.sv +SV_DEPS += ../../../library/drivers/dmac/dma_trans.sv +SV_DEPS += spi_execution_environment.sv +SV_DEPS += system_tb.sv + +ENV_DEPS += ../../../../library/util_cdc/sync_bits.v +ENV_DEPS += ../../../../library/common/ad_edge_detect.v + +ENV_DEPS += system_project.tcl +ENV_DEPS += system_bd.tcl +ENV_DEPS += spi_execution_test_bd.tcl +ENV_DEPS += ../../../scripts/adi_sim.tcl +ENV_DEPS += ../../../scripts/run_sim.tcl + +LIB_DEPS += axi_clkgen +LIB_DEPS += axi_pwm_gen +LIB_DEPS += axi_dmac +LIB_DEPS += axi_sysid +LIB_DEPS += spi_engine/spi_engine_execution +LIB_DEPS += sysid_rom + +SIM_LIB_DEPS +=spi_vip + +# 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 ../../../scripts/project-sim.mk + +# usage : +# +# run specific test on a specific configuration in gui mode +# make CFG=cfg1 TST=test_program MODE=gui +# +# run all test from a configuration +# make cfg1 + +#################################################################################### +#################################################################################### diff --git a/testbenches/ip/spi_engine_execution/README.md b/testbenches/ip/spi_engine_execution/README.md new file mode 100644 index 00000000..f1495cb4 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/README.md @@ -0,0 +1,27 @@ +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/ip/spi_engine_execution/cfgs/cfg1.tcl b/testbenches/ip/spi_engine_execution/cfgs/cfg1.tcl new file mode 100644 index 00000000..dd2d7c8a --- /dev/null +++ b/testbenches/ip/spi_engine_execution/cfgs/cfg1.tcl @@ -0,0 +1,42 @@ +global ad_project_params + +# SPI Engine DUT parameters +set ad_project_params(DATA_WIDTH) 32 +set ad_project_params(NUM_OF_CS) 1 +set ad_project_params(NUM_OF_SDI) 1 +set ad_project_params(NUM_OF_SDO) 1 +set ad_project_params(SDI_DELAY) 1 +set ad_project_params(ECHO_SCLK) 0 + +# Test parameters +set ad_project_params(DATA_DLENGTH) 18 +set ad_project_params(THREE_WIRE) 0 +set ad_project_params(CPOL) 0 +set ad_project_params(CPHA) 1 +set ad_project_params(SDO_IDLE_STATE) 0 +set ad_project_params(SLAVE_TIN) 0 +set ad_project_params(SLAVE_TOUT) 0 +set ad_project_params(MASTER_TIN) 0 +set ad_project_params(MASTER_TOUT) 0 +set ad_project_params(CS_TO_MISO) 0 +set ad_project_params(CLOCK_DIVIDER) 2 +set ad_project_params(NUM_OF_WORDS) 3 +set ad_project_params(NUM_OF_TRANSFERS) 5 +set ad_project_params(CS_ACTIVE_HIGH) 0 +set ad_project_params(ECHO_SCLK_DELAY) 0.1 +set ad_project_params(CMD_STREAM_BEAT_DELAY) 0 +set ad_project_params(SDO_STREAM_BEAT_DELAY) 50 + +set spi_s_vip_cfg [ list \ + MODE 0 \ + CPOL $ad_project_params(CPOL) \ + CPHA $ad_project_params(CPHA) \ + INV_CS $ad_project_params(CS_ACTIVE_HIGH) \ + SLAVE_TIN $ad_project_params(SLAVE_TIN) \ + SLAVE_TOUT $ad_project_params(SLAVE_TOUT) \ + MASTER_TIN $ad_project_params(MASTER_TIN) \ + MASTER_TOUT $ad_project_params(MASTER_TOUT) \ + CS_TO_MISO $ad_project_params(CS_TO_MISO) \ + DATA_DLENGTH $ad_project_params(DATA_DLENGTH) \ +] +set ad_project_params(spi_s_vip_cfg) $spi_s_vip_cfg \ No newline at end of file diff --git a/testbenches/ip/spi_engine_execution/spi_execution_environment.sv b/testbenches/ip/spi_engine_execution/spi_execution_environment.sv new file mode 100644 index 00000000..b0f7e683 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/spi_execution_environment.sv @@ -0,0 +1,205 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2018 (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" + +package spi_execution_environment_pkg; + + import axi_vip_pkg::*; + import axi4stream_vip_pkg::*; + import m_axi_sequencer_pkg::*; + import s_axi_sequencer_pkg::*; + import s_spi_sequencer_pkg::*; + import m_axis_sequencer_pkg::*; + import s_axis_sequencer_pkg::*; + import adi_spi_vip_pkg::*; + import test_harness_env_pkg::*; + import `PKGIFY(test_harness, mng_axi_vip)::*; + import `PKGIFY(test_harness, ddr_axi_vip)::*; + import `PKGIFY(test_harness, cmd_src)::*; + import `PKGIFY(test_harness, sdo_src)::*; + import `PKGIFY(test_harness, sdi_sink)::*; + import `PKGIFY(test_harness, sync_sink)::*; + import `PKGIFY(test_harness, spi_s_vip)::*; + + class spi_execution_environment extends test_harness_env; + + // Agents + adi_spi_agent #(`SPI_VIP_PARAMS(test_harness, spi_s_vip)) spi_agent; + `AGENT(test_harness, cmd_src, mst_t) cmd_src_agent; + `AGENT(test_harness, sdo_src, mst_t) sdo_src_agent; + `AGENT(test_harness, sdi_sink, slv_t) sdi_sink_agent; + `AGENT(test_harness, sync_sink, slv_t) sync_sink_agent; + + // Sequencers + s_spi_sequencer #(`SPI_VIP_PARAMS(test_harness, spi_s_vip)) spi_seq; + m_axis_sequencer #(`AGENT(test_harness, cmd_src, mst_t), + `AXIS_VIP_PARAMS(test_harness, cmd_src) + ) cmd_src_seq; + m_axis_sequencer #(`AGENT(test_harness, sdo_src, mst_t), + `AXIS_VIP_PARAMS(test_harness, sdo_src) + ) sdo_src_seq; + s_axis_sequencer #(`AGENT(test_harness, sdi_sink, slv_t)) sdi_sink_seq; + s_axis_sequencer #(`AGENT(test_harness, sync_sink, slv_t)) sync_sink_seq; + + //============================================================================ + // Constructor + //============================================================================ + function new( + virtual interface clk_vip_if #(.C_CLK_CLOCK_PERIOD(10)) sys_clk_vip_if, + virtual interface clk_vip_if #(.C_CLK_CLOCK_PERIOD(5)) dma_clk_vip_if, + virtual interface clk_vip_if #(.C_CLK_CLOCK_PERIOD(2.5)) ddr_clk_vip_if, + + virtual interface rst_vip_if #(.C_ASYNCHRONOUS(1), .C_RST_POLARITY(1)) sys_rst_vip_if, + + virtual interface axi_vip_if #(`AXI_VIP_IF_PARAMS(test_harness, mng_axi_vip)) mng_vip_if, + virtual interface axi_vip_if #(`AXI_VIP_IF_PARAMS(test_harness, ddr_axi_vip)) ddr_vip_if, + virtual interface axi4stream_vip_if #(`AXIS_VIP_IF_PARAMS(test_harness, cmd_src)) cmd_src_axis_vip_if, + virtual interface axi4stream_vip_if #(`AXIS_VIP_IF_PARAMS(test_harness, sdo_src)) sdo_src_axis_vip_if, + virtual interface axi4stream_vip_if #(`AXIS_VIP_IF_PARAMS(test_harness, sdi_sink)) sdi_sink_axis_vip_if, + virtual interface axi4stream_vip_if #(`AXIS_VIP_IF_PARAMS(test_harness, sync_sink)) sync_sink_axis_vip_if, + virtual interface spi_vip_if #(`SPI_VIP_PARAMS(test_harness, spi_s_vip)) spi_s_vip_if + ); + + super.new(sys_clk_vip_if, + dma_clk_vip_if, + ddr_clk_vip_if, + sys_rst_vip_if, + mng_vip_if, + ddr_vip_if); + + // Creating the agents + spi_agent = new(spi_s_vip_if); + cmd_src_agent = new("CMD Source AXI Stream Agent", cmd_src_axis_vip_if); + sdo_src_agent = new("SDO Source AXI Stream Agent", sdo_src_axis_vip_if); + sdi_sink_agent = new("SDI Sink AXI Stream Agent", sdi_sink_axis_vip_if); + sync_sink_agent = new("SYNC Sink AXI Stream Agent", sync_sink_axis_vip_if); + + // Creating the sequencers + spi_seq = new(spi_agent); + cmd_src_seq = new(cmd_src_agent); + sdo_src_seq = new(sdo_src_agent); + sdi_sink_seq = new(sdi_sink_agent); + sync_sink_seq = new(sync_sink_agent); + + + // downgrade reset check: we are currently using a clock generator for the SPI clock, + // so it will come a bit after the reset and trigger the default error. + // This is harmless for this test (we don't want to test any reset scheme) + cmd_src_axis_vip_if.set_xilinx_reset_check_to_warn(); + sdo_src_axis_vip_if.set_xilinx_reset_check_to_warn(); + sdi_sink_axis_vip_if.set_xilinx_reset_check_to_warn(); + sync_sink_axis_vip_if.set_xilinx_reset_check_to_warn(); + + endfunction + + //============================================================================ + // Configure environment + // - Configure the sequencer VIPs with an initial configuration before starting them + //============================================================================ + task configure(); + + xil_axi4stream_ready_gen_policy_t sdi_sink_mode; + xil_axi4stream_ready_gen_policy_t sync_sink_mode; + + // source stub + cmd_src_seq.set_stop_policy(STOP_POLICY_PACKET); + sdo_src_seq.set_stop_policy(STOP_POLICY_PACKET); + cmd_src_seq.set_data_gen_mode(DATA_GEN_MODE_TEST_DATA); + sdo_src_seq.set_data_gen_mode(DATA_GEN_MODE_TEST_DATA); + cmd_src_seq.set_data_beat_delay(`CMD_STREAM_BEAT_DELAY); + sdo_src_seq.set_data_beat_delay(`SDO_STREAM_BEAT_DELAY); + + // destination stub + sdi_sink_mode = XIL_AXI4STREAM_READY_GEN_RANDOM; + sync_sink_mode = XIL_AXI4STREAM_READY_GEN_RANDOM; + sdi_sink_seq.set_mode(sdi_sink_mode); + sync_sink_seq.set_mode(sync_sink_mode); + + endtask + + //============================================================================ + // Start environment + // - Connect all the agents to the scoreboard + // - Start the agents + //============================================================================ + task start(); + super.start(); + spi_agent.start(); + cmd_src_agent.start_master(); + sdo_src_agent.start_master(); + sdi_sink_agent.start_slave(); + sync_sink_agent.start_slave(); + endtask + + //============================================================================ + // Start the test + // - start the scoreboard + // - start the sequencers + //============================================================================ + task test(); + super.test(); + fork + cmd_src_seq.run(); + sdo_src_seq.run(); + sdi_sink_seq.run(); + sync_sink_seq.run(); + join_none + endtask + + //============================================================================ + // Run subroutine + //============================================================================ + task run; + test(); + endtask + + //============================================================================ + // Stop subroutine + //============================================================================ + task stop; + spi_agent.stop(); + super.stop(); + cmd_src_seq.stop(); + sdo_src_seq.stop(); + cmd_src_agent.stop_master(); + sdo_src_agent.stop_master(); + sdi_sink_agent.stop_slave(); + sync_sink_agent.stop_slave(); + endtask + + endclass + +endpackage diff --git a/testbenches/ip/spi_engine_execution/spi_execution_test_bd.tcl b/testbenches/ip/spi_engine_execution/spi_execution_test_bd.tcl new file mode 100644 index 00000000..f4ca1a38 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/spi_execution_test_bd.tcl @@ -0,0 +1,58 @@ +############################################################################### +## Copyright (C) 2024 Analog Devices, Inc. All rights reserved. +### SPDX short identifier: ADIBSD +############################################################################### +puts "spi execution test bd" +source $ad_hdl_dir/library/spi_engine/scripts/spi_engine.tcl + +set data_width $ad_project_params(DATA_WIDTH) +set num_cs $ad_project_params(NUM_OF_CS) +set num_sdi $ad_project_params(NUM_OF_SDI) +set num_sdo $ad_project_params(NUM_OF_SDO) +set sdi_delay $ad_project_params(SDI_DELAY) +set echo_sclk $ad_project_params(ECHO_SCLK) + +create_bd_intf_port -mode Monitor -vlnv analog.com:interface:spi_engine_rtl:1.0 spi_execution_spi +create_bd_intf_port -mode Slave -vlnv analog.com:interface:spi_engine_ctrl_rtl:1.0 s_spi_execution_ctrl +create_bd_port -dir O spi_execution_trigger + +set execution spi_execution +ad_ip_instance spi_engine_execution $execution +ad_ip_parameter $execution CONFIG.DATA_WIDTH $data_width +ad_ip_parameter $execution CONFIG.NUM_OF_CS $num_cs +ad_ip_parameter $execution CONFIG.NUM_OF_SDI $num_sdi +ad_ip_parameter $execution CONFIG.SDO_DEFAULT 1 +ad_ip_parameter $execution CONFIG.SDI_DELAY $sdi_delay +ad_ip_parameter $execution CONFIG.ECHO_SCLK $echo_sclk + +ad_ip_instance axi_clkgen spi_clkgen +ad_ip_parameter spi_clkgen CONFIG.CLK0_DIV 5 +ad_ip_parameter spi_clkgen CONFIG.VCO_DIV 1 +ad_ip_parameter spi_clkgen CONFIG.VCO_MUL 8 + +ad_ip_instance axi_pwm_gen spi_engine_trigger_gen +ad_ip_parameter spi_engine_trigger_gen CONFIG.PULSE_0_PERIOD 120 +ad_ip_parameter spi_engine_trigger_gen CONFIG.PULSE_0_WIDTH 1 + +ad_connect $sys_cpu_clk spi_clkgen/clk +ad_connect spi_clk spi_clkgen/clk_0 + +ad_connect spi_clk spi_engine_trigger_gen/ext_clk +ad_connect $sys_cpu_clk spi_engine_trigger_gen/s_axi_aclk +ad_connect sys_cpu_resetn spi_engine_trigger_gen/s_axi_aresetn +ad_connect spi_engine_trigger_gen/pwm_0 spi_execution_trigger + +ad_connect $execution/spi spi_execution_spi +ad_connect $execution/ctrl s_spi_execution_ctrl + +ad_connect spi_clk $execution/clk +ad_connect sys_cpu_resetn $execution/resetn + +ad_cpu_interconnect 0x44a70000 spi_clkgen +ad_cpu_interconnect 0x44b00000 spi_engine_trigger_gen + +ad_mem_hp1_interconnect $sys_cpu_clk sys_ps7/S_AXI_HP1 + +if {$ad_project_params(ECHO_SCLK)} { + adi_sim_add_define DEF_ECHO_SCLK +} \ No newline at end of file diff --git a/testbenches/ip/spi_engine_execution/system_bd.tcl b/testbenches/ip/spi_engine_execution/system_bd.tcl new file mode 100644 index 00000000..9aadad73 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/system_bd.tcl @@ -0,0 +1,132 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright 2024 (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 + +global ad_project_params + +adi_project_files [list \ + "../../../../library/common/ad_edge_detect.v" \ + "../../../../library/util_cdc/sync_bits.v" \ + "../../../../library/common/ad_iobuf.v" \ +] + +# +# Block design under test +# + +source ./spi_execution_test_bd.tcl + +# Add test-specific VIPs +ad_ip_instance adi_spi_vip spi_s_vip $ad_project_params(spi_s_vip_cfg) + +adi_sim_add_define "SPI_S=spi_s_vip" +ad_connect spi_execution/spi spi_s_vip/s_spi + +ad_ip_instance axi4stream_vip cmd_src [list \ + INTERFACE_MODE {MASTER} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES 2 \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +adi_sim_add_define "CMD_SRC=cmd_src" +ad_connect spi_clk cmd_src/aclk +ad_connect sys_cpu_resetn cmd_src/aresetn +ad_connect cmd_src/m_axis_tdata spi_execution/cmd +ad_connect cmd_src/m_axis_tvalid spi_execution/cmd_valid +ad_connect cmd_src/m_axis_tready spi_execution/cmd_ready + +ad_ip_instance axi4stream_vip sdo_src [list \ + INTERFACE_MODE {MASTER} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES [expr $data_width/8] \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +adi_sim_add_define "SDO_SRC=sdo_src" +ad_connect spi_clk sdo_src/aclk +ad_connect sys_cpu_resetn sdo_src/aresetn +ad_connect sdo_src/m_axis_tdata spi_execution/sdo_data +ad_connect sdo_src/m_axis_tvalid spi_execution/sdo_data_valid +ad_connect sdo_src/m_axis_tready spi_execution/sdo_data_ready + +ad_ip_instance axi4stream_vip sdi_sink [list \ + INTERFACE_MODE {SLAVE} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES [expr $num_sdi*$data_width/8] \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +adi_sim_add_define "SDI_SINK=sdi_sink" +ad_connect spi_clk sdi_sink/aclk +ad_connect sys_cpu_resetn sdi_sink/aresetn +ad_connect sdi_sink/s_axis_tdata spi_execution/sdi_data +ad_connect sdi_sink/s_axis_tvalid spi_execution/sdi_data_valid +ad_connect sdi_sink/s_axis_tready spi_execution/sdi_data_ready + +ad_ip_instance axi4stream_vip sync_sink [list \ + INTERFACE_MODE {SLAVE} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES 1 \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +adi_sim_add_define "SYNC_SINK=sync_sink" +ad_connect spi_clk sync_sink/aclk +ad_connect sys_cpu_resetn sync_sink/aresetn +ad_connect sync_sink/s_axis_tdata spi_execution/sync +ad_connect sync_sink/s_axis_tvalid spi_execution/sync_valid +ad_connect sync_sink/s_axis_tready spi_execution/sync_ready + +# Last tasks +create_bd_port -dir O spi_execution_spi_clk +if {$ad_project_params(ECHO_SCLK)} { + create_bd_port -dir I spi_execution_echo_sclk + ad_connect spi_execution_echo_sclk spi_execution/echo_sclk +} + +ad_connect spi_execution_spi_clk spi_clkgen/clk_0 + +set BA_CLKGEN 0x44A70000 +set_property offset $BA_CLKGEN [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_data_spi_clkgen}] +adi_sim_add_define "SPI_ENGINE_AXI_CLKGEN_BA=[format "%d" ${BA_CLKGEN}]" + +set BA_PWM 0x44B00000 +set_property offset $BA_PWM [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_data_spi_engine_trigger_gen}] +adi_sim_add_define "SPI_ENGINE_PWM_GEN_BA=[format "%d" ${BA_PWM}]" \ No newline at end of file diff --git a/testbenches/ip/spi_engine_execution/system_project.tcl b/testbenches/ip/spi_engine_execution/system_project.tcl new file mode 100644 index 00000000..052950db --- /dev/null +++ b/testbenches/ip/spi_engine_execution/system_project.tcl @@ -0,0 +1,52 @@ +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 to use SmartConnect or AXI Interconnect +set use_smartconnect 1 + +# Create the project +adi_sim_project_xilinx $project_name "xc7z007sclg400-1" + +# Add test files to the project +adi_sim_project_files [list \ + "../../../library/utilities/utils.svh" \ + "../../../library/utilities/logger_pkg.sv" \ + "../../../library/regmaps/reg_accessor.sv" \ + "../../../library/vip/amd/m_axis_sequencer.sv" \ + "../../../library/vip/amd/s_axis_sequencer.sv" \ + "../../../library/vip/amd/m_axi_sequencer.sv" \ + "../../../library/vip/amd/s_axi_sequencer.sv" \ + "../../../library/vip/adi/spi_vip/adi_spi_vip_pkg.sv" \ + "../../../library/vip/adi/spi_vip/s_spi_sequencer.sv" \ + "../../../library/drivers/dmac/dmac_api.sv" \ + "../../../library/regmaps/adi_regmap_pkg.sv" \ + "../../../library/regmaps/adi_regmap_clkgen_pkg.sv" \ + "../../../library/regmaps/adi_regmap_dmac_pkg.sv" \ + "../../../library/regmaps/adi_regmap_pwm_gen_pkg.sv" \ + "../../../library/regmaps/adi_regmap_spi_engine_pkg.sv" \ + "../../../library/drivers/dmac/dma_trans.sv" \ + "../../../library/utilities/test_harness_env.sv" \ + "../../../library/drivers/spi_engine/spi_engine_instr_pkg.sv" \ + "spi_execution_environment.sv" \ + "tests/test_program.sv" \ + "system_tb.sv" \ + ] + +#set a default test program +adi_sim_add_define "TEST_PROGRAM=test_program" + +adi_sim_generate $project_name diff --git a/testbenches/ip/spi_engine_execution/system_tb.sv b/testbenches/ip/spi_engine_execution/system_tb.sv new file mode 100644 index 00000000..183f7a55 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/system_tb.sv @@ -0,0 +1,72 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2021 - 2023 (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(); + wire spi_execution_spi_cs; + wire spi_execution_spi_sclk; + wire spi_execution_spi_clk; + wire spi_execution_spi_sdi; + wire spi_execution_spi_sdo; + wire spi_execution_trigger; +`ifdef DEF_ECHO_SCLK + wire spi_execution_echo_sclk; +`endif + + `TEST_PROGRAM test( + .spi_execution_spi_sclk(spi_execution_spi_sclk), + .spi_execution_spi_cs(spi_execution_spi_cs), + .spi_execution_spi_clk(spi_execution_spi_clk), + .spi_execution_trigger(spi_execution_trigger), + `ifdef DEF_ECHO_SCLK + .spi_execution_echo_sclk(spi_execution_echo_sclk), + `endif + .spi_execution_spi_sdi(spi_execution_spi_sdi)); + + test_harness `TH ( + .spi_execution_spi_cs(spi_execution_spi_cs), + .spi_execution_spi_sclk(spi_execution_spi_sclk), + .spi_execution_spi_clk(spi_execution_spi_clk), + .spi_execution_spi_sdi(spi_execution_spi_sdi), + .spi_execution_trigger(spi_execution_trigger), + `ifdef DEF_ECHO_SCLK + .spi_execution_echo_sclk(spi_execution_echo_sclk), + `endif + .spi_execution_spi_sdo(spi_execution_spi_sdo)); + +endmodule diff --git a/testbenches/ip/spi_engine_execution/tests/test_program.sv b/testbenches/ip/spi_engine_execution/tests/test_program.sv new file mode 100644 index 00000000..e758f3d7 --- /dev/null +++ b/testbenches/ip/spi_engine_execution/tests/test_program.sv @@ -0,0 +1,336 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2021 - 2024 (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 m_axis_sequencer_pkg::*; +import s_axis_sequencer_pkg::*; +import adi_regmap_pkg::*; +import adi_regmap_clkgen_pkg::*; +import adi_regmap_dmac_pkg::*; +import adi_regmap_pwm_gen_pkg::*; +import adi_regmap_spi_engine_pkg::*; +import logger_pkg::*; +import spi_execution_environment_pkg::*; +import spi_engine_instr_pkg::*; +import adi_spi_vip_pkg::*; + + +program test_program ( + inout spi_execution_spi_sclk, + inout [(`NUM_OF_CS - 1):0] spi_execution_spi_cs, + inout spi_execution_spi_clk, + inout spi_execution_trigger, + `ifdef DEF_ECHO_SCLK + inout spi_execution_echo_sclk, + `endif + inout [(`NUM_OF_SDI - 1):0] spi_execution_spi_sdi); + +timeunit 1ns; +timeprecision 100ps; + +spi_execution_environment env; + +// -------------------------- +// Wrapper function for AXI read verify +// -------------------------- +task axi_read_v( + input [31:0] raddr, + input [31:0] vdata); + env.mng.RegReadVerify32(raddr,vdata); +endtask + +task axi_read( + input [31:0] raddr, + output [31:0] data); + env.mng.RegRead32(raddr,data); +endtask + +// -------------------------- +// Wrapper function for AXI write +// -------------------------- +task axi_write( + input [31:0] waddr, + input [31:0] wdata); + env.mng.RegWrite32(waddr,wdata); +endtask + +// -------------------------- +// Wrapper function for SPI receive (from DUT) +// -------------------------- +task spi_receive( + output [`DATA_DLENGTH:0] data); + env.spi_seq.receive_data(data); +endtask + +// -------------------------- +// Wrapper function for SPI receive & verify (from DUT) +// -------------------------- +task spi_receive_v( + input [`DATA_DLENGTH:0] data); + env.spi_seq.receive_data_verify(data); +endtask + + +// -------------------------- +// Wrapper function for SPI send (to DUT) +// -------------------------- +task spi_send( + input [`DATA_DLENGTH:0] data); + env.spi_seq.send_data(data); +endtask + +// -------------------------- +// Wrapper function for waiting for all SPI +// -------------------------- +task spi_wait_send(); + env.spi_seq.flush_send(); +endtask + +// -------------------------- +// Main procedure +// -------------------------- +initial begin + + //creating environment + env = new(`TH.`SYS_CLK.inst.IF, + `TH.`DMA_CLK.inst.IF, + `TH.`DDR_CLK.inst.IF, + `TH.`SYS_RST.inst.IF, + `TH.`MNG_AXI.inst.IF, + `TH.`DDR_AXI.inst.IF, + `TH.`CMD_SRC.inst.IF, + `TH.`SDO_SRC.inst.IF, + `TH.`SDI_SINK.inst.IF, + `TH.`SYNC_SINK.inst.IF, + `TH.`SPI_S.inst.IF + ); + + setLoggerVerbosity(6); + `INFO(("Test Start")); + env.start(); + + env.configure(); + + env.sys_reset(); + + env.run(); + + env.spi_seq.set_default_miso_data('h2AA55); + + env.cmd_src_seq.start(); // start command source (will wait for data enqueued) + env.sdo_src_seq.start(); + + #100ns + + spi_execution_test(); + + `INFO(("Test Done")); + + $finish; + +end + + +//--------------------------------------------------------------------------- +// SPI Engine generate transfer +//--------------------------------------------------------------------------- +task generate_transfer( + input [7:0] sync_id); + xil_axi4stream_data_byte cmd[1:0]; + `INFOV(("Transfer generation waiting for trigger."), 6); + @(posedge spi_execution_trigger); + // assert CS + cmd[0] = (`SET_CS(8'hFE)) & 8'hFF; + cmd[1] = ((`SET_CS(8'hFE)) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // transfer data + cmd[0] = (`INST_WRD) & 8'hFF; + cmd[1] = ((`INST_WRD) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // de-assert CS + cmd[0] = (`SET_CS(8'hFF)) & 8'hFF; + cmd[1] = ((`SET_CS(8'hFF)) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // SYNC command + cmd[0] = (`INST_SYNC) & 8'hFF; + cmd[1] = ((`INST_SYNC) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // generate transfer descriptor + env.cmd_src_seq.add_xfer_descriptor(8,0,0); + `INFOV(("Transfer generation finished."), 6); +endtask + +//--------------------------------------------------------------------------- +// SPI Engine configure +//--------------------------------------------------------------------------- +task configure_spi_execution(); + xil_axi4stream_data_byte cmd[1:0]; + bit [7:0] mask; + // write cfg bits + cmd[0] = (`INST_CFG) & 8'hFF; + cmd[1] = ((`INST_CFG) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // write prescaler value + cmd[0] = (`INST_PRESCALE) & 8'hFF; + cmd[1] = ((`INST_PRESCALE) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // write data length + cmd[0] = (`INST_DLENGTH) & 8'hFF; + cmd[1] = ((`INST_DLENGTH) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // write cs inv mask + if (`CS_ACTIVE_HIGH) begin + mask = 8'hFF; + end else begin + mask = 8'h00; + end + cmd[0] = (`SET_CS_INV_MASK(mask)) & 8'hFF; + cmd[1] = ((`SET_CS_INV_MASK(mask)) & 16'hFF00) >> 8; + env.cmd_src_seq.push_byte_for_stream(cmd[0]); + env.cmd_src_seq.push_byte_for_stream(cmd[1]); + // generate transfer descriptor + env.cmd_src_seq.add_xfer_descriptor(8,0,0); +endtask + +//--------------------------------------------------------------------------- +// SPI Engine SDO data +//--------------------------------------------------------------------------- +task generate_sdo_data( + output [`DATA_DLENGTH:0] rand_data); + xil_axi4stream_data_byte data[(`DATA_WIDTH/8)-1:0]; + rand_data = $urandom; + for (int i = 0; i<(`DATA_WIDTH/8);i++) begin + data[i] = (rand_data & (8'hFF << 8*i)) >> 8*i; + env.sdo_src_seq.push_byte_for_stream(data[i]); + end + env.sdo_src_seq.add_xfer_descriptor((`DATA_WIDTH/8),0,0); +endtask + +//--------------------------------------------------------------------------- +// Echo SCLK generation - we need this only if ECHO_SCLK is enabled +//--------------------------------------------------------------------------- +`ifdef DEF_ECHO_SCLK + assign #(`ECHO_SCLK_DELAY * 1ns) spi_execution_echo_sclk = spi_execution_spi_sclk; +`endif + + +//--------------------------------------------------------------------------- +// SPI Execution Test +//--------------------------------------------------------------------------- + +bit [`DATA_DLENGTH-1:0] sdi_read_data [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)-1:0]= '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdi_read_data_store [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)-1:0]; +bit [`DATA_DLENGTH-1:0] sdo_write_data [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)-1:0]= '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdo_write_data_store [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)-1:0]; +bit [`DATA_DLENGTH-1:0] rx_data; +bit [`DATA_DLENGTH-1:0] tx_data; +bit [`DATA_DLENGTH-1:0] temp_data; +bit [7:0] data_byte; +bit [`DATA_WIDTH:0] data; + +task spi_execution_test(); + // Start spi clk generator + axi_write (`SPI_ENGINE_AXI_CLKGEN_BA + GetAddrs(AXI_CLKGEN_REG_RSTN), + `SET_AXI_CLKGEN_REG_RSTN_MMCM_RSTN(1) | + `SET_AXI_CLKGEN_REG_RSTN_RSTN(1) + ); + + // Config pwm + axi_write (`SPI_ENGINE_PWM_GEN_BA + GetAddrs(AXI_PWM_GEN_REG_RSTN), `SET_AXI_PWM_GEN_REG_RSTN_RESET(1)); // PWM_GEN reset in regmap (ACTIVE HIGH) + axi_write (`SPI_ENGINE_PWM_GEN_BA + GetAddrs(AXI_PWM_GEN_REG_PULSE_X_PERIOD), `SET_AXI_PWM_GEN_REG_PULSE_X_PERIOD_PULSE_X_PERIOD('d1000)); // set PWM period + + // Configure the execution module + configure_spi_execution(); + + // Enqueue transfer to DUT + for (int i = 0; i<((`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)) ; i=i+1) begin + rx_data = $urandom; + spi_send(rx_data); + sdi_read_data_store[i] = rx_data; + generate_sdo_data(tx_data); + sdo_write_data_store[i] = tx_data; + end + + axi_write (`SPI_ENGINE_PWM_GEN_BA + GetAddrs(AXI_PWM_GEN_REG_RSTN), `SET_AXI_PWM_GEN_REG_RSTN_LOAD_CONFIG(1)); // load AXI_PWM_GEN configuration + `INFOV(("axi_pwm_gen started."),6); + + for (int i = 0; i<(`NUM_OF_TRANSFERS) ; i=i+1) begin + generate_transfer(i); + //#100 + end + + spi_wait_send(); + + for (int i = 0; i<((`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)) ; i=i+1) begin + env.sdi_sink_seq.get_transfer(); + for (int b =0; b<((`DATA_WIDTH+7)/8);b++) begin + env.sdi_sink_seq.get_byte(data_byte); + data[8*b+:8] = data_byte; + end + sdi_read_data[i] = data[`DATA_DLENGTH-1:0]; + if (sdi_read_data_store[i] !== sdi_read_data[i]) begin + `INFOV(("sdi_read_data[i]: %x; sdi_read_data_store[i]: %x", sdi_read_data[i], sdi_read_data_store[i]),6); + `ERROR(("SPI Execution Read Test FAILED")); + end + end + `INFO(("SPI Execution Read Test PASSED")); + + for (int i = 0; i<((`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)) ; i=i+1) begin + spi_receive(sdo_write_data[i]); + if (sdo_write_data_store[i] !== sdo_write_data[i]) begin + `INFOV(("sdo_write_data[i]: %x; sdo_write_data_store[i]: %x", sdo_write_data[i], sdo_write_data_store[i]),6); + `ERROR(("SPI Execution Write Test FAILED")); + end + end + `INFO(("SPI Execution Write Test PASSED")); + + #200ns + + `INFO(("SPI Execution Test PASSED")); +endtask + +endprogram diff --git a/testbenches/ip/spi_engine_execution/waves/cfg1.wcfg b/testbenches/ip/spi_engine_execution/waves/cfg1.wcfg new file mode 100644 index 00000000..ebfc6edc --- /dev/null +++ b/testbenches/ip/spi_engine_execution/waves/cfg1.wcfg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + spi_execution_spi_cs + spi_execution_spi_cs + + + spi_execution_spi_sclk + spi_execution_spi_sclk + + + spi_execution_spi_clk + spi_execution_spi_clk + + + spi_execution_spi_sdi + spi_execution_spi_sdi + + + spi_execution_spi_sdo + spi_execution_spi_sdo + + + spi_execution_trigger + spi_execution_trigger + + + offload_captured_word_arr[19:0][31:0] + offload_captured_word_arr[19:0][31:0] + + + offload_sdi_data_store_arr[19:0][31:0] + offload_sdi_data_store_arr[19:0][31:0] + + + sdi_read_data[19:0][31:0] + sdi_read_data[19:0][31:0] + + + sdi_read_data_store[19:0][31:0] + sdi_read_data_store[19:0][31:0] + +