From 66b575e9fa449fcd71d72ded37ce7b8ac9623f5b Mon Sep 17 00:00:00 2001 From: Laez Barbosa Date: Fri, 29 Nov 2024 16:53:39 -0300 Subject: [PATCH] SPI Engine: improve cfg, add test_slowdata Signed-off-by: Laez Barbosa --- testbenches/ip/spi_engine/cfgs/cfg00.tcl | 58 ++ .../spi_engine/cfgs/{cfg1.tcl => cfg01.tcl} | 0 testbenches/ip/spi_engine/cfgs/cfg10.tcl | 58 ++ testbenches/ip/spi_engine/cfgs/cfg11.tcl | 58 ++ testbenches/ip/spi_engine/system_project.tcl | 1 + .../ip/spi_engine/tests/test_slowdata.sv | 597 ++++++++++++++++++ .../tests/test_program.sv | 2 +- 7 files changed, 773 insertions(+), 1 deletion(-) create mode 100644 testbenches/ip/spi_engine/cfgs/cfg00.tcl rename testbenches/ip/spi_engine/cfgs/{cfg1.tcl => cfg01.tcl} (100%) create mode 100644 testbenches/ip/spi_engine/cfgs/cfg10.tcl create mode 100644 testbenches/ip/spi_engine/cfgs/cfg11.tcl create mode 100644 testbenches/ip/spi_engine/tests/test_slowdata.sv 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 100% rename from testbenches/ip/spi_engine/cfgs/cfg1.tcl rename to testbenches/ip/spi_engine/cfgs/cfg01.tcl 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/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_slowdata.sv b/testbenches/ip/spi_engine/tests/test_slowdata.sv new file mode 100644 index 00000000..1ac93a9a --- /dev/null +++ b/testbenches/ip/spi_engine/tests/test_slowdata.sv @@ -0,0 +1,597 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright (C) 2024 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/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/tests/test_program.sv b/testbenches/ip/spi_engine_execution/tests/test_program.sv index e758f3d7..9658be91 100644 --- a/testbenches/ip/spi_engine_execution/tests/test_program.sv +++ b/testbenches/ip/spi_engine_execution/tests/test_program.sv @@ -153,7 +153,7 @@ initial begin 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();