accumulator-dma bundary test
This commit is contained in:
@@ -1,74 +1,54 @@
|
||||
TOPLEVEL_LANG = verilog
|
||||
SIM ?= verilator
|
||||
SIM ?= questa
|
||||
WAVES = 1
|
||||
WLF_FILE := $(SIM_BUILD)/waves.wlf
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
WRAP_DIR = $(PWD)/../src
|
||||
RTL_CTRL_DIR = $(PWD)/../../controller_new/src
|
||||
RTL_ACCUM_DIR = $(PWD)/../../accum/src
|
||||
RTL_GENERATOR_DIR = $(PWD)/../../generator/src
|
||||
RTL_SAMPLER_DIR = $(PWD)/../../sampler/src
|
||||
RTL_ADC_DAC_MODELS_DIR = $(PWD)/../reflectometer_base
|
||||
|
||||
RTL_DIR = $(PWD)/../src
|
||||
RTL_ACCUM_DIR = $(PWD)/../src/accum/src
|
||||
LIBS_DIR = $(PWD)/../../../external/rtl_libs
|
||||
|
||||
#axi primitives
|
||||
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi_pkg.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/dma_reg_pkg.sv
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi_if.sv
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axis_if.sv
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axis_if_to_flat.sv
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi4l_flat_to_if.sv
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/axi/axi_reg/axi4l_reg_map.sv
|
||||
|
||||
#dma primitives
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/dma_reg_pkg.sv
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_dma_rd.v
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_dma_wr.v
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_dma.v
|
||||
VERILOG_SOURCES += $(WRAP_DIR)/axi_dma_wrapper_if.sv
|
||||
|
||||
# controller primitives
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/controller.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/dma_controller.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/shaper_axis_desc.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/shaper_axis_status.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/controller_wrapper_axil.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/axi4l_reg_map_controller_pkg.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/axis_defaults_helper.sv
|
||||
VERILOG_SOURCES += $(RTL_CTRL_DIR)/axi4l_reg_map_controller.sv
|
||||
|
||||
# accumulator primitives
|
||||
VERILOG_SOURCES += $(LIBS_DIR)/external/verilog-axi/rtl/axi_ram.v
|
||||
VERILOG_SOURCES += $(RTL_DIR)/axi_ram_wrapper.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/controller.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/dma_controller.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/shaper_axis_desc.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/shaper_axis_status.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/controller_wrapper_axil.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/axi4l_reg_map_controller_pkg.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/axis_defaults_helper.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/axi4l_reg_map_controller.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/axi_dma_wrapper_if.sv
|
||||
VERILOG_SOURCES += $(RTL_DIR)/wrapper_controller_dma.sv
|
||||
VERILOG_SOURCES += $(RTL_ACCUM_DIR)/adder.sv
|
||||
VERILOG_SOURCES += $(RTL_ACCUM_DIR)/accum.sv
|
||||
VERILOG_SOURCES += $(RTL_ACCUM_DIR)/out_axis_fifo.sv
|
||||
VERILOG_SOURCES += $(RTL_ACCUM_DIR)/accum.sv
|
||||
VERILOG_SOURCES += $(RTL_ACCUM_DIR)/accum_top.sv
|
||||
|
||||
# generator primitives
|
||||
VERILOG_SOURCES += $(RTL_GENERATOR_DIR)/generator.sv
|
||||
|
||||
#sampler_primitives
|
||||
VERILOG_SOURCES += $(RTL_SAMPLER_DIR)/sampler.sv
|
||||
|
||||
# project primitives
|
||||
VERILOG_SOURCES += $(WRAP_DIR)/reflectometer_ip.sv
|
||||
VERILOG_SOURCES += $(WRAP_DIR)/reflectometer_and_dma_wrapper.sv
|
||||
|
||||
# testbench primitives
|
||||
VERILOG_SOURCES += $(RTL_ADC_DAC_MODELS_DIR)/adc_model.sv
|
||||
VERILOG_SOURCES += $(RTL_ADC_DAC_MODELS_DIR)/dac_model.sv
|
||||
VERILOG_SOURCES += $(PWD)/tb_reflectometer_and_dma_wrapper.sv
|
||||
VERILOG_SOURCES += $(PWD)/sim_top.sv
|
||||
VERILOG_SOURCES += /mnt/c/Xilinx/Vivado/2021.2/data/verilog/src/glbl.v
|
||||
|
||||
TOPLEVEL = tb_reflectometer_and_dma_wrapper
|
||||
TOPLEVEL = sim_top
|
||||
MODULE = test_reflectometer_and_dma
|
||||
|
||||
|
||||
ifeq ($(SIM),verilator)
|
||||
EXTRA_ARGS += --trace --trace-structs
|
||||
EXTRA_ARGS += -I$(LIBS_DIR)/axi/rtl/
|
||||
COMPILE_ARGS += -Wno-fatal
|
||||
COMPILE_ARGS += -I$(LIBS_DIR)/axi/rtl/
|
||||
EXTRA_ARGS += --trace
|
||||
EXTRA_ARGS += --trace-structs
|
||||
EXTRA_ARGS += --public-flat-rw
|
||||
EXTRA_ARGS += -Wno-fatal
|
||||
EXTRA_ARGS += --timing
|
||||
ifeq ($(SIM),questa)
|
||||
SIM_ARGS += -L xpm
|
||||
SIM_ARGS += -wlf $(WLF_FILE)
|
||||
COMPILE_ARGS += +acc
|
||||
endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
module sim_top
|
||||
#(
|
||||
parameter int unsigned ADDR_W = 16,
|
||||
parameter int unsigned DATA_W = 32,
|
||||
parameter int unsigned USER_W = 1,
|
||||
|
||||
parameter int unsigned DAC_DATA_WIDTH = 12,
|
||||
|
||||
parameter int unsigned AXI_DATA_WIDTH = 32,
|
||||
|
||||
parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXI_ID_WIDTH = 8,
|
||||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_MAX_BURST_LEN = 16,
|
||||
|
||||
parameter int unsigned AXIS_DATA_WIDTH = AXI_DATA_WIDTH,
|
||||
parameter int unsigned AXIS_KEEP_ENABLE = AXIS_DATA_WIDTH > 8,
|
||||
parameter int unsigned AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXIS_LAST_ENABLE = 1,
|
||||
parameter int unsigned AXIS_ID_ENABLE = 1,
|
||||
parameter int unsigned AXIS_DEST_ENABLE = 0,
|
||||
parameter int unsigned AXIS_USER_ENABLE = 1,
|
||||
|
||||
parameter int unsigned ENABLE_SG = 0,
|
||||
parameter int unsigned ENABLE_UNALIGNED = 0,
|
||||
|
||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||
parameter int unsigned ACCUM_WIDTH = 32,
|
||||
parameter int unsigned N_MAX = 4096,
|
||||
parameter int unsigned PACKET_SIZE = 64,
|
||||
parameter int unsigned RD_FIFO_WIDTH = 32
|
||||
)(
|
||||
input logic ctrl_clk,
|
||||
input logic rst,
|
||||
|
||||
input logic [ADDR_W-1:0] s_axil_awaddr,
|
||||
input logic [2:0] s_axil_awprot,
|
||||
input logic s_axil_awvalid,
|
||||
output logic s_axil_awready,
|
||||
|
||||
input logic [DATA_W-1:0] s_axil_wdata,
|
||||
input logic [DATA_W/8-1:0] s_axil_wstrb,
|
||||
input logic s_axil_wvalid,
|
||||
output logic s_axil_wready,
|
||||
|
||||
output logic [1:0] s_axil_bresp,
|
||||
output logic s_axil_bvalid,
|
||||
input logic s_axil_bready,
|
||||
|
||||
input logic [ADDR_W-1:0] s_axil_araddr,
|
||||
input logic [2:0] s_axil_arprot,
|
||||
input logic s_axil_arvalid,
|
||||
output logic s_axil_arready,
|
||||
|
||||
output logic [DATA_W-1:0] s_axil_rdata,
|
||||
output logic [1:0] s_axil_rresp,
|
||||
output logic s_axil_rvalid,
|
||||
input logic s_axil_rready,
|
||||
|
||||
output wire [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata,
|
||||
output wire [AXIS_KEEP_WIDTH-1:0] m_axis_read_data_tkeep,
|
||||
output wire m_axis_read_data_tvalid,
|
||||
input wire m_axis_read_data_tready,
|
||||
output wire m_axis_read_data_tlast,
|
||||
output wire [AXIS_ID_WIDTH-1:0] m_axis_read_data_tid,
|
||||
output wire [dma_reg_pkg::AXIS_DEST_WIDTH-1:0] m_axis_read_data_tdest,
|
||||
output wire [dma_reg_pkg::AXIS_USER_WIDTH-1:0] m_axis_read_data_tuser,
|
||||
|
||||
input wire [ADC_DATA_WIDTH-1:0] sampler_m_axis_tdata,
|
||||
input wire sampler_m_axis_tvalid
|
||||
);
|
||||
|
||||
glbl glbl();
|
||||
|
||||
|
||||
tb_controller_wrapper_axil
|
||||
#(
|
||||
.ADDR_W(ADDR_W),
|
||||
.DATA_W(DATA_W),
|
||||
.USER_W(USER_W),
|
||||
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_USER_WIDTH(AXI_USER_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
|
||||
.AXIS_DATA_WIDTH(AXIS_DATA_WIDTH),
|
||||
.AXIS_LAST_ENABLE(AXIS_LAST_ENABLE),
|
||||
.AXIS_ID_ENABLE(AXIS_ID_ENABLE),
|
||||
.AXIS_DEST_ENABLE(AXIS_DEST_ENABLE),
|
||||
.AXIS_USER_ENABLE(AXIS_USER_ENABLE),
|
||||
.ENABLE_SG(ENABLE_SG),
|
||||
.ENABLE_UNALIGNED(ENABLE_UNALIGNED),
|
||||
|
||||
.ADC_DATA_WIDTH(ADC_DATA_WIDTH),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.PACKET_SIZE(PACKET_SIZE),
|
||||
.RD_FIFO_WIDTH(RD_FIFO_WIDTH)
|
||||
) dut (
|
||||
.ctrl_clk (ctrl_clk),
|
||||
.rst (rst),
|
||||
|
||||
.s_axil_awaddr (s_axil_awaddr),
|
||||
.s_axil_awprot (s_axil_awprot),
|
||||
.s_axil_awvalid (s_axil_awvalid),
|
||||
.s_axil_awready (s_axil_awready),
|
||||
|
||||
.s_axil_wdata (s_axil_wdata),
|
||||
.s_axil_wstrb (s_axil_wstrb),
|
||||
.s_axil_wvalid (s_axil_wvalid),
|
||||
.s_axil_wready (s_axil_wready),
|
||||
|
||||
.s_axil_bresp (s_axil_bresp),
|
||||
.s_axil_bvalid (s_axil_bvalid),
|
||||
.s_axil_bready (s_axil_bready),
|
||||
|
||||
.s_axil_araddr (s_axil_araddr),
|
||||
.s_axil_arprot (s_axil_arprot),
|
||||
.s_axil_arvalid (s_axil_arvalid),
|
||||
.s_axil_arready (s_axil_arready),
|
||||
|
||||
.s_axil_rdata (s_axil_rdata),
|
||||
.s_axil_rresp (s_axil_rresp),
|
||||
.s_axil_rvalid (s_axil_rvalid),
|
||||
.s_axil_rready (s_axil_rready),
|
||||
|
||||
.m_axis_read_data_tdata (m_axis_read_data_tdata),
|
||||
.m_axis_read_data_tkeep (m_axis_read_data_tkeep),
|
||||
.m_axis_read_data_tvalid (m_axis_read_data_tvalid),
|
||||
.m_axis_read_data_tready (m_axis_read_data_tready),
|
||||
.m_axis_read_data_tlast (m_axis_read_data_tlast),
|
||||
.m_axis_read_data_tid (m_axis_read_data_tid),
|
||||
.m_axis_read_data_tdest (m_axis_read_data_tdest),
|
||||
.m_axis_read_data_tuser (m_axis_read_data_tuser),
|
||||
|
||||
.sampler_m_axis_tdata (sampler_m_axis_tdata),
|
||||
.sampler_m_axis_tvalid (sampler_m_axis_tvalid)
|
||||
);
|
||||
|
||||
endmodule
|
||||
+85
-163
@@ -1,21 +1,8 @@
|
||||
|
||||
import dma_reg_pkg::*;
|
||||
`timescale 1 ns / 1 ns
|
||||
|
||||
module tb_reflectometer_and_dma_wrapper
|
||||
#(
|
||||
// parameters for base reflectometer works
|
||||
parameter int unsigned DAC_DATA_WIDTH = 14,
|
||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||
parameter int unsigned PACK_FACTOR = 1,
|
||||
parameter int unsigned PROCESS_MODE = 0,
|
||||
parameter int unsigned ZERO_LEVEL = 8192,
|
||||
parameter int unsigned ACCUM_WIDTH = 32,
|
||||
parameter int unsigned N_MAX = 4096,
|
||||
parameter int unsigned PACKET_SIZE = 1024,
|
||||
parameter int unsigned RD_FIFO_WIDTH = 32,
|
||||
|
||||
// parameters for DMA and interfaces
|
||||
parameter int unsigned ADDR_W = 16,
|
||||
module tb_controller_wrapper_axil #(
|
||||
parameter int unsigned ADDR_W = 16,
|
||||
parameter int unsigned DATA_W = 32,
|
||||
parameter int unsigned USER_W = 1,
|
||||
|
||||
@@ -39,36 +26,40 @@ module tb_reflectometer_and_dma_wrapper
|
||||
parameter int unsigned ENABLE_SG = 0,
|
||||
parameter int unsigned ENABLE_UNALIGNED = 0,
|
||||
|
||||
parameter int unsigned PIPELINE_OUTPUT = 0
|
||||
)
|
||||
(
|
||||
input logic ctrl_clk,
|
||||
input logic rst_n,
|
||||
output wire locked,
|
||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||
parameter int unsigned ACCUM_WIDTH = 32,
|
||||
parameter int unsigned N_MAX = 4096,
|
||||
parameter int unsigned PACKET_SIZE = 64,
|
||||
parameter int unsigned RD_FIFO_WIDTH = 32
|
||||
)(
|
||||
input logic ctrl_clk,
|
||||
//input logic adc_clk_in,
|
||||
//input logic dac_clk_in,
|
||||
input logic rst,
|
||||
|
||||
input logic [ADDR_W-1:0] s_axil_awaddr,
|
||||
input logic [2:0] s_axil_awprot,
|
||||
input logic s_axil_awvalid,
|
||||
output logic s_axil_awready,
|
||||
input logic [ADDR_W-1:0] s_axil_awaddr,
|
||||
input logic [2:0] s_axil_awprot,
|
||||
input logic s_axil_awvalid,
|
||||
output logic s_axil_awready,
|
||||
|
||||
input logic [DATA_W-1:0] s_axil_wdata,
|
||||
input logic [DATA_W/8-1:0] s_axil_wstrb,
|
||||
input logic s_axil_wvalid,
|
||||
output logic s_axil_wready,
|
||||
input logic [DATA_W-1:0] s_axil_wdata,
|
||||
input logic [DATA_W/8-1:0] s_axil_wstrb,
|
||||
input logic s_axil_wvalid,
|
||||
output logic s_axil_wready,
|
||||
|
||||
output logic [1:0] s_axil_bresp,
|
||||
output logic s_axil_bvalid,
|
||||
input logic s_axil_bready,
|
||||
output logic [1:0] s_axil_bresp,
|
||||
output logic s_axil_bvalid,
|
||||
input logic s_axil_bready,
|
||||
|
||||
input logic [ADDR_W-1:0] s_axil_araddr,
|
||||
input logic [2:0] s_axil_arprot,
|
||||
input logic s_axil_arvalid,
|
||||
output logic s_axil_arready,
|
||||
input logic [ADDR_W-1:0] s_axil_araddr,
|
||||
input logic [2:0] s_axil_arprot,
|
||||
input logic s_axil_arvalid,
|
||||
output logic s_axil_arready,
|
||||
|
||||
output logic [DATA_W-1:0] s_axil_rdata,
|
||||
output logic [1:0] s_axil_rresp,
|
||||
output logic s_axil_rvalid,
|
||||
input logic s_axil_rready,
|
||||
output logic [DATA_W-1:0] s_axil_rdata,
|
||||
output logic [1:0] s_axil_rresp,
|
||||
output logic s_axil_rvalid,
|
||||
input logic s_axil_rready,
|
||||
|
||||
output wire [AXIS_DATA_WIDTH-1:0] m_axis_read_data_tdata,
|
||||
output wire [AXIS_KEEP_WIDTH-1:0] m_axis_read_data_tkeep,
|
||||
@@ -76,53 +67,25 @@ module tb_reflectometer_and_dma_wrapper
|
||||
input wire m_axis_read_data_tready,
|
||||
output wire m_axis_read_data_tlast,
|
||||
output wire [AXIS_ID_WIDTH-1:0] m_axis_read_data_tid,
|
||||
output wire [AXIS_DEST_WIDTH-1:0] m_axis_read_data_tdest,
|
||||
output wire [AXIS_USER_WIDTH-1:0] m_axis_read_data_tuser,
|
||||
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [7:0] m_axi_awlen,
|
||||
output wire [2:0] m_axi_awsize,
|
||||
output wire [1:0] m_axi_awburst,
|
||||
output wire m_axi_awlock,
|
||||
output wire [3:0] m_axi_awcache,
|
||||
output wire [2:0] m_axi_awprot,
|
||||
output wire m_axi_awvalid,
|
||||
input wire m_axi_awready,
|
||||
output wire [AXI_DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [AXI_STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire m_axi_wlast,
|
||||
output wire m_axi_wvalid,
|
||||
input wire m_axi_wready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [1:0] m_axi_bresp,
|
||||
input wire m_axi_bvalid,
|
||||
output wire m_axi_bready,
|
||||
output wire [AXI_ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [AXI_ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [7:0] m_axi_arlen,
|
||||
output wire [2:0] m_axi_arsize,
|
||||
output wire [1:0] m_axi_arburst,
|
||||
output wire m_axi_arlock,
|
||||
output wire [3:0] m_axi_arcache,
|
||||
output wire [2:0] m_axi_arprot,
|
||||
output wire m_axi_arvalid,
|
||||
input wire m_axi_arready,
|
||||
input wire [AXI_ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [AXI_DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [1:0] m_axi_rresp,
|
||||
input wire m_axi_rlast,
|
||||
input wire m_axi_rvalid,
|
||||
output wire m_axi_rready
|
||||
output wire [dma_reg_pkg::AXIS_DEST_WIDTH-1:0] m_axis_read_data_tdest,
|
||||
output wire [dma_reg_pkg::AXIS_USER_WIDTH-1:0] m_axis_read_data_tuser,
|
||||
|
||||
input wire [ADC_DATA_WIDTH-1:0] sampler_m_axis_tdata,
|
||||
input wire sampler_m_axis_tvalid
|
||||
);
|
||||
|
||||
logic rst_n;
|
||||
assign rst_n = ~rst;
|
||||
logic dac_clk_in;
|
||||
logic adc_clk_in;
|
||||
assign dac_clk_in = ctrl_clk;
|
||||
assign adc_clk_in = ctrl_clk;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// AXI-Lite flat -> axi4l_if
|
||||
// ---------------------------------------------------------------------------
|
||||
logic rst_n;
|
||||
|
||||
assign rst_n = ~rst;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// AXI-Lite flat -> axi4l_if
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
axi4l_if #(
|
||||
.ADDR_W(ADDR_W),
|
||||
@@ -169,14 +132,14 @@ module tb_reflectometer_and_dma_wrapper
|
||||
// AXIS interfaces for the updated controller_wrapper_axil
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// AXIS READ DATA DMA MASTER output
|
||||
// AXIS READ DMA MASTER output
|
||||
axis_if #(
|
||||
.DATA_W (AXIS_DATA_WIDTH),
|
||||
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
) read_data (
|
||||
.DEST_W (dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W (dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) dma_read_data (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
@@ -187,10 +150,10 @@ axis_if_to_flat #(
|
||||
.DATA_W (AXIS_DATA_WIDTH),
|
||||
.KEEP_W (AXIS_KEEP_WIDTH),
|
||||
.ID_W (AXIS_ID_WIDTH),
|
||||
.DEST_W (AXIS_DEST_WIDTH),
|
||||
.USER_W (AXIS_USER_WIDTH)
|
||||
.DEST_W (dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W (dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) u_read_data_if_to_flat (
|
||||
.s_axis(read_data),
|
||||
.s_axis(dma_read_data),
|
||||
|
||||
.m_axis_tdata (m_axis_read_data_tdata),
|
||||
.m_axis_tkeep (m_axis_read_data_tkeep),
|
||||
@@ -203,80 +166,39 @@ axis_if_to_flat #(
|
||||
.m_axis_tready(m_axis_read_data_tready)
|
||||
);
|
||||
|
||||
// Интерфейс хендшейка с MAC-PHY
|
||||
wire send_request;
|
||||
logic request_ready;
|
||||
// Сигнал между ЦАП и АЦП
|
||||
real signal_voltage;
|
||||
|
||||
// ADC интерфейс
|
||||
wire clk_adc;
|
||||
wire adc_otr;
|
||||
wire [ADC_DATA_WIDTH-1:0] adc_data;
|
||||
wrapper_controller_dma_accum #(
|
||||
.ADDR_W(ADDR_W),
|
||||
.DATA_W(DATA_W),
|
||||
.USER_W(USER_W),
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH),
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_ID_WIDTH(AXI_ID_WIDTH),
|
||||
.AXI_USER_WIDTH(AXI_USER_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.AXIS_LAST_ENABLE(AXIS_LAST_ENABLE),
|
||||
.AXIS_ID_ENABLE(AXIS_ID_ENABLE),
|
||||
.AXIS_DEST_ENABLE(AXIS_DEST_ENABLE),
|
||||
.AXIS_USER_ENABLE(AXIS_USER_ENABLE),
|
||||
.ENABLE_SG(ENABLE_SG),
|
||||
.ENABLE_UNALIGNED(ENABLE_UNALIGNED),
|
||||
|
||||
virtual_adc_model #( // default voltage range is +/- 5V
|
||||
.ADC_DATA_WIDTH(ADC_DATA_WIDTH)
|
||||
) virtual_adc (
|
||||
.clk_i(clk_adc),
|
||||
.voltage_i(signal_voltage),
|
||||
.otr_o(adc_otr),
|
||||
.data_o(adc_data)
|
||||
);
|
||||
.ADC_DATA_WIDTH(ADC_DATA_WIDTH),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.PACKET_SIZE(PACKET_SIZE),
|
||||
.RD_FIFO_WIDTH(RD_FIFO_WIDTH)
|
||||
) dut (
|
||||
.ctrl_clk(ctrl_clk),
|
||||
.clk_generator(dac_clk_in),
|
||||
.clk_sampler(adc_clk_in),
|
||||
.rst_n(rst_n),
|
||||
.s_axil(axil_bus),
|
||||
|
||||
// DAC интерфейс
|
||||
wire clk_dac;
|
||||
wire dac_wrt;
|
||||
wire [DAC_DATA_WIDTH-1:0] dac_data;
|
||||
.sampler_m_axis_tdata(sampler_m_axis_tdata),
|
||||
.sampler_m_axis_tvalid(sampler_m_axis_tvalid),
|
||||
|
||||
virtual_dac_model #( // default voltage range is +/- 5V
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||
// ,.VOLTAGE_GAIN(2)
|
||||
) virtual_dac (
|
||||
.clk_i(clk_dac),
|
||||
.wrt_i(dac_wrt),
|
||||
.data_i(dac_data),
|
||||
.voltage_o(signal_voltage)
|
||||
);
|
||||
.m_axis_read_data(dma_read_data)
|
||||
);
|
||||
|
||||
reflectometer_and_dma_wrapper #(
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH),
|
||||
.ADC_DATA_WIDTH(ADC_DATA_WIDTH),
|
||||
.ADC_DATA_WIDTH(ADC_DATA_WIDTH),
|
||||
.PACK_FACTOR(PACK_FACTOR),
|
||||
.PROCESS_MODE(PROCESS_MODE),
|
||||
.ZERO_LEVEL(ZERO_LEVEL),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.PACKET_SIZE(PACKET_SIZE),
|
||||
.RD_FIFO_WIDTH(RD_FIFO_WIDTH),
|
||||
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_USER_WIDTH(AXI_USER_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.AXIS_DATA_WIDTH(AXIS_DATA_WIDTH),
|
||||
.AXIS_KEEP_ENABLE(AXIS_KEEP_ENABLE),
|
||||
.AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH),
|
||||
.AXIS_LAST_ENABLE(AXIS_LAST_ENABLE),
|
||||
.AXIS_ID_ENABLE(AXIS_ID_ENABLE),
|
||||
.AXIS_DEST_ENABLE(AXIS_DEST_ENABLE),
|
||||
.AXIS_USER_ENABLE(AXIS_USER_ENABLE),
|
||||
.ENABLE_SG(ENABLE_SG),
|
||||
.ENABLE_UNALIGNED(ENABLE_UNALIGNED)
|
||||
) reflectometer_and_dma_wrapper_dut (
|
||||
.ctrl_clk(ctrl_clk),
|
||||
.rst_n(rst_n),
|
||||
.locked(locked),
|
||||
.s_axil(axil_bus),
|
||||
.m_axi(m_axi),
|
||||
.m_axis_read_data(read_data),
|
||||
|
||||
.dac_clk_o(clk_dac),
|
||||
.dac_data(dac_data),
|
||||
.dac_wrt(dac_wrt),
|
||||
.adc_clk_o(clk_adc),
|
||||
.adc_data(adc_data),
|
||||
.adc_otr(adc_otr)
|
||||
);
|
||||
|
||||
endmodule
|
||||
endmodule : tb_controller_wrapper_axil
|
||||
|
||||
+546
@@ -0,0 +1,546 @@
|
||||
import cocotb
|
||||
import random
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotbext.axi import AxiLiteBus, AxiLiteMaster
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSink, AxiStreamFrame
|
||||
|
||||
|
||||
# Register indexes from axi4l_reg_map_controller_pkg.sv
|
||||
REG_CONTROL = 0
|
||||
REG_STATUS = 1
|
||||
REG_DAC_WIDTH = 2
|
||||
REG_DAC_PERIOD = 3
|
||||
REG_DAC_PULSE_NUM = 4
|
||||
REG_DAC_PULSE_HEIGHT = 5
|
||||
REG_ADC_PERIOD = 6
|
||||
REG_WINDOW_SIZE = 7
|
||||
REG_ERROR = 8
|
||||
REG_DESC_READ_ADDR = 9
|
||||
REG_DESC_READ_LEN = 10
|
||||
REG_DESC_READ_CONFIG = 11
|
||||
REG_READ_STATUS = 12
|
||||
REG_DESC_WRITE_ADDR = 13
|
||||
REG_DESC_WRITE_LEN_AND_TAG = 14
|
||||
REG_STATUS_WRITE_LEN = 15
|
||||
REG_STATUS_WRITE_CONFIG = 16
|
||||
|
||||
|
||||
# REG_CONTROL pulse bits
|
||||
CTRL_START = 1 << 0
|
||||
CTRL_RST_SOFT = 1 << 1
|
||||
CTRL_CFG_BUS_VALID = 1 << 2
|
||||
CTRL_SEND_DESC_READ = 1 << 3
|
||||
CTRL_SEND_DESC_WRITE = 1 << 4
|
||||
CTRL_TAKE_STATUS_READ = 1 << 5
|
||||
CTRL_TAKE_STATUS_WRITE = 1 << 6
|
||||
|
||||
# REG_STATUS bits
|
||||
STATUS_BUSY = 1 << 0
|
||||
STATUS_PROCESSING_DONE = 1 << 1
|
||||
|
||||
STATUS_DESC_READ_BUSY = 1 << 2
|
||||
STATUS_DESC_WRITE_BUSY = 1 << 3
|
||||
STATUS_STATUS_READ_BUSY = 1 << 4
|
||||
STATUS_STATUS_WRITE_BUSY = 1 << 5
|
||||
|
||||
STATUS_DESC_READ_HS = 1 << 6
|
||||
STATUS_DESC_WRITE_HS = 1 << 7
|
||||
STATUS_STATUS_READ_HS = 1 << 8
|
||||
STATUS_STATUS_WRITE_HS = 1 << 9
|
||||
|
||||
# PARAMETERS for accumulator reference model
|
||||
|
||||
DAC_DATA_WIDTH = 14
|
||||
ADC_DATA_WIDTH = 12
|
||||
PACK_FACTOR = 1
|
||||
PROCESS_MODE = 0
|
||||
ZERO_LEVEL = 8192
|
||||
ACCUM_WIDTH = 32
|
||||
N_MAX = 4096
|
||||
PACKET_SIZE = 1024
|
||||
RD_FIFO_WIDTH = 32
|
||||
|
||||
|
||||
def reg_addr(reg_index: int) -> int:
|
||||
# AXI-Lite uses byte addresses, 32-bit registers are spaced by 4 bytes.
|
||||
return reg_index * 4
|
||||
|
||||
|
||||
def u32(value: int) -> bytes:
|
||||
return int(value & 0xFFFFFFFF).to_bytes(4, "little")
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
|
||||
cocotb.start_soon(Clock(dut.ctrl_clk, 10, unit="ns").start())
|
||||
|
||||
# cocotb.start_soon(Clock(dut.adc_clk_in, 15, unit="ns").start())
|
||||
|
||||
# cocotb.start_soon(Clock(dut.dac_clk_in, 8, unit="ns").start())
|
||||
|
||||
self.axil = AxiLiteMaster(
|
||||
AxiLiteBus.from_prefix(dut, "s_axil"),
|
||||
dut.ctrl_clk,
|
||||
dut.rst
|
||||
)
|
||||
|
||||
|
||||
# self.axis_source = AxiStreamSource(
|
||||
# AxiStreamBus.from_prefix(dut, "s_axis_write_data"),
|
||||
# dut.ctrl_clk,
|
||||
# dut.rst
|
||||
# )
|
||||
|
||||
self.axis_sink = AxiStreamSink(
|
||||
AxiStreamBus.from_prefix(dut, "m_axis_read_data"),
|
||||
dut.ctrl_clk,
|
||||
dut.rst
|
||||
)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.value = 1
|
||||
for _ in range(20):
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
self.dut.rst.value = 0
|
||||
for _ in range(20):
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
async def write_reg(self, reg_index: int, value: int):
|
||||
await self.axil.write(reg_addr(reg_index), u32(value))
|
||||
|
||||
async def read_reg(self, reg_index: int) -> int:
|
||||
resp = await self.axil.read(reg_addr(reg_index), 4)
|
||||
return int.from_bytes(bytes(resp.data), "little")
|
||||
|
||||
async def pulse_control(self, mask):
|
||||
await self.write_reg( REG_CONTROL, mask )
|
||||
|
||||
# Reflectometer Driver
|
||||
|
||||
async def configure_reflectometer (
|
||||
self,
|
||||
pulse_width,
|
||||
pulse_period,
|
||||
pulse_num,
|
||||
pulse_height,
|
||||
adc_period,
|
||||
window_size,
|
||||
timeout_cycles
|
||||
):
|
||||
await self.write_reg(REG_DAC_WIDTH, pulse_width)
|
||||
await self.write_reg(REG_DAC_PERIOD, pulse_period)
|
||||
await self.write_reg(REG_DAC_PULSE_NUM, pulse_num)
|
||||
await self.write_reg(REG_DAC_PULSE_HEIGHT, pulse_height)
|
||||
await self.write_reg(REG_ADC_PERIOD, adc_period)
|
||||
await self.write_reg(REG_WINDOW_SIZE, window_size)
|
||||
|
||||
await self.pulse_control(CTRL_CFG_BUS_VALID)
|
||||
|
||||
control = self.dut.dut.dut.controller_wrapper_axil_inst.controller
|
||||
|
||||
for cycle in range(timeout_cycles):
|
||||
dac_wait = int(control.cfg_wait_dac_ack.value)
|
||||
adc_wait = int(control.cfg_wait_adc_ack.value)
|
||||
|
||||
if dac_wait == 0 and adc_wait == 0:
|
||||
print(f"Configuration done after {cycle} ctrl_clk cycles")
|
||||
return
|
||||
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
async def send_start(self):
|
||||
await self.pulse_control(CTRL_START)
|
||||
|
||||
async def soft_reset(self):
|
||||
await self.pulse_control(CTRL_RST_SOFT)
|
||||
|
||||
async def get_status(self):
|
||||
status = await self.read_reg(REG_STATUS)
|
||||
return {
|
||||
"busy": bool(status & STATUS_BUSY),
|
||||
"processing_done": bool(status & STATUS_PROCESSING_DONE),
|
||||
"desc_read_busy": bool(status & STATUS_DESC_READ_BUSY),
|
||||
"desc_write_busy": bool(status & STATUS_DESC_WRITE_BUSY),
|
||||
"status_read_busy": bool(status & STATUS_STATUS_READ_BUSY),
|
||||
"status_write_busy": bool(status & STATUS_STATUS_WRITE_BUSY),
|
||||
"desc_read_hs": bool(status & STATUS_DESC_READ_HS),
|
||||
"desc_write_hs": bool(status & STATUS_DESC_WRITE_HS),
|
||||
"status_read_hs": bool(status & STATUS_STATUS_READ_HS),
|
||||
"status_write_hs": bool(status & STATUS_STATUS_WRITE_HS)
|
||||
}
|
||||
|
||||
async def wait_status(self, field, value=True, timeout_cycles=1000):
|
||||
|
||||
for _ in range(timeout_cycles):
|
||||
|
||||
status = await self.get_status()
|
||||
|
||||
if status[field] == value:
|
||||
return
|
||||
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
status = await self.get_status()
|
||||
|
||||
raise TimeoutError( f"Timeout waiting for status.{field} == {value}. " f"Current status = {status}")
|
||||
|
||||
async def wait_processing_done(self, timeout_cycles=1000):
|
||||
await self.wait_status("processing_done", True, timeout_cycles)
|
||||
|
||||
|
||||
async def wait_finish(self, timeout_cycles=1000):
|
||||
await self.wait_status("busy", False, timeout_cycles)
|
||||
|
||||
# DMA Driver
|
||||
|
||||
async def send_desc_write(self, addr, length_tag):
|
||||
|
||||
await self.write_reg(REG_DESC_WRITE_ADDR, addr)
|
||||
await self.write_reg(REG_DESC_WRITE_LEN_AND_TAG, length_tag)
|
||||
await self.pulse_control(CTRL_SEND_DESC_WRITE)
|
||||
|
||||
async def send_desc_read(self, addr, length, config):
|
||||
|
||||
await self.write_reg(REG_DESC_READ_ADDR, addr)
|
||||
await self.write_reg(REG_DESC_READ_LEN, length)
|
||||
await self.write_reg(REG_DESC_READ_CONFIG, config)
|
||||
await self.pulse_control( CTRL_SEND_DESC_READ)
|
||||
|
||||
async def take_status_write(self, status_write_len, status_write_config):
|
||||
await self.write_reg(REG_CONTROL, CTRL_TAKE_STATUS_WRITE)
|
||||
|
||||
for _ in range(10):
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
|
||||
assert await self.read_reg(REG_STATUS_WRITE_CONFIG) == status_write_config
|
||||
assert await self.read_reg(REG_STATUS_WRITE_LEN) == status_write_len
|
||||
|
||||
async def take_read_status(self):
|
||||
|
||||
await self.pulse_control( CTRL_TAKE_STATUS_READ)
|
||||
return await self.read_reg(REG_READ_STATUS)
|
||||
|
||||
async def wait_dma_write_done(self, timeout_cycles=1000):
|
||||
await self.wait_status("desc_write_busy", False, timeout_cycles)
|
||||
|
||||
async def wait_dma_read_done(self, timeout_cycles=1000):
|
||||
await self.wait_status("desc_read_busy", False, timeout_cycles)
|
||||
|
||||
async def wait_status_read_handshake(self, timeout_cycles=1000):
|
||||
await self.wait_status("status_read_hs", True, timeout_cycles)
|
||||
|
||||
async def wait_status_write_handshake(self, timeout_cycles=1000):
|
||||
await self.wait_status("status_write_hs", True, timeout_cycles)
|
||||
|
||||
# AxiStream Driver
|
||||
|
||||
# async def send_axis_data(self, data: bytes):
|
||||
|
||||
# await self.axis_source.send(AxiStreamFrame(data) )
|
||||
|
||||
async def receive_axis_data(self):
|
||||
|
||||
frame = await self.axis_sink.recv()
|
||||
return bytes(frame)
|
||||
|
||||
# Accum transaction generator
|
||||
|
||||
def generate_samples(
|
||||
self,
|
||||
seq_num: int,
|
||||
smp_num: int,
|
||||
data_width: int,
|
||||
seed: int | None = None):
|
||||
if seq_num <= 0:
|
||||
raise ValueError(f"seq_num must be > 0, got {seq_num}")
|
||||
|
||||
if smp_num <= 0:
|
||||
raise ValueError(f"smp_num must be > 0, got {smp_num}")
|
||||
|
||||
rng = random.Random(seed)
|
||||
|
||||
max_value = (1 << data_width) - 1
|
||||
|
||||
samples = []
|
||||
|
||||
for _ in range(seq_num):
|
||||
seq_samples = []
|
||||
|
||||
for _ in range(smp_num):
|
||||
seq_samples.append( rng.randint(0, max_value))
|
||||
|
||||
samples.append(seq_samples)
|
||||
|
||||
return samples
|
||||
|
||||
def calculate_expected(
|
||||
self,
|
||||
samples,
|
||||
window_size: int,
|
||||
accum_width: int):
|
||||
if window_size <= 0:
|
||||
raise ValueError( f"window_size must be > 0, got {window_size}")
|
||||
|
||||
if not samples:
|
||||
raise ValueError("samples must not be empty")
|
||||
|
||||
seq_num = len(samples)
|
||||
smp_num = len(samples[0])
|
||||
|
||||
if smp_num == 0:
|
||||
raise ValueError("samples must not contain empty sequences")
|
||||
|
||||
for seq_idx, seq_samples in enumerate(samples):
|
||||
if len(seq_samples) != smp_num:
|
||||
raise ValueError(f"Sequence {seq_idx} has {len(seq_samples)} samples, " f"expected {smp_num}" )
|
||||
|
||||
if smp_num % window_size != 0:
|
||||
raise ValueError(f"smp_num ({smp_num}) must be divisible " f"by window_size ({window_size})")
|
||||
|
||||
exp_word_count = smp_num // window_size
|
||||
accum_mask = (1 << accum_width) - 1
|
||||
|
||||
expected = []
|
||||
|
||||
for word_idx in range(exp_word_count):
|
||||
local_sum = 0
|
||||
|
||||
for seq_idx in range(seq_num):
|
||||
for k in range(window_size):
|
||||
sample_idx = word_idx * window_size + k
|
||||
local_sum += samples[seq_idx][sample_idx]
|
||||
|
||||
expected.append(local_sum & accum_mask)
|
||||
|
||||
return expected
|
||||
|
||||
async def send_samples(self, samples):
|
||||
self.dut.sampler_m_axis_tvalid.value = 0
|
||||
self.dut.sampler_m_axis_tdata.value = 0
|
||||
|
||||
for seq_samples in samples:
|
||||
|
||||
for sample in seq_samples:
|
||||
|
||||
self.dut.sampler_m_axis_tdata.value = sample
|
||||
self.dut.sampler_m_axis_tvalid.value = 1
|
||||
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
self.dut.sampler_m_axis_tdata.value = 0
|
||||
self.dut.sampler_m_axis_tvalid.value = 0
|
||||
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
await RisingEdge(self.dut.ctrl_clk)
|
||||
|
||||
def bytes_to_words(self, data: bytes, word_width: int = 32):
|
||||
word_bytes = word_width // 8
|
||||
|
||||
if len(data) % word_bytes != 0:
|
||||
raise ValueError(f"Data length {len(data)} is not divisible " f"by word size {word_bytes}" )
|
||||
|
||||
words = []
|
||||
|
||||
for i in range(0, len(data), word_bytes):
|
||||
word = int.from_bytes(data[i:i + word_bytes], byteorder="little" )
|
||||
words.append(word)
|
||||
|
||||
return words
|
||||
|
||||
def check_results(self, expected, received):
|
||||
|
||||
assert len(received) == len(expected), (
|
||||
f"Number of words mismatch: "
|
||||
f"expected={len(expected)}, "
|
||||
f"received={len(received)}" )
|
||||
|
||||
for i, (exp, rec) in enumerate(zip(expected, received)):
|
||||
assert rec == exp, (
|
||||
f"Payload mismatch at index {i}: "
|
||||
f"expected=0x{exp:08X}, "
|
||||
f"received=0x{rec:08X}" )
|
||||
|
||||
print( f"Payload check passed: " f"{len(expected)} words")
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def rest_init(dut):
|
||||
tb = TB(dut)
|
||||
await tb.reset()
|
||||
|
||||
@cocotb.test()
|
||||
async def simple_axil_write_read(dut):
|
||||
tb = TB(dut)
|
||||
await tb.reset()
|
||||
|
||||
await tb.write_reg(REG_DAC_WIDTH, 0x0000_0123)
|
||||
|
||||
value = await tb.read_reg(REG_DAC_WIDTH)
|
||||
assert value == 0x0000_0123
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def simple_controller_config_write(dut):
|
||||
tb = TB(dut)
|
||||
await tb.reset()
|
||||
|
||||
await tb.write_reg(REG_DAC_WIDTH, 0x10)
|
||||
await tb.write_reg(REG_DAC_PERIOD, 0x40)
|
||||
await tb.write_reg(REG_DAC_PULSE_NUM, 3)
|
||||
await tb.write_reg(REG_DAC_PULSE_HEIGHT, 0x7FF)
|
||||
await tb.write_reg(REG_ADC_PERIOD, 0x80)
|
||||
await tb.write_reg(REG_WINDOW_SIZE, 16)
|
||||
|
||||
assert await tb.read_reg(REG_DAC_WIDTH) == 0x10
|
||||
assert await tb.read_reg(REG_WINDOW_SIZE) == 16
|
||||
|
||||
# write data: set cfg_bus_valid signal
|
||||
await tb.write_reg(REG_CONTROL, CTRL_CFG_BUS_VALID)
|
||||
|
||||
# wait
|
||||
for _ in range(10):
|
||||
await RisingEdge(dut.ctrl_clk)
|
||||
|
||||
dac_pulse_width = dut.dut.dut.controller_wrapper_axil_inst.dac_pulse_width
|
||||
dac_pulse_period = dut.dut.dut.controller_wrapper_axil_inst.dac_pulse_period
|
||||
dac_pulse_num = dut.dut.dut.controller_wrapper_axil_inst.dac_pulse_num
|
||||
dac_pulse_height = dut.dut.dut.controller_wrapper_axil_inst.dac_pulse_height
|
||||
adc_pulse_period = dut.dut.dut.controller_wrapper_axil_inst.adc_pulse_period
|
||||
adc_window_size = dut.dut.dut.controller_wrapper_axil_inst.adc_window_size
|
||||
|
||||
# check config
|
||||
assert int(dac_pulse_width) == 0x10
|
||||
assert int(dac_pulse_period) == 0x40
|
||||
assert int(dac_pulse_num) == 3
|
||||
assert int(dac_pulse_height) == 0x7FF
|
||||
assert int(adc_pulse_period) == 0x80
|
||||
assert int(adc_window_size) == 16
|
||||
|
||||
await RisingEdge(dut.ctrl_clk)
|
||||
|
||||
|
||||
@cocotb.test()
|
||||
async def simple_controller_start_check(dut):
|
||||
tb = TB(dut)
|
||||
await tb.reset()
|
||||
await tb.write_reg(REG_CONTROL, CTRL_START)
|
||||
|
||||
await RisingEdge(dut.dut.dut.controller_wrapper_axil_inst.adc_start)
|
||||
|
||||
@cocotb.test()
|
||||
async def dma_accum_connection(dut):
|
||||
tb = TB(dut)
|
||||
await tb.reset()
|
||||
await tb.soft_reset()
|
||||
|
||||
SEQ_NUM = 1
|
||||
SMP_NUM = 16
|
||||
WINDOW_SIZE = 16
|
||||
|
||||
PULSE_WIDTH = 0x10
|
||||
PULSE_PERIOD = 0x40
|
||||
PULSE_HEIGHT = 0x7FF
|
||||
ADC_PERIOD = 1
|
||||
|
||||
RANDOM_SEED = 12345
|
||||
|
||||
RESULT_ADDR = 0x1000
|
||||
|
||||
await tb.configure_reflectometer(
|
||||
pulse_width=PULSE_WIDTH,
|
||||
pulse_period=PULSE_PERIOD,
|
||||
pulse_num=SEQ_NUM,
|
||||
pulse_height=PULSE_HEIGHT,
|
||||
adc_period=ADC_PERIOD,
|
||||
window_size=WINDOW_SIZE,
|
||||
timeout_cycles=1000 )
|
||||
|
||||
samples = tb.generate_samples(
|
||||
seq_num=SEQ_NUM,
|
||||
smp_num=SMP_NUM,
|
||||
data_width=ADC_DATA_WIDTH,
|
||||
seed=RANDOM_SEED )
|
||||
|
||||
|
||||
expected = tb.calculate_expected(
|
||||
samples=samples,
|
||||
window_size=WINDOW_SIZE,
|
||||
accum_width=ACCUM_WIDTH
|
||||
)
|
||||
|
||||
print("")
|
||||
print("========================================")
|
||||
print("ACCUMULATOR RANDOM TEST")
|
||||
print("========================================")
|
||||
print(f"seq_num = {SEQ_NUM}")
|
||||
print(f"smp_num = {SMP_NUM}")
|
||||
print(f"window_size = {WINDOW_SIZE}")
|
||||
print(f"data_width = {ADC_DATA_WIDTH}")
|
||||
print(f"accum_width = {ACCUM_WIDTH}")
|
||||
print(f"expected words = {len(expected)}")
|
||||
|
||||
RESULT_WORDS = len(expected)
|
||||
RESULT_BYTES = RESULT_WORDS * 4
|
||||
|
||||
print("==============================")
|
||||
print("ACCUM TEST")
|
||||
print("words =", RESULT_WORDS)
|
||||
print("bytes =", RESULT_BYTES)
|
||||
print("==============================")
|
||||
|
||||
for _ in range(10):
|
||||
await RisingEdge(dut.ctrl_clk)
|
||||
|
||||
await tb.send_start()
|
||||
|
||||
for _ in range(4):
|
||||
await RisingEdge(dut.ctrl_clk)
|
||||
|
||||
await tb.send_samples(samples)
|
||||
|
||||
await tb.wait_processing_done(timeout_cycles=5000)
|
||||
|
||||
await tb.send_desc_write( addr=RESULT_ADDR, length_tag=RESULT_BYTES )
|
||||
await tb.wait_dma_write_done(timeout_cycles=5000)
|
||||
|
||||
await tb.take_status_write(status_write_len=0x4, status_write_config=0)
|
||||
|
||||
await tb.send_desc_read(addr=RESULT_ADDR, length=RESULT_BYTES, config=0x0000_0001 )
|
||||
|
||||
received_data = await tb.receive_axis_data()
|
||||
|
||||
await tb.wait_dma_read_done(timeout_cycles=5000)
|
||||
|
||||
read_status = await tb.take_read_status()
|
||||
|
||||
assert read_status == 0x1
|
||||
|
||||
received = tb.bytes_to_words(received_data, RD_FIFO_WIDTH)
|
||||
|
||||
print("")
|
||||
print("Expected:")
|
||||
for i, value in enumerate(expected):
|
||||
print(f" [{i}] = 0x{value:08X}")
|
||||
|
||||
print("")
|
||||
print("Received:")
|
||||
for i, value in enumerate(received):
|
||||
print(f" [{i}] = 0x{value:08X}")
|
||||
|
||||
tb.check_results(
|
||||
expected=expected,
|
||||
received=received
|
||||
)
|
||||
|
||||
print("")
|
||||
print("========================================")
|
||||
print("ACCUMULATOR RANDOM TEST PASSED")
|
||||
print("========================================")
|
||||
|
||||
|
||||
|
||||
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
import dma_reg_pkg::*;
|
||||
|
||||
module wrapper_controller_dma_accum
|
||||
#(
|
||||
parameter int unsigned ADDR_W = 16,
|
||||
parameter int unsigned DATA_W = 32,
|
||||
parameter int unsigned USER_W = 1,
|
||||
|
||||
parameter int unsigned DAC_DATA_WIDTH = 12,
|
||||
|
||||
parameter int unsigned AXI_DATA_WIDTH = 32,
|
||||
|
||||
parameter int unsigned AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXI_ID_WIDTH = 8,
|
||||
parameter int unsigned AXI_USER_WIDTH = 1,
|
||||
parameter int unsigned AXI_MAX_BURST_LEN = 16,
|
||||
|
||||
parameter int unsigned AXIS_DATA_WIDTH = AXI_DATA_WIDTH,
|
||||
parameter int unsigned AXIS_KEEP_ENABLE = AXIS_DATA_WIDTH > 8,
|
||||
parameter int unsigned AXIS_KEEP_WIDTH = AXIS_DATA_WIDTH / 8,
|
||||
parameter int unsigned AXIS_LAST_ENABLE = 1,
|
||||
parameter int unsigned AXIS_ID_ENABLE = 1,
|
||||
parameter int unsigned AXIS_DEST_ENABLE = 0,
|
||||
parameter int unsigned AXIS_USER_ENABLE = 1,
|
||||
|
||||
parameter int unsigned ENABLE_SG = 0,
|
||||
parameter int unsigned ENABLE_UNALIGNED = 0,
|
||||
|
||||
parameter int unsigned PIPELINE_OUTPUT = 0,
|
||||
|
||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||
parameter int unsigned ACCUM_WIDTH = 32,
|
||||
parameter int unsigned N_MAX = 4096,
|
||||
parameter int unsigned PACKET_SIZE = 64,
|
||||
parameter int unsigned RD_FIFO_WIDTH = 32
|
||||
)
|
||||
(
|
||||
input logic ctrl_clk,
|
||||
input logic clk_generator,
|
||||
input logic clk_sampler,
|
||||
input logic rst_n,
|
||||
axi4l_if.slave s_axil,
|
||||
|
||||
// adc_clk_in domain
|
||||
|
||||
input logic [ADC_DATA_WIDTH-1:0] sampler_m_axis_tdata,
|
||||
input logic sampler_m_axis_tvalid,
|
||||
|
||||
axis_if.master m_axis_read_data
|
||||
);
|
||||
|
||||
logic workflow_done, processing_done;
|
||||
logic [31:0] window_size;
|
||||
logic adc_start, adc_rst;
|
||||
logic [31:0] dac_pulse_width;
|
||||
logic [31:0] dac_pulse_period;
|
||||
logic [DAC_DATA_WIDTH-1:0] dac_pulse_height;
|
||||
logic [15:0] dac_pulse_num;
|
||||
|
||||
// adc_clk_in domain outputs
|
||||
logic [31:0] adc_pulse_period;
|
||||
logic [15:0] adc_pulse_num;
|
||||
|
||||
// pulse outputs
|
||||
logic dac_start, dac_rst;
|
||||
|
||||
axis_if #(
|
||||
.DATA_W($bits(dma_read_status_t)),
|
||||
.KEEP_W(($bits(dma_read_status_t)+7)/8),
|
||||
.ID_W(dma_reg_pkg::AXIS_ID_WIDTH),
|
||||
.DEST_W(dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W(dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) s_axis_status_read (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W($bits(dma_write_status_t)),
|
||||
.KEEP_W(($bits(dma_write_status_t)+7)/8),
|
||||
.ID_W(dma_reg_pkg::AXIS_ID_WIDTH),
|
||||
.DEST_W(dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W(dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) s_axis_status_write (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W(RD_FIFO_WIDTH),
|
||||
.KEEP_W((RD_FIFO_WIDTH+7)/8),
|
||||
.ID_W(dma_reg_pkg::AXIS_ID_WIDTH),
|
||||
.DEST_W(dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W(dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) m_axis_accum (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W($bits(dma_read_desc_t)),
|
||||
.KEEP_W(($bits(dma_read_desc_t)+7)/8),
|
||||
.ID_W(dma_reg_pkg::AXIS_ID_WIDTH),
|
||||
.DEST_W(dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W(dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) m_axis_desc_read (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
|
||||
axis_if #(
|
||||
.DATA_W($bits(dma_write_desc_t)),
|
||||
.KEEP_W(($bits(dma_write_desc_t)+7)/8),
|
||||
.ID_W(dma_reg_pkg::AXIS_ID_WIDTH),
|
||||
.DEST_W(dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||
.USER_W(dma_reg_pkg::AXIS_USER_WIDTH)
|
||||
) m_axis_desc_write (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
|
||||
controller_wrapper_axil #(
|
||||
.ADDR_W(ADDR_W),
|
||||
.DATA_W(DATA_W),
|
||||
.USER_W(USER_W),
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||
) controller_wrapper_axil_inst
|
||||
(
|
||||
.ctrl_clk(ctrl_clk),
|
||||
.dac_clk_in(clk_generator),
|
||||
.adc_clk_in(clk_sampler),
|
||||
.rst_n(rst_n),
|
||||
|
||||
.s_axil(s_axil),
|
||||
|
||||
.workflow_done(workflow_done),
|
||||
.processing_done(processing_done),
|
||||
|
||||
.adc_window_size(window_size),
|
||||
.dac_pulse_width(dac_pulse_width),
|
||||
.dac_pulse_period(dac_pulse_period),
|
||||
.dac_pulse_height(dac_pulse_height),
|
||||
.dac_pulse_num(dac_pulse_num),
|
||||
.adc_pulse_period(adc_pulse_period),
|
||||
.adc_pulse_num(adc_pulse_num),
|
||||
.dac_start(dac_start),
|
||||
.adc_start(adc_start),
|
||||
.dac_rst(dac_rst),
|
||||
.adc_rst(adc_rst),
|
||||
|
||||
.s_axis_status_read(s_axis_status_read),
|
||||
.s_axis_status_write(s_axis_status_write),
|
||||
.m_axis_desc_read(m_axis_desc_read),
|
||||
.m_axis_desc_write(m_axis_desc_write)
|
||||
);
|
||||
|
||||
axi4_if #(
|
||||
.ADDR_W(dma_reg_pkg::AXI_ADDR_WIDTH),
|
||||
.DATA_W(AXI_DATA_WIDTH),
|
||||
.ID_W (AXI_ID_WIDTH),
|
||||
.USER_W(AXI_USER_WIDTH)
|
||||
) m_axi (
|
||||
.aclk(ctrl_clk),
|
||||
.aresetn(rst_n)
|
||||
);
|
||||
|
||||
axi_dma_wrapper
|
||||
#(
|
||||
.AXI_DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.AXI_STRB_WIDTH(AXI_STRB_WIDTH),
|
||||
.AXI_USER_WIDTH(AXI_USER_WIDTH),
|
||||
.AXI_MAX_BURST_LEN(AXI_MAX_BURST_LEN),
|
||||
.AXIS_DATA_WIDTH(AXIS_DATA_WIDTH),
|
||||
.AXIS_KEEP_ENABLE(AXIS_KEEP_ENABLE),
|
||||
.AXIS_KEEP_WIDTH(AXIS_KEEP_WIDTH),
|
||||
.AXIS_LAST_ENABLE(AXIS_LAST_ENABLE),
|
||||
.AXIS_ID_ENABLE(AXIS_ID_ENABLE),
|
||||
.AXIS_DEST_ENABLE(AXIS_DEST_ENABLE),
|
||||
.AXIS_USER_ENABLE(AXIS_USER_ENABLE),
|
||||
.ENABLE_SG(ENABLE_SG),
|
||||
.ENABLE_UNALIGNED(ENABLE_UNALIGNED)
|
||||
)
|
||||
axi_dma_wrapper_inst
|
||||
(
|
||||
.clk(ctrl_clk),
|
||||
.rst(!rst_n),
|
||||
.s_axis_read_desc(m_axis_desc_read),
|
||||
.m_axis_read_desc_status(s_axis_status_read),
|
||||
.m_axis_read_data(m_axis_read_data),
|
||||
.s_axis_write_desc(m_axis_desc_write),
|
||||
.m_axis_write_desc_status(s_axis_status_write),
|
||||
.s_axis_write_data(m_axis_accum),
|
||||
.m_axi(m_axi)
|
||||
);
|
||||
|
||||
axi_ram_wrapper
|
||||
#(
|
||||
.DATA_WIDTH(AXI_DATA_WIDTH),
|
||||
.ADDR_WIDTH(dma_reg_pkg::AXI_ADDR_WIDTH),
|
||||
.ID_WIDTH(dma_reg_pkg::AXIS_ID_WIDTH),
|
||||
.PIPELINE_OUTPUT(PIPELINE_OUTPUT)
|
||||
) axi_ram_wrapper_inst
|
||||
(
|
||||
.clk(ctrl_clk),
|
||||
.rst(!rst_n),
|
||||
.s_axi(m_axi)
|
||||
);
|
||||
|
||||
accumulator_top #(
|
||||
.DATA_WIDTH(ADC_DATA_WIDTH),
|
||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||
.N_MAX(N_MAX),
|
||||
.PACKET_SIZE(PACKET_SIZE),
|
||||
.RW_WIDTH(RD_FIFO_WIDTH)
|
||||
) accumulator_top_inst (
|
||||
.clk_in(clk_sampler),
|
||||
.rst(adc_rst),
|
||||
.s_axis_tdata(sampler_m_axis_tdata),
|
||||
.s_axis_tvalid(sampler_m_axis_tvalid),
|
||||
.start(adc_start),
|
||||
.smp_num(adc_pulse_period),
|
||||
.seq_num(adc_pulse_num),
|
||||
.window_size(window_size),
|
||||
.dma_clk_in(ctrl_clk),
|
||||
.req_ready(1'b1),
|
||||
.m_axis_accum(m_axis_accum),
|
||||
.finish(workflow_done),
|
||||
.accum_done(processing_done)
|
||||
);
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user