diff --git a/library/regmaps/adi_regmap_spi_engine_pkg.sv b/library/regmaps/adi_regmap_spi_engine_pkg.sv index 830bb3a7..b7a90bd3 100644 --- a/library/regmaps/adi_regmap_spi_engine_pkg.sv +++ b/library/regmaps/adi_regmap_spi_engine_pkg.sv @@ -33,7 +33,7 @@ // *************************************************************************** // *************************************************************************** /* Auto generated Register Map */ -/* Wed Jul 24 09:28:37 2024 */ +/* Tue Oct 29 19:18:58 2024 */ package adi_regmap_spi_engine_pkg; import adi_regmap_pkg::*; @@ -43,7 +43,7 @@ package adi_regmap_spi_engine_pkg; const reg_t AXI_SPI_ENGINE_VERSION = '{ 'h0000, "VERSION" , '{ "VERSION_MAJOR": '{ 31, 16, RO, 'h00000001 }, - "VERSION_MINOR": '{ 15, 8, RO, 'h00000003 }, + "VERSION_MINOR": '{ 15, 8, RO, 'h00000004 }, "VERSION_PATCH": '{ 7, 0, RO, 'h00000001 }}}; `define SET_AXI_SPI_ENGINE_VERSION_VERSION_MAJOR(x) SetField(AXI_SPI_ENGINE_VERSION,"VERSION_MAJOR",x) `define GET_AXI_SPI_ENGINE_VERSION_VERSION_MAJOR(x) GetField(AXI_SPI_ENGINE_VERSION,"VERSION_MAJOR",x) @@ -257,6 +257,13 @@ package adi_regmap_spi_engine_pkg; `define DEFAULT_AXI_SPI_ENGINE_OFFLOAD0_MEM_RESET_OFFLOAD0_MEM_RESET GetResetValue(AXI_SPI_ENGINE_OFFLOAD0_MEM_RESET,"OFFLOAD0_MEM_RESET") `define UPDATE_AXI_SPI_ENGINE_OFFLOAD0_MEM_RESET_OFFLOAD0_MEM_RESET(x,y) UpdateField(AXI_SPI_ENGINE_OFFLOAD0_MEM_RESET,"OFFLOAD0_MEM_RESET",x,y) + const reg_t AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL = '{ 'h010c, "OFFLOAD0_SDO_SRC_SEL" , '{ + "OFFLOAD0_SDO_SRC_SEL": '{ 31, 0, RW, 'h00000000 }}}; + `define SET_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL(x) SetField(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL,"OFFLOAD0_SDO_SRC_SEL",x) + `define GET_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL(x) GetField(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL,"OFFLOAD0_SDO_SRC_SEL",x) + `define DEFAULT_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL GetResetValue(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL,"OFFLOAD0_SDO_SRC_SEL") + `define UPDATE_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL(x,y) UpdateField(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL,"OFFLOAD0_SDO_SRC_SEL",x,y) + const reg_t AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO = '{ 'h0110, "OFFLOAD0_CDM_FIFO" , '{ "OFFLOAD0_CDM_FIFO": '{ 31, 0, WO, 'hXXXXXXXX }}}; `define SET_AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO_OFFLOAD0_CDM_FIFO(x) SetField(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO,"OFFLOAD0_CDM_FIFO",x) diff --git a/library/vip/adi/spi_vip/adi_spi_vip.sv b/library/vip/adi/spi_vip/adi_spi_vip.sv index fd3ec55c..b02b6e45 100644 --- a/library/vip/adi/spi_vip/adi_spi_vip.sv +++ b/library/vip/adi/spi_vip/adi_spi_vip.sv @@ -33,8 +33,6 @@ // *************************************************************************** // *************************************************************************** -`include "utils.svh" - module adi_spi_vip #( parameter MODE = 0, // SLAVE=0 parameter CPOL = 0, diff --git a/library/vip/adi/spi_vip/adi_spi_vip_ip.tcl b/library/vip/adi/spi_vip/adi_spi_vip_ip.tcl index d6748352..6d873c85 100644 --- a/library/vip/adi/spi_vip/adi_spi_vip_ip.tcl +++ b/library/vip/adi/spi_vip/adi_spi_vip_ip.tcl @@ -8,7 +8,6 @@ source $ad_hdl_dir/library/scripts/adi_ip_xilinx.tcl adi_ip_create adi_spi_vip adi_ip_files adi_spi_vip [list \ - "adi_spi_vip_pkg.sv" \ "adi_spi_vip.sv" \ "spi_vip_if.sv" \ "adi_spi_vip_pkg.ttcl" \ @@ -157,7 +156,7 @@ set_property -dict [list \ ## DEFAULT_MISO_DATA set_property -dict [list \ "value_bit_string_length" "32" \ - "value_format" "bit_string" \ + "value_format" "bitString" \ "enablement_tcl_expr" "\$MODE==0" \ ] \ [ipx::get_user_parameters DEFAULT_MISO_DATA -of_objects $cc] diff --git a/library/vip/amd/s_axis_sequencer.sv b/library/vip/amd/s_axis_sequencer.sv index 35418e6c..7e3024b2 100644 --- a/library/vip/amd/s_axis_sequencer.sv +++ b/library/vip/amd/s_axis_sequencer.sv @@ -140,6 +140,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/cfgs/cfg00.tcl b/testbenches/ip/spi_engine/cfgs/cfg00.tcl new file mode 100644 index 00000000..03ad3cc9 --- /dev/null +++ b/testbenches/ip/spi_engine/cfgs/cfg00.tcl @@ -0,0 +1,58 @@ +global ad_project_params + +# SPI Engine DUT parameters +set ad_project_params(DATA_WIDTH) 32 +set ad_project_params(ASYNC_SPI_CLK) 1 +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 +set ad_project_params(CMD_MEM_ADDR_WIDTH) 4 +set ad_project_params(DATA_MEM_ADDR_WIDTH) 4 +set ad_project_params(SDI_FIFO_ADDR_WIDTH) 5 +set ad_project_params(SDO_FIFO_ADDR_WIDTH) 5 +set ad_project_params(SYNC_FIFO_ADDR_WIDTH) 4 +set ad_project_params(CMD_FIFO_ADDR_WIDTH) 4 +set ad_project_params(SDO_STREAMING) 0 + +# Test parameters +set ad_project_params(DATA_DLENGTH) 16 +set ad_project_params(THREE_WIRE) 0 +set ad_project_params(CPOL) 0 +set ad_project_params(CPHA) 0 +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) 5 +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 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 + +set axis_sdo_src_vip_cfg [ list \ + INTERFACE_MODE {MASTER} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES [expr $ad_project_params(DATA_WIDTH)/8] \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +set ad_project_params(axis_sdo_src_vip_cfg) $axis_sdo_src_vip_cfg diff --git a/testbenches/ip/spi_engine/cfgs/cfg1.tcl b/testbenches/ip/spi_engine/cfgs/cfg01.tcl similarity index 98% rename from testbenches/ip/spi_engine/cfgs/cfg1.tcl rename to testbenches/ip/spi_engine/cfgs/cfg01.tcl index 19d8eb87..14dc9642 100644 --- a/testbenches/ip/spi_engine/cfgs/cfg1.tcl +++ b/testbenches/ip/spi_engine/cfgs/cfg01.tcl @@ -32,7 +32,6 @@ 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(SDO_MEM_WORDS) 1 set spi_s_vip_cfg [ list \ MODE 0 \ diff --git a/testbenches/ip/spi_engine/cfgs/cfg10.tcl b/testbenches/ip/spi_engine/cfgs/cfg10.tcl new file mode 100644 index 00000000..3f15e6fc --- /dev/null +++ b/testbenches/ip/spi_engine/cfgs/cfg10.tcl @@ -0,0 +1,58 @@ +global ad_project_params + +# SPI Engine DUT parameters +set ad_project_params(DATA_WIDTH) 32 +set ad_project_params(ASYNC_SPI_CLK) 1 +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 +set ad_project_params(CMD_MEM_ADDR_WIDTH) 4 +set ad_project_params(DATA_MEM_ADDR_WIDTH) 4 +set ad_project_params(SDI_FIFO_ADDR_WIDTH) 5 +set ad_project_params(SDO_FIFO_ADDR_WIDTH) 5 +set ad_project_params(SYNC_FIFO_ADDR_WIDTH) 4 +set ad_project_params(CMD_FIFO_ADDR_WIDTH) 4 +set ad_project_params(SDO_STREAMING) 0 + +# Test parameters +set ad_project_params(DATA_DLENGTH) 18 +set ad_project_params(THREE_WIRE) 0 +set ad_project_params(CPOL) 1 +set ad_project_params(CPHA) 0 +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 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 + +set axis_sdo_src_vip_cfg [ list \ + INTERFACE_MODE {MASTER} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES [expr $ad_project_params(DATA_WIDTH)/8] \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +set ad_project_params(axis_sdo_src_vip_cfg) $axis_sdo_src_vip_cfg diff --git a/testbenches/ip/spi_engine/cfgs/cfg11.tcl b/testbenches/ip/spi_engine/cfgs/cfg11.tcl new file mode 100644 index 00000000..8cde6784 --- /dev/null +++ b/testbenches/ip/spi_engine/cfgs/cfg11.tcl @@ -0,0 +1,58 @@ +global ad_project_params + +# SPI Engine DUT parameters +set ad_project_params(DATA_WIDTH) 32 +set ad_project_params(ASYNC_SPI_CLK) 1 +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 +set ad_project_params(CMD_MEM_ADDR_WIDTH) 4 +set ad_project_params(DATA_MEM_ADDR_WIDTH) 4 +set ad_project_params(SDI_FIFO_ADDR_WIDTH) 5 +set ad_project_params(SDO_FIFO_ADDR_WIDTH) 5 +set ad_project_params(SYNC_FIFO_ADDR_WIDTH) 4 +set ad_project_params(CMD_FIFO_ADDR_WIDTH) 4 +set ad_project_params(SDO_STREAMING) 0 + +# Test parameters +set ad_project_params(DATA_DLENGTH) 18 +set ad_project_params(THREE_WIRE) 0 +set ad_project_params(CPOL) 1 +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 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 + +set axis_sdo_src_vip_cfg [ list \ + INTERFACE_MODE {MASTER} \ + HAS_TREADY 1 \ + HAS_TLAST 0 \ + TDATA_NUM_BYTES [expr $ad_project_params(DATA_WIDTH)/8] \ + TDEST_WIDTH 0 \ + TID_WIDTH 0 \ +] +set ad_project_params(axis_sdo_src_vip_cfg) $axis_sdo_src_vip_cfg diff --git a/testbenches/ip/spi_engine/cfgs/cfg_inv_cs.tcl b/testbenches/ip/spi_engine/cfgs/cfg_inv_cs.tcl index 1238c667..8e18ab15 100644 --- a/testbenches/ip/spi_engine/cfgs/cfg_inv_cs.tcl +++ b/testbenches/ip/spi_engine/cfgs/cfg_inv_cs.tcl @@ -32,7 +32,6 @@ set ad_project_params(NUM_OF_WORDS) 3 set ad_project_params(NUM_OF_TRANSFERS) 5 set ad_project_params(CS_ACTIVE_HIGH) 1 set ad_project_params(ECHO_SCLK_DELAY) 0.1 -set ad_project_params(SDO_MEM_WORDS) 2 set spi_s_vip_cfg [ list \ MODE 0 \ diff --git a/testbenches/ip/spi_engine/cfgs/cfg_sdo_streaming.tcl b/testbenches/ip/spi_engine/cfgs/cfg_sdo_streaming.tcl index a9cdd37e..523eadfc 100644 --- a/testbenches/ip/spi_engine/cfgs/cfg_sdo_streaming.tcl +++ b/testbenches/ip/spi_engine/cfgs/cfg_sdo_streaming.tcl @@ -32,7 +32,6 @@ set ad_project_params(NUM_OF_WORDS) 5 set ad_project_params(NUM_OF_TRANSFERS) 3 set ad_project_params(CS_ACTIVE_HIGH) 0 set ad_project_params(ECHO_SCLK_DELAY) 0.1 -set ad_project_params(SDO_MEM_WORDS) 2 set spi_s_vip_cfg [ list \ MODE 0 \ diff --git a/testbenches/ip/spi_engine/system_project.tcl b/testbenches/ip/spi_engine/system_project.tcl index fa8d6797..02f6f8d0 100644 --- a/testbenches/ip/spi_engine/system_project.tcl +++ b/testbenches/ip/spi_engine/system_project.tcl @@ -44,6 +44,7 @@ adi_sim_project_files [list \ "spi_environment.sv" \ "tests/test_program.sv" \ "tests/test_sleep_delay.sv" \ + "tests/test_slowdata.sv" \ "system_tb.sv" \ ] diff --git a/testbenches/ip/spi_engine/tests/test_program.sv b/testbenches/ip/spi_engine/tests/test_program.sv index b5cc0732..1d3bd654 100644 --- a/testbenches/ip/spi_engine/tests/test_program.sv +++ b/testbenches/ip/spi_engine/tests/test_program.sv @@ -274,8 +274,6 @@ bit [`DATA_DLENGTH-1:0] sdi_read_data_store [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS) 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; -localparam sdo_mem_num = (`SDO_STREAMING) ? (`MIN((`NUM_OF_WORDS),(`SDO_MEM_WORDS))) : (`NUM_OF_WORDS); -bit [`DATA_DLENGTH-1:0] one_shot_sdo_data [sdo_mem_num-1 :0] = '{default:'0}; task offload_spi_test(); //Configure DMA @@ -288,6 +286,11 @@ task offload_spi_test(); env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_DEST_ADDRESS), `SET_DMAC_DEST_ADDRESS_DEST_ADDRESS(`DDR_BA)); env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_TRANSFER_SUBMIT), `SET_DMAC_TRANSFER_SUBMIT_TRANSFER_SUBMIT(1)); + `ifdef DEF_SDO_STREAMING + // Enable SDO Offload + axi_write(`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL), `SET_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL(1)); + `endif + // Configure the Offload module axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_CFG); axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_PRESCALE); @@ -301,21 +304,22 @@ task offload_spi_test(); axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_SYNC | 2); // Enqueue transfers transfers to DUT - for (int i = 0; i +// +// 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/main/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_clkgen_pkg::*; +import adi_regmap_dmac_pkg::*; +import adi_regmap_pwm_gen_pkg::*; +import adi_regmap_spi_engine_pkg::*; +import logger_pkg::*; +import spi_environment_pkg::*; +import spi_engine_instr_pkg::*; +import adi_spi_vip_pkg::*; + +//--------------------------------------------------------------------------- +// SPI Engine configuration parameters +//--------------------------------------------------------------------------- + +program test_slowdata ( + inout spi_engine_irq, + inout spi_engine_spi_sclk, + inout [(`NUM_OF_CS - 1):0] spi_engine_spi_cs, + inout spi_engine_spi_clk, + `ifdef DEF_ECHO_SCLK + inout spi_engine_echo_sclk, + `endif + inout [(`NUM_OF_SDI - 1):0] spi_engine_spi_sdi); + +timeunit 1ns; +timeprecision 100ps; + +spi_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 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, + `ifdef DEF_SDO_STREAMING + `TH.`SDO_SRC.inst.IF, + `endif + `TH.`MNG_AXI.inst.IF, + `TH.`DDR_AXI.inst.IF, + `TH.`SPI_S.inst.IF + ); + + setLoggerVerbosity(6); + env.start(); + env.configure(); + + env.sys_reset(); + + env.run(); + + env.spi_seq.set_default_miso_data('h2AA55); + + // start sdo source (will wait for data enqueued) + `ifdef DEF_SDO_STREAMING + env.sdo_src_seq.start(); + `endif + + sanity_test(); + + #100ns + + fifo_init_test(); + + fifo_single_read_test(); + + fifo_double_write_test(); + + fifo_double_read_test(); + + fifo_double_write_test(); + + offload_spi_test(); + + #100ns + `INFO(("Test Done")); + + $finish; + +end + +//--------------------------------------------------------------------------- +// Sanity test reg interface +//--------------------------------------------------------------------------- + +task sanity_test(); + bit [31:0] pcore_version = (`DEFAULT_AXI_SPI_ENGINE_VERSION_VERSION_PATCH) + | (`DEFAULT_AXI_SPI_ENGINE_VERSION_VERSION_MINOR)<<8 + | (`DEFAULT_AXI_SPI_ENGINE_VERSION_VERSION_MAJOR)<<16; + //axi_read_v (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_VERSION), pcore_version); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SCRATCH), 32'hDEADBEEF); + axi_read_v (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SCRATCH), 32'hDEADBEEF); + `INFO(("Sanity Test Done")); +endtask + +//--------------------------------------------------------------------------- +// SPI Engine generate transfer +//--------------------------------------------------------------------------- + +task generate_init_transfer_cmd( + input [7:0] sync_id); + // configure cs + if (`CS_ACTIVE_HIGH) begin + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS_INV_MASK(8'hFF)); + end + // write cfg + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_CFG); + // assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFE)); + // write prescaler + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_PRESCALE); + // write dlen + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_DLENGTH); + // transfer data + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_WR); + // de-assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFF)); + // SYNC command to generate interrupt + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_SYNC | sync_id)); + `INFOV(("Transfer generation finished."), 6); +endtask + +task generate_single_rtransfer_cmd( + input [7:0] sync_id); + // configure cs + if (`CS_ACTIVE_HIGH) begin + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS_INV_MASK(8'hFF)); + end + // write cfg + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_CFG); + // assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFE)); + // write prescaler + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_PRESCALE); + // write dlen + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_DLENGTH); + // transfer data + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_RD & 16'hFF00)); + // de-assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFF)); + // SYNC command to generate interrupt + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_SYNC | sync_id)); + `INFOV(("Transfer generation finished."), 6); +endtask + + +task generate_double_rtransfer_cmd( + input [7:0] sync_id); + // configure cs + if (`CS_ACTIVE_HIGH) begin + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS_INV_MASK(8'hFF)); + end + // write cfg + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_CFG); + // assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFE)); + // write prescaler + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_PRESCALE); + // write dlen + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_DLENGTH); + // transfer data + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_RD & 16'hFF00)); + // transfer data + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_RD & 16'hFF00)); + // de-assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFF)); + // SYNC command to generate interrupt + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_SYNC | sync_id)); + `INFOV(("Transfer generation finished."), 6); +endtask + +task generate_double_wtransfer_cmd( + input [7:0] sync_id); + // configure cs + if (`CS_ACTIVE_HIGH) begin + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS_INV_MASK(8'hFF)); + end + // write cfg + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_CFG); + // assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFE)); + // write prescaler + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_PRESCALE); + // write dlen + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_DLENGTH); + // transfer data + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_WR & 16'hFF00)); + // transfer data + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_WR & 16'hFF00)); + // de-assert CSN + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `SET_CS(8'hFF)); + // SYNC command to generate interrupt + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), (`INST_SYNC | sync_id)); + `INFOV(("Transfer generation finished."), 6); +endtask + +//--------------------------------------------------------------------------- +// IRQ callback +//--------------------------------------------------------------------------- + +reg [4:0] irq_pending = 0; +reg [7:0] sync_id = 0; + +initial begin + forever begin + @(posedge spi_engine_irq); + // read pending IRQs + + axi_read (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_IRQ_PENDING), irq_pending); + // IRQ launched by Offload SYNC command + if (irq_pending & 5'b10000) begin + axi_read (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SYNC_ID), sync_id); + `INFOV(("Offload SYNC %d IRQ. An offload transfer just finished.", sync_id), 6); + end + // IRQ launched by SYNC command + if (irq_pending & 5'b01000) begin + axi_read (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SYNC_ID), sync_id); + `INFOV(("SYNC %d IRQ. FIFO transfer just finished.", sync_id),6); + end + // IRQ launched by SDI FIFO + if (irq_pending & 5'b00100) begin + `INFOV(("SDI FIFO IRQ."),6); + end + // IRQ launched by SDO FIFO + if (irq_pending & 5'b00010) begin + `INFOV(("SDO FIFO IRQ."),6); + end + // IRQ launched by SDO FIFO + if (irq_pending & 5'b00001) begin + `INFOV(("CMD FIFO IRQ."),6); + end + // Clear all pending IRQs + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_IRQ_PENDING), irq_pending); + end +end + +//--------------------------------------------------------------------------- +// SPI Engine SDO data +//--------------------------------------------------------------------------- + +task sdo_stream_gen( + input [`DATA_DLENGTH:0] tx_data); + xil_axi4stream_data_byte data[(`DATA_WIDTH/8)-1:0]; + `ifdef DEF_SDO_STREAMING + for (int i = 0; i<(`DATA_WIDTH/8);i++) begin + data[i] = (tx_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); + `endif +endtask + +//--------------------------------------------------------------------------- +// Echo SCLK generation - we need this only if ECHO_SCLK is enabled +//--------------------------------------------------------------------------- +`ifdef DEF_ECHO_SCLK + assign #(`ECHO_SCLK_DELAY * 1ns) spi_engine_echo_sclk = spi_engine_spi_sclk; +`endif + +//--------------------------------------------------------------------------- +// FIFO SPI Test +//--------------------------------------------------------------------------- + +bit [`DATA_DLENGTH-1:0] sdi_fifo_data [`NUM_OF_WORDS-1:0]= '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdo_fifo_data [`NUM_OF_WORDS-1:0]= '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdi_fifo_data_store [`NUM_OF_WORDS-1:0]; +bit [`DATA_DLENGTH-1:0] sdo_fifo_data_store [`NUM_OF_WORDS-1:0]; +bit [`DATA_DLENGTH-1:0] rx_data; +bit [`DATA_DLENGTH-1:0] tx_data; + +task fifo_init_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) + ); + + // Enable SPI Engine + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_ENABLE), `SET_AXI_SPI_ENGINE_ENABLE_ENABLE(0)); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_ENABLE), `SET_AXI_SPI_ENGINE_ENABLE_ENABLE(0)); + + // Set up the interrupts + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_IRQ_MASK), + `SET_AXI_SPI_ENGINE_IRQ_MASK_SYNC_EVENT(1) | + `SET_AXI_SPI_ENGINE_IRQ_MASK_OFFLOAD_SYNC_ID_PENDING(1) + ); + + #100ns + + // send cmd before data + generate_init_transfer_cmd(1); + + // write sdo fifo + for (int i = 0; i<(`NUM_OF_WORDS) ; i=i+1) begin + tx_data = ((i%6) == 5) ? 8'hFE : 8'hFF; + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SDO_FIFO), (tx_data));// << (`DATA_WIDTH - `DATA_DLENGTH))); + sdo_fifo_data_store[i] = tx_data; + end + + `INFO(("Wait for SPI VIP receiving data")); + for (int i = 0; i<(`NUM_OF_WORDS) ; i=i+1) begin + spi_receive(sdo_fifo_data[i]); + end + + if (sdo_fifo_data !== sdo_fifo_data_store) begin + `INFOV(("sdo_fifo_data: %x; sdo_fifo_data_store %x", sdo_fifo_data, sdo_fifo_data_store),6); + `ERROR(("Fifo Write Test FAILED")); + end + `INFO(("Fifo Write Test PASSED")); +endtask + +bit [`DATA_DLENGTH-1:0] sdo_2_fifo_data [2-1:0]= '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdo_2_fifo_data_store [2-1:0]; +task fifo_double_write_test(); + + #100ns + + // send cmd before data + generate_double_wtransfer_cmd(1); + + // write sdo fifo + for (int i = 0; i<(2) ; i=i+1) begin + tx_data = $urandom; + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SDO_FIFO), (tx_data));// << (`DATA_WIDTH - `DATA_DLENGTH))); + sdo_2_fifo_data_store[i] = tx_data; + end + + `INFO(("Wait for SPI VIP receiving data")); + for (int i = 0; i<(2) ; i=i+1) begin + spi_receive(sdo_2_fifo_data[i]); + end + + if (sdo_2_fifo_data !== sdo_2_fifo_data_store) begin + `INFOV(("sdo_2_fifo_data: %x; sdo_2_fifo_data_store %x", sdo_2_fifo_data, sdo_2_fifo_data_store),6); + `ERROR(("Double Write Test FAILED")); + end + `INFO(("Double Write Test PASSED")); +endtask + +bit [`DATA_DLENGTH-1:0] sdi_2_fifo_data [2-1:0]= '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdi_2_fifo_data_store [2-1:0]; +bit [`DATA_DLENGTH-1:0] foo; +task fifo_double_read_test(); + + #100ns + + + + for (int i = 0; i<(2) ; i=i+1) begin + rx_data = $urandom; + spi_send(rx_data); + sdi_2_fifo_data_store[i] = rx_data; + end + + generate_double_rtransfer_cmd(1); + + `INFO(("Wait for SPI VIP data send")); + spi_wait_send(); + `INFO(("SPI sent")); + + for (int i = 0; i<(2) ; i=i+1) begin + spi_receive(foo); // dummy tx, just for clearing the VIP queue + axi_read (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SDI_FIFO), sdi_2_fifo_data[i]); + end + + if (sdi_2_fifo_data !== sdi_2_fifo_data_store) begin + `INFOV(("sdi_2_fifo_data: %x; sdi_2_fifo_data_store %x", sdi_2_fifo_data, sdi_2_fifo_data_store),6); + `ERROR(("Double Read Test FAILED")); + end + `INFO(("Double Read Test PASSED")); +endtask + +bit [`DATA_DLENGTH-1:0] sdi_1_fifo_data = '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdi_1_fifo_data_store ; +task fifo_single_read_test(); + + #100ns + + rx_data = $urandom; + spi_send(rx_data); + sdi_1_fifo_data_store = rx_data; + + generate_single_rtransfer_cmd(1); + + `INFO(("Wait for SPI VIP data send")); + spi_wait_send(); + `INFO(("SPI sent")); + + spi_receive(foo); // dummy tx, just for clearing the VIP queue + axi_read (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_SDI_FIFO), sdi_1_fifo_data); + + if (sdi_1_fifo_data !== sdi_1_fifo_data_store) begin + `INFOV(("sdi_1_fifo_data: %x; sdi_1_fifo_data_store %x", sdi_1_fifo_data, sdi_1_fifo_data_store),6); + `ERROR(("Single Read Test FAILED")); + end + `INFO(("Single Read Test PASSED")); +endtask + +//--------------------------------------------------------------------------- +// Offload SPI Test +//--------------------------------------------------------------------------- + +bit [`DATA_DLENGTH-1:0] sdi_read_data [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS) -1 :0] = '{default:'0}; +bit [`DATA_DLENGTH-1:0] sdo_write_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_store [(`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS) -1 :0]; +bit [`DATA_DLENGTH-1:0] rx_data; +bit [`DATA_DLENGTH-1:0] tx_data; + +task offload_spi_test(); + + // 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('d105)); // set PWM period + 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); + + //Configure DMA + env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_CONTROL), `SET_DMAC_CONTROL_ENABLE(1)); + env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_FLAGS), + `SET_DMAC_FLAGS_TLAST(1) | + `SET_DMAC_FLAGS_PARTIAL_REPORTING_EN(1) + ); // Use TLAST + env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_X_LENGTH), `SET_DMAC_X_LENGTH_X_LENGTH(((`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS)*4)-1)); + env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_DEST_ADDRESS), `SET_DMAC_DEST_ADDRESS_DEST_ADDRESS(`DDR_BA)); + env.mng.RegWrite32(`SPI_ENGINE_DMA_BA + GetAddrs(DMAC_TRANSFER_SUBMIT), `SET_DMAC_TRANSFER_SUBMIT_TRANSFER_SUBMIT(1)); + + `ifdef DEF_SDO_STREAMING + // Enable SDO Offload + axi_write(`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL), `SET_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL(1)); + `endif + + // Configure the Offload module + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_CFG); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `SET_CS(8'hFE)); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_PRESCALE); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_DLENGTH); + if (`CS_ACTIVE_HIGH) begin + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `SET_CS_INV_MASK(8'hFF)); + end + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_WRD); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `SET_CS(8'hFF)); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_DLENGTH); + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_CDM_FIFO), `INST_SYNC | 2); + + // Enqueue transfers transfers 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; + tx_data = $urandom; + `ifdef DEF_SDO_STREAMING + sdo_stream_gen(tx_data); + sdo_write_data_store[i] = tx_data; + `else + if (i<(`NUM_OF_WORDS)) begin + sdo_write_data_store[i] = tx_data; + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_SDO_FIFO), sdo_write_data_store[i]); + end else begin + sdo_write_data_store[i] = sdo_write_data_store[i%(`NUM_OF_WORDS)]; + end + `endif + end + + // Start the offload + #100ns + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_EN), `SET_AXI_SPI_ENGINE_OFFLOAD0_EN_OFFLOAD0_EN(1)); + `INFOV(("Offload started."),6); + + spi_wait_send(); + + axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_EN), `SET_AXI_SPI_ENGINE_OFFLOAD0_EN_OFFLOAD0_EN(0)); + + `INFOV(("Offload stopped."),6); + + #2000ns + + if (irq_pending == 'h0) begin + `ERROR(("IRQ Test FAILED")); + end else begin + `INFO(("IRQ Test PASSED")); + end + + for (int i=0; i<=((`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS) -1); i=i+1) begin + sdi_read_data[i] = env.ddr_axi_agent.mem_model.backdoor_memory_read_4byte(`DDR_BA + 4*i); + if (sdi_read_data[i] != sdi_read_data_store[i]) begin + `INFOV(("sdi_read_data[%d]: %x; sdi_read_data_store[%d]: %x", i, sdi_read_data[i], i, sdi_read_data_store[i]),6); + `ERROR(("Offload Read Test FAILED")); + end + end + `INFO(("Offload Read Test PASSED")); + + for (int i=0; i<=((`NUM_OF_TRANSFERS)*(`NUM_OF_WORDS) -1); i=i+1) begin + spi_receive(sdo_write_data[i]); + if (sdo_write_data[i] != sdo_write_data_store[i]) begin + `INFOV(("sdo_write_data[%d]: %x; sdo_write_data_store[%d]: %x", i, sdo_write_data[i], i, sdo_write_data_store[i]),6); + `ERROR(("Offload Write Test FAILED")); + end + end + `INFO(("Offload Write Test PASSED")); +endtask + +endprogram 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..9658be91 --- /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] + + diff --git a/testbenches/project/ad57xx/tests/test_program.sv b/testbenches/project/ad57xx/tests/test_program.sv index e1bdb3e1..6ecc7c42 100644 --- a/testbenches/project/ad57xx/tests/test_program.sv +++ b/testbenches/project/ad57xx/tests/test_program.sv @@ -349,6 +349,9 @@ task config_spi(); // Enable SPI Engine axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_ENABLE), `SET_AXI_SPI_ENGINE_ENABLE_ENABLE(0)); + // Enable SDO Offload + axi_write(`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL), `SET_AXI_SPI_ENGINE_OFFLOAD0_SDO_SRC_SEL_OFFLOAD0_SDO_SRC_SEL(1)); + // Configure the execution module axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_CFG); axi_write (`SPI_ENGINE_SPI_REGMAP_BA + GetAddrs(AXI_SPI_ENGINE_CMD_FIFO), `INST_PRESCALE);