add: half-baked reflectometer TB

fix: constraints port names;
ready: reflectometer top module
This commit is contained in:
2026-07-08 14:56:51 +03:00
parent c3275d5b46
commit 7665afd50b
5 changed files with 285 additions and 378 deletions

View File

@ -1,3 +1,3 @@
# Primary clocks # Primary clocks
create_clock -name eth_clk -period 8.000 [get_ports dac_clk_in] create_clock -name eth_clk -period 8.000 [get_ports clk_dac]
create_clock -name acc_clk -period 15.385 [get_ports adc_clk_in] create_clock -name acc_clk -period 15.385 [get_ports clk_adc]

View File

@ -1 +1,4 @@
set_clock_groups -name ASYNC_UDP_CTRL -asynchronous -group [get_clocks rgmii_rxc] -group [get_clocks clk_out1_clk_wiz_ctrl_inst] -group [get_clocks clk_out2_clk_wiz_ctrl_inst] # Primary clocks
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]

View File

@ -11,75 +11,68 @@ module reflectometer_top #(
parameter int unsigned WINDOW_SIZE = 65, parameter int unsigned WINDOW_SIZE = 65,
parameter int unsigned PACKET_SIZE = 1024 parameter int unsigned PACKET_SIZE = 1024
)( )(
input sys_clk, input wire clk_in,
input rst_n, input wire rst_n,
output wire locked,
output [3:0] led, // 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 gmii_rx_clk, // Control AXI-S bus
input gmii_tx_clk, 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,
(* MARK_DEBUG="true" *) output logic [7:0] s_axis_tx_tdata, // RTL-MAC handshake
(* MARK_DEBUG="true" *) output logic s_axis_tx_tvalid, input wire request_ready,
(* MARK_DEBUG="true" *) input logic s_axis_tx_tready, output wire send_request,
(* MARK_DEBUG="true" *) output logic s_axis_tx_tlast,
(* MARK_DEBUG="true" *) input wire [7:0] m_axis_rx_tdata,
(* MARK_DEBUG="true" *) input wire m_axis_rx_tvalid,
(* MARK_DEBUG="true" *) input wire m_axis_rx_tlast,
(* MARK_DEBUG="true" *) output wire m_axis_rx_tready,
// axis_mac
(* MARK_DEBUG="true" *) input logic req_ready,
(* MARK_DEBUG="true" *) output logic send_req,
// DAC // DAC
output logic dac_clk_o, output wire dac_clk_o,
output logic [DAC_DATA_WIDTH-1:0] dac_data, output wire [DAC_DATA_WIDTH-1:0] dac_data,
output logic dac_wrt, output wire dac_wrt,
// ADC // ADC
output logic adc_clk_o, output wire adc_clk_o,
input wire [ADC_DATA_WIDTH-1:0] adc_data, input wire [ADC_DATA_WIDTH-1:0] adc_data,
input wire adc_otr input wire adc_otr
); );
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] sampler_m_axis_tdata;
wire sampler_m_axis_tvalid;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Generated clocks for controller // Generated clocks for controller
// Need to create this IP in Vivado: // Need to create this IP in Vivado:
// input : 200 MHz // input resetn
// output0: 130 MHz // input clk_200 : 200 MHz : Reference clock
// output1: 65 MHz // output clk_adc_65 : 65 MHz : ADC RTL clock
// output clk_adc_65_180 : 65 MHz, phase 180 deg. : ADC PHY clock
// output clk_adc_125 : 125 MHz : DAC RTL clock
// output clk_adc_125_180 : 125 MHz, phase 180 deg. : DAC PHY clock
// output locked
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
wire dac_clk; wire clk_sampler, clk_generator, clk_locked;
wire adc_clk;
wire clk_wiz_locked;
clk_wiz_ctrl_inst clock_wiz_inst clk_wiz_ctrl_inst clk_wiz_inst
( (
// Clock in ports // Clock in ports
.clk_200(clk_in), .clk_200(clk_in),
// Clock out ports // Clock out ports
.clk_adc_65(clk_adc), .clk_adc_65(clk_sampler),
.clk_adc_65_180(clk_sampler), .clk_adc_65_180(adc_clk_o),
.clk_dac_125(clk_dac), .clk_dac_125(clk_generator),
.clk_dac_125_180(clk_generator), .clk_dac_125_180(dac_clk_o),
// Status and control signals // Status and control signals
.resetn(rst_n), .resetn(rst_n),
.locked(clk_locked) .locked(clk_locked)
); );
// ------------------------------------------------------------------------- assign locked = clk_locked;
// axis_mac interface
// RX stream from Ethernet goes into controller
// TX stream is unused for now
// -------------------------------------------------------------------------
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Controller reset // Controller reset
@ -87,40 +80,36 @@ module reflectometer_top #(
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
wire ctrl_rst_n = rst_n & clk_locked; wire ctrl_rst_n = rst_n & clk_locked;
(* MARK_DEBUG="true" *) logic finish;
// Controller outputs to debug
(* MARK_DEBUG="true" *) wire [31:0] dac_pulse_width;
(* MARK_DEBUG="true" *) wire [31:0] dac_pulse_period;
(* MARK_DEBUG="true" *) wire [DAC_DATA_WIDTH-1:0] dac_pulse_height;
(* MARK_DEBUG="true" *) wire [15:0] dac_pulse_num;
(* MARK_DEBUG="true" *) wire [31:0] adc_pulse_period;
(* MARK_DEBUG="true" *) wire [15:0] adc_pulse_num;
(* MARK_DEBUG="true" *) wire dac_start;
(* MARK_DEBUG="true" *) wire adc_start;
(* MARK_DEBUG="true" *) wire dac_rst;
(* MARK_DEBUG="true" *) wire adc_rst;
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Controller // Controller
// ETH domain = gmii_rx_clk, because RX AXI master comes from axis_mac RX side
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
wire [31:0] dac_pulse_width;
wire [31:0] dac_pulse_period;
wire [DAC_DATA_WIDTH-1:0] dac_pulse_height;
wire [15:0] dac_pulse_num;
wire [31:0] adc_pulse_period;
wire [15:0] adc_pulse_num;
wire dac_start;
wire adc_start;
wire dac_rst;
wire adc_rst;
wire finish;
control #( control #(
.DAC_DATA_WIDTH(DAC_DATA_WIDTH) .DAC_DATA_WIDTH(DAC_DATA_WIDTH)
) udp_ctrl_inst ( ) udp_ctrl_inst (
.eth_clk_in (gmii_rx_clk), .eth_clk_in (clk_s_axis),
.dac_clk_in (dac_clk), .dac_clk_in (clk_generator),
.adc_clk_in (adc_clk), .adc_clk_in (clk_sampler),
.rst_n (ctrl_rst_n), .rst_n (ctrl_rst_n),
.s_axis_tdata (m_axis_rx_tdata), .s_axis_tdata (s_axis__tdata),
.s_axis_tvalid (m_axis_rx_tvalid), .s_axis_tvalid (s_axis_tvalid),
.s_axis_tready (m_axis_rx_tready), .s_axis_tready (s_axis_tready),
.s_axis_tlast (m_axis_rx_tlast), .s_axis_tlast (s_axis_tlast),
.finish (finish), .finish (finish),
@ -139,124 +128,80 @@ module reflectometer_top #(
.adc_rst (adc_rst) .adc_rst (adc_rst)
); );
// ------------------------------------------------------------------------- //------------------------------------------------------------
// DAC
// -------------------------------------------------------------------------
(* MARK_DEBUG="true" *) logic sample_req;
(* MARK_DEBUG="true" *) logic sample_req_sync1;
(* MARK_DEBUG="true" *) logic sample_req_sync2;
(* MARK_DEBUG="true" *) logic sample_req_sync3;
(* MARK_DEBUG="true" *) logic sample_done;
(* MARK_DEBUG="true" *) logic sample_done_sync1;
(* MARK_DEBUG="true" *) logic sample_done_sync2;
(* MARK_DEBUG="true" *) logic sample_done_sync3;
//------------------------------------------------------------
// DAC -> ADC CDC // DAC -> ADC CDC
//------------------------------------------------------------ //------------------------------------------------------------
always_ff @(posedge adc_clk or posedge adc_rst) begin logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
if (adc_rst) begin logic [1:0] sync_DA;
sample_req <= 1'b0; wire dac_done_stretched;
sample_req_sync2 <= 1'b0;
sample_req_sync3 <= 1'b0; wire generator_done, generator_request;
end wire sampler_done, sampler_request;
always_ff @(posedge clk_generator or posedge dac_rst)
begin
if (dac_rst)
stretch <= 0;
else begin else begin
sample_req_sync2 <= sample_req_sync1; stretch[0] <= generator_done;
sample_req_sync3 <= sample_req_sync2; stretch[1] <= stretch[0];
sample_req <= sample_req_sync3; stretch[2] <= stretch[1];
end end
end end
assign dac_done_stretched = |stretch;
//------------------------------------------------------------ always_ff @(posedge clk_sampler or posedge adc_rst) begin
if (adc_rst)
sync_DA <= 0;
else begin
sync_DA[0] <= dac_done_stretched;
sync_DA[1] <= sync_DA[0];
end
end
assign sampler_request = sync_DA[1];
//------------------------------------------------------------
// ADC -> DAC CDC // ADC -> DAC CDC
//------------------------------------------------------------ //------------------------------------------------------------
always_ff @(posedge dac_clk or posedge dac_rst) begin logic [1:0] sync_AD;
if (dac_rst) begin
sample_done <= 1'b0; always_ff @(posedge clk_generator or posedge dac_rst) begin
sample_done_sync2 <= 1'b0; if (dac_rst)
sample_done_sync3 <= 1'b0; sync_AD <= 0;
end
else begin else begin
sample_done_sync2 <= sample_done_sync1; sync_AD[0] <= sampler_done;
sample_done_sync3 <= sample_done_sync2; sync_AD[1] <= sync_AD[0];
sample_done <= sample_done_sync3;
end end
end end
assign generator_request = sync_AD[1];
//------------------------------------------------------------
// Generator
//------------------------------------------------------------ //------------------------------------------------------------
// Generator (DAC)
//------------------------------------------------------------
generator #( generator #(
.DATA_WIDTH(DAC_DATA_WIDTH), .DATA_WIDTH(DAC_DATA_WIDTH),
.ZERO_LEVEL(ZERO_LEVEL) .ZERO_LEVEL(ZERO_LEVEL)
) generator_inst ( ) generator_inst (
.clk_in(dac_clk), .clk_dac(clk_generator),
.rst(dac_rst), .rst(dac_rst),
.start(dac_start), .start(dac_start),
.pulse_width(dac_pulse_width), .pulse_width(dac_pulse_width),
.pulse_period(dac_pulse_period), .pulse_period(dac_pulse_period),
.pulse_height(dac_pulse_height), .pulse_height(dac_pulse_height),
.pulse_num(dac_pulse_num), .pulse_num(dac_pulse_num),
.pulse(p2_wrt), .dac_out(dac_data),
.pulse_height_out(p2_data), .done(generator_done),
.sample_done(sample_done), .request(generator_request)
.sample_req(sample_req_sync1)
); );
assign dac_wrt = dac_clk_o;
wire ch2_clk_oddr;
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"),
.INIT(1'b0),
.SRTYPE("SYNC")
) ODDR_ch2_clk (
.Q (ch2_clk_oddr),
.C (adc_clk),
.CE(1'b1),
.D1(1'b1),
.D2(1'b0),
.R (1'b0),
.S (1'b0)
);
OBUF OBUF_ch2_clk (
.I(ch2_clk_oddr),
.O(ch2_clk)
);
wire p2_clk_oddr;
ODDR #(
.DDR_CLK_EDGE("SAME_EDGE"),
.INIT(1'b0),
.SRTYPE("SYNC")
) ODDR_p2_clk (
.Q (p2_clk_oddr),
.C (dac_clk),
.CE(1'b1),
.D1(1'b1),
.D2(1'b0),
.R (1'b0),
.S (1'b0)
);
OBUF OBUF_p2_clk (
.I(p2_clk_oddr),
.O(p2_clk)
);
// -------------------------------------------------------------------------
// ADC
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Sampler (ADC)
// -------------------------------------------------------------------------
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] sampler_m_axis_tdata;
wire sampler_m_axis_tvalid;
(* MARK_DEBUG="true" *) logic [ADC_DATA_WIDTH*PACK_FACTOR-1:0] accum_m_axis_tdata; sampler #(
(* MARK_DEBUG="true" *) logic acum_m_axis_tvalid;
sampler
#(
.DATA_WIDTH(ADC_DATA_WIDTH), .DATA_WIDTH(ADC_DATA_WIDTH),
.PACK_FACTOR(PACK_FACTOR), .PACK_FACTOR(PACK_FACTOR),
.PROCESS_MODE(PROCESS_MODE) .PROCESS_MODE(PROCESS_MODE)
@ -268,50 +213,37 @@ module reflectometer_top #(
.m_axis_tdata(sampler_m_axis_tdata), .m_axis_tdata(sampler_m_axis_tdata),
.m_axis_tvalid(sampler_m_axis_tvalid), .m_axis_tvalid(sampler_m_axis_tvalid),
.smp_num(adc_pulse_period), .smp_num(adc_pulse_period),
.sample_req(sample_req), .done(sampler_done),
.sample_done(sample_done_sync1) .request(sampler_request)
); );
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Accumulator // Accumulator
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
accumulator_top #(
accumulator_top
#(
.DATA_WIDTH(ADC_DATA_WIDTH), .DATA_WIDTH(ADC_DATA_WIDTH),
.ACCUM_WIDTH(ACCUM_WIDTH), .ACCUM_WIDTH(ACCUM_WIDTH),
.N_MAX(N_MAX), .N_MAX(N_MAX),
.WINDOW_SIZE(WINDOW_SIZE), .WINDOW_SIZE(WINDOW_SIZE),
.PACKET_SIZE(PACKET_SIZE) .PACKET_SIZE(PACKET_SIZE)
) ) accumulator_top_dut (
accumulator_top_dut .clk_in(clk_sampler),
(
.clk_in(adc_clk),
.rst(adc_rst), .rst(adc_rst),
.s_axis_tdata(accum_m_axis_tdata), .s_axis_tdata(sampler_m_axis_tdata),
.s_axis_tvalid(acum_m_axis_tvalid), .s_axis_tvalid(sampler_m_axis_tvalid),
.start(adc_start), .start(adc_start),
.smp_num(adc_pulse_period), .smp_num(adc_pulse_period),
.seq_num(adc_pulse_num), .seq_num(adc_pulse_num),
.eth_clk_in(gmii_tx_clk), .req_ready(request_ready),
.req_ready(req_ready), .send_req(send_request),
.send_req(send_req), .eth_clk_in(clk_m_axis),
.m_axis_tdata(s_axis_tx_tdata), .m_axis_tdata(m_axis_tdata),
.m_axis_tvalid(s_axis_tx_tvalid), .m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(s_axis_tx_tready), .m_axis_tready(m_axis_tready),
.m_axis_tlast(s_axis_tx_tlast), .m_axis_tlast(m_axis_tlast),
.finish(finish) .finish(finish)
); );
// -------------------------------------------------------------------------
// Simple LED status
// -------------------------------------------------------------------------
assign status_led[0] = rst_n;
assign status_led[1] = clk_locked;
// assign status_led[2] = ;
// assign status_led[3] = ;
endmodule endmodule

View File

@ -1,75 +1,91 @@
`timescale 1ns / 1ps `timescale 1ns / 1ps
module tb_reflectometer; module tb_reflectometer;
//------------------------------------------------------------
// parameters // Параметры
//------------------------------------------------------------
localparam int unsigned DAC_DATA_WIDTH = 14; localparam int unsigned DAC_DATA_WIDTH = 14;
localparam int unsigned ADC_DATA_WIDTH = 12; 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 PACK_FACTOR = 1; // not used in TB
localparam PROCESS_MODE = 0; // 0 - uint, 1 - int localparam PROCESS_MODE = 0; // 0 - uint, 1 - int
localparam ZERO_LEVEL = 8192; // DAC zero voltage representation (2^14 / 2)
localparam ACCUM_WIDTH = 32; // accumulator number bit witdth localparam ACCUM_WIDTH = 32; // accumulator number bit witdth
localparam N_MAX = 4096; // max value of windows to average by experiments localparam N_MAX = 4096; // max value of windows to average by experiments
localparam WINDOW_SIZE = 65; // fixed subwindow size to average by time localparam WINDOW_SIZE = 65; // fixed subwindow size to average by time
localparam PACKET_SIZE = 1024; // bytes per UDP packet localparam PACKET_SIZE = 1024; // bytes per UDP packet
localparam int unsigned ADC_CLK_MHZ = 65; localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "true"
localparam int unsigned DAC_CLK_MHZ = 125;
// may be changed for test purposes localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz
localparam int unsigned PULSE_WIDTH = 2**6; localparam CLK_REF_PERIOD = 5.000; // 200 MHz
localparam int unsigned PULSE_PERIOD = 2**8;
localparam int unsigned PULSE_NUM = 10;
localparam int unsigned PULSE_HEIGHT = 2**12;
localparam int unsigned PULSE_PERIOD_ADC = (int'(real'(ADC_CLK_MHZ) / real'(DAC_CLK_MHZ) * real'(PULSE_PERIOD)) / int'(WINDOW_SIZE)) * int'(WINDOW_SIZE);
initial begin //------------------------------------------------------------
if (PULSE_WIDTH <= 0) // Тактовые сигналы и сброс
$fatal(1, "PULSE_WIDTH should be positive"); //------------------------------------------------------------
if (PULSE_PERIOD <= 0) logic clk_ref = 1'b0; // 200 MHz
$fatal(1, "PULSE_PERIOD should be positive"); logic clk_eth_phy = 1'b0; // common for RX & TX
if (PULSE_NUM <= 0) logic rst_n = 1'b0;
$fatal(1, "PULSE_NUM should be positive"); //------------------------------------------------------------
if (PULSE_HEIGHT <= 0) // Управление и конфиг
$fatal(1, "PULSE_HEIGHT should be positive"); //------------------------------------------------------------
if (PULSE_WIDTH >= 2**32-1)
$fatal(1, "PULSE_WIDTH too high");
if (PULSE_PERIOD >= 2**32-1)
$fatal(1, "PULSE_PERIOD too high");
if (PULSE_NUM >= 2**16-1)
$fatal(1, "PULSE_NUM too high");
if (PULSE_HEIGHT >= 2**DAC_DATA_WIDTH-1)
$fatal(1, "PULSE_HEIGHT too high");
if (PULSE_PERIOD_ADC % WINDOW_SIZE == 0)
$fatal(1, "PULSE_PERIOD_ADC isn't multiple of WINDOW_SIZE");
end
// DUT signals //------------------------------------------------------------
logic clk200, clk_eth_phy_tx, clk_eth_phy_rx; // GMII clocks // Входы
logic rst_n; //------------------------------------------------------------
wire [3:0] status_leds; // [ None, dac_start, m_axis_valid, clk_wiz_locked ]
wire dac_clk, dac_en; //------------------------------------------------------------
wire [DAC_DATA_WIDTH-1:0] dac_data; // Выходы
wire adc_clk; //------------------------------------------------------------
logic adc_otr; wire mmcm_locked;
logic [ADC_DATA_WIDTH-1:0] adc_data; //------------------------------------------------------------
// Внутренние сигналы тестбенча
//------------------------------------------------------------
// 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;
// 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;
// DAC интерфейс
wire clk_dac;
wire dac_wrt;
wire [DAC_DATA_WIDTH-1:0] dac_data;
// ADC интерфейс
wire clk_adc;
logic adc_otr = 1'b0;
logic [ADC_DATA_WIDTH-1:0] adc_data = '0;
// Интерфейс хендшейка с MAC-PHY
wire send_request;
logic request_ready = 1'b0;
wire [7:0] s_axis_tx_tdata; //------------------------------------------------------------
wire s_axis_tx_tvalid; // Virtual DAC
logic s_axis_tx_tready; //------------------------------------------------------------
wire s_axis_tx_tlast;
logic phy_ready; //------------------------------------------------------------
wire accum_tx_start; // Virtual ADC
logic [7:0] m_axis_rx_tdata; //------------------------------------------------------------
logic m_axis_rx_tvalid;
logic m_axis_rx_tlast;
logic m_axis_rx_tready;
logic [127:0] dut_config = 0; //------------------------------------------------------------
// Virtual conductor
//------------------------------------------------------------
//------------------------------------------------------------
// Statistics monitor
//------------------------------------------------------------
//------------------------------------------------------------
// Config handler
//------------------------------------------------------------
//------------------------------------------------------------
// DUT // DUT
//------------------------------------------------------------
reflectometer_top #( reflectometer_top #(
.DAC_DATA_WIDTH(DAC_DATA_WIDTH), .DAC_DATA_WIDTH(DAC_DATA_WIDTH),
.ADC_DATA_WIDTH(ADC_DATA_WIDTH), .ADC_DATA_WIDTH(ADC_DATA_WIDTH),
@ -81,105 +97,96 @@ module tb_reflectometer;
.WINDOW_SIZE(WINDOW_SIZE), .WINDOW_SIZE(WINDOW_SIZE),
.PACKET_SIZE(PACKET_SIZE) .PACKET_SIZE(PACKET_SIZE)
) DUT ( ) DUT (
.sys_clk(clk200), // main clk 200 mhz .clk_in(clk_ref),
.rst_n(rst_n), // rst_n .rst_n(rst_n),
.led(status_leds), // indication [3:0] .locked(mmcm_locked),
.gmii_rx_clk(clk_eth_phy_rx), // ext. clk from PHY
.gmii_tx_clk(clk_eth_phy_tx), // ext. clk from PHY
// accumulated data stream
.s_axis_tx_tdata(s_axis_tx_tdata),
.s_axis_tx_tvalid(s_axis_tx_tvalid),
.s_axis_tx_tready(s_axis_tx_tready),
.s_axis_tx_tlast(s_axis_tx_tlast),
// controller data stream
.m_axis_rx_tdata(m_axis_rx_tdata),
.m_axis_rx_tvalid(m_axis_rx_tvalid),
.m_axis_rx_tlast(m_axis_rx_tlast),
.m_axis_rx_tready(m_axis_rx_tready),
.req_ready(phy_ready), // AXI-stream requester ready // Accumulator AXI-S bus
.send_req(accum_tx_start), // AXI-stream start transmit .clk_m_axis(clk_eth_phy), // GMII PHY RX clock
.p2_clk(dac_clk), // DAC clk .m_axis_tdata(s_axis_accumulator_tdata),
.p2_data(dac_data), // DAC [DAC_DATA_WIDTH-1:0] data .m_axis_tvalid(s_axis_accumulator_tvalid),
.p2_wrt(dac_en), // DAC write enable .m_axis_tready(s_axis_accumulator_tready),
.ch2_clk(adc_clk), // ADC clk .m_axis_tlast(s_axis_accumulator_tlast),
.ch2_data(adc_data), // ADC [ADC_DATA_WIDTH-1:0] data
.ch2_otr(adc_otr) // ADC signal out-of-range // 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),
// 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)
); );
//------------------------------------------------------------
// clocks // Тактовые сигналы
//------------------------------------------------------------
initial begin initial begin
// 200 MHz forever #(CLK_REF_PERIOD/2) clk_ref = ~clk_ref;
clk200 = 1'b0;
forever #2.5 clk200 = ~clk200;
end end
initial begin initial begin
// 125 MHz forever #(CLK_ETH_PHY_PERIOD/2) clk_eth_phy = ~clk_eth_phy;
clk_eth_phy_tx = 1'b0;
forever #4 clk_eth_phy_tx = ~clk_eth_phy_tx;
end
initial begin
// 125 MHz
clk_eth_phy_rx = 1'b0;
forever #4 clk_eth_phy_rx = ~clk_eth_phy_rx;
end end
//------------------------------------------------------------
// Таски для тестирования
//------------------------------------------------------------
// ADC input noise simulation // task automatic axis_send_byte(
always @(posedge adc_clk or negedge rst_n) begin // ref logic clk,
if (!rst_n) begin // input logic [7:0] data,
adc_data <= '0; // input logic last,
end else begin // ref logic tvalid,
adc_data <= $urandom() & ((1 << ADC_DATA_WIDTH) - 1); // ref logic [7:0] tdata,
end // ref logic tlast,
end // input logic tready
assign adc_otr = 1'b0; // );
// @(posedge clk);
// tdata <= data;
// tlast <= last;
// tvalid <= 1'b1;
// AXIS tasks // // Ждем готовности приемника
task automatic axis_send_byte( // wait(tready === 1'b1);
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;
// Ждем готовности приемника // @(posedge clk);
wait(tready === 1'b1); // tvalid <= 1'b0;
// tlast <= 1'b0;
// endtask
@(posedge clk); // task automatic dut_soft_reset();
tvalid <= 1'b0; // axis_send_byte(
tlast <= 1'b0; // .clk(clk_eth_phy_rx),
endtask // .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_soft_reset(); // task automatic dut_start();
axis_send_byte( // axis_send_byte(
.clk(clk_eth_phy_rx), // .clk(clk_eth_phy_rx),
.data(8'b00001111), // .data(8'b11110000),
.last(1'b1), // .last(1'b1),
.tvalid(m_axis_rx_tvalid), // .tvalid(m_axis_rx_tvalid),
.tdata(m_axis_rx_tdata), // .tdata(m_axis_rx_tdata),
.tlast(m_axis_rx_tlast), // .tlast(m_axis_rx_tlast),
.tready(m_axis_rx_tready) // .tready(m_axis_rx_tready)
); // );
endtask // endtask
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
// task automatic dut_send_config( // task automatic dut_send_config(
// input logic [127:0] ctrl_config // input logic [127:0] ctrl_config
@ -217,51 +224,16 @@ module tb_reflectometer;
// endtask // endtask
//------------------------------------------------------------
// some helpers for controller axis // ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
//------------------------------------------------------------
// GAME PLAN
// 1. setup reflectometer
// 2. create some reference signal with noise + virtual ADC
// 3. setup m_axis endpoint for controller to start reflectometer (create multiple tasks)
// 4. setup s_axis endpoint for data gathering and plotting
// 5. check standalone reflectometer
// 6. add reference signal averaging loop throw generator pulse posedge detection
// 7. visual comparision of reference VS reflectometer
// 8. add statistics for signal comparision (MSE/RMSE)
// main TB
initial begin initial begin
// setup $display("[TB] Tests start");
rst_n = 1'b0;
s_axis_tx_tready = 1'b0;
m_axis_rx_tdata = 1'b0;
m_axis_rx_tvalid = 1'b0;
m_axis_rx_tlast = 1'b0;
phy_ready = 1'b0;
// startup wait(mmcm_locked === 1'b1);
#100; #10000;
rst_n = 1'b1;
wait(DUT.clk_wiz_ctrl_inst.locked == 1'b1);
#20;
$display("=== clocks ready / wiz. locked ===");
#40;
// ready to work
dut_config[31:0] = PULSE_WIDTH; $display("[TB] ALL PASSED");
dut_config[63:32] = PULSE_PERIOD;
dut_config[79:64] = PULSE_NUM;
dut_config[79+DAC_DATA_WIDTH:80] = PULSE_HEIGHT;
dut_config[127:96] = PULSE_PERIOD_ADC;
// dut_send_config(dut_config);
dut_start();
// dut_start();
#1000;
// dut_soft_reset();
$display("=== ALL BASIC TESTS PASSED ===");
$finish; $finish;
end end
endmodule endmodule