upd: reflectometer on axis bus iface + TB
This commit is contained in:
@ -10,16 +10,21 @@
|
||||
FPGA_PART = xc7a100tfgg484-2
|
||||
FPGA_TOP = reflectometer_top
|
||||
FPGA_ARCH = artix7
|
||||
SIM_TOP = reflectometer_tb
|
||||
|
||||
RTL_DIR = ../../rtl
|
||||
|
||||
|
||||
include ../../scripts/vivado.mk
|
||||
|
||||
|
||||
INC_FILES += interfaces.svh
|
||||
|
||||
TB_FILES += reflectometer_tb.sv
|
||||
SYN_FILES += reflectometer.sv
|
||||
SYN_FILES += dac_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' \)))
|
||||
|
||||
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 += debug.xdc
|
||||
|
||||
SIM_TOP = tb_reflectometer
|
||||
|
||||
|
||||
program: $(PROJECT).bit
|
||||
|
||||
@ -2,3 +2,8 @@
|
||||
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_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
|
||||
|
||||
`include "interfaces.svh"
|
||||
|
||||
module reflectometer_top #(
|
||||
parameter int unsigned DAC_DATA_WIDTH = 14,
|
||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||
@ -16,18 +18,12 @@ module reflectometer_top #(
|
||||
output wire locked,
|
||||
|
||||
// Accumulator AXI-S bus
|
||||
input wire clk_m_axis, // GMII PHY RX clock
|
||||
output wire [7:0] m_axis_tdata,
|
||||
output wire m_axis_tvalid,
|
||||
input wire m_axis_tready,
|
||||
output wire m_axis_tlast,
|
||||
input wire clk_axis_accumulator, // GMII PHY RX clock
|
||||
axis_if.master axis_accumulator,
|
||||
|
||||
// Control AXI-S bus
|
||||
input wire clk_s_axis, // GMII PHY TX clock
|
||||
input wire [7:0] s_axis__tdata,
|
||||
input wire s_axis_tvalid,
|
||||
input wire s_axis_tlast,
|
||||
output wire s_axis_tready,
|
||||
input wire clk_axis_control, // GMII PHY TX clock
|
||||
axis_if.slave axis_control,
|
||||
|
||||
// RTL-MAC handshake
|
||||
input wire request_ready,
|
||||
@ -101,15 +97,15 @@ module reflectometer_top #(
|
||||
control #(
|
||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||
) udp_ctrl_inst (
|
||||
.eth_clk_in (clk_s_axis),
|
||||
.eth_clk_in (clk_axis_control),
|
||||
.dac_clk_in (clk_generator),
|
||||
.adc_clk_in (clk_sampler),
|
||||
.rst_n (ctrl_rst_n),
|
||||
|
||||
.s_axis_tdata (s_axis__tdata),
|
||||
.s_axis_tvalid (s_axis_tvalid),
|
||||
.s_axis_tready (s_axis_tready),
|
||||
.s_axis_tlast (s_axis_tlast),
|
||||
.s_axis_tdata (axis_control.tdata),
|
||||
.s_axis_tvalid (axis_control.tvalid),
|
||||
.s_axis_tready (axis_control.tready),
|
||||
.s_axis_tlast (axis_control.tlast),
|
||||
|
||||
.finish (finish),
|
||||
|
||||
@ -131,9 +127,9 @@ module reflectometer_top #(
|
||||
//------------------------------------------------------------
|
||||
// DAC -> ADC CDC
|
||||
//------------------------------------------------------------
|
||||
logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
||||
logic [1:0] sync_DA;
|
||||
wire dac_done_stretched;
|
||||
(* ASYNC_REG = "TRUE" *) logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
||||
(* ASYNC_REG = "TRUE" *) logic [1:0] sync_DA;
|
||||
wire dac_done_stretched;
|
||||
|
||||
wire generator_done, generator_request;
|
||||
wire sampler_done, sampler_request;
|
||||
@ -163,7 +159,7 @@ module reflectometer_top #(
|
||||
//------------------------------------------------------------
|
||||
// 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
|
||||
if (dac_rst)
|
||||
@ -237,11 +233,11 @@ module reflectometer_top #(
|
||||
|
||||
.req_ready(request_ready),
|
||||
.send_req(send_request),
|
||||
.eth_clk_in(clk_m_axis),
|
||||
.m_axis_tdata(m_axis_tdata),
|
||||
.m_axis_tvalid(m_axis_tvalid),
|
||||
.m_axis_tready(m_axis_tready),
|
||||
.m_axis_tlast(m_axis_tlast),
|
||||
.eth_clk_in(clk_axis_accumulator),
|
||||
.m_axis_tdata(axis_accumulator.tdata),
|
||||
.m_axis_tvalid(axis_accumulator.tvalid),
|
||||
.m_axis_tready(axis_accumulator.tready),
|
||||
.m_axis_tlast(axis_accumulator.tlast),
|
||||
|
||||
.finish(finish)
|
||||
);
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module tb_reflectometer;
|
||||
`include "interfaces.svh"
|
||||
|
||||
module reflectometer_tb;
|
||||
//------------------------------------------------------------
|
||||
// Параметры
|
||||
//------------------------------------------------------------
|
||||
@ -42,15 +44,15 @@ module tb_reflectometer;
|
||||
// Внутренние сигналы тестбенча
|
||||
//------------------------------------------------------------
|
||||
// AXI-S интерфейс для управления
|
||||
logic [7:0] m_axis_control_tdata = 8'b0;
|
||||
logic m_axis_control_tvalid = 1'b0;
|
||||
wire m_axis_control_tready;
|
||||
logic m_axis_control_tlast = 1'b0;
|
||||
axis_if axis_control_if (
|
||||
.clk(clk_eth_phy),
|
||||
.rst_n(rst_n)
|
||||
);
|
||||
// AXI-S интерфейс для данных
|
||||
wire [7:0] s_axis_accumulator_tdata;
|
||||
wire s_axis_accumulator_tvalid;
|
||||
logic s_axis_accumulator_tready = 1'b0;
|
||||
wire s_axis_accumulator_tlast;
|
||||
axis_if axis_accumulator_if (
|
||||
.clk(clk_eth_phy),
|
||||
.rst_n(rst_n)
|
||||
);
|
||||
// DAC интерфейс
|
||||
wire clk_dac;
|
||||
wire dac_wrt;
|
||||
@ -114,18 +116,12 @@ module tb_reflectometer;
|
||||
.locked(mmcm_locked),
|
||||
|
||||
// Accumulator AXI-S bus
|
||||
.clk_m_axis(clk_eth_phy), // GMII PHY RX clock
|
||||
.m_axis_tdata(s_axis_accumulator_tdata),
|
||||
.m_axis_tvalid(s_axis_accumulator_tvalid),
|
||||
.m_axis_tready(s_axis_accumulator_tready),
|
||||
.m_axis_tlast(s_axis_accumulator_tlast),
|
||||
.clk_axis_accumulator(clk_eth_phy), // GMII PHY RX clock
|
||||
.axis_accumulator(axis_accumulator_if.master),
|
||||
|
||||
// Control AXI-S bus
|
||||
.clk_s_axis(clk_eth_phy), // GMII PHY TX clock
|
||||
.s_axis__tdata(maxis_control_tdata),
|
||||
.s_axis_tvalid(maxis_control_tvalid),
|
||||
.s_axis_tlast(maxis_control_tlast),
|
||||
.s_axis_tready(maxis_control_tready),
|
||||
.clk_axis_control(clk_eth_phy), // GMII PHY TX clock
|
||||
.axis_control(axis_control_if.slave),
|
||||
|
||||
// RTL-MAC handshake
|
||||
.request_ready(request_ready),
|
||||
@ -154,86 +150,100 @@ module tb_reflectometer;
|
||||
// Таски для тестирования
|
||||
//------------------------------------------------------------
|
||||
|
||||
// task automatic axis_send_byte(
|
||||
// ref logic clk,
|
||||
// input logic [7:0] data,
|
||||
// input logic last,
|
||||
// ref logic tvalid,
|
||||
// ref logic [7:0] tdata,
|
||||
// ref logic tlast,
|
||||
// input logic tready
|
||||
// );
|
||||
// @(posedge clk);
|
||||
// tdata <= data;
|
||||
// tlast <= last;
|
||||
// tvalid <= 1'b1;
|
||||
// AXI-S таски
|
||||
task automatic axis_send_packet(
|
||||
virtual axis_if.tb vif,
|
||||
const ref logic [7:0] payload[]
|
||||
);
|
||||
int packet_size = payload.size();
|
||||
|
||||
// // Ждем готовности приемника
|
||||
// wait(tready === 1'b1);
|
||||
if (packet_size == 0) begin
|
||||
$display("[WARNING] -axis_send_packet- Попытка отправить пустой пакет.");
|
||||
return;
|
||||
end
|
||||
|
||||
// @(posedge clk);
|
||||
// tvalid <= 1'b0;
|
||||
// tlast <= 1'b0;
|
||||
// endtask
|
||||
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 активен только на последнем байте
|
||||
|
||||
// task automatic dut_soft_reset();
|
||||
// axis_send_byte(
|
||||
// .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
|
||||
// Шагаем на следующий фронт клока, чтобы симулятор применил выходы
|
||||
@(vif.drv_cb);
|
||||
|
||||
// task automatic dut_start();
|
||||
// axis_send_byte(
|
||||
// .clk(clk_eth_phy_rx),
|
||||
// .data(8'b11110000),
|
||||
// .last(1'b1),
|
||||
// .tvalid(m_axis_rx_tvalid),
|
||||
// .tdata(m_axis_rx_tdata),
|
||||
// .tlast(m_axis_rx_tlast),
|
||||
// .tready(m_axis_rx_tready)
|
||||
// );
|
||||
// endtask
|
||||
// Ждем на последующих фронтах, пока tready не станет равен 1.
|
||||
while (vif.drv_cb.tready !== 1'b1) begin
|
||||
@(vif.drv_cb);
|
||||
end
|
||||
end
|
||||
|
||||
// task automatic dut_send_config(
|
||||
// input logic [127:0] ctrl_config
|
||||
// );
|
||||
// // команда set_data
|
||||
// axis_send_byte(
|
||||
// .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;
|
||||
// Снимаем валидность на следующем дельта-цикле
|
||||
vif.drv_cb.tvalid <= 1'b0;
|
||||
vif.drv_cb.tlast <= 1'b0;
|
||||
vif.drv_cb.tdata <= '0;
|
||||
endtask
|
||||
|
||||
// // get byte
|
||||
// byte_to_send = ctrl_config[i*8 +: 8];
|
||||
// // tlast for last byte
|
||||
// is_last = (i == 15);
|
||||
task automatic dut_soft_reset();
|
||||
logic [7:0] cmd[] = '{8'b00001111};
|
||||
axis_send_packet(
|
||||
.vif(axis_control_if.tb),
|
||||
.payload(cmd)
|
||||
);
|
||||
endtask
|
||||
|
||||
// axis_send_byte(
|
||||
// .clk(clk_eth_phy_rx),
|
||||
// .data(byte_to_send),
|
||||
// .last(is_last),
|
||||
// .tvalid(m_axis_rx_tvalid),
|
||||
// .tdata(m_axis_rx_tdata),
|
||||
// .tlast(m_axis_rx_tlast),
|
||||
// .tready(m_axis_rx_tready)
|
||||
// );
|
||||
// end
|
||||
// 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
|
||||
|
||||
// Таски сбора и обработки статистики
|
||||
|
||||
|
||||
//------------------------------------------------------------
|
||||
@ -245,10 +255,17 @@ module tb_reflectometer;
|
||||
// Инициализация
|
||||
rst_n = 1;
|
||||
wait(mmcm_locked === 1'b1);
|
||||
#10;
|
||||
|
||||
|
||||
|
||||
#100;
|
||||
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;
|
||||
Reference in New Issue
Block a user