upd: reflectometer on axis bus iface + TB
This commit is contained in:
273
designs/reflectometer_base/reflectometer_tb.sv
Normal file
273
designs/reflectometer_base/reflectometer_tb.sv
Normal file
@ -0,0 +1,273 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "interfaces.svh"
|
||||
|
||||
module reflectometer_tb;
|
||||
//------------------------------------------------------------
|
||||
// Параметры
|
||||
//------------------------------------------------------------
|
||||
localparam int unsigned DAC_DATA_WIDTH = 14;
|
||||
localparam int unsigned ADC_DATA_WIDTH = 12;
|
||||
localparam LOGIC_ZERO_LEVEL = 0; // DAC -5V for logic zero
|
||||
localparam VOLTAGE_ZERO_LEVEL = 2**(DAC_DATA_WIDTH-1); // DAC 0V for logic zero
|
||||
localparam PACK_FACTOR = 1; // not used in TB
|
||||
localparam PROCESS_MODE = 0; // 0 - uint, 1 - int
|
||||
localparam ACCUM_WIDTH = 32; // accumulator number bit witdth
|
||||
localparam N_MAX = 4096; // max value of windows to average by experiments
|
||||
localparam WINDOW_SIZE = 65; // fixed subwindow size to average by time
|
||||
localparam PACKET_SIZE = 1024; // bytes per UDP packet
|
||||
|
||||
localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "true"
|
||||
|
||||
localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz
|
||||
localparam CLK_REF_PERIOD = 5.000; // 200 MHz
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Тактовые сигналы и сброс
|
||||
//------------------------------------------------------------
|
||||
logic clk_ref = 1'b0; // 200 MHz
|
||||
logic clk_eth_phy = 1'b0; // common for RX & TX
|
||||
logic rst_n = 1'b0;
|
||||
//------------------------------------------------------------
|
||||
// Управление и конфиг
|
||||
//------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Входы
|
||||
//------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Выходы
|
||||
//------------------------------------------------------------
|
||||
wire mmcm_locked;
|
||||
//------------------------------------------------------------
|
||||
// Внутренние сигналы тестбенча
|
||||
//------------------------------------------------------------
|
||||
// AXI-S интерфейс для управления
|
||||
axis_if axis_control_if (
|
||||
.clk(clk_eth_phy),
|
||||
.rst_n(rst_n)
|
||||
);
|
||||
// AXI-S интерфейс для данных
|
||||
axis_if axis_accumulator_if (
|
||||
.clk(clk_eth_phy),
|
||||
.rst_n(rst_n)
|
||||
);
|
||||
// DAC интерфейс
|
||||
wire clk_dac;
|
||||
wire dac_wrt;
|
||||
wire [DAC_DATA_WIDTH-1:0] dac_data;
|
||||
// ADC интерфейс
|
||||
wire clk_adc;
|
||||
wire adc_otr = 1'b0;
|
||||
wire [ADC_DATA_WIDTH-1:0] adc_data = '0;
|
||||
// Интерфейс хендшейка с MAC-PHY
|
||||
wire send_request;
|
||||
logic request_ready = 1'b0;
|
||||
// Сигналы ЦАП и АЦП
|
||||
real signal_voltage;
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Virtual DAC
|
||||
//------------------------------------------------------------
|
||||
virtual_dac_model #( // default voltage range is +/- 5V
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||
) virtual_dac (
|
||||
.clk_i(clk_dac),
|
||||
.wrt_i(dac_wrt),
|
||||
.data_i(dac_data),
|
||||
.voltage_o(signal_voltage)
|
||||
);
|
||||
//------------------------------------------------------------
|
||||
// Virtual ADC
|
||||
//------------------------------------------------------------
|
||||
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)
|
||||
);
|
||||
//------------------------------------------------------------
|
||||
// Statistics monitor
|
||||
//------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------
|
||||
// Config handler
|
||||
//------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------
|
||||
// DUT
|
||||
//------------------------------------------------------------
|
||||
reflectometer_top #(
|
||||
.DAC_DATA_WIDTH(DAC_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),
|
||||
.WINDOW_SIZE(WINDOW_SIZE),
|
||||
.PACKET_SIZE(PACKET_SIZE)
|
||||
) DUT (
|
||||
.clk_in(clk_ref),
|
||||
.rst_n(rst_n),
|
||||
.locked(mmcm_locked),
|
||||
|
||||
// Accumulator AXI-S bus
|
||||
.clk_axis_accumulator(clk_eth_phy), // GMII PHY RX clock
|
||||
.axis_accumulator(axis_accumulator_if.master),
|
||||
|
||||
// Control AXI-S bus
|
||||
.clk_axis_control(clk_eth_phy), // GMII PHY TX clock
|
||||
.axis_control(axis_control_if.slave),
|
||||
|
||||
// RTL-MAC handshake
|
||||
.request_ready(request_ready),
|
||||
.send_request(send_request),
|
||||
|
||||
// DAC
|
||||
.dac_clk_o(clk_dac),
|
||||
.dac_data(dac_data),
|
||||
.dac_wrt(dac_wrt),
|
||||
|
||||
// ADC
|
||||
.adc_clk_o(clk_adc),
|
||||
.adc_data(adc_data),
|
||||
.adc_otr(adc_otr)
|
||||
);
|
||||
//------------------------------------------------------------
|
||||
// Тактовые сигналы
|
||||
//------------------------------------------------------------
|
||||
initial begin
|
||||
forever #(CLK_REF_PERIOD/2) clk_ref = ~clk_ref;
|
||||
end
|
||||
initial begin
|
||||
forever #(CLK_ETH_PHY_PERIOD/2) clk_eth_phy = ~clk_eth_phy;
|
||||
end
|
||||
//------------------------------------------------------------
|
||||
// Таски для тестирования
|
||||
//------------------------------------------------------------
|
||||
|
||||
// AXI-S таски
|
||||
task automatic axis_send_packet(
|
||||
virtual axis_if.tb vif,
|
||||
const ref logic [7:0] payload[]
|
||||
);
|
||||
int packet_size = payload.size();
|
||||
|
||||
if (packet_size == 0) begin
|
||||
$display("[WARNING] -axis_send_packet- Попытка отправить пустой пакет.");
|
||||
return;
|
||||
end
|
||||
|
||||
foreach (payload[i]) begin
|
||||
vif.drv_cb.tdata <= payload[i];
|
||||
vif.drv_cb.tvalid <= 1'b1;
|
||||
vif.drv_cb.tlast <= (i == packet_size - 1); // tlast активен только на последнем байте
|
||||
|
||||
// Шагаем на следующий фронт клока, чтобы симулятор применил выходы
|
||||
@(vif.drv_cb);
|
||||
|
||||
// Ждем на последующих фронтах, пока tready не станет равен 1.
|
||||
while (vif.drv_cb.tready !== 1'b1) begin
|
||||
@(vif.drv_cb);
|
||||
end
|
||||
end
|
||||
|
||||
// Снимаем валидность на следующем дельта-цикле
|
||||
vif.drv_cb.tvalid <= 1'b0;
|
||||
vif.drv_cb.tlast <= 1'b0;
|
||||
vif.drv_cb.tdata <= '0;
|
||||
endtask
|
||||
|
||||
task automatic dut_soft_reset();
|
||||
logic [7:0] cmd[] = '{8'b00001111};
|
||||
axis_send_packet(
|
||||
.vif(axis_control_if.tb),
|
||||
.payload(cmd)
|
||||
);
|
||||
endtask
|
||||
|
||||
task automatic dut_start();
|
||||
logic [7:0] cmd[] = '{8'b11110000};
|
||||
axis_send_packet(
|
||||
.vif(axis_control_if.tb),
|
||||
.payload(cmd)
|
||||
);
|
||||
endtask
|
||||
|
||||
task automatic dut_send_system_config(
|
||||
input logic [31:0] pulse_width,
|
||||
input logic [31:0] pulse_period,
|
||||
input logic [15:0] pulse_num,
|
||||
input logic [13:0] pulse_height,
|
||||
input logic [31:0] pulse_period_adc
|
||||
);
|
||||
// Выделяем 17 байт: 1 байт команды + 16 байт регистров
|
||||
logic [7:0] full_packet[] = new[17];
|
||||
|
||||
// 1. Сначала пишем команду в нулевой байт пакета
|
||||
full_packet[0] = 8'b10001000; // Твоя команда set_data
|
||||
|
||||
// 2. Упаковываем регистр pulse_width [31:0] (байты 1..4)
|
||||
full_packet[1] = pulse_width[7:0];
|
||||
full_packet[2] = pulse_width[15:8];
|
||||
full_packet[3] = pulse_width[23:16];
|
||||
full_packet[4] = pulse_width[31:24];
|
||||
|
||||
// 3. Упаковываем регистр pulse_period [63:32] (байты 5..8)
|
||||
full_packet[5] = pulse_period[7:0];
|
||||
full_packet[6] = pulse_period[15:8];
|
||||
full_packet[7] = pulse_period[23:16];
|
||||
full_packet[8] = pulse_period[31:24];
|
||||
|
||||
// 4. Упаковываем регистр pulse_num [79:64] (байты 9..10)
|
||||
full_packet[9] = pulse_num[7:0];
|
||||
full_packet[10] = pulse_num[15:8];
|
||||
|
||||
// 5. Упаковываем регистр pulse_height [79+dac_width:80] (байты 11..12)
|
||||
full_packet[11] = pulse_height[7:0];
|
||||
full_packet[12] = {2'b00, pulse_height[13:8]}; // дополняем до честного байта
|
||||
|
||||
// 6. Упаковываем регистр pulse_period_adc [127:96] (байты 13..16)
|
||||
full_packet[13] = pulse_period_adc[7:0];
|
||||
full_packet[14] = pulse_period_adc[15:8];
|
||||
full_packet[15] = pulse_period_adc[23:16];
|
||||
full_packet[16] = pulse_period_adc[31:24];
|
||||
|
||||
axis_send_packet(
|
||||
.vif(axis_control_if.tb),
|
||||
.payload(full_packet)
|
||||
);
|
||||
endtask
|
||||
|
||||
// Таски сбора и обработки статистики
|
||||
|
||||
|
||||
//------------------------------------------------------------
|
||||
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
|
||||
//------------------------------------------------------------
|
||||
initial begin
|
||||
$display("[TB] Tests start");
|
||||
|
||||
// Инициализация
|
||||
rst_n = 1;
|
||||
wait(mmcm_locked === 1'b1);
|
||||
#10;
|
||||
|
||||
dut_soft_reset();
|
||||
dut_send_system_config(
|
||||
.pulse_width(32'd350),
|
||||
.pulse_period(32'd1250),
|
||||
.pulse_num(16'd10),
|
||||
.pulse_height(14'd14000), // 0V
|
||||
.pulse_period_adc(32'd650)
|
||||
);
|
||||
dut_start();
|
||||
|
||||
$display("[TB] ALL PASSED");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Reference in New Issue
Block a user