upd: reflectometer on axis bus iface + TB
This commit is contained in:
@ -10,16 +10,21 @@
|
|||||||
FPGA_PART = xc7a100tfgg484-2
|
FPGA_PART = xc7a100tfgg484-2
|
||||||
FPGA_TOP = reflectometer_top
|
FPGA_TOP = reflectometer_top
|
||||||
FPGA_ARCH = artix7
|
FPGA_ARCH = artix7
|
||||||
|
SIM_TOP = reflectometer_tb
|
||||||
|
|
||||||
RTL_DIR = ../../rtl
|
RTL_DIR = ../../rtl
|
||||||
|
|
||||||
|
|
||||||
include ../../scripts/vivado.mk
|
include ../../scripts/vivado.mk
|
||||||
|
|
||||||
|
|
||||||
|
INC_FILES += interfaces.svh
|
||||||
|
|
||||||
|
TB_FILES += reflectometer_tb.sv
|
||||||
SYN_FILES += reflectometer.sv
|
SYN_FILES += reflectometer.sv
|
||||||
SYN_FILES += dac_model.sv
|
SYN_FILES += dac_model.sv
|
||||||
SYN_FILES += adc_model.sv
|
SYN_FILES += adc_model.sv
|
||||||
SYN_FILES += tb_reflectometer.sv
|
SYN_FILES += reflectometer_tb.sv
|
||||||
SYN_FILES += $(sort $(shell find ../../rtl -type f \( -name '*.v' -o -name '*.sv' \)))
|
SYN_FILES += $(sort $(shell find ../../rtl -type f \( -name '*.v' -o -name '*.sv' \)))
|
||||||
|
|
||||||
XCI_FILES = $(sort $(shell find ../../rtl/ethernet-udp/src -type f -name '*.xci'))
|
XCI_FILES = $(sort $(shell find ../../rtl/ethernet-udp/src -type f -name '*.xci'))
|
||||||
@ -28,7 +33,6 @@ XCI_FILES += $(sort $(shell find ip/ -type f -name '*.xci'))
|
|||||||
XDC_FILES += ../../constraints/ax7102.xdc
|
XDC_FILES += ../../constraints/ax7102.xdc
|
||||||
XDC_FILES += debug.xdc
|
XDC_FILES += debug.xdc
|
||||||
|
|
||||||
SIM_TOP = tb_reflectometer
|
|
||||||
|
|
||||||
|
|
||||||
program: $(PROJECT).bit
|
program: $(PROJECT).bit
|
||||||
|
|||||||
@ -2,3 +2,8 @@
|
|||||||
create_clock -name ref_clock -period 5.000 [get_ports clk_in]
|
create_clock -name ref_clock -period 5.000 [get_ports clk_in]
|
||||||
create_clock -name phy_rx_clock -period 8.000 [get_ports clk_m_axis]
|
create_clock -name phy_rx_clock -period 8.000 [get_ports clk_m_axis]
|
||||||
create_clock -name phy_tx_clock -period 8.000 [get_ports clk_s_axis]
|
create_clock -name phy_tx_clock -period 8.000 [get_ports clk_s_axis]
|
||||||
|
|
||||||
|
set clk_125_name [get_clocks -of_objects [get_pins generator_inst/clk_dac_125]]
|
||||||
|
set clk_65_name [get_clocks -of_objects [get_pins accumulator_top_dut/clk_adc_65]]
|
||||||
|
|
||||||
|
set_clock_groups -asynchronous -group $clk_125_name -group $clk_65_name
|
||||||
53
designs/reflectometer_base/interfaces.svh
Normal file
53
designs/reflectometer_base/interfaces.svh
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
`ifndef AXIS_INTERFACE_SVH
|
||||||
|
`define AXIS_INTERFACE_SVH
|
||||||
|
|
||||||
|
interface axis_if #(
|
||||||
|
parameter int DATA_WIDTH = 8
|
||||||
|
)(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst_n
|
||||||
|
);
|
||||||
|
|
||||||
|
// Сигналы шины AXI-Stream
|
||||||
|
logic [DATA_WIDTH-1:0] tdata;
|
||||||
|
logic tvalid;
|
||||||
|
logic tlast;
|
||||||
|
logic tready;
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Clocking block для Testbench (Driver/Monitor)
|
||||||
|
// Защищает от Race Conditions в симуляции
|
||||||
|
//------------------------------------------------------------
|
||||||
|
clocking drv_cb @(posedge clk);
|
||||||
|
default input #1step output #100ps;
|
||||||
|
output tdata, tvalid, tlast;
|
||||||
|
input tready;
|
||||||
|
endclocking
|
||||||
|
|
||||||
|
clocking mon_cb @(posedge clk);
|
||||||
|
default input #1step;
|
||||||
|
input tdata, tvalid, tlast, tready;
|
||||||
|
endclocking
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Modports для автоматического подключения одной строчкой
|
||||||
|
//------------------------------------------------------------
|
||||||
|
modport master (
|
||||||
|
output tdata, tvalid, tlast,
|
||||||
|
input tready
|
||||||
|
);
|
||||||
|
|
||||||
|
modport slave (
|
||||||
|
input tdata, tvalid, tlast,
|
||||||
|
output tready
|
||||||
|
);
|
||||||
|
|
||||||
|
// Modport для тестбенча (чтобы работать через функции)
|
||||||
|
modport tb (
|
||||||
|
clocking drv_cb,
|
||||||
|
clocking mon_cb
|
||||||
|
);
|
||||||
|
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
`endif // AXIS_INTERFACE_SVH
|
||||||
@ -1,5 +1,7 @@
|
|||||||
`timescale 1 ns / 1 ns
|
`timescale 1 ns / 1 ns
|
||||||
|
|
||||||
|
`include "interfaces.svh"
|
||||||
|
|
||||||
module reflectometer_top #(
|
module reflectometer_top #(
|
||||||
parameter int unsigned DAC_DATA_WIDTH = 14,
|
parameter int unsigned DAC_DATA_WIDTH = 14,
|
||||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||||
@ -16,18 +18,12 @@ module reflectometer_top #(
|
|||||||
output wire locked,
|
output wire locked,
|
||||||
|
|
||||||
// Accumulator AXI-S bus
|
// Accumulator AXI-S bus
|
||||||
input wire clk_m_axis, // GMII PHY RX clock
|
input wire clk_axis_accumulator, // GMII PHY RX clock
|
||||||
output wire [7:0] m_axis_tdata,
|
axis_if.master axis_accumulator,
|
||||||
output wire m_axis_tvalid,
|
|
||||||
input wire m_axis_tready,
|
|
||||||
output wire m_axis_tlast,
|
|
||||||
|
|
||||||
// Control AXI-S bus
|
// Control AXI-S bus
|
||||||
input wire clk_s_axis, // GMII PHY TX clock
|
input wire clk_axis_control, // GMII PHY TX clock
|
||||||
input wire [7:0] s_axis__tdata,
|
axis_if.slave axis_control,
|
||||||
input wire s_axis_tvalid,
|
|
||||||
input wire s_axis_tlast,
|
|
||||||
output wire s_axis_tready,
|
|
||||||
|
|
||||||
// RTL-MAC handshake
|
// RTL-MAC handshake
|
||||||
input wire request_ready,
|
input wire request_ready,
|
||||||
@ -101,15 +97,15 @@ module reflectometer_top #(
|
|||||||
control #(
|
control #(
|
||||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||||
) udp_ctrl_inst (
|
) udp_ctrl_inst (
|
||||||
.eth_clk_in (clk_s_axis),
|
.eth_clk_in (clk_axis_control),
|
||||||
.dac_clk_in (clk_generator),
|
.dac_clk_in (clk_generator),
|
||||||
.adc_clk_in (clk_sampler),
|
.adc_clk_in (clk_sampler),
|
||||||
.rst_n (ctrl_rst_n),
|
.rst_n (ctrl_rst_n),
|
||||||
|
|
||||||
.s_axis_tdata (s_axis__tdata),
|
.s_axis_tdata (axis_control.tdata),
|
||||||
.s_axis_tvalid (s_axis_tvalid),
|
.s_axis_tvalid (axis_control.tvalid),
|
||||||
.s_axis_tready (s_axis_tready),
|
.s_axis_tready (axis_control.tready),
|
||||||
.s_axis_tlast (s_axis_tlast),
|
.s_axis_tlast (axis_control.tlast),
|
||||||
|
|
||||||
.finish (finish),
|
.finish (finish),
|
||||||
|
|
||||||
@ -131,9 +127,9 @@ module reflectometer_top #(
|
|||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// DAC -> ADC CDC
|
// DAC -> ADC CDC
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
(* ASYNC_REG = "TRUE" *) logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
||||||
logic [1:0] sync_DA;
|
(* ASYNC_REG = "TRUE" *) logic [1:0] sync_DA;
|
||||||
wire dac_done_stretched;
|
wire dac_done_stretched;
|
||||||
|
|
||||||
wire generator_done, generator_request;
|
wire generator_done, generator_request;
|
||||||
wire sampler_done, sampler_request;
|
wire sampler_done, sampler_request;
|
||||||
@ -163,7 +159,7 @@ module reflectometer_top #(
|
|||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// ADC -> DAC CDC
|
// ADC -> DAC CDC
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic [1:0] sync_AD;
|
(* ASYNC_REG = "TRUE" *) logic [1:0] sync_AD;
|
||||||
|
|
||||||
always_ff @(posedge clk_generator or posedge dac_rst) begin
|
always_ff @(posedge clk_generator or posedge dac_rst) begin
|
||||||
if (dac_rst)
|
if (dac_rst)
|
||||||
@ -237,11 +233,11 @@ module reflectometer_top #(
|
|||||||
|
|
||||||
.req_ready(request_ready),
|
.req_ready(request_ready),
|
||||||
.send_req(send_request),
|
.send_req(send_request),
|
||||||
.eth_clk_in(clk_m_axis),
|
.eth_clk_in(clk_axis_accumulator),
|
||||||
.m_axis_tdata(m_axis_tdata),
|
.m_axis_tdata(axis_accumulator.tdata),
|
||||||
.m_axis_tvalid(m_axis_tvalid),
|
.m_axis_tvalid(axis_accumulator.tvalid),
|
||||||
.m_axis_tready(m_axis_tready),
|
.m_axis_tready(axis_accumulator.tready),
|
||||||
.m_axis_tlast(m_axis_tlast),
|
.m_axis_tlast(axis_accumulator.tlast),
|
||||||
|
|
||||||
.finish(finish)
|
.finish(finish)
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module tb_reflectometer;
|
`include "interfaces.svh"
|
||||||
|
|
||||||
|
module reflectometer_tb;
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Параметры
|
// Параметры
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
@ -42,15 +44,15 @@ module tb_reflectometer;
|
|||||||
// Внутренние сигналы тестбенча
|
// Внутренние сигналы тестбенча
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// AXI-S интерфейс для управления
|
// AXI-S интерфейс для управления
|
||||||
logic [7:0] m_axis_control_tdata = 8'b0;
|
axis_if axis_control_if (
|
||||||
logic m_axis_control_tvalid = 1'b0;
|
.clk(clk_eth_phy),
|
||||||
wire m_axis_control_tready;
|
.rst_n(rst_n)
|
||||||
logic m_axis_control_tlast = 1'b0;
|
);
|
||||||
// AXI-S интерфейс для данных
|
// AXI-S интерфейс для данных
|
||||||
wire [7:0] s_axis_accumulator_tdata;
|
axis_if axis_accumulator_if (
|
||||||
wire s_axis_accumulator_tvalid;
|
.clk(clk_eth_phy),
|
||||||
logic s_axis_accumulator_tready = 1'b0;
|
.rst_n(rst_n)
|
||||||
wire s_axis_accumulator_tlast;
|
);
|
||||||
// DAC интерфейс
|
// DAC интерфейс
|
||||||
wire clk_dac;
|
wire clk_dac;
|
||||||
wire dac_wrt;
|
wire dac_wrt;
|
||||||
@ -114,18 +116,12 @@ module tb_reflectometer;
|
|||||||
.locked(mmcm_locked),
|
.locked(mmcm_locked),
|
||||||
|
|
||||||
// Accumulator AXI-S bus
|
// Accumulator AXI-S bus
|
||||||
.clk_m_axis(clk_eth_phy), // GMII PHY RX clock
|
.clk_axis_accumulator(clk_eth_phy), // GMII PHY RX clock
|
||||||
.m_axis_tdata(s_axis_accumulator_tdata),
|
.axis_accumulator(axis_accumulator_if.master),
|
||||||
.m_axis_tvalid(s_axis_accumulator_tvalid),
|
|
||||||
.m_axis_tready(s_axis_accumulator_tready),
|
|
||||||
.m_axis_tlast(s_axis_accumulator_tlast),
|
|
||||||
|
|
||||||
// Control AXI-S bus
|
// Control AXI-S bus
|
||||||
.clk_s_axis(clk_eth_phy), // GMII PHY TX clock
|
.clk_axis_control(clk_eth_phy), // GMII PHY TX clock
|
||||||
.s_axis__tdata(maxis_control_tdata),
|
.axis_control(axis_control_if.slave),
|
||||||
.s_axis_tvalid(maxis_control_tvalid),
|
|
||||||
.s_axis_tlast(maxis_control_tlast),
|
|
||||||
.s_axis_tready(maxis_control_tready),
|
|
||||||
|
|
||||||
// RTL-MAC handshake
|
// RTL-MAC handshake
|
||||||
.request_ready(request_ready),
|
.request_ready(request_ready),
|
||||||
@ -154,86 +150,100 @@ module tb_reflectometer;
|
|||||||
// Таски для тестирования
|
// Таски для тестирования
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
|
|
||||||
// task automatic axis_send_byte(
|
// AXI-S таски
|
||||||
// ref logic clk,
|
task automatic axis_send_packet(
|
||||||
// input logic [7:0] data,
|
virtual axis_if.tb vif,
|
||||||
// input logic last,
|
const ref logic [7:0] payload[]
|
||||||
// ref logic tvalid,
|
);
|
||||||
// ref logic [7:0] tdata,
|
int packet_size = payload.size();
|
||||||
// ref logic tlast,
|
|
||||||
// input logic tready
|
|
||||||
// );
|
|
||||||
// @(posedge clk);
|
|
||||||
// tdata <= data;
|
|
||||||
// tlast <= last;
|
|
||||||
// tvalid <= 1'b1;
|
|
||||||
|
|
||||||
// // Ждем готовности приемника
|
if (packet_size == 0) begin
|
||||||
// wait(tready === 1'b1);
|
$display("[WARNING] -axis_send_packet- Попытка отправить пустой пакет.");
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
// @(posedge clk);
|
foreach (payload[i]) begin
|
||||||
// tvalid <= 1'b0;
|
vif.drv_cb.tdata <= payload[i];
|
||||||
// tlast <= 1'b0;
|
vif.drv_cb.tvalid <= 1'b1;
|
||||||
// endtask
|
vif.drv_cb.tlast <= (i == packet_size - 1); // tlast активен только на последнем байте
|
||||||
|
|
||||||
// task automatic dut_soft_reset();
|
// Шагаем на следующий фронт клока, чтобы симулятор применил выходы
|
||||||
// axis_send_byte(
|
@(vif.drv_cb);
|
||||||
// .clk(clk_eth_phy_rx),
|
|
||||||
// .data(8'b00001111),
|
|
||||||
// .last(1'b1),
|
|
||||||
// .tvalid(m_axis_rx_tvalid),
|
|
||||||
// .tdata(m_axis_rx_tdata),
|
|
||||||
// .tlast(m_axis_rx_tlast),
|
|
||||||
// .tready(m_axis_rx_tready)
|
|
||||||
// );
|
|
||||||
// endtask
|
|
||||||
|
|
||||||
// task automatic dut_start();
|
// Ждем на последующих фронтах, пока tready не станет равен 1.
|
||||||
// axis_send_byte(
|
while (vif.drv_cb.tready !== 1'b1) begin
|
||||||
// .clk(clk_eth_phy_rx),
|
@(vif.drv_cb);
|
||||||
// .data(8'b11110000),
|
end
|
||||||
// .last(1'b1),
|
end
|
||||||
// .tvalid(m_axis_rx_tvalid),
|
|
||||||
// .tdata(m_axis_rx_tdata),
|
|
||||||
// .tlast(m_axis_rx_tlast),
|
|
||||||
// .tready(m_axis_rx_tready)
|
|
||||||
// );
|
|
||||||
// endtask
|
|
||||||
|
|
||||||
// task automatic dut_send_config(
|
// Снимаем валидность на следующем дельта-цикле
|
||||||
// input logic [127:0] ctrl_config
|
vif.drv_cb.tvalid <= 1'b0;
|
||||||
// );
|
vif.drv_cb.tlast <= 1'b0;
|
||||||
// // команда set_data
|
vif.drv_cb.tdata <= '0;
|
||||||
// axis_send_byte(
|
endtask
|
||||||
// .clk(clk_eth_phy_rx),
|
|
||||||
// .data(8'b10001000),
|
|
||||||
// .last(1'b0),
|
|
||||||
// .tvalid(m_axis_rx_tvalid),
|
|
||||||
// .tdata(m_axis_rx_tdata),
|
|
||||||
// .tlast(m_axis_rx_tlast),
|
|
||||||
// .tready(m_axis_rx_tready)
|
|
||||||
// );
|
|
||||||
// // config burst
|
|
||||||
// for (int i = 0; i < 16; i++) begin
|
|
||||||
// logic [7:0] byte_to_send;
|
|
||||||
// logic is_last;
|
|
||||||
|
|
||||||
// // get byte
|
task automatic dut_soft_reset();
|
||||||
// byte_to_send = ctrl_config[i*8 +: 8];
|
logic [7:0] cmd[] = '{8'b00001111};
|
||||||
// // tlast for last byte
|
axis_send_packet(
|
||||||
// is_last = (i == 15);
|
.vif(axis_control_if.tb),
|
||||||
|
.payload(cmd)
|
||||||
|
);
|
||||||
|
endtask
|
||||||
|
|
||||||
// axis_send_byte(
|
task automatic dut_start();
|
||||||
// .clk(clk_eth_phy_rx),
|
logic [7:0] cmd[] = '{8'b11110000};
|
||||||
// .data(byte_to_send),
|
axis_send_packet(
|
||||||
// .last(is_last),
|
.vif(axis_control_if.tb),
|
||||||
// .tvalid(m_axis_rx_tvalid),
|
.payload(cmd)
|
||||||
// .tdata(m_axis_rx_tdata),
|
);
|
||||||
// .tlast(m_axis_rx_tlast),
|
endtask
|
||||||
// .tready(m_axis_rx_tready)
|
|
||||||
// );
|
task automatic dut_send_system_config(
|
||||||
// end
|
input logic [31:0] pulse_width,
|
||||||
// endtask
|
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
|
||||||
|
|
||||||
|
// Таски сбора и обработки статистики
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
@ -245,10 +255,17 @@ module tb_reflectometer;
|
|||||||
// Инициализация
|
// Инициализация
|
||||||
rst_n = 1;
|
rst_n = 1;
|
||||||
wait(mmcm_locked === 1'b1);
|
wait(mmcm_locked === 1'b1);
|
||||||
|
#10;
|
||||||
|
|
||||||
|
dut_soft_reset();
|
||||||
|
dut_send_system_config(
|
||||||
#100;
|
.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");
|
$display("[TB] ALL PASSED");
|
||||||
$finish;
|
$finish;
|
||||||
Reference in New Issue
Block a user