Compare commits
44
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd4b17be0d | ||
|
|
806bab9520 | ||
|
|
95540713e0 | ||
|
|
ee83bcbb9e | ||
|
|
8648747380 | ||
|
|
e06ef3a16b | ||
|
|
c121c2c103 | ||
|
|
56c33d2769 | ||
|
|
fc33aa6862 | ||
|
|
490d3dcfd0 | ||
|
|
1c2eccaf1d | ||
|
|
076ad542b2 | ||
|
|
e685a6a9fc | ||
|
|
c057890007 | ||
|
|
42df57be7d | ||
|
|
606d1d7f1c | ||
|
|
8aefa4f3f6 | ||
|
|
7cf727883f | ||
|
|
cec4c84fd9 | ||
|
|
691e69693a | ||
|
|
e467700368 | ||
|
|
984461afc0 | ||
|
|
6c171c55d7 | ||
|
|
c1031f6a26 | ||
|
|
d0f48ba513 | ||
|
|
19bade1c8c | ||
|
|
0866b5da8d | ||
|
|
126b66e4f5 | ||
|
|
1ba94690d5 | ||
|
|
c0a2f0e403 | ||
|
|
7bd1aa68da | ||
|
|
061f8fe12b | ||
|
|
99a344d534 | ||
|
|
e7c45101d1 | ||
|
|
fc3134f2d8 | ||
|
|
a82140feda | ||
|
|
bafd084f0d | ||
|
|
d71655885c | ||
|
|
56e31a6cc6 | ||
|
|
14a1df8bae | ||
|
|
a6ade44b4d | ||
|
|
14f4a5eb2a | ||
|
|
1eb21b5087 | ||
|
|
9285ce42e1 |
+1
-6
@@ -16,7 +16,6 @@
|
|||||||
.Xil
|
.Xil
|
||||||
xvlog.pb
|
xvlog.pb
|
||||||
*vivado_pid*
|
*vivado_pid*
|
||||||
**/work/*
|
|
||||||
|
|
||||||
# some generated files (they annoy me)
|
# some generated files (they annoy me)
|
||||||
update_config.tcl
|
update_config.tcl
|
||||||
@@ -27,8 +26,4 @@ run_sim.tcl
|
|||||||
*.bit
|
*.bit
|
||||||
*.xsa
|
*.xsa
|
||||||
*.ltx
|
*.ltx
|
||||||
*.bin
|
*.bin
|
||||||
|
|
||||||
# slang files
|
|
||||||
.slang
|
|
||||||
files.f
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "external/rtl_libs"]
|
||||||
|
path = external/rtl_libs
|
||||||
|
url = https://git.radiophotonics.ru/baulin.fa/rtl_libs.git
|
||||||
@@ -27,7 +27,6 @@ XDC_FILES += ../../constraints/ax7102.xdc
|
|||||||
XDC_FILES += debug.xdc
|
XDC_FILES += debug.xdc
|
||||||
|
|
||||||
SYN_FILES += tb_sync_top.sv
|
SYN_FILES += tb_sync_top.sv
|
||||||
|
|
||||||
SIM_TOP = tb_top
|
SIM_TOP = tb_top
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
# Primary clocks
|
# Primary clocks
|
||||||
create_clock -name geneartor_clk -period 8.000 [get_ports clk_dac]
|
create_clock -name eth_clk -period 8.000 [get_ports dac_clk_in]
|
||||||
create_clock -name sampler_clk -period 15.385 [get_ports clk_adc]
|
create_clock -name acc_clk -period 15.385 [get_ports adc_clk_in]
|
||||||
set_clock_groups -asynchronous -group [get_clocks geneartor_clk] -group [get_clocks sampler_clk]
|
|
||||||
|
|
||||||
# set_false_path -through [get_nets -hierarchical {*dac_signal* *internal_wire_singnal* *adc_singnal*}]
|
|
||||||
# set_false_path -through [get_nets {dac_done dac_done_stretched dac_request adc_done adc_request}]
|
|
||||||
|
|
||||||
set_property DONT_TOUCH true [get_cells -hierarchical -filter {NAME =~ *generator_inst*pulse_height_reg*}]
|
# Asynchronous clock groups
|
||||||
set_property DONT_TOUCH true [get_cells -hierarchical -filter {NAME =~ *generator_inst*dac_out_reg*}]
|
|
||||||
# Применяем к самому проводу сигнала CE, чтобы Vivado не дробила его
|
set_clock_groups -name ASYNC_ETH_ACC -asynchronous \
|
||||||
# set_property DONT_TOUCH true [get_nets -of_objects [get_pins -hierarchical -filter {PIN_NAME =~ *CE} -of_objects [get_cells *pulse_height_reg*]]]
|
-group [get_clocks eth_clk] \
|
||||||
|
-group [get_clocks acc_clk]
|
||||||
@@ -2,137 +2,113 @@
|
|||||||
|
|
||||||
module sync_top
|
module sync_top
|
||||||
#(
|
#(
|
||||||
parameter int unsigned DAC_DATA_WIDTH = 14, // DAC bit-width
|
parameter int unsigned DAC_DATA_WIDTH = 14,
|
||||||
parameter int unsigned ADC_DATA_WIDTH = 12, // ADC bit-width
|
parameter int unsigned ADC_DATA_WIDTH = 12,
|
||||||
parameter int unsigned PACK_FACTOR = 1, // number of ADC readings per transaction
|
parameter int unsigned PACK_FACTOR = 1,
|
||||||
parameter int unsigned PROCESS_MODE = 0, // representation format of ADC readings (0 - direct code, 1 - 2's completment)
|
parameter int unsigned PROCESS_MODE = 0
|
||||||
parameter int unsigned ZERO_LEVEL = 0,
|
|
||||||
parameter int unsigned USE_DELAY_LINE = 0
|
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input clk_adc,
|
input adc_clk_in,
|
||||||
input rst_adc,
|
input adc_rst,
|
||||||
input clk_dac,
|
|
||||||
input rst_dac,
|
input dac_clk_in,
|
||||||
input start,
|
input dac_rst,
|
||||||
input out_of_range,
|
|
||||||
|
input dac_start,
|
||||||
|
|
||||||
input [31:0] pulse_width,
|
input [31:0] pulse_width,
|
||||||
input [31:0] pulse_period, // DAC counter limit
|
input [31:0] pulse_period,
|
||||||
input [DAC_DATA_WIDTH-1:0] pulse_height,
|
input [DAC_DATA_WIDTH-1:0] pulse_height,
|
||||||
input [15:0] pulse_num,
|
input [15:0] pulse_num,
|
||||||
input [31:0] smp_num, // ADC counter limit
|
input [31:0] smp_num,
|
||||||
output [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
|
||||||
output m_axis_tvalid
|
output logic [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||||
|
output logic m_axis_tvalid
|
||||||
);
|
);
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Internal signals
|
// Internal signals
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
wire dac_done, dac_request, adc_done, adc_request;
|
|
||||||
wire [DAC_DATA_WIDTH-1:0] dac_signal;
|
|
||||||
wire [ADC_DATA_WIDTH-1:0] internal_wire_signal;
|
|
||||||
wire [ADC_DATA_WIDTH-1:0] adc_signal;
|
|
||||||
|
|
||||||
// 1. Адаптация разрядности и «заземление» лишних бит
|
(* MARK_DEBUG="true" *) logic sample_req;
|
||||||
generate
|
(* MARK_DEBUG="true" *) logic sample_req_sync1;
|
||||||
if (ADC_DATA_WIDTH > DAC_DATA_WIDTH) begin : g_pad_zeros
|
(* MARK_DEBUG="true" *) logic sample_req_sync2;
|
||||||
// АЦП шире ЦАП: добиваем нулями старшие биты
|
(* MARK_DEBUG="true" *) logic sample_req_sync3;
|
||||||
assign internal_wire_signal = { {(ADC_DATA_WIDTH - DAC_DATA_WIDTH){1'b0}}, dac_signal };
|
|
||||||
end
|
|
||||||
else if (ADC_DATA_WIDTH < DAC_DATA_WIDTH) begin : g_truncate
|
|
||||||
// ЦАП шире АЦП (например, 14 -> 12): забираем младшие биты
|
|
||||||
assign internal_wire_signal = dac_signal[DAC_DATA_WIDTH-1:DAC_DATA_WIDTH-ADC_DATA_WIDTH];
|
|
||||||
// (* mark_debug = "true" *) wire dummy;
|
|
||||||
// assign dummy = ^dac_signal;
|
|
||||||
end
|
|
||||||
else begin : g_match
|
|
||||||
// Разрядности равны
|
|
||||||
assign internal_wire_signal = dac_signal;
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
generate
|
(* MARK_DEBUG="true" *) logic sample_done;
|
||||||
if (USE_DELAY_LINE > 0) begin : g_delay_line
|
(* MARK_DEBUG="true" *) logic sample_done_sync1;
|
||||||
localparam int DELAY_LENGTH = USE_DELAY_LINE;
|
(* MARK_DEBUG="true" *) logic sample_done_sync2;
|
||||||
// Двумерный массив для линии задержки
|
(* MARK_DEBUG="true" *) logic sample_done_sync3;
|
||||||
logic [DELAY_LENGTH-1:0][ADC_DATA_WIDTH-1:0] signal_delay_line;
|
|
||||||
|
(* MARK_DEBUG="true" *) logic pulse;
|
||||||
always_ff @(posedge clk_dac) begin
|
(* MARK_DEBUG="true" *) logic [DAC_DATA_WIDTH-1:0] pulse_height_out;
|
||||||
signal_delay_line[0] <= internal_wire_signal;
|
|
||||||
for (int i = 0; i < DELAY_LENGTH-1; i++) begin
|
//------------------------------------------------------------
|
||||||
signal_delay_line[i+1] <= signal_delay_line[i];
|
// Simple DAC -> ADC test source
|
||||||
end
|
//
|
||||||
end
|
// generator output is directly connected to sampler input
|
||||||
|
// with width truncation:
|
||||||
// ИСПРАВЛЕНО: читаем из последнего элемента массива
|
//
|
||||||
assign adc_signal = signal_delay_line[DELAY_LENGTH-1];
|
// pulse_height_out[13:0] -> data_in[11:0]
|
||||||
end
|
//------------------------------------------------------------
|
||||||
else begin : g_no_delay
|
(* MARK_DEBUG="true" *) logic [ADC_DATA_WIDTH-1:0] data_in;
|
||||||
assign adc_signal = internal_wire_signal;
|
(* MARK_DEBUG="true" *) logic out_of_range;
|
||||||
end
|
|
||||||
endgenerate
|
assign data_in = pulse_height_out[ADC_DATA_WIDTH-1:0];
|
||||||
|
assign out_of_range = 1'b0;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// DAC -> ADC CDC
|
// DAC -> ADC CDC
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
always_ff @(posedge adc_clk_in or posedge adc_rst) begin
|
||||||
logic [1:0] sync_DA;
|
if (adc_rst) begin
|
||||||
wire dac_done_stretched;
|
sample_req <= 1'b0;
|
||||||
|
sample_req_sync2 <= 1'b0;
|
||||||
always_ff @(posedge clk_dac or posedge rst_dac)
|
sample_req_sync3 <= 1'b0;
|
||||||
begin
|
end
|
||||||
if (rst_dac)
|
|
||||||
stretch <= 0;
|
|
||||||
else begin
|
else begin
|
||||||
stretch[0] <= dac_done;
|
sample_req_sync2 <= sample_req_sync1;
|
||||||
stretch[1] <= stretch[0];
|
sample_req_sync3 <= sample_req_sync2;
|
||||||
stretch[2] <= stretch[1];
|
sample_req <= sample_req_sync3;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assign dac_done_stretched = |stretch;
|
|
||||||
|
|
||||||
always_ff @(posedge clk_adc or posedge rst_adc) begin
|
|
||||||
if (rst_adc)
|
|
||||||
sync_DA <= 0;
|
|
||||||
else begin
|
|
||||||
sync_DA[0] <= dac_done_stretched;
|
|
||||||
sync_DA[1] <= sync_DA[0];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
assign adc_request = sync_DA[1];
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// ADC -> DAC CDC
|
// ADC -> DAC CDC
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic [1:0] sync_AD;
|
always_ff @(posedge dac_clk_in or posedge dac_rst) begin
|
||||||
|
if (dac_rst) begin
|
||||||
always_ff @(posedge clk_dac or posedge rst_dac) begin
|
sample_done <= 1'b0;
|
||||||
if (rst_dac)
|
sample_done_sync2 <= 1'b0;
|
||||||
sync_AD <= 0;
|
sample_done_sync3 <= 1'b0;
|
||||||
|
end
|
||||||
else begin
|
else begin
|
||||||
sync_AD[0] <= adc_done;
|
sample_done_sync2 <= sample_done_sync1;
|
||||||
sync_AD[1] <= sync_AD[0];
|
sample_done_sync3 <= sample_done_sync2;
|
||||||
|
sample_done <= sample_done_sync3;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assign dac_request = sync_AD[1];
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Generator
|
// Generator
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
generator #(
|
generator #(
|
||||||
.DATA_WIDTH(DAC_DATA_WIDTH),
|
.DATA_WIDTH(DAC_DATA_WIDTH)
|
||||||
.ZERO_LEVEL(ZERO_LEVEL)
|
|
||||||
) generator_inst (
|
) generator_inst (
|
||||||
.clk_dac(clk_dac),
|
.clk_in(dac_clk_in),
|
||||||
.rst(rst_dac),
|
.rst(dac_rst),
|
||||||
.start(start),
|
.start(dac_start),
|
||||||
|
|
||||||
.pulse_width(pulse_width),
|
.pulse_width(pulse_width),
|
||||||
.pulse_period(pulse_period),
|
.pulse_period(pulse_period),
|
||||||
.pulse_height(pulse_height),
|
.pulse_height(pulse_height),
|
||||||
.pulse_num(pulse_num),
|
.pulse_num(pulse_num),
|
||||||
.dac_out(dac_signal),
|
|
||||||
.request(dac_request),
|
.sample_done(sample_done),
|
||||||
.done(dac_done)
|
|
||||||
|
.pulse(pulse),
|
||||||
|
.pulse_height_out(pulse_height_out),
|
||||||
|
.sample_req(sample_req_sync1)
|
||||||
);
|
);
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
@@ -143,15 +119,18 @@ module sync_top
|
|||||||
.PACK_FACTOR(PACK_FACTOR),
|
.PACK_FACTOR(PACK_FACTOR),
|
||||||
.PROCESS_MODE(PROCESS_MODE)
|
.PROCESS_MODE(PROCESS_MODE)
|
||||||
) sampler_inst (
|
) sampler_inst (
|
||||||
.clk_in(clk_adc),
|
.clk_in(adc_clk_in),
|
||||||
.rst(rst_adc),
|
.rst(adc_rst),
|
||||||
.data_in(adc_signal),
|
|
||||||
|
.data_in(data_in),
|
||||||
.out_of_range(out_of_range),
|
.out_of_range(out_of_range),
|
||||||
|
|
||||||
.smp_num(smp_num),
|
.smp_num(smp_num),
|
||||||
|
.sample_req(sample_req),
|
||||||
|
|
||||||
.m_axis_tdata(m_axis_tdata),
|
.m_axis_tdata(m_axis_tdata),
|
||||||
.m_axis_tvalid(m_axis_tvalid),
|
.m_axis_tvalid(m_axis_tvalid),
|
||||||
.request(adc_request),
|
.sample_done(sample_done_sync1)
|
||||||
.done(adc_done)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
@@ -2,50 +2,39 @@
|
|||||||
|
|
||||||
module tb_top;
|
module tb_top;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
localparam DAC_DATA_WIDTH = 14;
|
||||||
// Параметры
|
localparam ADC_DATA_WIDTH = 12;
|
||||||
//------------------------------------------------------------
|
localparam PACK_FACTOR = 1;
|
||||||
parameter string ZERO_LEVEL_PARAM = "logic"; // "logic" VS "true"
|
localparam PROCESS_MODE = 0;
|
||||||
parameter VERBOSE = 1;
|
|
||||||
|
|
||||||
localparam DAC_DATA_WIDTH = 14;
|
|
||||||
localparam ADC_DATA_WIDTH = 12;
|
|
||||||
localparam PACK_FACTOR = 1;
|
|
||||||
localparam PROCESS_MODE = 0;
|
|
||||||
localparam CLK_DAC_PERIOD = 8;
|
|
||||||
localparam CLK_ADC_PERIOD = 15.385;
|
|
||||||
localparam USE_DELAY_LINE = 0;
|
|
||||||
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 ZERO_LEVEL = (ZERO_LEVEL_PARAM == "logic") ? LOGIC_ZERO_LEVEL : VOLTAGE_ZERO_LEVEL;
|
|
||||||
|
|
||||||
localparam CLOCK_DEVIATION = 3; // Maximum clock deviation of pulse stats
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Тактовые сигналы и сброс
|
// clocks / reset
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic clk_dac;
|
logic adc_clk_in;
|
||||||
logic rst_dac;
|
logic adc_rst;
|
||||||
logic clk_adc;
|
|
||||||
logic rst_adc;
|
logic dac_clk_in;
|
||||||
|
logic dac_rst;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Управление и конфиг
|
// control
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic dac_start;
|
logic dac_start;
|
||||||
logic [31:0] pulse_width;
|
|
||||||
logic [31:0] pulse_period;
|
logic [31:0] pulse_width;
|
||||||
logic [DAC_DATA_WIDTH-1:0] pulse_height;
|
logic [31:0] pulse_period;
|
||||||
logic [15:0] pulse_num;
|
logic [DAC_DATA_WIDTH-1:0] pulse_height;
|
||||||
logic [31:0] smp_num;
|
logic [15:0] pulse_num;
|
||||||
|
logic [31:0] smp_num;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Входы
|
// outputs
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
reg out_of_range;
|
logic [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
||||||
//------------------------------------------------------------
|
logic m_axis_tvalid;
|
||||||
// Выходы
|
|
||||||
//------------------------------------------------------------
|
integer valid_count;
|
||||||
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
|
||||||
wire m_axis_tvalid;
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// DUT
|
// DUT
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
@@ -53,521 +42,127 @@ module tb_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),
|
||||||
.PACK_FACTOR(PACK_FACTOR),
|
.PACK_FACTOR(PACK_FACTOR),
|
||||||
.PROCESS_MODE(PROCESS_MODE),
|
.PROCESS_MODE(PROCESS_MODE)
|
||||||
.ZERO_LEVEL(ZERO_LEVEL),
|
|
||||||
.USE_DELAY_LINE(USE_DELAY_LINE)
|
|
||||||
) dut (
|
) dut (
|
||||||
.clk_adc(clk_adc),
|
.adc_clk_in(adc_clk_in),
|
||||||
.clk_dac(clk_dac),
|
.adc_rst(adc_rst),
|
||||||
.rst_adc(rst_adc),
|
|
||||||
.rst_dac(rst_dac),
|
.dac_clk_in(dac_clk_in),
|
||||||
.start(dac_start),
|
.dac_rst(dac_rst),
|
||||||
|
|
||||||
|
.dac_start(dac_start),
|
||||||
|
|
||||||
.pulse_width(pulse_width),
|
.pulse_width(pulse_width),
|
||||||
.pulse_period(pulse_period),
|
.pulse_period(pulse_period),
|
||||||
.pulse_height(pulse_height),
|
.pulse_height(pulse_height),
|
||||||
.pulse_num(pulse_num),
|
.pulse_num(pulse_num),
|
||||||
.smp_num(smp_num),
|
.smp_num(smp_num),
|
||||||
|
|
||||||
.m_axis_tdata(m_axis_tdata),
|
.m_axis_tdata(m_axis_tdata),
|
||||||
.m_axis_tvalid(m_axis_tvalid),
|
.m_axis_tvalid(m_axis_tvalid)
|
||||||
.out_of_range(out_of_range)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Тактовые сигналы
|
//------------------------------------------------------------
|
||||||
|
// ADC clock
|
||||||
|
//------------------------------------------------------------
|
||||||
initial begin
|
initial begin
|
||||||
clk_adc = 0;
|
adc_clk_in = 1'b0;
|
||||||
forever #(CLK_ADC_PERIOD/2) clk_adc = ~clk_adc;
|
forever #5 adc_clk_in = ~adc_clk_in; // 100 MHz
|
||||||
end
|
|
||||||
initial begin
|
|
||||||
clk_dac = 0;
|
|
||||||
forever #(CLK_DAC_PERIOD/2) clk_dac = ~clk_dac;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
// === Таски для тестирования ===
|
//------------------------------------------------------------
|
||||||
// Функция модуля
|
// DAC clock
|
||||||
function automatic real fabs(real val);
|
//------------------------------------------------------------
|
||||||
return (val < 0.0) ? -val : val;
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
`define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
|
||||||
|
|
||||||
// Таска сброса DAC DUT
|
|
||||||
task automatic reset_dut_dac(
|
|
||||||
input int rst_duration // сколько тактов держать сброс
|
|
||||||
);
|
|
||||||
@(negedge clk_dac);
|
|
||||||
rst_dac <= 1;
|
|
||||||
repeat(rst_duration) @(negedge clk_dac);
|
|
||||||
rst_dac <= 0;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска сброса ADC DUT
|
|
||||||
task automatic reset_dut_adc(
|
|
||||||
input int rst_duration // сколько тактов держать сброс
|
|
||||||
);
|
|
||||||
@(negedge clk_adc);
|
|
||||||
rst_adc <= 1;
|
|
||||||
repeat(rst_duration) @(negedge clk_adc);
|
|
||||||
rst_adc <= 0;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска запуска DUT
|
|
||||||
task automatic start_dut(
|
|
||||||
input int start_duration // сколько тактов держать импульс
|
|
||||||
);
|
|
||||||
@(negedge clk_dac); // to make signal stable
|
|
||||||
dac_start <= 1;
|
|
||||||
repeat(start_duration) @(negedge clk_dac);
|
|
||||||
dac_start <= 0;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска конфигурации DUT
|
|
||||||
task automatic set_config(
|
|
||||||
input logic [31:0] w, // ширина импульса
|
|
||||||
input logic [31:0] p, // период импульса
|
|
||||||
input logic [15:0] n, // количество импульсов
|
|
||||||
input logic [DAC_DATA_WIDTH-1:0] h, // высота импульса
|
|
||||||
input logic [31:0] sn // число сэмплов
|
|
||||||
);
|
|
||||||
// Задаем конфигурационные регистры
|
|
||||||
pulse_width <= w;
|
|
||||||
pulse_period <= p;
|
|
||||||
pulse_num <= n;
|
|
||||||
pulse_height <= h;
|
|
||||||
smp_num <= sn;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Основная таска проверки DUT
|
|
||||||
task automatic run_test_case(
|
|
||||||
input int pulse_width,
|
|
||||||
input int pulse_period,
|
|
||||||
input int pulse_height,
|
|
||||||
input int pulse_num,
|
|
||||||
input int sample_num,
|
|
||||||
input bit skip_reset,
|
|
||||||
input bit randomize_start_timing,
|
|
||||||
input bit out_of_range_val,
|
|
||||||
input bit randomize_out_of_range
|
|
||||||
);
|
|
||||||
int error_flag = 0;
|
|
||||||
int start_hold_time = 1;
|
|
||||||
realtime sync_start_time, pulse_start_time, pulse_update_val_time;
|
|
||||||
realtime sync_time_stats[$], pulse_width_time_stats[$], pulse_period_time_stats[$], pulse_delay_time_stats[$];
|
|
||||||
realtime avearge_pulse_delay, average_pulse_width, average_pulse_period, average_sync_time;
|
|
||||||
|
|
||||||
out_of_range = out_of_range_val;
|
|
||||||
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Starting test case");
|
|
||||||
end
|
|
||||||
|
|
||||||
if (randomize_out_of_range)
|
|
||||||
fork
|
|
||||||
begin : randomize_out_of_range_proc
|
|
||||||
forever begin
|
|
||||||
@(posedge clk_adc);
|
|
||||||
out_of_range = $urandom_range(0, 1);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
join_none
|
|
||||||
|
|
||||||
if (!skip_reset)
|
|
||||||
fork
|
|
||||||
reset_dut_adc(1);
|
|
||||||
reset_dut_dac(1);
|
|
||||||
join
|
|
||||||
|
|
||||||
set_config(
|
|
||||||
.w(pulse_width),
|
|
||||||
.p(pulse_period),
|
|
||||||
.n(pulse_num),
|
|
||||||
.h(pulse_height),
|
|
||||||
.sn(sample_num)
|
|
||||||
);
|
|
||||||
@(posedge clk_dac);
|
|
||||||
@(posedge clk_dac);
|
|
||||||
|
|
||||||
if (randomize_start_timing)
|
|
||||||
start_hold_time = $urandom_range(1, 15);
|
|
||||||
fork // warning: check not forever
|
|
||||||
start_dut(start_hold_time);
|
|
||||||
begin
|
|
||||||
@(posedge clk_dac);
|
|
||||||
// старт первой синхронизации
|
|
||||||
sync_start_time = $realtime;
|
|
||||||
end
|
|
||||||
join_none
|
|
||||||
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Starting pulse generation");
|
|
||||||
end
|
|
||||||
|
|
||||||
for (int i = 0; i < pulse_num; i++) begin
|
|
||||||
if (VERBOSE >= 3) begin
|
|
||||||
$display("[TB] -run_test_case- Start sync for pulse #%d", i);
|
|
||||||
end
|
|
||||||
@(posedge m_axis_tvalid);
|
|
||||||
if (VERBOSE >= 3) begin
|
|
||||||
$display("[TB] -run_test_case- Found valid pulse response data positive front");
|
|
||||||
end
|
|
||||||
// Старт цикла. Завершение синхронизации
|
|
||||||
sync_time_stats.push_back($realtime - sync_start_time);
|
|
||||||
pulse_start_time = $realtime;
|
|
||||||
|
|
||||||
fork
|
|
||||||
// Поток будет запущен для ненулевых импульсов и гарантированно завершится как только зафиксирует статистику импульса
|
|
||||||
// Начало импульса
|
|
||||||
if (pulse_height != ZERO_LEVEL && pulse_width != 0) begin
|
|
||||||
if (VERBOSE >= 4) begin
|
|
||||||
$display("[TB] -run_test_case- Wait until pulse become high");
|
|
||||||
end
|
|
||||||
wait(m_axis_tdata != ZERO_LEVEL);
|
|
||||||
// Фактическое начало импульса. Поступление высокого уровня
|
|
||||||
pulse_update_val_time = $realtime;
|
|
||||||
pulse_delay_time_stats.push_back(pulse_update_val_time - pulse_start_time);
|
|
||||||
|
|
||||||
// Проверим что высота импульса совпала с заданной. Т.к. OTR != 0 влияет на выходные данные сэмплера, то не будем проверять такие случаи.
|
|
||||||
@(posedge clk_adc);
|
|
||||||
#1.5; // Ожидание завершения переходных процессов
|
|
||||||
// Будем считать что из-за OTR данные изменились (по условию OTR + MSB), проверка пропускается, т.к. сложно понять точное значение OTR в момент обработки данных от tdata
|
|
||||||
if (m_axis_tdata != (pulse_height >> 2) && (randomize_out_of_range || out_of_range_val)) begin
|
|
||||||
$display("[ERROR] -run_test_case- Wrong pulse height: %d. Must be: %d", m_axis_tdata, pulse_height >> 2);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (VERBOSE >= 4) begin
|
|
||||||
$display("[TB] -run_test_case- Wait until pulse become low");
|
|
||||||
end
|
|
||||||
wait(m_axis_tdata == ZERO_LEVEL);
|
|
||||||
pulse_width_time_stats.push_back($realtime - pulse_update_val_time);
|
|
||||||
end
|
|
||||||
// Конец импульса
|
|
||||||
join_none
|
|
||||||
|
|
||||||
@(negedge m_axis_tvalid);
|
|
||||||
if (VERBOSE >= 3) begin
|
|
||||||
$display("[TB] -run_test_case- Found valid pulse response data negative front");
|
|
||||||
end
|
|
||||||
// Завершение цикла. Старт синхронизации
|
|
||||||
pulse_period_time_stats.push_back($realtime - pulse_start_time);
|
|
||||||
sync_start_time = $realtime;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Stop pulse generation");
|
|
||||||
end
|
|
||||||
|
|
||||||
fork // Проверка с таймаутом на лишние циклы
|
|
||||||
@(posedge m_axis_tvalid);
|
|
||||||
repeat(30) @(posedge clk_adc);
|
|
||||||
join_any
|
|
||||||
if (m_axis_tvalid == 1) begin
|
|
||||||
$display("[ERROR] -run_test_case- Extra pulse cycle num. More than must be.");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Exit waiting via timeout");
|
|
||||||
end
|
|
||||||
|
|
||||||
if (randomize_out_of_range) begin
|
|
||||||
disable randomize_out_of_range_proc;
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Stop randomize_out_of_range_proc");
|
|
||||||
end
|
|
||||||
end
|
|
||||||
out_of_range = 0;
|
|
||||||
|
|
||||||
// Проверка по статистике. Подсчет средних значений
|
|
||||||
if (pulse_delay_time_stats.size() != pulse_num && pulse_height != ZERO_LEVEL && pulse_width != 0 && !(randomize_out_of_range || out_of_range_val)) begin // Detected with pulse level. Skip if pulse level undetectable
|
|
||||||
$display("[ERROR] -run_test_case- Size of pulse_delay_time_stats samples not equal to pulse_num: %d VS %d", pulse_delay_time_stats.size(), pulse_num);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
if (pulse_width_time_stats.size() != pulse_num && pulse_height != ZERO_LEVEL && pulse_width != 0 && !(randomize_out_of_range || out_of_range_val)) begin // Detected with pulse level. Skip if pulse level undetectable
|
|
||||||
$display("[ERROR] -run_test_case- Size of pulse_width_time_stats samples not equal to pulse_num: %d VS %d", pulse_width_time_stats.size(), pulse_num);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
if (pulse_period_time_stats.size() != pulse_num) begin
|
|
||||||
$display("[ERROR] -run_test_case- Size of pulse_period_time_stats samples not equal to pulse_num: %d VS %d", pulse_period_time_stats.size(), pulse_num);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
if (sync_time_stats.size() != pulse_num) begin
|
|
||||||
$display("[ERROR] -run_test_case- Size of sync_time_stats samples not equal to pulse_num: %d VS %d", sync_time_stats.size(), pulse_num);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
avearge_pulse_delay = 0;
|
|
||||||
foreach (pulse_delay_time_stats[i])
|
|
||||||
avearge_pulse_delay += pulse_delay_time_stats[i];
|
|
||||||
avearge_pulse_delay /= pulse_num;
|
|
||||||
|
|
||||||
average_pulse_width = 0;
|
|
||||||
foreach (pulse_width_time_stats[i])
|
|
||||||
average_pulse_width += pulse_width_time_stats[i];
|
|
||||||
average_pulse_width /= pulse_num;
|
|
||||||
|
|
||||||
average_pulse_period = 0;
|
|
||||||
foreach (pulse_period_time_stats[i])
|
|
||||||
average_pulse_period += pulse_period_time_stats[i];
|
|
||||||
average_pulse_period /= pulse_num;
|
|
||||||
|
|
||||||
average_sync_time = 0;
|
|
||||||
foreach (sync_time_stats[i])
|
|
||||||
average_sync_time += sync_time_stats[i];
|
|
||||||
average_sync_time /= pulse_num;
|
|
||||||
|
|
||||||
if (VERBOSE >= 1) begin
|
|
||||||
$display("[TB] -run_test_case- Pulse test stats:\n\tavearge_pulse_delay: %0.3f\n\taverage_pulse_width: %0.3f\n\taverage_pulse_period: %0.3f\n\taverage_sync_time: %0.3f", avearge_pulse_delay, average_pulse_width, average_pulse_period, average_sync_time);
|
|
||||||
end
|
|
||||||
|
|
||||||
if (avearge_pulse_delay > CLOCK_DEVIATION * CLK_ADC_PERIOD) begin
|
|
||||||
$display("[ERROR] -run_test_case- avearge_pulse_delay too big: %0.3f", avearge_pulse_delay);
|
|
||||||
error_flag = 1;
|
|
||||||
end
|
|
||||||
if (fabs(average_pulse_width - pulse_width * CLK_DAC_PERIOD * (pulse_height != ZERO_LEVEL)) > CLOCK_DEVIATION * CLK_ADC_PERIOD && sample_num * CLK_ADC_PERIOD >= pulse_width * CLK_DAC_PERIOD) begin
|
|
||||||
$display("[ERROR] -run_test_case- average_pulse_width deviates from choosen pulse_width. Deviation: %0.3f > %0.3f ns", fabs(average_pulse_width - pulse_width * CLK_DAC_PERIOD), CLOCK_DEVIATION * CLK_ADC_PERIOD);
|
|
||||||
error_flag = 1;
|
|
||||||
end
|
|
||||||
if (fabs(average_pulse_period - sample_num * CLK_ADC_PERIOD) > CLOCK_DEVIATION * CLK_ADC_PERIOD) begin
|
|
||||||
$display("[ERROR] -run_test_case- average_pulse_period deviates from choosen pulse_width. Deviation: %0.3f > %0.3f ns", fabs(average_pulse_period - sample_num * CLK_ADC_PERIOD), CLOCK_DEVIATION * CLK_ADC_PERIOD);
|
|
||||||
error_flag = 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Pass error processing");
|
|
||||||
end
|
|
||||||
|
|
||||||
if (error_flag)
|
|
||||||
$finish;
|
|
||||||
|
|
||||||
if (VERBOSE >= 2) begin
|
|
||||||
$display("[TB] -run_test_case- Passed checks");
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
// Таска
|
|
||||||
|
|
||||||
// --- ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ ---
|
|
||||||
initial begin
|
initial begin
|
||||||
$display("[TB] Tests start");
|
dac_clk_in = 1'b0;
|
||||||
|
forever #8 dac_clk_in = ~dac_clk_in; // slower domain
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// monitor output stream
|
||||||
|
//------------------------------------------------------------
|
||||||
|
always @(posedge adc_clk_in) begin
|
||||||
|
if (m_axis_tvalid) begin
|
||||||
|
valid_count = valid_count + 1;
|
||||||
|
|
||||||
|
$display("[%0t] VALID: data=%0d",
|
||||||
|
$time,
|
||||||
|
m_axis_tdata);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// test
|
||||||
|
//------------------------------------------------------------
|
||||||
|
initial begin
|
||||||
|
|
||||||
|
adc_rst = 1'b1;
|
||||||
|
dac_rst = 1'b1;
|
||||||
|
|
||||||
|
dac_start = 1'b0;
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
dac_start = 0;
|
|
||||||
pulse_width = 0;
|
pulse_width = 0;
|
||||||
pulse_period = 0;
|
pulse_period = 0;
|
||||||
pulse_height = 0;
|
pulse_height = 0;
|
||||||
pulse_num = 0;
|
pulse_num = 0;
|
||||||
smp_num = 0;
|
smp_num = 0;
|
||||||
out_of_range = 0;
|
|
||||||
rst_adc = 0;
|
|
||||||
rst_dac = 0;
|
|
||||||
|
|
||||||
#100; // init
|
valid_count = 0;
|
||||||
|
|
||||||
$display("[TB] Test 1. Simple test. (1/4)");
|
//--------------------------------------------------------
|
||||||
run_test_case(
|
// reset
|
||||||
.pulse_width(50),
|
//--------------------------------------------------------
|
||||||
.pulse_period(125),
|
repeat (10) @(posedge adc_clk_in);
|
||||||
.pulse_height(2**DAC_DATA_WIDTH-1),
|
repeat (10) @(posedge dac_clk_in);
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(0),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 1. Simple test. (2/4)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(25),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(2**(ADC_DATA_WIDTH-1)),
|
|
||||||
.pulse_num(10),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 1. Simple test. (3/4)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(50),
|
|
||||||
.pulse_height(ZERO_LEVEL),
|
|
||||||
.pulse_num(4),
|
|
||||||
.sample_num(25),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
$display("[TB] Test 1. Simple test. (4/4)");
|
adc_rst = 1'b0;
|
||||||
run_test_case(
|
dac_rst = 1'b0;
|
||||||
.pulse_width(25),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(2**(DAC_DATA_WIDTH-1)),
|
|
||||||
.pulse_num(10),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 1 complete");
|
|
||||||
|
|
||||||
$display("[TB] Test 2. Edge cases. Pulse width 0%%. (1/7)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(0),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(2**(ADC_DATA_WIDTH-1)),
|
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 2. Edge cases. Pulse width 100%%. (2/7)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(10),
|
|
||||||
.pulse_height(2**(ADC_DATA_WIDTH-1)),
|
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 2. Edge cases. Pulse height == ZERO_LEVEL. (3/7)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(ZERO_LEVEL),
|
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 2. Edge cases. Pulse num == 0. (4/7)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(2**(ADC_DATA_WIDTH-3)),
|
|
||||||
.pulse_num(0),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
$display("[TB] Test 2. Edge cases. Sample num time << Pulse width time. (5/7)");
|
repeat (5) @(posedge dac_clk_in);
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(2**(ADC_DATA_WIDTH-1)),
|
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(2),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(0),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ожидание окончания работы генератора. Т.к. конец работы определяется по tvalid сэмплера, а он завершается сильно раньше. Чтобы не пропустить start следующей таски, ждем
|
//--------------------------------------------------------
|
||||||
wait(dut.generator_inst.enable == 0);
|
// config
|
||||||
#50;
|
//--------------------------------------------------------
|
||||||
|
pulse_width = 32'd3;
|
||||||
|
pulse_period = 32'd8;
|
||||||
|
pulse_height = 14'd200;
|
||||||
|
pulse_num = 16'd4;
|
||||||
|
smp_num = 32'd8;
|
||||||
|
|
||||||
$display("[TB] Test 2. Edge cases. Sample num == 0. (6/7)");
|
//--------------------------------------------------------
|
||||||
// Запустим в работу вручную, т.к. run_test_case обязательно ждет pulse num циклов. Детекция цикла производится по активности сэплера. Ее не должно быть при sample num = 0
|
// start
|
||||||
set_config(
|
//--------------------------------------------------------
|
||||||
.w(10),
|
@(posedge dac_clk_in);
|
||||||
.p(125),
|
dac_start = 1'b1;
|
||||||
.h(2**(ADC_DATA_WIDTH-1)),
|
|
||||||
.n(5),
|
|
||||||
.sn(0)
|
|
||||||
);
|
|
||||||
start_dut(3);
|
|
||||||
fork
|
|
||||||
begin : wait_sampler_active_proc
|
|
||||||
@(posedge m_axis_tvalid);
|
|
||||||
$display("[ERROR] Sampler active with sample num == 0");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
@(negedge dut.generator_inst.enable);
|
|
||||||
end
|
|
||||||
join_any
|
|
||||||
disable wait_sampler_active_proc;
|
|
||||||
repeat(30) @(posedge clk_adc);
|
|
||||||
|
|
||||||
// Данный тест должен приводить к тому, что сэмплер будет давать крайние значения вместо заданного pulse height из-за OTR=1
|
|
||||||
// Дописать авто тест
|
|
||||||
$display("[TB] Test 2. Edge cases. OTR == 1. (7/7)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(10), // goes to 0x0..
|
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(1),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 2. Edge cases. OTR == 1. (7-2/7)");
|
|
||||||
run_test_case(
|
|
||||||
.pulse_width(10),
|
|
||||||
.pulse_period(125),
|
|
||||||
.pulse_height(14'b11010000000000), // goes to 0xff..
|
|
||||||
.pulse_num(5),
|
|
||||||
.sample_num(65),
|
|
||||||
.skip_reset(1),
|
|
||||||
.randomize_start_timing(1),
|
|
||||||
.out_of_range_val(1),
|
|
||||||
.randomize_out_of_range(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 2 complete");
|
|
||||||
|
|
||||||
$display("[TB] Test 3. Random tests");
|
@(posedge dac_clk_in);
|
||||||
for (int i = 0; i < 100; i++) begin
|
dac_start = 1'b0;
|
||||||
int r_w, r_p, r_n, r_h, r_sn;
|
|
||||||
bit r_skip, r_otr, r_otr_rand;
|
|
||||||
|
|
||||||
// Генерируем параметры
|
$display("==================================");
|
||||||
r_p = $urandom_range(50, 150); // Период от 5 до 50
|
$display("TEST START");
|
||||||
r_w = $urandom_range(10, r_p); // Ширина не больше периода
|
$display("==================================");
|
||||||
r_n = $urandom_range(1, 10); // Количество импульсов
|
|
||||||
r_h = $urandom_range(0, 2**(`MIN(ADC_DATA_WIDTH, DAC_DATA_WIDTH))-1); // Высота импульса
|
|
||||||
r_sn = $urandom_range(2, 40); // Число сэмплов
|
|
||||||
r_skip = $urandom_range(0, 1); // Случайный сброс (0 - сброс, 1 - пропуск)
|
|
||||||
r_otr = 0; // Out Of Range стартовое значение
|
|
||||||
r_otr_rand = 0; // Сделать OTR случайным
|
|
||||||
|
|
||||||
if (VERBOSE >= 1)
|
//--------------------------------------------------------
|
||||||
$display("[TB] --- Test #%0d (Config: W=%0d, P=%0d, N=%0d, H=%0d, SN=%0d, SkipReset=%0b) ---",
|
// wait
|
||||||
i+1, r_w, r_p, r_n, r_h, r_sn, r_skip);
|
//--------------------------------------------------------
|
||||||
|
repeat (600) @(posedge adc_clk_in);
|
||||||
run_test_case(
|
|
||||||
.pulse_width(r_w),
|
|
||||||
.pulse_period(r_p),
|
|
||||||
.pulse_height(r_h),
|
|
||||||
.pulse_num(r_n),
|
|
||||||
.sample_num(r_sn),
|
|
||||||
.skip_reset(r_skip),
|
|
||||||
.randomize_start_timing(0),
|
|
||||||
.out_of_range_val(r_otr),
|
|
||||||
.randomize_out_of_range(r_otr_rand)
|
|
||||||
);
|
|
||||||
|
|
||||||
wait(dut.generator_inst.enable == 0); // Проверка на завершение работы
|
//--------------------------------------------------------
|
||||||
#50;
|
// check
|
||||||
|
//--------------------------------------------------------
|
||||||
|
if (valid_count > 0) begin
|
||||||
|
$display("==================================");
|
||||||
|
$display("TEST PASSED");
|
||||||
|
$display("valid_count = %0d", valid_count);
|
||||||
|
$display("==================================");
|
||||||
end
|
end
|
||||||
$display("[TB] Test 3 complete");
|
else begin
|
||||||
|
$display("==================================");
|
||||||
$display("[TB] ALL PASSED");
|
$display("TEST FAILED");
|
||||||
$display("[TB] Maximum clock deviation of stats %0.2f", CLOCK_DEVIATION);
|
$display("No valid output detected");
|
||||||
|
$display("==================================");
|
||||||
|
end
|
||||||
|
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
//
|
||||||
|
// SystemVerilog interface wrapper around alexforencich/verilog-axi axi_dma.v.
|
||||||
|
//
|
||||||
|
// AXI memory, AXI-Stream data, DMA descriptor, and DMA status channels are all
|
||||||
|
// exposed through compact interfaces. The original Forencich core remains
|
||||||
|
// untouched and is connected through local flat wires.
|
||||||
|
|
||||||
|
`default_nettype none
|
||||||
|
import dma_reg_pkg::*;
|
||||||
|
|
||||||
|
// DMA Specific wrappers & converters
|
||||||
|
module axi_dma_wrapper #(
|
||||||
|
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
|
||||||
|
)(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
|
||||||
|
axis_if.slave s_axis_read_desc,
|
||||||
|
|
||||||
|
axis_if.master m_axis_read_desc_status,
|
||||||
|
|
||||||
|
axis_if.master m_axis_read_data,
|
||||||
|
|
||||||
|
axis_if.slave s_axis_write_desc,
|
||||||
|
|
||||||
|
axis_if.master m_axis_write_desc_status,
|
||||||
|
|
||||||
|
axis_if.slave s_axis_write_data,
|
||||||
|
|
||||||
|
axi4_if.master m_axi
|
||||||
|
);
|
||||||
|
|
||||||
|
dma_read_desc_t read_desc;
|
||||||
|
assign read_desc = dma_read_desc_t'(s_axis_read_desc.req.t.data);
|
||||||
|
|
||||||
|
|
||||||
|
dma_write_desc_t write_desc;
|
||||||
|
assign write_desc = dma_write_desc_t'(s_axis_write_desc.req.t.data);
|
||||||
|
|
||||||
|
|
||||||
|
dma_read_status_t read_status;
|
||||||
|
assign m_axis_read_desc_status.req.t.data = read_status;
|
||||||
|
logic m_axis_read_desc_status_valid;
|
||||||
|
assign m_axis_read_desc_status.req.t.valid = m_axis_read_desc_status_valid;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dma_write_status_t write_status;
|
||||||
|
assign m_axis_write_desc_status.req.t.data = write_status;
|
||||||
|
logic m_axis_write_desc_status_valid;
|
||||||
|
assign m_axis_write_desc_status.req.t.valid = m_axis_write_desc_status_valid;
|
||||||
|
|
||||||
|
|
||||||
|
// Original DMA: flat ports only.
|
||||||
|
axi_dma #(
|
||||||
|
.AXI_DATA_WIDTH (AXI_DATA_WIDTH),
|
||||||
|
.AXI_ADDR_WIDTH (dma_reg_pkg::AXI_ADDR_WIDTH),
|
||||||
|
.AXI_STRB_WIDTH (AXI_STRB_WIDTH),
|
||||||
|
.AXI_ID_WIDTH (AXI_ID_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_ID_WIDTH (dma_reg_pkg::AXIS_ID_WIDTH),
|
||||||
|
.AXIS_DEST_ENABLE (AXIS_DEST_ENABLE),
|
||||||
|
.AXIS_DEST_WIDTH (dma_reg_pkg::AXIS_DEST_WIDTH),
|
||||||
|
.AXIS_USER_ENABLE (AXIS_USER_ENABLE),
|
||||||
|
.AXIS_USER_WIDTH (dma_reg_pkg::AXIS_USER_WIDTH),
|
||||||
|
.LEN_WIDTH (dma_reg_pkg::LEN_WIDTH),
|
||||||
|
.TAG_WIDTH (dma_reg_pkg::TAG_WIDTH),
|
||||||
|
.ENABLE_SG (ENABLE_SG),
|
||||||
|
.ENABLE_UNALIGNED (ENABLE_UNALIGNED)
|
||||||
|
) i_axi_dma (
|
||||||
|
.clk (clk),
|
||||||
|
.rst (rst),
|
||||||
|
|
||||||
|
.s_axis_read_desc_addr (read_desc.addr),
|
||||||
|
.s_axis_read_desc_len (read_desc.len),
|
||||||
|
.s_axis_read_desc_tag (read_desc.tag),
|
||||||
|
.s_axis_read_desc_id (read_desc.id),
|
||||||
|
.s_axis_read_desc_dest (read_desc.dest),
|
||||||
|
.s_axis_read_desc_user (read_desc.user),
|
||||||
|
.s_axis_read_desc_valid (s_axis_read_desc.req.t.valid),
|
||||||
|
.s_axis_read_desc_ready (s_axis_read_desc.resp.ready),
|
||||||
|
|
||||||
|
.m_axis_read_desc_status_tag (read_status.tag),
|
||||||
|
.m_axis_read_desc_status_error (read_status.error),
|
||||||
|
.m_axis_read_desc_status_valid (m_axis_read_desc_status_valid),
|
||||||
|
|
||||||
|
.m_axis_read_data_tdata (m_axis_read_data.req.t.data),
|
||||||
|
.m_axis_read_data_tkeep (m_axis_read_data.req.t.keep),
|
||||||
|
.m_axis_read_data_tvalid (m_axis_read_data.req.t.valid),
|
||||||
|
.m_axis_read_data_tready (m_axis_read_data.resp.ready),
|
||||||
|
.m_axis_read_data_tlast (m_axis_read_data.req.t.last),
|
||||||
|
.m_axis_read_data_tid (m_axis_read_data.req.t.id),
|
||||||
|
.m_axis_read_data_tdest (m_axis_read_data.req.t.dest),
|
||||||
|
.m_axis_read_data_tuser (m_axis_read_data.req.t.user),
|
||||||
|
|
||||||
|
.s_axis_write_desc_addr (write_desc.addr),
|
||||||
|
.s_axis_write_desc_len (write_desc.len),
|
||||||
|
.s_axis_write_desc_tag (write_desc.tag),
|
||||||
|
.s_axis_write_desc_valid (s_axis_write_desc.req.t.valid),
|
||||||
|
.s_axis_write_desc_ready (s_axis_write_desc.resp.ready),
|
||||||
|
|
||||||
|
.m_axis_write_desc_status_len (write_status.len),
|
||||||
|
.m_axis_write_desc_status_tag (write_status.tag),
|
||||||
|
.m_axis_write_desc_status_id (write_status.id),
|
||||||
|
.m_axis_write_desc_status_dest (write_status.dest),
|
||||||
|
.m_axis_write_desc_status_user (write_status.user),
|
||||||
|
.m_axis_write_desc_status_error (write_status.error),
|
||||||
|
.m_axis_write_desc_status_valid (m_axis_write_desc_status_valid),
|
||||||
|
|
||||||
|
.s_axis_write_data_tdata (s_axis_write_data.req.t.data),
|
||||||
|
.s_axis_write_data_tkeep (s_axis_write_data.req.t.keep),
|
||||||
|
.s_axis_write_data_tvalid (s_axis_write_data.req.t.valid),
|
||||||
|
.s_axis_write_data_tready (s_axis_write_data.resp.ready),
|
||||||
|
.s_axis_write_data_tlast (s_axis_write_data.req.t.last),
|
||||||
|
.s_axis_write_data_tid (s_axis_write_data.req.t.id),
|
||||||
|
.s_axis_write_data_tdest (s_axis_write_data.req.t.dest),
|
||||||
|
.s_axis_write_data_tuser (s_axis_write_data.req.t.user),
|
||||||
|
|
||||||
|
.m_axi_awid (m_axi.req.aw.id),
|
||||||
|
.m_axi_awaddr (m_axi.req.aw.addr),
|
||||||
|
.m_axi_awlen (m_axi.req.aw.len),
|
||||||
|
.m_axi_awsize (m_axi.req.aw.size),
|
||||||
|
.m_axi_awburst (m_axi.req.aw.burst),
|
||||||
|
.m_axi_awlock (m_axi.req.aw.lock),
|
||||||
|
.m_axi_awcache (m_axi.req.aw.cache),
|
||||||
|
.m_axi_awprot (m_axi.req.aw.prot),
|
||||||
|
.m_axi_awvalid (m_axi.req.aw.valid),
|
||||||
|
.m_axi_awready (m_axi.resp.aw_ready),
|
||||||
|
|
||||||
|
.m_axi_wdata (m_axi.req.w.data),
|
||||||
|
.m_axi_wstrb (m_axi.req.w.strb),
|
||||||
|
.m_axi_wlast ( m_axi.req.w.last),
|
||||||
|
.m_axi_wvalid (m_axi.req.w.valid),
|
||||||
|
.m_axi_wready (m_axi.resp.w_ready),
|
||||||
|
|
||||||
|
.m_axi_bid (m_axi.resp.b.id),
|
||||||
|
.m_axi_bresp (m_axi.resp.b.resp),
|
||||||
|
.m_axi_bvalid (m_axi.resp.b.valid),
|
||||||
|
.m_axi_bready (m_axi.req.b_ready),
|
||||||
|
|
||||||
|
.m_axi_arid (m_axi.req.ar.id),
|
||||||
|
.m_axi_araddr (m_axi.req.ar.addr),
|
||||||
|
.m_axi_arlen (m_axi.req.ar.len),
|
||||||
|
.m_axi_arsize (m_axi.req.ar.size),
|
||||||
|
.m_axi_arburst (m_axi.req.ar.burst),
|
||||||
|
.m_axi_arlock (m_axi.req.ar.lock),
|
||||||
|
.m_axi_arcache (m_axi.req.ar.cache),
|
||||||
|
.m_axi_arprot (m_axi.req.ar.prot),
|
||||||
|
.m_axi_arvalid (m_axi.req.ar.valid),
|
||||||
|
.m_axi_arready (m_axi.resp.ar_ready),
|
||||||
|
|
||||||
|
.m_axi_rid (m_axi.resp.r.id),
|
||||||
|
.m_axi_rdata (m_axi.resp.r.data),
|
||||||
|
.m_axi_rresp (m_axi.resp.r.resp),
|
||||||
|
.m_axi_rlast (m_axi.resp.r.last),
|
||||||
|
.m_axi_rvalid (m_axi.resp.r.valid),
|
||||||
|
.m_axi_rready (m_axi.req.r_ready),
|
||||||
|
|
||||||
|
.read_enable (1'b1),
|
||||||
|
.write_enable (1'b1),
|
||||||
|
.write_abort (1'b0)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
endmodule : axi_dma_wrapper
|
||||||
|
|
||||||
|
`default_nettype wire
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
module axi_ram_wrapper
|
||||||
|
#(
|
||||||
|
parameter int unsigned DATA_WIDTH = 32,
|
||||||
|
parameter int unsigned ADDR_WIDTH = 16,
|
||||||
|
parameter int unsigned ID_WIDTH = 8,
|
||||||
|
parameter int unsigned PIPELINE_OUTPUT = 0
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
axi4_if.slave s_axi
|
||||||
|
);
|
||||||
|
|
||||||
|
axi_ram
|
||||||
|
#(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.ADDR_WIDTH(ADDR_WIDTH),
|
||||||
|
.ID_WIDTH(ID_WIDTH),
|
||||||
|
.PIPELINE_OUTPUT(PIPELINE_OUTPUT)
|
||||||
|
) axi_ram_inst
|
||||||
|
(
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.s_axi_awid(s_axi.req.aw.id),
|
||||||
|
.s_axi_awaddr(s_axi.req.aw.addr),
|
||||||
|
.s_axi_awlen(s_axi.req.aw.len),
|
||||||
|
.s_axi_awsize(s_axi.req.aw.size),
|
||||||
|
.s_axi_awburst(s_axi.req.aw.burst),
|
||||||
|
.s_axi_awlock(s_axi.req.aw.lock),
|
||||||
|
.s_axi_awcache(s_axi.req.aw.cache),
|
||||||
|
.s_axi_awprot(s_axi.req.aw.prot),
|
||||||
|
.s_axi_awvalid(s_axi.req.aw.valid),
|
||||||
|
.s_axi_awready(s_axi.resp.aw_ready),
|
||||||
|
.s_axi_wdata(s_axi.req.w.data),
|
||||||
|
.s_axi_wstrb(s_axi.req.w.strb),
|
||||||
|
.s_axi_wlast(s_axi.req.w.last),
|
||||||
|
.s_axi_wvalid(s_axi.req.w.valid),
|
||||||
|
.s_axi_wready(s_axi.resp.w_ready),
|
||||||
|
.s_axi_bid(s_axi.resp.b.id),
|
||||||
|
.s_axi_bresp(s_axi.resp.b.resp),
|
||||||
|
.s_axi_bvalid(s_axi.resp.b.valid),
|
||||||
|
.s_axi_bready(s_axi.req.b_ready),
|
||||||
|
.s_axi_arid(s_axi.req.ar.id),
|
||||||
|
.s_axi_araddr(s_axi.req.ar.addr),
|
||||||
|
.s_axi_arlen(s_axi.req.ar.len),
|
||||||
|
.s_axi_arsize(s_axi.req.ar.size),
|
||||||
|
.s_axi_arburst(s_axi.req.ar.burst),
|
||||||
|
.s_axi_arlock(s_axi.req.ar.lock),
|
||||||
|
.s_axi_arcache(s_axi.req.ar.cache),
|
||||||
|
.s_axi_arprot(s_axi.req.ar.prot),
|
||||||
|
.s_axi_arvalid(s_axi.req.ar.valid),
|
||||||
|
.s_axi_arready(s_axi.resp.ar_ready),
|
||||||
|
.s_axi_rid(s_axi.resp.r.id),
|
||||||
|
.s_axi_rdata(s_axi.resp.r.data),
|
||||||
|
.s_axi_rresp(s_axi.resp.r.resp),
|
||||||
|
.s_axi_rlast(s_axi.resp.r.last),
|
||||||
|
.s_axi_rvalid(s_axi.resp.r.valid),
|
||||||
|
.s_axi_rready(s_axi.req.r_ready)
|
||||||
|
);
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,193 @@
|
|||||||
|
import dma_reg_pkg::*;
|
||||||
|
|
||||||
|
module wrapper_controller_dma
|
||||||
|
#(
|
||||||
|
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
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input logic ctrl_clk,
|
||||||
|
input logic dac_clk_in,
|
||||||
|
input logic adc_clk_in,
|
||||||
|
input logic rst_n,
|
||||||
|
axi4l_if.slave s_axil,
|
||||||
|
|
||||||
|
// adc_clk_in domain
|
||||||
|
input logic finish,
|
||||||
|
output logic [31:0] adc_window_size,
|
||||||
|
|
||||||
|
// dac_clk_in domain outputs
|
||||||
|
output logic [31:0] dac_pulse_width,
|
||||||
|
output logic [31:0] dac_pulse_period,
|
||||||
|
output logic [DAC_DATA_WIDTH-1:0] dac_pulse_height,
|
||||||
|
output logic [15:0] dac_pulse_num,
|
||||||
|
|
||||||
|
// adc_clk_in domain outputs
|
||||||
|
output logic [31:0] adc_pulse_period,
|
||||||
|
output logic [15:0] adc_pulse_num,
|
||||||
|
|
||||||
|
// pulse outputs
|
||||||
|
output logic dac_start,
|
||||||
|
output logic adc_start,
|
||||||
|
output logic dac_rst,
|
||||||
|
output logic adc_rst,
|
||||||
|
|
||||||
|
axis_if.master m_axis_read_data,
|
||||||
|
axis_if.slave s_axis_write_data
|
||||||
|
);
|
||||||
|
|
||||||
|
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($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(dac_clk_in),
|
||||||
|
.adc_clk_in(adc_clk_in),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
|
||||||
|
.s_axil(s_axil),
|
||||||
|
|
||||||
|
.finish(finish),
|
||||||
|
.adc_window_size(adc_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(s_axis_write_data),
|
||||||
|
.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)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
TOPLEVEL_LANG = verilog
|
||||||
|
SIM ?= verilator
|
||||||
|
|
||||||
|
PWD := $(shell pwd)
|
||||||
|
|
||||||
|
WRAP_DIR = $(PWD)/../src
|
||||||
|
RTL_DIR = $(PWD)/../../controller/src
|
||||||
|
LIBS_DIR = $(PWD)/../../../external/rtl_libs
|
||||||
|
|
||||||
|
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/axi_reg/axi4l_reg_map.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 += $(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 += $(WRAP_DIR)/wrapper_controller_dma.sv
|
||||||
|
VERILOG_SOURCES += $(WRAP_DIR)/axi_dma_wrapper_if.sv
|
||||||
|
VERILOG_SOURCES += $(PWD)/tb_controller_dma_wrapper_axil.sv
|
||||||
|
|
||||||
|
TOPLEVEL = tb_controller_dma_wrapper_axil
|
||||||
|
MODULE = test_controller_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
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||||
@@ -0,0 +1,298 @@
|
|||||||
|
|
||||||
|
import dma_reg_pkg::*;
|
||||||
|
|
||||||
|
module tb_controller_wrapper_axil #(
|
||||||
|
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
|
||||||
|
)(
|
||||||
|
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,
|
||||||
|
|
||||||
|
input wire [AXIS_DATA_WIDTH-1:0] s_axis_write_data_tdata,
|
||||||
|
input wire [AXIS_KEEP_WIDTH-1:0] s_axis_write_data_tkeep,
|
||||||
|
input wire s_axis_write_data_tvalid,
|
||||||
|
output wire s_axis_write_data_tready,
|
||||||
|
input wire s_axis_write_data_tlast,
|
||||||
|
input wire [AXIS_ID_WIDTH-1:0] s_axis_write_data_tid,
|
||||||
|
input wire [AXIS_DEST_WIDTH-1:0] s_axis_write_data_tdest,
|
||||||
|
input wire [AXIS_USER_WIDTH-1:0] s_axis_write_data_tuser,
|
||||||
|
|
||||||
|
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 [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
|
||||||
|
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
logic rst_n;
|
||||||
|
assign rst_n = ~rst;
|
||||||
|
|
||||||
|
// Для минимального теста держим все clock domain-ы на одном clock.
|
||||||
|
logic dac_clk_in;
|
||||||
|
logic adc_clk_in;
|
||||||
|
assign dac_clk_in = ctrl_clk;
|
||||||
|
assign adc_clk_in = ctrl_clk;
|
||||||
|
|
||||||
|
logic finish;
|
||||||
|
assign finish = 1'b0;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// AXI-Lite flat -> axi4l_if
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
axi4l_if #(
|
||||||
|
.ADDR_W(ADDR_W),
|
||||||
|
.DATA_W(DATA_W),
|
||||||
|
.USER_W(USER_W)
|
||||||
|
) axil_bus (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
axi4l_flat_to_if #(
|
||||||
|
.ADDR_W(ADDR_W),
|
||||||
|
.DATA_W(DATA_W),
|
||||||
|
.USER_W(USER_W)
|
||||||
|
) u_axil_flat_to_if (
|
||||||
|
.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_axil(axil_bus)
|
||||||
|
);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// AXIS interfaces for the updated controller_wrapper_axil
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
) dma_read_data (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [AXIS_KEEP_WIDTH-1:0] unused_read_tstrb;
|
||||||
|
|
||||||
|
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)
|
||||||
|
) u_read_data_if_to_flat (
|
||||||
|
.s_axis(dma_read_data),
|
||||||
|
|
||||||
|
.m_axis_tdata (m_axis_read_data_tdata),
|
||||||
|
.m_axis_tkeep (m_axis_read_data_tkeep),
|
||||||
|
.m_axis_tstrb (unused_read_tstrb),
|
||||||
|
.m_axis_tlast (m_axis_read_data_tlast),
|
||||||
|
.m_axis_tid (m_axis_read_data_tid),
|
||||||
|
.m_axis_tdest (m_axis_read_data_tdest),
|
||||||
|
.m_axis_tuser (m_axis_read_data_tuser),
|
||||||
|
.m_axis_tvalid(m_axis_read_data_tvalid),
|
||||||
|
.m_axis_tready(m_axis_read_data_tready)
|
||||||
|
);
|
||||||
|
|
||||||
|
// AXIS WRITE DMA SLAVE input
|
||||||
|
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)
|
||||||
|
) dma_write_data (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
axis_flat_to_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)
|
||||||
|
) u_write_data_flat_to_if (
|
||||||
|
.s_axis_tdata (s_axis_write_data_tdata),
|
||||||
|
.s_axis_tkeep (s_axis_write_data_tkeep),
|
||||||
|
.s_axis_tstrb (s_axis_write_data_tkeep),
|
||||||
|
.s_axis_tlast (s_axis_write_data_tlast),
|
||||||
|
.s_axis_tid (s_axis_write_data_tid),
|
||||||
|
.s_axis_tdest (s_axis_write_data_tdest),
|
||||||
|
.s_axis_tuser (s_axis_write_data_tuser),
|
||||||
|
.s_axis_tvalid(s_axis_write_data_tvalid),
|
||||||
|
.s_axis_tready(s_axis_write_data_tready),
|
||||||
|
|
||||||
|
.m_axis(dma_write_data)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Controller ADC/DAC outputs.
|
||||||
|
logic [31:0] adc_window_size;
|
||||||
|
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;
|
||||||
|
logic [31:0] adc_pulse_period;
|
||||||
|
logic [15:0] adc_pulse_num;
|
||||||
|
logic dac_start;
|
||||||
|
logic adc_start;
|
||||||
|
logic dac_rst;
|
||||||
|
logic adc_rst;
|
||||||
|
|
||||||
|
wrapper_controller_dma #(
|
||||||
|
.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)
|
||||||
|
) dut (
|
||||||
|
.ctrl_clk(ctrl_clk),
|
||||||
|
.dac_clk_in(dac_clk_in),
|
||||||
|
.adc_clk_in(adc_clk_in),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.s_axil(axil_bus),
|
||||||
|
|
||||||
|
.finish(finish),
|
||||||
|
.adc_window_size(adc_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),
|
||||||
|
|
||||||
|
.m_axis_read_data(dma_read_data),
|
||||||
|
.s_axis_write_data(dma_write_data)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule : tb_controller_wrapper_axil
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
import cocotb
|
||||||
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.triggers import RisingEdge
|
||||||
|
from cocotbext.axi import AxiLiteBus, AxiLiteMaster
|
||||||
|
from cocotbext.axi import AxiBus, AxiRam, AxiStreamBus, AxiStreamSource, 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 = 0
|
||||||
|
CTRL_RST_SOFT = 1
|
||||||
|
CTRL_CFG_BUS_VALID = 2
|
||||||
|
CTRL_SEND_DESC_READ = 3
|
||||||
|
CTRL_SEND_DESC_WRITE = 4
|
||||||
|
CTRL_TAKE_STATUS_READ = 5
|
||||||
|
CTRL_TAKE_STATUS_WRITE = 6
|
||||||
|
|
||||||
|
|
||||||
|
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, units="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(5):
|
||||||
|
await RisingEdge(self.dut.ctrl_clk)
|
||||||
|
|
||||||
|
self.dut.rst.value = 0
|
||||||
|
for _ in range(5):
|
||||||
|
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")
|
||||||
|
|
||||||
|
|
||||||
|
@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, 1 << CTRL_CFG_BUS_VALID)
|
||||||
|
|
||||||
|
# wait
|
||||||
|
for _ in range(30):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
# check config
|
||||||
|
assert int(dut.dac_pulse_width) == 0x10
|
||||||
|
assert int(dut.dac_pulse_period) == 0x40
|
||||||
|
assert int(dut.dac_pulse_num) == 3
|
||||||
|
assert int(dut.dac_pulse_height) == 0x7FF
|
||||||
|
assert int(dut.adc_pulse_period) == 0x80
|
||||||
|
assert int(dut.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, 1 << CTRL_START)
|
||||||
|
|
||||||
|
await RisingEdge(dut.dac_start)
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def simple_dma_mem_to_mem(dut):
|
||||||
|
tb = TB(dut)
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
SRC_ADDR = 0x1000
|
||||||
|
LENGTH = 8
|
||||||
|
|
||||||
|
tx_data = bytes([ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 ])
|
||||||
|
|
||||||
|
## write part
|
||||||
|
|
||||||
|
await tb.write_reg(REG_DESC_WRITE_ADDR, SRC_ADDR)
|
||||||
|
await tb.write_reg(REG_DESC_WRITE_LEN_AND_TAG, LENGTH)
|
||||||
|
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_SEND_DESC_WRITE)
|
||||||
|
|
||||||
|
await tb.axis_source.send(AxiStreamFrame(tx_data))
|
||||||
|
|
||||||
|
for _ in range(20):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_TAKE_STATUS_WRITE)
|
||||||
|
|
||||||
|
for _ in range(10):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
|
||||||
|
assert await tb.read_reg(REG_STATUS_WRITE_CONFIG) == 0
|
||||||
|
assert await tb.read_reg(REG_STATUS_WRITE_LEN) == 0x8
|
||||||
|
|
||||||
|
## read part
|
||||||
|
|
||||||
|
await tb.write_reg(REG_DESC_READ_ADDR, SRC_ADDR)
|
||||||
|
await tb.write_reg(REG_DESC_READ_LEN, LENGTH)
|
||||||
|
await tb.write_reg(REG_DESC_READ_CONFIG, 0x0000_0001)
|
||||||
|
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_SEND_DESC_READ)
|
||||||
|
|
||||||
|
rx_frame = await tb.axis_sink.recv()
|
||||||
|
|
||||||
|
for _ in range(20):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_TAKE_STATUS_READ)
|
||||||
|
|
||||||
|
for _ in range(10):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
assert await tb.read_reg(REG_READ_STATUS) == 0x1
|
||||||
|
|
||||||
|
assert bytes(rx_frame) == tx_data
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Primary clocks
|
||||||
|
create_clock -name eth_clk -period 8.000 [get_ports eth_clk_in]
|
||||||
|
create_clock -name dac_clk -period 7.692 [get_ports dac_clk_in]
|
||||||
|
create_clock -name adc_clk -period 15.385 [get_ports adc_clk_in]
|
||||||
|
|
||||||
|
|
||||||
|
# Asynchronous clock groups
|
||||||
|
# eth, dac, adc are independent domains
|
||||||
|
|
||||||
|
set_clock_groups -name ASYNC_ETH_DAC_ADC -asynchronous \
|
||||||
|
-group [get_clocks eth_clk] \
|
||||||
|
-group [get_clocks dac_clk] \
|
||||||
|
-group [get_clocks adc_clk]
|
||||||
@@ -10,21 +10,13 @@
|
|||||||
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 += adc_model.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'))
|
||||||
|
|||||||
@@ -86,15 +86,15 @@
|
|||||||
|
|
||||||
Система работает в нескольких тактовых доменах:
|
Система работает в нескольких тактовых доменах:
|
||||||
|
|
||||||
- Ethernet RX (`clk_axis_control`)
|
- Ethernet RX (`gmii_rx_clk`)
|
||||||
- Ethernet TX (`clk_axis_accumulator`)
|
- Ethernet TX (`gmii_tx_clk`)
|
||||||
- DAC (`clk_generator`)
|
- DAC (`dac_clk`)
|
||||||
- ADC (`clk_sampler`)
|
- ADC (`adc_clk`)
|
||||||
|
|
||||||
Для корректной синхронизации между DAC и ADC используются специальные CDC-регистры для сигналов:
|
Для корректной синхронизации между DAC и ADC используются специальные CDC-регистры для сигналов:
|
||||||
|
|
||||||
- `done`
|
- `sample_req`
|
||||||
- `request`
|
- `sample_done`
|
||||||
|
|
||||||
Это обеспечивает безопасную передачу handshake-сигналов между тактовыми доменами.
|
Это обеспечивает безопасную передачу handshake-сигналов между тактовыми доменами.
|
||||||
|
|
||||||
@@ -110,8 +110,8 @@
|
|||||||
|
|
||||||
Типовые значения:
|
Типовые значения:
|
||||||
|
|
||||||
- `8192` — середина диапазона ЦАП (0V)
|
- `8192` — середина диапазона ЦАП
|
||||||
- `0` — нулевой уровень (-5V)
|
- `0` — нулевой уровень
|
||||||
|
|
||||||
### ADC_DATA_WIDTH
|
### ADC_DATA_WIDTH
|
||||||
Ширина входных данных, получаемых с АЦП.
|
Ширина входных данных, получаемых с АЦП.
|
||||||
@@ -143,5 +143,3 @@
|
|||||||
```make all``` - собрать все до битстрима
|
```make all``` - собрать все до битстрима
|
||||||
|
|
||||||
```make vivado``` - открыть проект в Vivado
|
```make vivado``` - открыть проект в Vivado
|
||||||
|
|
||||||
```make sim``` - симуляция и верификация проекта
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
// AN9238 virtual ADC model (1 port)
|
|
||||||
|
|
||||||
module virtual_adc_model #(
|
|
||||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
|
||||||
|
|
||||||
// Bipolar input range: +/- VOLTAGE_RANGE
|
|
||||||
parameter real VOLTAGE_RANGE = 1.0,
|
|
||||||
|
|
||||||
// Analog input correction
|
|
||||||
parameter real VOLTAGE_GAIN = 0.2,
|
|
||||||
parameter real GROUND_BIAS = 0.0,
|
|
||||||
|
|
||||||
// ADC timing parameters
|
|
||||||
parameter time CONVERSION_DELAY = 250ps
|
|
||||||
)(
|
|
||||||
input logic clk_i,
|
|
||||||
input real voltage_i,
|
|
||||||
|
|
||||||
output logic otr_o,
|
|
||||||
output logic [ADC_DATA_WIDTH-1:0] data_o
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam int unsigned ZERO_CODE = (1 << (ADC_DATA_WIDTH - 1));
|
|
||||||
localparam real VOLTAGE_STEP = (2 * VOLTAGE_RANGE) / real'((1 << ADC_DATA_WIDTH) - 1);
|
|
||||||
|
|
||||||
real voltage_corrected;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Convert analog voltage to ADC code
|
|
||||||
//------------------------------------------------------------
|
|
||||||
function automatic logic [ADC_DATA_WIDTH-1:0] voltage_to_code( input real voltage );
|
|
||||||
if (voltage <= -VOLTAGE_RANGE) return '0;
|
|
||||||
if (voltage >= VOLTAGE_RANGE) return {ADC_DATA_WIDTH{1'b1}};
|
|
||||||
return $rtoi(voltage / VOLTAGE_STEP + real'((ZERO_CODE)) + 0.5);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function automatic logic range_check( input real voltage );
|
|
||||||
real v_abs = (voltage < 0.0) ? -voltage : voltage;
|
|
||||||
return v_abs >= VOLTAGE_RANGE;
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Initial state
|
|
||||||
//------------------------------------------------------------
|
|
||||||
initial begin
|
|
||||||
data_o = ZERO_CODE; // 0V
|
|
||||||
otr_o = 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Update analog output
|
|
||||||
//------------------------------------------------------------
|
|
||||||
always @(posedge clk_i) begin
|
|
||||||
voltage_corrected = (voltage_i - GROUND_BIAS) * VOLTAGE_GAIN;
|
|
||||||
data_o <= #(CONVERSION_DELAY) voltage_to_code(voltage_corrected);
|
|
||||||
otr_o <= #(CONVERSION_DELAY) range_check(voltage_corrected);
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// AN9767 model (1 port)
|
|
||||||
|
|
||||||
module virtual_dac_model #(
|
|
||||||
parameter int unsigned DAC_DATA_WIDTH = 14,
|
|
||||||
|
|
||||||
// Bipolar output range: +/- VOLTAGE_RANGE
|
|
||||||
parameter real VOLTAGE_RANGE = 5.0,
|
|
||||||
|
|
||||||
// Analog output correction
|
|
||||||
parameter real VOLTAGE_GAIN = 1.0,
|
|
||||||
parameter real GROUND_BIAS = 0.0,
|
|
||||||
|
|
||||||
// DAC timing parameters
|
|
||||||
parameter time TRANSMISSION_DELAY = 150ps,
|
|
||||||
parameter time CONVERSION_DELAY = 150ps
|
|
||||||
)(
|
|
||||||
input logic clk_i,
|
|
||||||
input logic wrt_i,
|
|
||||||
input logic [DAC_DATA_WIDTH-1:0] data_i,
|
|
||||||
|
|
||||||
output real voltage_o
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam int unsigned ZERO_CODE = (1 << (DAC_DATA_WIDTH - 1));
|
|
||||||
localparam real VOLTAGE_STEP = (2 * VOLTAGE_RANGE) / real'((1 << DAC_DATA_WIDTH) - 1);
|
|
||||||
|
|
||||||
logic [DAC_DATA_WIDTH-1:0] dac_code;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Convert DAC code to analog voltage
|
|
||||||
//------------------------------------------------------------
|
|
||||||
function automatic real code_to_voltage( input logic [DAC_DATA_WIDTH-1:0] code);
|
|
||||||
return (int'(code) - int'(ZERO_CODE)) * VOLTAGE_STEP;
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Initial state
|
|
||||||
//------------------------------------------------------------
|
|
||||||
initial begin
|
|
||||||
dac_code = '0;
|
|
||||||
voltage_o = code_to_voltage('0) * VOLTAGE_GAIN + GROUND_BIAS;
|
|
||||||
end
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Latch new DAC code
|
|
||||||
//------------------------------------------------------------
|
|
||||||
always @(posedge wrt_i) begin
|
|
||||||
dac_code <= #(TRANSMISSION_DELAY) data_i;
|
|
||||||
end
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Update analog output
|
|
||||||
//------------------------------------------------------------
|
|
||||||
always @(posedge clk_i) begin
|
|
||||||
voltage_o <= #(CONVERSION_DELAY) code_to_voltage(dac_code) * VOLTAGE_GAIN + GROUND_BIAS;
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
@@ -1,9 +1 @@
|
|||||||
# Primary clocks
|
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]
|
||||||
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
|
|
||||||
|
|||||||
@@ -1,130 +0,0 @@
|
|||||||
`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;
|
|
||||||
|
|
||||||
initial begin // Default values
|
|
||||||
tdata = 'x;
|
|
||||||
tvalid = 1'b0;
|
|
||||||
tlast = 1'b0;
|
|
||||||
tready = 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Master Clocking Block (для отправки данных из TB)
|
|
||||||
clocking drv_cb @(posedge clk);
|
|
||||||
default input #1step output #100ps;
|
|
||||||
output tdata, tvalid, tlast;
|
|
||||||
input tready;
|
|
||||||
endclocking
|
|
||||||
|
|
||||||
// Slave Clocking Block (для приема данных в TB с генерацией tready)
|
|
||||||
clocking slv_cb @(posedge clk);
|
|
||||||
default input #1step output #100ps;
|
|
||||||
input tdata, tvalid, tlast;
|
|
||||||
output tready;
|
|
||||||
endclocking
|
|
||||||
|
|
||||||
// Passive Monitor Clocking Block
|
|
||||||
clocking mon_cb @(posedge clk);
|
|
||||||
default input #1step;
|
|
||||||
input tdata, tvalid, tlast, tready;
|
|
||||||
endclocking
|
|
||||||
|
|
||||||
modport master (output tdata, tvalid, tlast, input tready);
|
|
||||||
modport slave (input tdata, tvalid, tlast, output tready);
|
|
||||||
|
|
||||||
// Модпорт для тестбенча с тасками
|
|
||||||
modport tb (
|
|
||||||
clocking drv_cb,
|
|
||||||
clocking slv_cb,
|
|
||||||
clocking mon_cb,
|
|
||||||
import master_send,
|
|
||||||
import slave_recv,
|
|
||||||
import monitor_recv
|
|
||||||
);
|
|
||||||
|
|
||||||
// Отправка пакета (Тестбенч выступает как Master)
|
|
||||||
task automatic master_send(input logic [DATA_WIDTH-1:0] payload[]);
|
|
||||||
if (payload.size() == 0) return;
|
|
||||||
|
|
||||||
@(drv_cb);
|
|
||||||
|
|
||||||
for (int i = 0; i < payload.size(); i++) begin
|
|
||||||
drv_cb.tdata <= payload[i];
|
|
||||||
drv_cb.tvalid <= 1'b1;
|
|
||||||
drv_cb.tlast <= (i == payload.size() - 1);
|
|
||||||
|
|
||||||
forever begin // Ждем подтверждение от слейва пока не получим
|
|
||||||
@(drv_cb);
|
|
||||||
if (drv_cb.tready === 1'b1) begin
|
|
||||||
break;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// Сбрасываем сигналы после отправки пакета
|
|
||||||
drv_cb.tvalid <= 1'b0;
|
|
||||||
drv_cb.tlast <= 1'b0;
|
|
||||||
drv_cb.tdata <= 'x;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Прием пакета (Тестбенч выступает как Slave и управляет tready). Не применять если есть реальный Slave (его tready опустится насильно)
|
|
||||||
task automatic slave_recv(output logic [DATA_WIDTH-1:0] payload[]);
|
|
||||||
logic [DATA_WIDTH-1:0] local_queue[$]; // Внутри таски очередь использовать можно
|
|
||||||
|
|
||||||
slv_cb.tready <= 1'b1; // Показываем, что готовы принимать
|
|
||||||
|
|
||||||
forever begin
|
|
||||||
@(slv_cb);
|
|
||||||
if (slv_cb.tvalid === 1'b1) begin
|
|
||||||
local_queue.push_back(slv_cb.tdata);
|
|
||||||
if (slv_cb.tlast === 1'b1) begin
|
|
||||||
break; // Пакет закончился
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
slv_cb.tready <= 1'b0; // Снимаем готовность
|
|
||||||
|
|
||||||
// Перекладываем из очереди в динамический массив
|
|
||||||
payload = new[local_queue.size()](local_queue);
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Прием пакета (Тестбенч выступает как пассивный наблюдатель без tready)
|
|
||||||
task automatic monitor_recv(output logic [DATA_WIDTH-1:0] payload[]);
|
|
||||||
logic [DATA_WIDTH-1:0] local_queue[$]; // Внутри таски очередь использовать можно
|
|
||||||
|
|
||||||
forever begin
|
|
||||||
if (mon_cb.tready === 1'b1) begin
|
|
||||||
break; // Дождались слейва
|
|
||||||
end
|
|
||||||
@(slv_cb);
|
|
||||||
end
|
|
||||||
|
|
||||||
forever begin
|
|
||||||
@(mon_cb);
|
|
||||||
if (mon_cb.tvalid === 1'b1) begin
|
|
||||||
local_queue.push_back(mon_cb.tdata);
|
|
||||||
if (mon_cb.tlast === 1'b1) begin
|
|
||||||
break; // Пакет закончился
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Перекладываем из очереди в динамический массив
|
|
||||||
payload = new[local_queue.size()](local_queue);
|
|
||||||
endtask
|
|
||||||
|
|
||||||
endinterface
|
|
||||||
|
|
||||||
`endif // AXIS_INTERFACE_SVH`
|
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
"ip_inst": {
|
"ip_inst": {
|
||||||
"xci_name": "clk_wiz_ctrl_inst",
|
"xci_name": "clk_wiz_ctrl_inst",
|
||||||
"component_reference": "xilinx.com:ip:clk_wiz:6.0",
|
"component_reference": "xilinx.com:ip:clk_wiz:6.0",
|
||||||
"ip_revision": "17",
|
"ip_revision": "16",
|
||||||
"gen_directory": "../../../../reflectometer_top.gen/sources_1/ip/clk_wiz_ctrl_inst",
|
"gen_directory": "../../../../eth_generator_top.gen/sources_1/ip/clk_wiz_ctrl_inst",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"component_parameters": {
|
"component_parameters": {
|
||||||
"Component_Name": [ { "value": "clk_wiz_ctrl_inst", "resolve_type": "user", "usage": "all" } ],
|
"Component_Name": [ { "value": "clk_wiz_ctrl_inst", "resolve_type": "user", "usage": "all" } ],
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"USE_MIN_POWER": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_MIN_POWER": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"USE_DYN_PHASE_SHIFT": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_DYN_PHASE_SHIFT": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"USE_DYN_RECONFIG": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_DYN_RECONFIG": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"JITTER_SEL": [ { "value": "Min_O_Jitter", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"JITTER_SEL": [ { "value": "No_Jitter", "resolve_type": "user", "usage": "all" } ],
|
||||||
"PRIM_IN_FREQ": [ { "value": "200.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"PRIM_IN_FREQ": [ { "value": "200.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"PRIM_IN_TIMEPERIOD": [ { "value": "10.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"PRIM_IN_TIMEPERIOD": [ { "value": "10.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"IN_FREQ_UNITS": [ { "value": "Units_MHz", "resolve_type": "user", "usage": "all" } ],
|
"IN_FREQ_UNITS": [ { "value": "Units_MHz", "resolve_type": "user", "usage": "all" } ],
|
||||||
@@ -52,12 +52,12 @@
|
|||||||
"CLKIN2_JITTER_PS": [ { "value": "100.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKIN2_JITTER_PS": [ { "value": "100.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT1_USED": [ { "value": "true", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT1_USED": [ { "value": "true", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT2_USED": [ { "value": "true", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT2_USED": [ { "value": "true", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT3_USED": [ { "value": "true", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT3_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT4_USED": [ { "value": "true", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT4_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT5_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT5_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT6_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT6_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT7_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT7_USED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"NUM_OUT_CLKS": [ { "value": "4", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"NUM_OUT_CLKS": [ { "value": "2", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"CLK_OUT1_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLK_OUT1_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLK_OUT2_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLK_OUT2_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLK_OUT3_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLK_OUT3_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
@@ -65,11 +65,11 @@
|
|||||||
"CLK_OUT5_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLK_OUT5_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLK_OUT6_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLK_OUT6_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLK_OUT7_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLK_OUT7_USE_FINE_PS_GUI": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"PRIMARY_PORT": [ { "value": "clk_200", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"PRIMARY_PORT": [ { "value": "clk_in1", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT1_PORT": [ { "value": "clk_adc_65", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT1_PORT": [ { "value": "clk_out1", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT2_PORT": [ { "value": "clk_adc_65_180", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT2_PORT": [ { "value": "clk_out2", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT3_PORT": [ { "value": "clk_dac_125", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT3_PORT": [ { "value": "clk_out3", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT4_PORT": [ { "value": "clk_dac_125_180", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT4_PORT": [ { "value": "clk_out4", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT5_PORT": [ { "value": "clk_out5", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT5_PORT": [ { "value": "clk_out5", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT6_PORT": [ { "value": "clk_out6", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT6_PORT": [ { "value": "clk_out6", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_OUT7_PORT": [ { "value": "clk_out7", "resolve_type": "user", "usage": "all" } ],
|
"CLK_OUT7_PORT": [ { "value": "clk_out7", "resolve_type": "user", "usage": "all" } ],
|
||||||
@@ -84,17 +84,17 @@
|
|||||||
"PSEN_PORT": [ { "value": "psen", "resolve_type": "user", "usage": "all" } ],
|
"PSEN_PORT": [ { "value": "psen", "resolve_type": "user", "usage": "all" } ],
|
||||||
"PSINCDEC_PORT": [ { "value": "psincdec", "resolve_type": "user", "usage": "all" } ],
|
"PSINCDEC_PORT": [ { "value": "psincdec", "resolve_type": "user", "usage": "all" } ],
|
||||||
"PSDONE_PORT": [ { "value": "psdone", "resolve_type": "user", "usage": "all" } ],
|
"PSDONE_PORT": [ { "value": "psdone", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT1_REQUESTED_OUT_FREQ": [ { "value": "65", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT1_REQUESTED_OUT_FREQ": [ { "value": "125", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT1_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT1_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT1_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT1_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT2_REQUESTED_OUT_FREQ": [ { "value": "65", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT2_REQUESTED_OUT_FREQ": [ { "value": "65.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT2_REQUESTED_PHASE": [ { "value": "180", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT2_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT2_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT2_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT3_REQUESTED_OUT_FREQ": [ { "value": "125", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT3_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT3_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT3_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT3_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT3_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT4_REQUESTED_OUT_FREQ": [ { "value": "125", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT4_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT4_REQUESTED_PHASE": [ { "value": "180", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT4_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT4_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT4_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT5_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT5_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT5_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT5_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
@@ -115,14 +115,14 @@
|
|||||||
"CLKOUT6_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT6_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT7_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"CLKOUT7_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"PRIM_SOURCE": [ { "value": "Single_ended_clock_capable_pin", "resolve_type": "user", "usage": "all" } ],
|
"PRIM_SOURCE": [ { "value": "Single_ended_clock_capable_pin", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT1_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT1_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT2_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT2_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT3_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT3_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT4_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT4_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT5_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT5_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT6_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT6_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKOUT7_DRIVES": [ { "value": "BUFGCE", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"CLKOUT7_DRIVES": [ { "value": "BUFG", "resolve_type": "user", "usage": "all" } ],
|
||||||
"FEEDBACK_SOURCE": [ { "value": "FDBK_AUTO", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"FEEDBACK_SOURCE": [ { "value": "FDBK_AUTO", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKFB_IN_SIGNALING": [ { "value": "SINGLE", "resolve_type": "user", "usage": "all" } ],
|
"CLKFB_IN_SIGNALING": [ { "value": "SINGLE", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKFB_IN_PORT": [ { "value": "clkfb_in", "resolve_type": "user", "usage": "all" } ],
|
"CLKFB_IN_PORT": [ { "value": "clkfb_in", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLKFB_IN_P_PORT": [ { "value": "clkfb_in_p", "resolve_type": "user", "usage": "all" } ],
|
"CLKFB_IN_P_PORT": [ { "value": "clkfb_in_p", "resolve_type": "user", "usage": "all" } ],
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
"USE_CLK_VALID": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_CLK_VALID": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"USE_INCLK_STOPPED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_INCLK_STOPPED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"USE_CLKFB_STOPPED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_CLKFB_STOPPED": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"RESET_PORT": [ { "value": "resetn", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"RESET_PORT": [ { "value": "reset", "resolve_type": "user", "usage": "all" } ],
|
||||||
"LOCKED_PORT": [ { "value": "locked", "resolve_type": "user", "usage": "all" } ],
|
"LOCKED_PORT": [ { "value": "locked", "resolve_type": "user", "usage": "all" } ],
|
||||||
"POWER_DOWN_PORT": [ { "value": "power_down", "resolve_type": "user", "usage": "all" } ],
|
"POWER_DOWN_PORT": [ { "value": "power_down", "resolve_type": "user", "usage": "all" } ],
|
||||||
"CLK_VALID_PORT": [ { "value": "CLK_VALID", "resolve_type": "user", "usage": "all" } ],
|
"CLK_VALID_PORT": [ { "value": "CLK_VALID", "resolve_type": "user", "usage": "all" } ],
|
||||||
@@ -154,34 +154,34 @@
|
|||||||
"SS_MOD_TIME": [ { "value": "0.004", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"SS_MOD_TIME": [ { "value": "0.004", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"OVERRIDE_MMCM": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"OVERRIDE_MMCM": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_NOTES": [ { "value": "None", "resolve_type": "user", "usage": "all" } ],
|
"MMCM_NOTES": [ { "value": "None", "resolve_type": "user", "usage": "all" } ],
|
||||||
"MMCM_DIVCLK_DIVIDE": [ { "value": "5", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"MMCM_DIVCLK_DIVIDE": [ { "value": "4", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"MMCM_BANDWIDTH": [ { "value": "HIGH", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"MMCM_BANDWIDTH": [ { "value": "OPTIMIZED", "resolve_type": "user", "usage": "all" } ],
|
||||||
"MMCM_CLKFBOUT_MULT_F": [ { "value": "34.125", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKFBOUT_MULT_F": [ { "value": "16.875", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKFBOUT_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKFBOUT_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKFBOUT_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLKFBOUT_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLKIN1_PERIOD": [ { "value": "5.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKIN1_PERIOD": [ { "value": "5.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKIN2_PERIOD": [ { "value": "10.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKIN2_PERIOD": [ { "value": "10.0", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT4_CASCADE": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLKOUT4_CASCADE": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLOCK_HOLD": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLOCK_HOLD": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_COMPENSATION": [ { "value": "ZHOLD", "resolve_type": "user", "usage": "all" } ],
|
"MMCM_COMPENSATION": [ { "value": "ZHOLD", "resolve_type": "user", "usage": "all" } ],
|
||||||
"MMCM_REF_JITTER1": [ { "value": "0.010", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_REF_JITTER1": [ { "value": "0.010", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_REF_JITTER2": [ { "value": "0.010", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_REF_JITTER2": [ { "value": "0.010", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_STARTUP_WAIT": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_STARTUP_WAIT": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT0_DIVIDE_F": [ { "value": "21.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT0_DIVIDE_F": [ { "value": "6.750", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT0_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT0_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT0_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT0_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT0_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLKOUT0_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT1_DIVIDE": [ { "value": "21", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"MMCM_CLKOUT1_DIVIDE": [ { "value": "13", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT1_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT1_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT1_PHASE": [ { "value": "180.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT1_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT1_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLKOUT1_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT2_DIVIDE": [ { "value": "11", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"MMCM_CLKOUT2_DIVIDE": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT2_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT2_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT2_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT2_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT2_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLKOUT2_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT3_DIVIDE": [ { "value": "11", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"MMCM_CLKOUT3_DIVIDE": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT3_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT3_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT3_PHASE": [ { "value": "180.000", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT3_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT3_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"MMCM_CLKOUT3_USE_FINE_PS": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT4_DIVIDE": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"MMCM_CLKOUT4_DIVIDE": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"MMCM_CLKOUT4_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"MMCM_CLKOUT4_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
@@ -223,8 +223,8 @@
|
|||||||
"PLL_CLKOUT5_DIVIDE": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"PLL_CLKOUT5_DIVIDE": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"PLL_CLKOUT5_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"PLL_CLKOUT5_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"PLL_CLKOUT5_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"PLL_CLKOUT5_PHASE": [ { "value": "0.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"RESET_TYPE": [ { "value": "ACTIVE_LOW", "value_src": "user", "resolve_type": "user", "usage": "all" } ],
|
"RESET_TYPE": [ { "value": "ACTIVE_HIGH", "resolve_type": "user", "usage": "all" } ],
|
||||||
"USE_SAFE_CLOCK_STARTUP": [ { "value": "true", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_SAFE_CLOCK_STARTUP": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"USE_CLOCK_SEQUENCING": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"USE_CLOCK_SEQUENCING": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUT1_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"CLKOUT1_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
"CLKOUT2_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
"CLKOUT2_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "user", "format": "long", "usage": "all" } ],
|
||||||
@@ -245,14 +245,14 @@
|
|||||||
"CDDCREQ_PORT": [ { "value": "cddcreq", "resolve_type": "user", "usage": "all" } ],
|
"CDDCREQ_PORT": [ { "value": "cddcreq", "resolve_type": "user", "usage": "all" } ],
|
||||||
"ENABLE_CLKOUTPHY": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
"ENABLE_CLKOUTPHY": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ],
|
||||||
"CLKOUTPHY_REQUESTED_FREQ": [ { "value": "600.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUTPHY_REQUESTED_FREQ": [ { "value": "600.000", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT1_JITTER": [ { "value": "137.256", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT1_JITTER": [ { "value": "162.582", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT1_PHASE_ERROR": [ { "value": "148.044", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT1_PHASE_ERROR": [ { "value": "137.238", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT2_JITTER": [ { "value": "137.256", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT2_JITTER": [ { "value": "185.296", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT2_PHASE_ERROR": [ { "value": "148.044", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT2_PHASE_ERROR": [ { "value": "137.238", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT3_JITTER": [ { "value": "123.850", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT3_JITTER": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT3_PHASE_ERROR": [ { "value": "148.044", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT3_PHASE_ERROR": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT4_JITTER": [ { "value": "123.850", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT4_JITTER": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT4_PHASE_ERROR": [ { "value": "148.044", "value_src": "user", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT4_PHASE_ERROR": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT5_JITTER": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT5_JITTER": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT5_PHASE_ERROR": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT5_PHASE_ERROR": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
"CLKOUT6_JITTER": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
"CLKOUT6_JITTER": [ { "value": "0.0", "resolve_type": "user", "format": "float", "usage": "all" } ],
|
||||||
@@ -280,8 +280,8 @@
|
|||||||
"C_Enable_PLL1": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_Enable_PLL1": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_REF_CLK_FREQ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_REF_CLK_FREQ": [ { "value": "100.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_PRECISION": [ { "value": "1", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_PRECISION": [ { "value": "1", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT3_USED": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT3_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT4_USED": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT4_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT5_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT5_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT6_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT6_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT7_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT7_USED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
@@ -295,9 +295,9 @@
|
|||||||
"C_USE_PHASE_ALIGNMENT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_PHASE_ALIGNMENT": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_PRIM_IN_JITTER": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_PRIM_IN_JITTER": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_SECONDARY_IN_JITTER": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_SECONDARY_IN_JITTER": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_JITTER_SEL": [ { "value": "Min_O_Jitter", "resolve_type": "generated", "usage": "all" } ],
|
"C_JITTER_SEL": [ { "value": "No_Jitter", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_USE_MIN_POWER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_MIN_POWER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_MIN_O_JITTER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_MIN_O_JITTER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_MAX_I_JITTER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_MAX_I_JITTER": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_DYN_PHASE_SHIFT": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_DYN_PHASE_SHIFT": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_OPTIMIZE_CLOCKING_STRUCTURE_EN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_OPTIMIZE_CLOCKING_STRUCTURE_EN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
@@ -318,44 +318,44 @@
|
|||||||
"C_SECONDARY_SOURCE": [ { "value": "Single_ended_clock_capable_pin", "resolve_type": "generated", "usage": "all" } ],
|
"C_SECONDARY_SOURCE": [ { "value": "Single_ended_clock_capable_pin", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKFB_IN_SIGNALING": [ { "value": "SINGLE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKFB_IN_SIGNALING": [ { "value": "SINGLE", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_USE_RESET": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_RESET": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_RESET_LOW": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_RESET_LOW": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_LOCKED": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_LOCKED": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_INCLK_STOPPED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_INCLK_STOPPED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_CLKFB_STOPPED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_CLKFB_STOPPED": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_POWER_DOWN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_POWER_DOWN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_STATUS": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_STATUS": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_FREEZE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_FREEZE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_NUM_OUT_CLKS": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_NUM_OUT_CLKS": [ { "value": "2", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT1_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT1_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT2_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT2_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT3_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT3_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT4_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT4_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT5_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT5_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT6_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT6_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT7_DRIVES": [ { "value": "BUFGCE", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT7_DRIVES": [ { "value": "BUFG", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_INCLK_SUM_ROW0": [ { "value": "Input Clock Freq (MHz) Input Jitter (UI)", "resolve_type": "generated", "usage": "all" } ],
|
"C_INCLK_SUM_ROW0": [ { "value": "Input Clock Freq (MHz) Input Jitter (UI)", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_INCLK_SUM_ROW1": [ { "value": "__primary_________200.000____________0.010", "resolve_type": "generated", "usage": "all" } ],
|
"C_INCLK_SUM_ROW1": [ { "value": "__primary_________200.000____________0.010", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_INCLK_SUM_ROW2": [ { "value": "no_secondary_input_clock ", "resolve_type": "generated", "usage": "all" } ],
|
"C_INCLK_SUM_ROW2": [ { "value": "no_secondary_input_clock ", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW0A": [ { "value": " Output Output Phase Duty Cycle Pk-to-Pk Phase", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW0A": [ { "value": " Output Output Phase Duty Cycle Pk-to-Pk Phase", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW0B": [ { "value": " Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps)", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW0B": [ { "value": " Clock Freq (MHz) (degrees) (%) Jitter (ps) Error (ps)", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW1": [ { "value": "clk_adc_65__65.00000______0.000______50.0______137.256____148.044", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW1": [ { "value": "clk_out1__125.00000______0.000______50.0______162.582____137.238", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW2": [ { "value": "clk_adc_65_180__65.00000____180.000______50.0______137.256____148.044", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW2": [ { "value": "clk_out2__64.90385______0.000______50.0______185.296____137.238", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW3": [ { "value": "clk_dac_125__124.09091______0.000______50.0______123.850____148.044", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW3": [ { "value": "no_CLK_OUT3_output", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW4": [ { "value": "clk_dac_125_180__124.09091____180.000______50.0______123.850____148.044", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW4": [ { "value": "no_CLK_OUT4_output", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW5": [ { "value": "no_CLK_OUT5_output", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW5": [ { "value": "no_CLK_OUT5_output", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW6": [ { "value": "no_CLK_OUT6_output", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW6": [ { "value": "no_CLK_OUT6_output", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OUTCLK_SUM_ROW7": [ { "value": "no_CLK_OUT7_output", "resolve_type": "generated", "usage": "all" } ],
|
"C_OUTCLK_SUM_ROW7": [ { "value": "no_CLK_OUT7_output", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT1_REQUESTED_OUT_FREQ": [ { "value": "65", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT1_REQUESTED_OUT_FREQ": [ { "value": "125", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT2_REQUESTED_OUT_FREQ": [ { "value": "65", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT2_REQUESTED_OUT_FREQ": [ { "value": "65.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT3_REQUESTED_OUT_FREQ": [ { "value": "125", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT3_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT4_REQUESTED_OUT_FREQ": [ { "value": "125", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT4_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT5_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT5_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT6_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT6_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT7_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT7_REQUESTED_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT1_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT1_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT2_REQUESTED_PHASE": [ { "value": "180", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT2_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT3_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT3_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT4_REQUESTED_PHASE": [ { "value": "180", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT4_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT5_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT5_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT6_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT6_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT7_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT7_REQUESTED_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
@@ -366,28 +366,28 @@
|
|||||||
"C_CLKOUT5_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT5_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT6_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT6_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT7_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT7_REQUESTED_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT1_OUT_FREQ": [ { "value": "65.00000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT1_OUT_FREQ": [ { "value": "125.00000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT2_OUT_FREQ": [ { "value": "65.00000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT2_OUT_FREQ": [ { "value": "64.90385", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT3_OUT_FREQ": [ { "value": "124.09091", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT3_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT4_OUT_FREQ": [ { "value": "124.09091", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT4_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT5_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT5_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT6_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT6_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT7_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT7_OUT_FREQ": [ { "value": "100.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT1_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT1_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT2_PHASE": [ { "value": "180.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT2_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT3_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT3_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT4_PHASE": [ { "value": "180.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT4_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT5_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT5_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT6_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT6_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT7_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT7_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT1_DUTY_CYCLE": [ { "value": "50.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT1_DUTY_CYCLE": [ { "value": "50.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT2_DUTY_CYCLE": [ { "value": "50.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT2_DUTY_CYCLE": [ { "value": "50.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT3_DUTY_CYCLE": [ { "value": "50.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT3_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT4_DUTY_CYCLE": [ { "value": "50.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT4_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT5_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT5_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT6_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT6_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_CLKOUT7_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_CLKOUT7_DUTY_CYCLE": [ { "value": "50.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_USE_SAFE_CLOCK_STARTUP": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_SAFE_CLOCK_STARTUP": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_USE_CLOCK_SEQUENCING": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_USE_CLOCK_SEQUENCING": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT1_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT1_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT2_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT2_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
@@ -397,21 +397,21 @@
|
|||||||
"C_CLKOUT6_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT6_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_CLKOUT7_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_CLKOUT7_SEQUENCE_NUMBER": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_NOTES": [ { "value": "None", "resolve_type": "generated", "usage": "all" } ],
|
"C_MMCM_NOTES": [ { "value": "None", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_MMCM_BANDWIDTH": [ { "value": "HIGH", "resolve_type": "generated", "usage": "all" } ],
|
"C_MMCM_BANDWIDTH": [ { "value": "OPTIMIZED", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_MMCM_CLKFBOUT_MULT_F": [ { "value": "34.125", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKFBOUT_MULT_F": [ { "value": "16.875", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKIN1_PERIOD": [ { "value": "5.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKIN1_PERIOD": [ { "value": "5.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKIN2_PERIOD": [ { "value": "10.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKIN2_PERIOD": [ { "value": "10.0", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT4_CASCADE": [ { "value": "FALSE", "resolve_type": "generated", "format": "bool", "usage": "all" } ],
|
"C_MMCM_CLKOUT4_CASCADE": [ { "value": "FALSE", "resolve_type": "generated", "format": "bool", "usage": "all" } ],
|
||||||
"C_MMCM_CLOCK_HOLD": [ { "value": "FALSE", "resolve_type": "generated", "format": "bool", "usage": "all" } ],
|
"C_MMCM_CLOCK_HOLD": [ { "value": "FALSE", "resolve_type": "generated", "format": "bool", "usage": "all" } ],
|
||||||
"C_MMCM_COMPENSATION": [ { "value": "ZHOLD", "resolve_type": "generated", "usage": "all" } ],
|
"C_MMCM_COMPENSATION": [ { "value": "ZHOLD", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_MMCM_DIVCLK_DIVIDE": [ { "value": "5", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_DIVCLK_DIVIDE": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_REF_JITTER1": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_REF_JITTER1": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_REF_JITTER2": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_REF_JITTER2": [ { "value": "0.010", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_STARTUP_WAIT": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ],
|
"C_MMCM_STARTUP_WAIT": [ { "value": "FALSE", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT0_DIVIDE_F": [ { "value": "21.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT0_DIVIDE_F": [ { "value": "6.750", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT1_DIVIDE": [ { "value": "21", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_CLKOUT1_DIVIDE": [ { "value": "13", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT2_DIVIDE": [ { "value": "11", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_CLKOUT2_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT3_DIVIDE": [ { "value": "11", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_CLKOUT3_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT4_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_CLKOUT4_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT5_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_CLKOUT5_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT6_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_MMCM_CLKOUT6_DIVIDE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
@@ -424,9 +424,9 @@
|
|||||||
"C_MMCM_CLKOUT6_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT6_DUTY_CYCLE": [ { "value": "0.500", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKFBOUT_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKFBOUT_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT0_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT0_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT1_PHASE": [ { "value": "180.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT1_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT2_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT2_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT3_PHASE": [ { "value": "180.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT3_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT4_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT4_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT5_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT5_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_MMCM_CLKOUT6_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_MMCM_CLKOUT6_PHASE": [ { "value": "0.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
@@ -468,16 +468,16 @@
|
|||||||
"C_CLOCK_MGR_TYPE": [ { "value": "NA", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLOCK_MGR_TYPE": [ { "value": "NA", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_OVERRIDE_MMCM": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_OVERRIDE_MMCM": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_OVERRIDE_PLL": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
"C_OVERRIDE_PLL": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ],
|
||||||
"C_PRIMARY_PORT": [ { "value": "clk_200", "resolve_type": "generated", "usage": "all" } ],
|
"C_PRIMARY_PORT": [ { "value": "clk_in1", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_SECONDARY_PORT": [ { "value": "clk_in2", "resolve_type": "generated", "usage": "all" } ],
|
"C_SECONDARY_PORT": [ { "value": "clk_in2", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT1_PORT": [ { "value": "clk_adc_65", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT1_PORT": [ { "value": "clk_out1", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT2_PORT": [ { "value": "clk_adc_65_180", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT2_PORT": [ { "value": "clk_out2", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT3_PORT": [ { "value": "clk_dac_125", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT3_PORT": [ { "value": "clk_out3", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT4_PORT": [ { "value": "clk_dac_125_180", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT4_PORT": [ { "value": "clk_out4", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT5_PORT": [ { "value": "clk_out5", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT5_PORT": [ { "value": "clk_out5", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT6_PORT": [ { "value": "clk_out6", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT6_PORT": [ { "value": "clk_out6", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLK_OUT7_PORT": [ { "value": "clk_out7", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLK_OUT7_PORT": [ { "value": "clk_out7", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_RESET_PORT": [ { "value": "resetn", "resolve_type": "generated", "usage": "all" } ],
|
"C_RESET_PORT": [ { "value": "reset", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_LOCKED_PORT": [ { "value": "locked", "resolve_type": "generated", "usage": "all" } ],
|
"C_LOCKED_PORT": [ { "value": "locked", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKFB_IN_PORT": [ { "value": "clkfb_in", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKFB_IN_PORT": [ { "value": "clkfb_in", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKFB_IN_P_PORT": [ { "value": "clkfb_in_p", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKFB_IN_P_PORT": [ { "value": "clkfb_in_p", "resolve_type": "generated", "usage": "all" } ],
|
||||||
@@ -540,12 +540,12 @@
|
|||||||
"C_FILTER_1": [ { "value": "0000", "resolve_type": "generated", "usage": "all" } ],
|
"C_FILTER_1": [ { "value": "0000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_FILTER_2": [ { "value": "0000", "resolve_type": "generated", "usage": "all" } ],
|
"C_FILTER_2": [ { "value": "0000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE1_AUTO": [ { "value": "1", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE1_AUTO": [ { "value": "1", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE2_AUTO": [ { "value": "1.0", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE2_AUTO": [ { "value": "1.9259259259259258", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE3_AUTO": [ { "value": "0.5238095238095238", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE3_AUTO": [ { "value": "0.14814814814814814", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE4_AUTO": [ { "value": "0.5238095238095238", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE4_AUTO": [ { "value": "0.14814814814814814", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE5_AUTO": [ { "value": "0.047619047619047616", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE5_AUTO": [ { "value": "0.14814814814814814", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE6_AUTO": [ { "value": "0.047619047619047616", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE6_AUTO": [ { "value": "0.14814814814814814", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_DIVIDE7_AUTO": [ { "value": "0.047619047619047616", "resolve_type": "generated", "usage": "all" } ],
|
"C_DIVIDE7_AUTO": [ { "value": "0.14814814814814814", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_PLLBUFGCEDIV": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
"C_PLLBUFGCEDIV": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_MMCMBUFGCEDIV": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
"C_MMCMBUFGCEDIV": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_PLLBUFGCEDIV1": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
"C_PLLBUFGCEDIV1": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
||||||
@@ -566,68 +566,66 @@
|
|||||||
"C_CLKOUT5_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT5_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT6_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT6_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT7_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT7_MATCHED_ROUTING": [ { "value": "false", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT0_ACTUAL_FREQ": [ { "value": "65.00000", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT0_ACTUAL_FREQ": [ { "value": "125.00000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT1_ACTUAL_FREQ": [ { "value": "65.00000", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT1_ACTUAL_FREQ": [ { "value": "64.90385", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT2_ACTUAL_FREQ": [ { "value": "124.09091", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT2_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT3_ACTUAL_FREQ": [ { "value": "124.09091", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT3_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT4_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT4_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT5_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT5_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_CLKOUT6_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
"C_CLKOUT6_ACTUAL_FREQ": [ { "value": "100.000", "resolve_type": "generated", "usage": "all" } ],
|
||||||
"C_M_MAX": [ { "value": "64.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_M_MAX": [ { "value": "64.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_M_MIN": [ { "value": "2.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_M_MIN": [ { "value": "2.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_D_MAX": [ { "value": "93.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_D_MAX": [ { "value": "80.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_D_MIN": [ { "value": "1.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_D_MIN": [ { "value": "1.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_O_MAX": [ { "value": "128.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_O_MAX": [ { "value": "128.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_O_MIN": [ { "value": "1.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_O_MIN": [ { "value": "1.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_VCO_MIN": [ { "value": "600.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
"C_VCO_MIN": [ { "value": "600.000", "resolve_type": "generated", "format": "float", "usage": "all" } ],
|
||||||
"C_VCO_MAX": [ { "value": "1440.000", "resolve_type": "generated", "format": "float", "usage": "all" } ]
|
"C_VCO_MAX": [ { "value": "1200.000", "resolve_type": "generated", "format": "float", "usage": "all" } ]
|
||||||
},
|
},
|
||||||
"project_parameters": {
|
"project_parameters": {
|
||||||
"ARCHITECTURE": [ { "value": "artix7", "resolve_type": "generated", "usage": "all" } ],
|
"ARCHITECTURE": [ { "value": "artix7" } ],
|
||||||
"BASE_BOARD_PART": [ { "value": "", "resolve_type": "generated", "usage": "all" } ],
|
"BASE_BOARD_PART": [ { "value": "" } ],
|
||||||
"BOARD_CONNECTIONS": [ { "value": "", "resolve_type": "generated", "usage": "all" } ],
|
"BOARD_CONNECTIONS": [ { "value": "" } ],
|
||||||
"DEVICE": [ { "value": "xc7a100t", "resolve_type": "generated", "usage": "all" } ],
|
"DEVICE": [ { "value": "xc7a35t" } ],
|
||||||
"PACKAGE": [ { "value": "fgg484", "resolve_type": "generated", "usage": "all" } ],
|
"PACKAGE": [ { "value": "fgg484" } ],
|
||||||
"PREFHDL": [ { "value": "VERILOG", "resolve_type": "generated", "usage": "all" } ],
|
"PREFHDL": [ { "value": "VERILOG" } ],
|
||||||
"SILICON_REVISION": [ { "value": "", "resolve_type": "generated", "usage": "all" } ],
|
"SILICON_REVISION": [ { "value": "" } ],
|
||||||
"SIMULATOR_LANGUAGE": [ { "value": "MIXED", "resolve_type": "generated", "usage": "all" } ],
|
"SIMULATOR_LANGUAGE": [ { "value": "MIXED" } ],
|
||||||
"SPEEDGRADE": [ { "value": "-2", "resolve_type": "generated", "usage": "all" } ],
|
"SPEEDGRADE": [ { "value": "-1" } ],
|
||||||
"STATIC_POWER": [ { "value": "", "resolve_type": "generated", "usage": "all" } ],
|
"STATIC_POWER": [ { "value": "" } ],
|
||||||
"TEMPERATURE_GRADE": [ { "value": "", "resolve_type": "generated", "usage": "all" } ]
|
"TEMPERATURE_GRADE": [ { "value": "" } ]
|
||||||
},
|
},
|
||||||
"runtime_parameters": {
|
"runtime_parameters": {
|
||||||
"IPCONTEXT": [ { "value": "IP_Flow" } ],
|
"IPCONTEXT": [ { "value": "IP_Flow" } ],
|
||||||
"IPREVISION": [ { "value": "17" } ],
|
"IPREVISION": [ { "value": "16" } ],
|
||||||
"MANAGED": [ { "value": "TRUE" } ],
|
"MANAGED": [ { "value": "TRUE" } ],
|
||||||
"OUTPUTDIR": [ { "value": "../../../../reflectometer_top.gen/sources_1/ip/clk_wiz_ctrl_inst" } ],
|
"OUTPUTDIR": [ { "value": "../../../../eth_generator_top.gen/sources_1/ip/clk_wiz_ctrl_inst" } ],
|
||||||
"SELECTEDSIMMODEL": [ { "value": "" } ],
|
"SELECTEDSIMMODEL": [ { "value": "" } ],
|
||||||
"SHAREDDIR": [ { "value": "." } ],
|
"SHAREDDIR": [ { "value": "." } ],
|
||||||
"SWVERSION": [ { "value": "2025.2" } ],
|
"SWVERSION": [ { "value": "2025.1" } ],
|
||||||
"SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ]
|
"SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"boundary": {
|
"boundary": {
|
||||||
"ports": {
|
"ports": {
|
||||||
"resetn": [ { "direction": "in", "driver_value": "0" } ],
|
"reset": [ { "direction": "in", "driver_value": "0" } ],
|
||||||
"clk_200": [ { "direction": "in" } ],
|
"clk_in1": [ { "direction": "in" } ],
|
||||||
"clk_adc_65": [ { "direction": "out" } ],
|
"clk_out1": [ { "direction": "out" } ],
|
||||||
"clk_adc_65_180": [ { "direction": "out" } ],
|
"clk_out2": [ { "direction": "out" } ],
|
||||||
"clk_dac_125": [ { "direction": "out" } ],
|
|
||||||
"clk_dac_125_180": [ { "direction": "out" } ],
|
|
||||||
"locked": [ { "direction": "out" } ]
|
"locked": [ { "direction": "out" } ]
|
||||||
},
|
},
|
||||||
"interfaces": {
|
"interfaces": {
|
||||||
"resetn": {
|
"reset": {
|
||||||
"vlnv": "xilinx.com:signal:reset:1.0",
|
"vlnv": "xilinx.com:signal:reset:1.0",
|
||||||
"abstraction_type": "xilinx.com:signal:reset_rtl:1.0",
|
"abstraction_type": "xilinx.com:signal:reset_rtl:1.0",
|
||||||
"mode": "slave",
|
"mode": "slave",
|
||||||
"parameters": {
|
"parameters": {
|
||||||
"POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ],
|
"POLARITY": [ { "value": "ACTIVE_HIGH", "value_src": "constant", "usage": "all" } ],
|
||||||
"BOARD.ASSOCIATED_PARAM": [ { "value": "RESET_BOARD_INTERFACE", "value_src": "constant", "usage": "all" } ],
|
"BOARD.ASSOCIATED_PARAM": [ { "value": "RESET_BOARD_INTERFACE", "value_src": "constant", "usage": "all" } ],
|
||||||
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
||||||
},
|
},
|
||||||
"port_maps": {
|
"port_maps": {
|
||||||
"RST": [ { "physical_name": "resetn" } ]
|
"RST": [ { "physical_name": "reset" } ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clock_CLK_IN1": {
|
"clock_CLK_IN1": {
|
||||||
@@ -646,7 +644,7 @@
|
|||||||
"BOARD.ASSOCIATED_PARAM": [ { "value": "CLK_IN1_BOARD_INTERFACE", "usage": "all", "is_static_object": false } ]
|
"BOARD.ASSOCIATED_PARAM": [ { "value": "CLK_IN1_BOARD_INTERFACE", "usage": "all", "is_static_object": false } ]
|
||||||
},
|
},
|
||||||
"port_maps": {
|
"port_maps": {
|
||||||
"CLK_IN1": [ { "physical_name": "clk_200" } ]
|
"CLK_IN1": [ { "physical_name": "clk_in1" } ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clock_CLK_OUT1": {
|
"clock_CLK_OUT1": {
|
||||||
@@ -664,7 +662,7 @@
|
|||||||
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
||||||
},
|
},
|
||||||
"port_maps": {
|
"port_maps": {
|
||||||
"CLK_OUT1": [ { "physical_name": "clk_adc_65" } ]
|
"CLK_OUT1": [ { "physical_name": "clk_out1" } ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"clock_CLK_OUT2": {
|
"clock_CLK_OUT2": {
|
||||||
@@ -682,47 +680,10 @@
|
|||||||
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
||||||
},
|
},
|
||||||
"port_maps": {
|
"port_maps": {
|
||||||
"CLK_OUT2": [ { "physical_name": "clk_adc_65_180" } ]
|
"CLK_OUT2": [ { "physical_name": "clk_out2" } ]
|
||||||
}
|
|
||||||
},
|
|
||||||
"clock_CLK_OUT3": {
|
|
||||||
"vlnv": "xilinx.com:signal:clock:1.0",
|
|
||||||
"abstraction_type": "xilinx.com:signal:clock_rtl:1.0",
|
|
||||||
"mode": "master",
|
|
||||||
"parameters": {
|
|
||||||
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
|
||||||
},
|
|
||||||
"port_maps": {
|
|
||||||
"CLK_OUT3": [ { "physical_name": "clk_dac_125" } ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"clock_CLK_OUT4": {
|
|
||||||
"vlnv": "xilinx.com:signal:clock:1.0",
|
|
||||||
"abstraction_type": "xilinx.com:signal:clock_rtl:1.0",
|
|
||||||
"mode": "master",
|
|
||||||
"parameters": {
|
|
||||||
"FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"ASSOCIATED_BUSIF": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"ASSOCIATED_RESET": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ],
|
|
||||||
"INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ]
|
|
||||||
},
|
|
||||||
"port_maps": {
|
|
||||||
"CLK_OUT4": [ { "physical_name": "clk_dac_125_180" } ]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"checksum": "3ec15bbf"
|
|
||||||
}
|
}
|
||||||
@@ -1,115 +1,128 @@
|
|||||||
`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,
|
||||||
parameter int unsigned PACK_FACTOR = 1,
|
parameter PACK_FACTOR = 1,
|
||||||
parameter int unsigned PROCESS_MODE = 0,
|
parameter PROCESS_MODE = 0,
|
||||||
parameter int unsigned ZERO_LEVEL = 8192,
|
parameter ZERO_LEVEL = 8192,
|
||||||
parameter int unsigned ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
parameter int unsigned N_MAX = 4096,
|
parameter N_MAX = 4096,
|
||||||
parameter int unsigned PACKET_SIZE = 1024
|
parameter WINDOW_SIZE = 65,
|
||||||
|
parameter PACKET_SIZE = 1024
|
||||||
)(
|
)(
|
||||||
input wire clk_in,
|
input sys_clk,
|
||||||
input wire rst_n,
|
input rst_n,
|
||||||
output wire locked,
|
|
||||||
|
|
||||||
// Accumulator AXI-S bus
|
output [3:0] led,
|
||||||
input wire clk_axis_accumulator, // GMII PHY RX clock
|
|
||||||
axis_if.master axis_accumulator,
|
|
||||||
|
|
||||||
// Control AXI-S bus
|
input gmii_rx_clk,
|
||||||
input wire clk_axis_control, // GMII PHY TX clock
|
input gmii_tx_clk,
|
||||||
axis_if.slave axis_control,
|
|
||||||
input wire [31:0] window_size, // New accum & old controller crutch
|
|
||||||
|
|
||||||
// Status signals
|
(* MARK_DEBUG="true" *) output logic [7:0] s_axis_tx_tdata,
|
||||||
output wire workflow_done,
|
(* MARK_DEBUG="true" *) output logic s_axis_tx_tvalid,
|
||||||
output wire processing_done,
|
(* MARK_DEBUG="true" *) input logic s_axis_tx_tready,
|
||||||
|
(* MARK_DEBUG="true" *) output logic s_axis_tx_tlast,
|
||||||
|
|
||||||
// RTL-MAC handshake
|
(* MARK_DEBUG="true" *) input wire [7:0] m_axis_rx_tdata,
|
||||||
input wire request_ready,
|
(* MARK_DEBUG="true" *) input wire m_axis_rx_tvalid,
|
||||||
output wire send_request,
|
(* 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 wire dac_clk_o,
|
|
||||||
output wire [DAC_DATA_WIDTH-1:0] dac_data,
|
output wire p2_clk,
|
||||||
output wire dac_wrt,
|
(* MARK_DEBUG="true" *) output wire [DAC_DATA_WIDTH-1:0] p2_data,
|
||||||
|
(* MARK_DEBUG="true" *) output wire p2_wrt,
|
||||||
|
|
||||||
// ADC
|
// ADC
|
||||||
output wire adc_clk_o,
|
output ch2_clk,
|
||||||
input wire [ADC_DATA_WIDTH-1:0] adc_data,
|
(* MARK_DEBUG="true" *) input [ADC_DATA_WIDTH-1:0] ch2_data,
|
||||||
input wire adc_otr
|
input ch2_otr
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Generated clocks for controller
|
// IDELAYCTRL
|
||||||
// Need to create this IP in Vivado:
|
|
||||||
// input resetn
|
|
||||||
// input clk_200 : 200 MHz : Reference clock
|
|
||||||
// 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 clk_sampler, clk_generator, clk_locked;
|
(* IODELAY_GROUP = "rgmii_idelay_group" *)
|
||||||
|
IDELAYCTRL IDELAYCTRL_inst (
|
||||||
clk_wiz_ctrl_inst clk_wiz_inst
|
.RDY (),
|
||||||
(
|
.REFCLK (sys_clk),
|
||||||
// Clock in ports
|
.RST (1'b0)
|
||||||
.clk_200(clk_in),
|
|
||||||
// Clock out ports
|
|
||||||
.clk_adc_65(clk_sampler),
|
|
||||||
.clk_adc_65_180(adc_clk_o),
|
|
||||||
.clk_dac_125(clk_generator),
|
|
||||||
.clk_dac_125_180(dac_clk_o),
|
|
||||||
// Status and control signals
|
|
||||||
.resetn(rst_n),
|
|
||||||
.locked(clk_locked)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assign locked = clk_locked;
|
// -------------------------------------------------------------------------
|
||||||
|
// Generated clocks for controller
|
||||||
|
// Need to create this IP in Vivado:
|
||||||
|
// input : 200 MHz
|
||||||
|
// output0: 130 MHz
|
||||||
|
// output1: 65 MHz
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
wire dac_clk;
|
||||||
|
wire adc_clk;
|
||||||
|
wire clk_wiz_locked;
|
||||||
|
|
||||||
|
clk_wiz_ctrl_inst clk_wiz_ctrl_inst (
|
||||||
|
.clk_in1 (sys_clk),
|
||||||
|
.reset (~rst_n),
|
||||||
|
.clk_out1 (dac_clk), // 130 MHz
|
||||||
|
.clk_out2 (adc_clk), // 65 MHz
|
||||||
|
.locked (clk_wiz_locked)
|
||||||
|
);
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// axis_mac interface
|
||||||
|
// RX stream from Ethernet goes into controller
|
||||||
|
// TX stream is unused for now
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Controller reset
|
// Controller reset
|
||||||
// Use both external reset and clk_wiz lock
|
// Use both external reset and clk_wiz lock
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
wire ctrl_rst_n = rst_n & clk_locked;
|
wire ctrl_rst_n = rst_n & clk_wiz_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 (clk_axis_control),
|
.eth_clk_in (gmii_rx_clk),
|
||||||
.dac_clk_in (clk_generator),
|
.dac_clk_in (dac_clk),
|
||||||
.adc_clk_in (clk_sampler),
|
.adc_clk_in (adc_clk),
|
||||||
.rst_n (ctrl_rst_n),
|
.rst_n (ctrl_rst_n),
|
||||||
|
|
||||||
.s_axis_tdata (axis_control.tdata),
|
.s_axis_tdata (m_axis_rx_tdata),
|
||||||
.s_axis_tvalid (axis_control.tvalid),
|
.s_axis_tvalid (m_axis_rx_tvalid),
|
||||||
.s_axis_tready (axis_control.tready),
|
.s_axis_tready (m_axis_rx_tready),
|
||||||
.s_axis_tlast (axis_control.tlast),
|
.s_axis_tlast (m_axis_rx_tlast),
|
||||||
|
|
||||||
.finish (finish),
|
.finish (finish),
|
||||||
|
|
||||||
@@ -128,125 +141,180 @@ 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
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
(* ASYNC_REG = "TRUE" *) logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
always_ff @(posedge adc_clk or posedge adc_rst) begin
|
||||||
(* ASYNC_REG = "TRUE" *) logic [1:0] sync_DA;
|
if (adc_rst) begin
|
||||||
wire dac_done_stretched;
|
sample_req <= 1'b0;
|
||||||
|
sample_req_sync2 <= 1'b0;
|
||||||
wire generator_done, generator_request;
|
sample_req_sync3 <= 1'b0;
|
||||||
wire sampler_done, sampler_request;
|
end
|
||||||
|
|
||||||
always_ff @(posedge clk_generator or posedge dac_rst)
|
|
||||||
begin
|
|
||||||
if (dac_rst)
|
|
||||||
stretch <= 0;
|
|
||||||
else begin
|
else begin
|
||||||
stretch[0] <= generator_done;
|
sample_req_sync2 <= sample_req_sync1;
|
||||||
stretch[1] <= stretch[0];
|
sample_req_sync3 <= sample_req_sync2;
|
||||||
stretch[2] <= stretch[1];
|
sample_req <= sample_req_sync3;
|
||||||
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
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
(* ASYNC_REG = "TRUE" *) logic [1:0] sync_AD;
|
always_ff @(posedge dac_clk or posedge dac_rst) begin
|
||||||
|
if (dac_rst) begin
|
||||||
always_ff @(posedge clk_generator or posedge dac_rst) begin
|
sample_done <= 1'b0;
|
||||||
if (dac_rst)
|
sample_done_sync2 <= 1'b0;
|
||||||
sync_AD <= 0;
|
sample_done_sync3 <= 1'b0;
|
||||||
|
end
|
||||||
else begin
|
else begin
|
||||||
sync_AD[0] <= sampler_done;
|
sample_done_sync2 <= sample_done_sync1;
|
||||||
sync_AD[1] <= sync_AD[0];
|
sample_done_sync3 <= sample_done_sync2;
|
||||||
|
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_dac(clk_generator),
|
.clk_in(dac_clk),
|
||||||
.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),
|
||||||
.dac_out(dac_data),
|
.pulse(p2_wrt),
|
||||||
.done(generator_done),
|
.pulse_height_out(p2_data),
|
||||||
.request(generator_request)
|
.sample_done(sample_done),
|
||||||
|
.sample_req(sample_req_sync1)
|
||||||
);
|
);
|
||||||
assign dac_wrt = dac_clk_o;
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
wire ch2_clk_oddr;
|
||||||
// Sampler (ADC)
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] sampler_m_axis_tdata;
|
|
||||||
wire sampler_m_axis_tvalid;
|
|
||||||
|
|
||||||
sampler #(
|
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
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(* MARK_DEBUG="true" *) logic [ADC_DATA_WIDTH*PACK_FACTOR-1:0] accum_m_axis_tdata;
|
||||||
|
(* 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)
|
||||||
) sampler_dut (
|
)
|
||||||
.clk_in(clk_sampler),
|
sampler_dut
|
||||||
.rst(adc_rst),
|
(
|
||||||
.data_in(adc_data),
|
.clk_in(adc_clk),
|
||||||
.out_of_range(adc_otr),
|
.rst(adc_rst),
|
||||||
.m_axis_tdata(sampler_m_axis_tdata),
|
.data_in(ch2_data),
|
||||||
.m_axis_tvalid(sampler_m_axis_tvalid),
|
.out_of_range(ch2_otr),
|
||||||
|
.m_axis_tdata(accum_m_axis_tdata),
|
||||||
|
.m_axis_tvalid(acum_m_axis_tvalid),
|
||||||
.smp_num(adc_pulse_period),
|
.smp_num(adc_pulse_period),
|
||||||
.done(sampler_done),
|
.sample_req(sample_req),
|
||||||
.request(sampler_request)
|
.sample_done(sample_done_sync1)
|
||||||
);
|
);
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// Accumulator
|
// Accumulator
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
assign workflow_done = finish;
|
|
||||||
|
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),
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
.PACKET_SIZE(PACKET_SIZE)
|
||||||
) accumulator_top_dut (
|
)
|
||||||
.clk_in(clk_sampler),
|
accumulator_top_dut
|
||||||
|
(
|
||||||
|
.clk_in(adc_clk),
|
||||||
.rst(adc_rst),
|
.rst(adc_rst),
|
||||||
.s_axis_tdata(sampler_m_axis_tdata),
|
.s_axis_tdata(accum_m_axis_tdata),
|
||||||
.s_axis_tvalid(sampler_m_axis_tvalid),
|
.s_axis_tvalid(acum_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),
|
||||||
.window_size(window_size),
|
|
||||||
|
|
||||||
.req_ready(request_ready),
|
.eth_clk_in(gmii_tx_clk),
|
||||||
.send_req(send_request),
|
.req_ready(req_ready),
|
||||||
.eth_clk_in(clk_axis_accumulator),
|
.send_req(send_req),
|
||||||
.m_axis_tdata(axis_accumulator.tdata),
|
.m_axis_tdata(s_axis_tx_tdata),
|
||||||
.m_axis_tvalid(axis_accumulator.tvalid),
|
.m_axis_tvalid(s_axis_tx_tvalid),
|
||||||
.m_axis_tready(axis_accumulator.tready),
|
.m_axis_tready(s_axis_tx_tready),
|
||||||
.m_axis_tlast(axis_accumulator.tlast),
|
.m_axis_tlast(s_axis_tx_tlast),
|
||||||
|
|
||||||
.finish(finish), // full reflectometer workflow complete (with transaction)
|
.finish(finish)
|
||||||
.accum_done(processing_done) // signal generation, sampling and processing complete
|
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Simple LED status
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
assign led[0] = clk_wiz_locked;
|
||||||
|
assign led[1] = m_axis_rx_tvalid;
|
||||||
|
assign led[2] = dac_start;
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -1,794 +0,0 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
`include "interfaces.svh"
|
|
||||||
|
|
||||||
// `define DEBUG
|
|
||||||
|
|
||||||
`define MEASURE_CLK(clk, period) \
|
|
||||||
begin \
|
|
||||||
realtime t1, t2; \
|
|
||||||
@(posedge clk); \
|
|
||||||
t1 = $realtime; \
|
|
||||||
@(posedge clk); \
|
|
||||||
t2 = $realtime; \
|
|
||||||
period = t2 - t1; \
|
|
||||||
end
|
|
||||||
|
|
||||||
`define ERR_CHECK \
|
|
||||||
total_tests++; \
|
|
||||||
if (result_flag) begin \
|
|
||||||
total_failed_tests++; \
|
|
||||||
$error("Test #%0d failed. Err code: %0d", total_tests, result_flag); \
|
|
||||||
end \
|
|
||||||
|
|
||||||
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. Current accumulator don't support signed sum
|
|
||||||
localparam ACCUM_WIDTH = 32; // accumulator number bit witdth
|
|
||||||
localparam N_MAX = 4096; // max value of windows to average by experiments
|
|
||||||
localparam PACKET_SIZE = 1024; // bytes per UDP packet
|
|
||||||
|
|
||||||
localparam int REQUEST_TIMEOUT = 3 * PACKET_SIZE; // timeout for packet receiving from accumulator
|
|
||||||
localparam int TEST_NUM = 100; // number of random tests
|
|
||||||
|
|
||||||
localparam real PEARSON_THRESHOLD = 0.99;
|
|
||||||
localparam real NRMSE_THRESHOLD = 0.1;
|
|
||||||
|
|
||||||
localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "voltage"
|
|
||||||
|
|
||||||
localparam CLK_ETH_PHY_PERIOD = 8.000; // 125 MHz
|
|
||||||
localparam CLK_REF_PERIOD = 5.000; // 200 MHz
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Глобальные перменные
|
|
||||||
//------------------------------------------------------------
|
|
||||||
realtime CLK_ADC_PERIOD;
|
|
||||||
realtime CLK_DAC_PERIOD;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Тактовые сигналы и сброс
|
|
||||||
//------------------------------------------------------------
|
|
||||||
logic clk_ref = 1'b0; // 200 MHz
|
|
||||||
logic clk_eth_phy = 1'b0; // common for RX & TX
|
|
||||||
logic rst_n = 1'b0;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Управление и конфиг DUT
|
|
||||||
//------------------------------------------------------------
|
|
||||||
logic [31:0] window_size_port;
|
|
||||||
// AXI-S интерфейс для управления
|
|
||||||
axis_if axis_control_if (
|
|
||||||
.clk(clk_eth_phy),
|
|
||||||
.rst_n(rst_n)
|
|
||||||
);
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Входы DUT
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// ADC интерфейс
|
|
||||||
wire clk_adc;
|
|
||||||
wire adc_otr;
|
|
||||||
wire [ADC_DATA_WIDTH-1:0] adc_data;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Выходы
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Статусы
|
|
||||||
wire mmcm_locked;
|
|
||||||
wire workflow_done;
|
|
||||||
wire processing_done;
|
|
||||||
// DAC интерфейс
|
|
||||||
wire clk_dac;
|
|
||||||
wire dac_wrt;
|
|
||||||
wire [DAC_DATA_WIDTH-1:0] dac_data;
|
|
||||||
// AXI-S интерфейс для данных
|
|
||||||
axis_if axis_accumulator_if (
|
|
||||||
.clk(clk_eth_phy),
|
|
||||||
.rst_n(rst_n)
|
|
||||||
);
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Внутренние сигналы тестбенча
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Интерфейс хендшейка с MAC-PHY
|
|
||||||
wire send_request;
|
|
||||||
logic request_ready;
|
|
||||||
// Сигнал между ЦАП и АЦП
|
|
||||||
real signal_voltage;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Virtual DAC
|
|
||||||
//------------------------------------------------------------
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// 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 processing
|
|
||||||
//------------------------------------------------------------
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// 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),
|
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
|
||||||
) DUT (
|
|
||||||
.clk_in(clk_ref),
|
|
||||||
.rst_n(rst_n),
|
|
||||||
|
|
||||||
// Status
|
|
||||||
.locked(mmcm_locked),
|
|
||||||
.workflow_done(workflow_done),
|
|
||||||
.processing_done(processing_done),
|
|
||||||
|
|
||||||
// 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),
|
|
||||||
.window_size(window_size_port), // direct signal crutch (old controller)
|
|
||||||
|
|
||||||
// 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-Stream
|
|
||||||
task automatic dut_soft_reset(virtual axis_if#(8).tb vif);
|
|
||||||
logic [7:0] tx_packet[];
|
|
||||||
tx_packet = '{8'h0f};
|
|
||||||
vif.master_send(tx_packet);
|
|
||||||
endtask
|
|
||||||
|
|
||||||
task automatic dut_start(virtual axis_if#(8).tb vif);
|
|
||||||
logic [7:0] tx_packet[];
|
|
||||||
tx_packet = '{8'hf0};
|
|
||||||
vif.master_send(tx_packet);
|
|
||||||
endtask
|
|
||||||
|
|
||||||
task automatic dut_send_system_config(
|
|
||||||
virtual axis_if#(8).tb vif,
|
|
||||||
input logic [31:0] pulse_width,
|
|
||||||
input logic [31:0] pulse_period,
|
|
||||||
input logic [15:0] pulse_num,
|
|
||||||
input logic [13:0] pulse_height, // achtung! p_height strictly must have 14 bits of width
|
|
||||||
input logic [31:0] pulse_period_adc,
|
|
||||||
input logic [31:0] window_size
|
|
||||||
);
|
|
||||||
// Создаем временный фиксированный массив и упаковываем всё одной строкой
|
|
||||||
logic [7:0] tx_packet[];
|
|
||||||
|
|
||||||
// Ахтунг, 14-битный ЦАП захардкожен
|
|
||||||
if (DAC_DATA_WIDTH != 14)
|
|
||||||
$warning("[WARNING] -dut_send_system_config- Default pulse height (DAC bitwidth) is equal to 14. Be aware, controller packet structure is coded for 14 bits");
|
|
||||||
|
|
||||||
tx_packet = '{
|
|
||||||
8'h88, // Команда
|
|
||||||
pulse_width[7:0], pulse_width[15:8], pulse_width[23:16], pulse_width[31:24],
|
|
||||||
pulse_period[7:0], pulse_period[15:8], pulse_period[23:16], pulse_period[31:24],
|
|
||||||
pulse_num[7:0], pulse_num[15:8], pulse_height[7:0], 8'({2'b00, pulse_height[13:8]}),
|
|
||||||
pulse_period_adc[7:0], pulse_period_adc[15:8], pulse_period_adc[23:16], pulse_period_adc[31:24]
|
|
||||||
};
|
|
||||||
|
|
||||||
vif.master_send(tx_packet);
|
|
||||||
|
|
||||||
// TODO remove for new controller
|
|
||||||
window_size_port = window_size;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таски сбора статистики
|
|
||||||
task automatic dut_read_output(
|
|
||||||
virtual axis_if#(8).tb vif,
|
|
||||||
input int sample_num,
|
|
||||||
input int window_size,
|
|
||||||
input bit randomize_recv_delays,
|
|
||||||
output int output_data[]
|
|
||||||
);
|
|
||||||
logic [7:0] rx_packet[];
|
|
||||||
logic [ACCUM_WIDTH-1:0] data_packet[];
|
|
||||||
int numbers_per_packet = PACKET_SIZE/(ACCUM_WIDTH/8);
|
|
||||||
int packet_num = $ceil(real'(sample_num / window_size) / real'(numbers_per_packet));
|
|
||||||
int timeout_flag = 0;
|
|
||||||
int packet_counter = 0;
|
|
||||||
|
|
||||||
if (sample_num % window_size) begin
|
|
||||||
$error("-dut_read_output- Sample_num must be multiple of window_size: %0d %% %0d = %0d", sample_num, window_size, sample_num % window_size);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
data_packet = new[numbers_per_packet];
|
|
||||||
output_data = new[numbers_per_packet * packet_num];
|
|
||||||
|
|
||||||
// count send_request pulses (equal to number of packets)
|
|
||||||
fork
|
|
||||||
begin : packet_counter_proc
|
|
||||||
forever begin
|
|
||||||
@(posedge clk_eth_phy);
|
|
||||||
if(send_request === 1)
|
|
||||||
packet_counter++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
join_none
|
|
||||||
|
|
||||||
// Wait until reflectometer done sampling and averaging
|
|
||||||
wait(processing_done == 1);
|
|
||||||
|
|
||||||
// recv loop
|
|
||||||
// если число пакетов превышает заложенное предрассчитанное значение -- ошибка
|
|
||||||
fork : recv_loop_proc
|
|
||||||
begin
|
|
||||||
// packet recv loop
|
|
||||||
forever begin
|
|
||||||
if (packet_counter > packet_num) begin
|
|
||||||
$error("-dut_read_output- Packet overflow detected. Number of data packets exceeds expected amount of packets");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (randomize_recv_delays)
|
|
||||||
repeat($urandom_range(0, 500)) @(posedge clk_eth_phy);
|
|
||||||
|
|
||||||
timeout_flag = 0;
|
|
||||||
fork : receive_packet_timeout
|
|
||||||
begin
|
|
||||||
request_ready = 1;
|
|
||||||
vif.slave_recv(rx_packet);
|
|
||||||
request_ready = 0;
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
repeat(REQUEST_TIMEOUT) @(posedge clk_eth_phy);
|
|
||||||
timeout_flag = 1;
|
|
||||||
end
|
|
||||||
join_any
|
|
||||||
|
|
||||||
disable receive_packet_timeout;
|
|
||||||
if (timeout_flag) begin
|
|
||||||
$error("-dut_read_output- Timeout detected when receiving packet");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rx_packet.size() != PACKET_SIZE) begin
|
|
||||||
$error("-dut_read_output- Wrong packet size received: %0d bytes received, %0d bytes expected", rx_packet.size(), PACKET_SIZE);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
// unpack values
|
|
||||||
data_packet = {<< byte {rx_packet}};
|
|
||||||
data_packet = {<< ACCUM_WIDTH {data_packet}};
|
|
||||||
|
|
||||||
// copy and convert values
|
|
||||||
for (int j = 0; j < data_packet.size(); j++) begin
|
|
||||||
output_data[(packet_counter-1) * data_packet.size() + j] = int'(data_packet[j]);
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
begin
|
|
||||||
// IP workflow completion event
|
|
||||||
wait(workflow_done == 1);
|
|
||||||
end
|
|
||||||
join_any
|
|
||||||
|
|
||||||
disable recv_loop_proc;
|
|
||||||
disable packet_counter_proc;
|
|
||||||
|
|
||||||
if (packet_counter != packet_num) begin
|
|
||||||
$error("-dut_read_output- Wrong number of packets received: %0d received, %0d expected", packet_counter, packet_num);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
wait(processing_done == 0);
|
|
||||||
|
|
||||||
endtask
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Функции и таски для верификации сигналов
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Таска генерации идеального тестового сигнала
|
|
||||||
task automatic reference_signal(
|
|
||||||
input int pulse_width,
|
|
||||||
input int pulse_height,
|
|
||||||
input int pulse_period_adc,
|
|
||||||
input int window_size,
|
|
||||||
output real result[]
|
|
||||||
);
|
|
||||||
/*
|
|
||||||
Globals:
|
|
||||||
ADC and DAC clock periods,
|
|
||||||
Virtual ADC and DAC voltage steps
|
|
||||||
|
|
||||||
Task developed with assumption that first discrete values of DAC and ADC
|
|
||||||
are syncrhonized at t==0 and started simultaneously.
|
|
||||||
|
|
||||||
Gains and biases of virtual ADC & DAC are default and ranges are [-5V;5V].
|
|
||||||
Bitwidths may be altered.
|
|
||||||
|
|
||||||
Returned result[] array is an array of sums of voltage potentials in discrete time points.
|
|
||||||
Discrete samples summed over a time window.
|
|
||||||
|
|
||||||
result[time] = (voltage)
|
|
||||||
*/
|
|
||||||
|
|
||||||
int sample_num = pulse_period_adc / window_size; // total averaged output samples from accumulator
|
|
||||||
|
|
||||||
real current_signal_sample, partial_sum;
|
|
||||||
real ref_signal_active_voltage = virtual_dac.code_to_voltage(pulse_height);
|
|
||||||
real ref_signal_zero_voltage = virtual_dac.code_to_voltage(ZERO_LEVEL);
|
|
||||||
|
|
||||||
if (pulse_period_adc % window_size) begin
|
|
||||||
$error("-reference_signal- pulse_period_adc must be multiple of window_size: %0d %% %0d = %0d", pulse_period_adc, window_size, pulse_period_adc % window_size);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
|
|
||||||
result = new[sample_num];
|
|
||||||
partial_sum = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < pulse_period_adc; i++) begin
|
|
||||||
// var i in ADC timespace
|
|
||||||
// i == 0 is a t0 of pulse generation and sampling
|
|
||||||
current_signal_sample = (i*CLK_ADC_PERIOD <= pulse_width*CLK_DAC_PERIOD) ? ref_signal_active_voltage : ref_signal_zero_voltage;
|
|
||||||
partial_sum += current_signal_sample;
|
|
||||||
if (i % window_size == (window_size-1)) begin
|
|
||||||
result[i / window_size] = partial_sum;
|
|
||||||
partial_sum = 0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Функция проверки размеров выборок
|
|
||||||
function automatic void check_size(
|
|
||||||
input real a[],
|
|
||||||
input real b[]
|
|
||||||
);
|
|
||||||
if (a.size() != b.size())
|
|
||||||
$fatal(1, "Array size mismatch: %0d != %0d",
|
|
||||||
a.size(), b.size());
|
|
||||||
|
|
||||||
if (a.size() == 0)
|
|
||||||
$error(1, "Empty array");
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Среднее по выборке
|
|
||||||
function automatic real array_mean(
|
|
||||||
input real a[]
|
|
||||||
);
|
|
||||||
real sum = 0.0;
|
|
||||||
|
|
||||||
foreach (a[i])
|
|
||||||
sum += a[i];
|
|
||||||
|
|
||||||
return sum / a.size();
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// MSE двух выборок
|
|
||||||
function automatic real calc_mse(
|
|
||||||
input real a[],
|
|
||||||
input real b[]
|
|
||||||
);
|
|
||||||
real sum = 0.0;
|
|
||||||
|
|
||||||
check_size(a, b);
|
|
||||||
|
|
||||||
foreach (a[i]) begin
|
|
||||||
real err;
|
|
||||||
err = a[i] - b[i];
|
|
||||||
sum += err * err;
|
|
||||||
end
|
|
||||||
|
|
||||||
return sum / a.size();
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// NRMSE двух выборок (нормирование RMSE)
|
|
||||||
function automatic real calc_nrmse(
|
|
||||||
input real a[],
|
|
||||||
input real b[]
|
|
||||||
);
|
|
||||||
const real EPS = 1e-12;
|
|
||||||
real mse, ms = 0;
|
|
||||||
|
|
||||||
mse = calc_mse(a, b);
|
|
||||||
|
|
||||||
foreach (a[i]) begin
|
|
||||||
ms += a[i] * a[i];
|
|
||||||
end
|
|
||||||
ms /= a.size();
|
|
||||||
|
|
||||||
return $sqrt(mse / (ms + EPS));
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Функция модуля
|
|
||||||
function automatic real abs_f(input real x);
|
|
||||||
return (x < 0.0) ? -x : x;
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Максимальная абсолютная ошибка
|
|
||||||
function automatic real calc_max_error(
|
|
||||||
input real a[],
|
|
||||||
input real b[]
|
|
||||||
);
|
|
||||||
real max_err = 0.0;
|
|
||||||
|
|
||||||
check_size(a, b);
|
|
||||||
|
|
||||||
foreach (a[i]) begin
|
|
||||||
real err;
|
|
||||||
|
|
||||||
err = abs_f(a[i] - b[i]);
|
|
||||||
|
|
||||||
if (err > max_err)
|
|
||||||
max_err = err;
|
|
||||||
end
|
|
||||||
|
|
||||||
return max_err;
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Коэффициент корреляции Пирсона
|
|
||||||
function automatic real calc_pearson(
|
|
||||||
input real a[],
|
|
||||||
input real b[]
|
|
||||||
);
|
|
||||||
real mean_a;
|
|
||||||
real mean_b;
|
|
||||||
real numerator = 0.0;
|
|
||||||
real denom_a = 0.0;
|
|
||||||
real denom_b = 0.0;
|
|
||||||
|
|
||||||
check_size(a, b);
|
|
||||||
|
|
||||||
mean_a = array_mean(a);
|
|
||||||
mean_b = array_mean(b);
|
|
||||||
|
|
||||||
foreach (a[i]) begin
|
|
||||||
real da;
|
|
||||||
real db;
|
|
||||||
|
|
||||||
da = a[i] - mean_a;
|
|
||||||
db = b[i] - mean_b;
|
|
||||||
|
|
||||||
numerator += da * db;
|
|
||||||
denom_a += da * da;
|
|
||||||
denom_b += db * db;
|
|
||||||
end
|
|
||||||
|
|
||||||
if ((denom_a == 0.0) || (denom_b == 0.0))
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
return numerator / $sqrt(denom_a * denom_b);
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Вспомогательная функция для вывода массива
|
|
||||||
function automatic void display_array_f(input real a[]);
|
|
||||||
$write("\t");
|
|
||||||
foreach(a[i])
|
|
||||||
$write("%f ", a[i]);
|
|
||||||
$write("\n");
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Вспомогательная функция для вывода массива
|
|
||||||
function automatic void display_array(input int a[]);
|
|
||||||
$write("\t");
|
|
||||||
foreach(a[i])
|
|
||||||
$write("%0d ", a[i]);
|
|
||||||
$write("\n");
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
// Основная таска типового теста
|
|
||||||
task automatic run_test_case(
|
|
||||||
virtual axis_if#(8).tb ctrl_vif,
|
|
||||||
virtual axis_if#(8).tb accum_vif,
|
|
||||||
input int pulse_width,
|
|
||||||
input int pulse_period,
|
|
||||||
input int pulse_num,
|
|
||||||
input int pulse_height,
|
|
||||||
input int pulse_period_adc,
|
|
||||||
input int window_size,
|
|
||||||
input bit rand_recv_delays,
|
|
||||||
input bit use_reset,
|
|
||||||
output int result
|
|
||||||
);
|
|
||||||
int output_data[]; // raw accum values
|
|
||||||
real output_signal_v[]; // accum values after voltage conversion
|
|
||||||
real reference_signal_v[]; // reference signal voltage values
|
|
||||||
real nrmse, pearson, max_err; // error and correlation metrics
|
|
||||||
|
|
||||||
if (use_reset) begin
|
|
||||||
dut_soft_reset(ctrl_vif);
|
|
||||||
#100;
|
|
||||||
end
|
|
||||||
|
|
||||||
dut_send_system_config(
|
|
||||||
.vif(ctrl_vif),
|
|
||||||
.pulse_width(pulse_width),
|
|
||||||
.pulse_period(pulse_period),
|
|
||||||
.pulse_num(pulse_num),
|
|
||||||
.pulse_height(pulse_height),
|
|
||||||
.pulse_period_adc(pulse_period_adc),
|
|
||||||
.window_size(window_size)
|
|
||||||
);
|
|
||||||
#100;
|
|
||||||
|
|
||||||
dut_start(ctrl_vif);
|
|
||||||
|
|
||||||
dut_read_output(
|
|
||||||
.vif(accum_vif),
|
|
||||||
.sample_num(pulse_period_adc),
|
|
||||||
.window_size(window_size),
|
|
||||||
.randomize_recv_delays(rand_recv_delays),
|
|
||||||
.output_data(output_data)
|
|
||||||
);
|
|
||||||
// actual size of payload is pulse_period_adc / window_size
|
|
||||||
output_signal_v = new[pulse_period_adc / window_size];
|
|
||||||
|
|
||||||
`ifdef DEBUG
|
|
||||||
$display("[TB] Output data stream");
|
|
||||||
display_array(output_data);
|
|
||||||
`endif
|
|
||||||
|
|
||||||
// voltage conversion
|
|
||||||
begin
|
|
||||||
// zero level for partial sum
|
|
||||||
real zero_level_bias = window_size * virtual_adc.ZERO_CODE;
|
|
||||||
// common voltage multiplier for step & amplifier
|
|
||||||
real voltage_multiplier = virtual_adc.VOLTAGE_STEP / virtual_adc.VOLTAGE_GAIN;
|
|
||||||
// array conversion
|
|
||||||
foreach (output_signal_v[i]) begin
|
|
||||||
real average_code_per_pulse = real'(output_data[i]) / pulse_num;
|
|
||||||
output_signal_v[i] = (average_code_per_pulse - zero_level_bias) * voltage_multiplier;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
reference_signal(
|
|
||||||
.pulse_width(pulse_width),
|
|
||||||
.pulse_height(pulse_height),
|
|
||||||
.pulse_period_adc(pulse_period_adc),
|
|
||||||
.window_size(window_size),
|
|
||||||
.result(reference_signal_v)
|
|
||||||
);
|
|
||||||
|
|
||||||
`ifdef DEBUG
|
|
||||||
$display("[TB] Output signal");
|
|
||||||
display_array_f(output_signal_v);
|
|
||||||
$display("[TB] Reference signal");
|
|
||||||
display_array_f(reference_signal_v);
|
|
||||||
`endif
|
|
||||||
|
|
||||||
nrmse = calc_nrmse(output_signal_v, reference_signal_v);
|
|
||||||
pearson = calc_pearson(output_signal_v, reference_signal_v);
|
|
||||||
max_err = calc_max_error(output_signal_v, reference_signal_v);
|
|
||||||
|
|
||||||
`ifdef DEBUG
|
|
||||||
$display("[TB] Metrics:\n\tNRMSE = %0.4f\t|\tPearson = %0.4f\t|\tMax error = %0.4f", nrmse, pearson, max_err);
|
|
||||||
`endif
|
|
||||||
|
|
||||||
// check metrics
|
|
||||||
result = 0;
|
|
||||||
// if (pearson < PEARSON_THRESHOLD)
|
|
||||||
// result += 1;
|
|
||||||
if (nrmse > NRMSE_THRESHOLD)
|
|
||||||
result += 2;
|
|
||||||
/*
|
|
||||||
Max error not used in evaluation because of fast pulse edge falling
|
|
||||||
resulting in plain difference between active signal level and zero level
|
|
||||||
For ex.: zero_level = 0x00 = -5V. pulse_height = 2^14-1 = 0x3fff = 5V
|
|
||||||
In some cases like jitter this may cause max error = 5 - (-5) = 10(V)
|
|
||||||
This cases are hardly traceble, thus max error not used in eval.
|
|
||||||
|
|
||||||
Pearson not used in evaluation because it only shows correlation of changing signals. Tests broke on static signals.
|
|
||||||
|
|
||||||
Pearson and max err remain in test for info.
|
|
||||||
*/
|
|
||||||
endtask
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ
|
|
||||||
//------------------------------------------------------------
|
|
||||||
initial begin
|
|
||||||
int result_flag;
|
|
||||||
int total_failed_tests = 0, total_tests = 0;
|
|
||||||
|
|
||||||
automatic virtual axis_if.tb control_vif = axis_control_if.tb;
|
|
||||||
automatic virtual axis_if.tb accumulator_vif = axis_accumulator_if.tb;
|
|
||||||
|
|
||||||
$info("[TB] DUT initializaton");
|
|
||||||
// Инициализация
|
|
||||||
request_ready = 0;
|
|
||||||
rst_n = 0;
|
|
||||||
#100;
|
|
||||||
rst_n = 1;
|
|
||||||
wait(mmcm_locked === 1'b1);
|
|
||||||
#150;
|
|
||||||
$info("[TB] MMCM locked");
|
|
||||||
|
|
||||||
// Meause periods because actual values hardcoded in IP
|
|
||||||
fork
|
|
||||||
`MEASURE_CLK(DUT.clk_sampler, CLK_ADC_PERIOD);
|
|
||||||
`MEASURE_CLK(DUT.clk_generator, CLK_DAC_PERIOD);
|
|
||||||
join
|
|
||||||
$info("[TB] ADC & DAC clock periods measured: ADC_period = %0.3f, DAC_period = %0.3f", CLK_ADC_PERIOD, CLK_DAC_PERIOD);
|
|
||||||
|
|
||||||
// Тесты
|
|
||||||
$info("[TB] Tests start");
|
|
||||||
$info("[TB] Simple test run");
|
|
||||||
run_test_case(
|
|
||||||
.ctrl_vif(control_vif),
|
|
||||||
.accum_vif(accumulator_vif),
|
|
||||||
.pulse_width(4000),
|
|
||||||
.pulse_period(10000),
|
|
||||||
.pulse_num(5),
|
|
||||||
.pulse_height(12000),
|
|
||||||
.pulse_period_adc(6000),
|
|
||||||
.window_size(10),
|
|
||||||
.rand_recv_delays(1),
|
|
||||||
.use_reset(1),
|
|
||||||
.result(result_flag)
|
|
||||||
);
|
|
||||||
`ERR_CHECK
|
|
||||||
|
|
||||||
$info("[TB] Random test run");
|
|
||||||
for (int i = 0; i < TEST_NUM; i++) begin
|
|
||||||
int pulse_width, pulse_period, pulse_num, pulse_height, pulse_period_adc, window_size;
|
|
||||||
bit rand_recv_delays, use_reset;
|
|
||||||
|
|
||||||
// Генерируемые параметры
|
|
||||||
pulse_period = $urandom_range(500, 5000);
|
|
||||||
pulse_width = $urandom_range(50, pulse_period);
|
|
||||||
pulse_num = $urandom_range(1, 10);
|
|
||||||
pulse_height = $urandom_range(0, 2**DAC_DATA_WIDTH-1);
|
|
||||||
window_size = $urandom_range(1, 11);
|
|
||||||
pulse_period_adc = $urandom_range(50, N_MAX-1) * window_size;
|
|
||||||
rand_recv_delays = 1;
|
|
||||||
use_reset = 1; // ($urandom_range(0, 10) >= 9);
|
|
||||||
|
|
||||||
$display("Test #%0d", total_tests);
|
|
||||||
`ifdef DEBUG
|
|
||||||
$display("Parameters:\n\tpulse_width=%0d\n\tpulse_period=%0d\n\tpulse_num=%0d\n\tpulse_height=%0d\n\tpulse_period_adc=%0d\n\twindow_size=%0d\n\trand_recv_delays=%0d\n\tuse_reset=%0d",
|
|
||||||
pulse_width, pulse_period, pulse_num, pulse_height, pulse_period_adc, window_size, rand_recv_delays, use_reset);
|
|
||||||
`endif
|
|
||||||
|
|
||||||
run_test_case(
|
|
||||||
.ctrl_vif(control_vif),
|
|
||||||
.accum_vif(accumulator_vif),
|
|
||||||
.pulse_width(pulse_width),
|
|
||||||
.pulse_period(pulse_period),
|
|
||||||
.pulse_num(pulse_num),
|
|
||||||
.pulse_height(pulse_height),
|
|
||||||
.pulse_period_adc(pulse_period_adc),
|
|
||||||
.window_size(window_size),
|
|
||||||
.rand_recv_delays(rand_recv_delays),
|
|
||||||
.use_reset(use_reset),
|
|
||||||
.result(result_flag)
|
|
||||||
);
|
|
||||||
|
|
||||||
`ERR_CHECK
|
|
||||||
if (result_flag) begin
|
|
||||||
$display("Parameters:\n\tpulse_width=%0d\n\tpulse_period=%0d\n\tpulse_num=%0d\n\tpulse_height=%0d\n\tpulse_period_adc=%0d\n\twindow_size=%0d\n\trand_recv_delays=%0d\n\tuse_reset=%0d",
|
|
||||||
pulse_width, pulse_period, pulse_num, pulse_height, pulse_period_adc, window_size, rand_recv_delays, use_reset);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
$info("[TB] Corner case test run");
|
|
||||||
run_test_case(
|
|
||||||
.ctrl_vif(control_vif),
|
|
||||||
.accum_vif(accumulator_vif),
|
|
||||||
.pulse_width(0),
|
|
||||||
.pulse_period(1000),
|
|
||||||
.pulse_num(5),
|
|
||||||
.pulse_height(12000),
|
|
||||||
.pulse_period_adc(600),
|
|
||||||
.window_size(10),
|
|
||||||
.rand_recv_delays(0),
|
|
||||||
.use_reset(1),
|
|
||||||
.result(result_flag)
|
|
||||||
);
|
|
||||||
`ERR_CHECK
|
|
||||||
|
|
||||||
run_test_case(
|
|
||||||
.ctrl_vif(control_vif),
|
|
||||||
.accum_vif(accumulator_vif),
|
|
||||||
.pulse_width(1000),
|
|
||||||
.pulse_period(1000),
|
|
||||||
.pulse_num(5),
|
|
||||||
.pulse_height(12000),
|
|
||||||
.pulse_period_adc(600),
|
|
||||||
.window_size(10),
|
|
||||||
.rand_recv_delays(0),
|
|
||||||
.use_reset(1),
|
|
||||||
.result(result_flag)
|
|
||||||
);
|
|
||||||
`ERR_CHECK
|
|
||||||
|
|
||||||
run_test_case(
|
|
||||||
.ctrl_vif(control_vif),
|
|
||||||
.accum_vif(accumulator_vif),
|
|
||||||
.pulse_width(500),
|
|
||||||
.pulse_period(1000),
|
|
||||||
.pulse_num(5),
|
|
||||||
.pulse_height(2**(DAC_DATA_WIDTH-1)),
|
|
||||||
.pulse_period_adc(600),
|
|
||||||
.window_size(10),
|
|
||||||
.rand_recv_delays(0),
|
|
||||||
.use_reset(1),
|
|
||||||
.result(result_flag)
|
|
||||||
);
|
|
||||||
`ERR_CHECK
|
|
||||||
|
|
||||||
run_test_case(
|
|
||||||
.ctrl_vif(control_vif),
|
|
||||||
.accum_vif(accumulator_vif),
|
|
||||||
.pulse_width(500),
|
|
||||||
.pulse_period(1000),
|
|
||||||
.pulse_num(5),
|
|
||||||
.pulse_height(15000),
|
|
||||||
.pulse_period_adc(10),
|
|
||||||
.window_size(1),
|
|
||||||
.rand_recv_delays(0),
|
|
||||||
.use_reset(1),
|
|
||||||
.result(result_flag)
|
|
||||||
);
|
|
||||||
`ERR_CHECK
|
|
||||||
|
|
||||||
$display("[TB] Tests done. [%0d/%0d] tests passed, %0d failed", total_tests - total_failed_tests, total_tests, total_failed_tests);
|
|
||||||
if (!total_failed_tests)
|
|
||||||
$display("[TB] ALL PASSED");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<wave_config>
|
|
||||||
<wave_state>
|
|
||||||
</wave_state>
|
|
||||||
<db_ref_list>
|
|
||||||
<db_ref path="reflectometer_tb_behav.wdb" id="1">
|
|
||||||
<top_modules>
|
|
||||||
<top_module name="glbl" />
|
|
||||||
<top_module name="reflectometer_tb" />
|
|
||||||
</top_modules>
|
|
||||||
</db_ref>
|
|
||||||
</db_ref_list>
|
|
||||||
<zoom_setting>
|
|
||||||
<ZoomStartTime time="0.000 ns"></ZoomStartTime>
|
|
||||||
<ZoomEndTime time="1,506.001 ns"></ZoomEndTime>
|
|
||||||
<Cursor1Time time="1,000.000 ns"></Cursor1Time>
|
|
||||||
</zoom_setting>
|
|
||||||
<column_width_setting>
|
|
||||||
<NameColumnWidth column_width="196"></NameColumnWidth>
|
|
||||||
<ValueColumnWidth column_width="76"></ValueColumnWidth>
|
|
||||||
</column_width_setting>
|
|
||||||
<WVObjectSize size="7" />
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/rst_n">
|
|
||||||
<obj_property name="ElementShortName">rst_n</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">rst_n</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/mmcm_locked">
|
|
||||||
<obj_property name="ElementShortName">mmcm_locked</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">mmcm_locked</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="group" fp_name="group28">
|
|
||||||
<obj_property name="label">Signal</obj_property>
|
|
||||||
<obj_property name="DisplayName">label</obj_property>
|
|
||||||
<wvobject type="array" fp_name="/reflectometer_tb/dac_data">
|
|
||||||
<obj_property name="ElementShortName">dac_data[13:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">dac_data[13:0]</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="other" fp_name="/reflectometer_tb/signal_voltage">
|
|
||||||
<obj_property name="ElementShortName">signal_voltage</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">signal_voltage</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="array" fp_name="/reflectometer_tb/adc_data">
|
|
||||||
<obj_property name="ElementShortName">adc_data[11:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">adc_data[11:0]</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/adc_otr">
|
|
||||||
<obj_property name="ElementShortName">adc_otr</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">adc_otr</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/send_request">
|
|
||||||
<obj_property name="ElementShortName">send_request</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">send_request</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/request_ready">
|
|
||||||
<obj_property name="ElementShortName">request_ready</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">request_ready</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="group" fp_name="group51">
|
|
||||||
<obj_property name="label">Controller</obj_property>
|
|
||||||
<obj_property name="DisplayName">label</obj_property>
|
|
||||||
<obj_property name="isExpanded"></obj_property>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_control_if/clk">
|
|
||||||
<obj_property name="ElementShortName">clk</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">clk</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_control_if/rst_n">
|
|
||||||
<obj_property name="ElementShortName">rst_n</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">rst_n</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="array" fp_name="/reflectometer_tb/axis_control_if/tdata">
|
|
||||||
<obj_property name="ElementShortName">tdata[7:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tdata[7:0]</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_control_if/tvalid">
|
|
||||||
<obj_property name="ElementShortName">tvalid</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tvalid</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_control_if/tlast">
|
|
||||||
<obj_property name="ElementShortName">tlast</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tlast</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_control_if/tready">
|
|
||||||
<obj_property name="ElementShortName">tready</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tready</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="group" fp_name="group52">
|
|
||||||
<obj_property name="label">Accumulator</obj_property>
|
|
||||||
<obj_property name="DisplayName">label</obj_property>
|
|
||||||
<obj_property name="isExpanded"></obj_property>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_accumulator_if/clk">
|
|
||||||
<obj_property name="ElementShortName">clk</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">clk</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_accumulator_if/rst_n">
|
|
||||||
<obj_property name="ElementShortName">rst_n</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">rst_n</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="array" fp_name="/reflectometer_tb/axis_accumulator_if/tdata">
|
|
||||||
<obj_property name="ElementShortName">tdata[7:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tdata[7:0]</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_accumulator_if/tvalid">
|
|
||||||
<obj_property name="ElementShortName">tvalid</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tvalid</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_accumulator_if/tlast">
|
|
||||||
<obj_property name="ElementShortName">tlast</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tlast</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/reflectometer_tb/axis_accumulator_if/tready">
|
|
||||||
<obj_property name="ElementShortName">tready</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">tready</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
</wvobject>
|
|
||||||
</wave_config>
|
|
||||||
+1
Submodule external/rtl_libs added at e4311214eb
+47
-171
@@ -5,6 +5,7 @@ module accumulator
|
|||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
parameter ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
parameter N_MAX = 4096,
|
parameter N_MAX = 4096,
|
||||||
|
parameter WINDOW_SIZE = 4,
|
||||||
parameter PACKET_SIZE = 8,
|
parameter PACKET_SIZE = 8,
|
||||||
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
||||||
)
|
)
|
||||||
@@ -16,18 +17,15 @@ module accumulator
|
|||||||
input start,
|
input start,
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input [15:0] seq_num,
|
input [15:0] seq_num,
|
||||||
input [31:0] window_size,
|
|
||||||
|
|
||||||
output [ACCUM_WIDTH-1:0] out_data,
|
output [ACCUM_WIDTH-1:0] out_data,
|
||||||
output out_valid,
|
output out_valid,
|
||||||
output readout_begin,
|
output readout_begin,
|
||||||
input batch_req,
|
input batch_req,
|
||||||
input finish,
|
input finish
|
||||||
output logic accum_done
|
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [31:0] smp_num_reg, cnt_smp_num;
|
logic [31:0] smp_num_reg, cnt_smp_num;
|
||||||
logic [31:0] window_size_reg;
|
|
||||||
logic [15:0] seq_num_reg, cnt_seq_num;
|
logic [15:0] seq_num_reg, cnt_seq_num;
|
||||||
logic [15:0] cnt_addr, addra, addrb;
|
logic [15:0] cnt_addr, addra, addrb;
|
||||||
|
|
||||||
@@ -41,6 +39,10 @@ module accumulator
|
|||||||
logic out_valid_reg;
|
logic out_valid_reg;
|
||||||
logic finish_reg, finish_buf;
|
logic finish_reg, finish_buf;
|
||||||
|
|
||||||
|
// registers for port b data request
|
||||||
|
reg req_data_b;
|
||||||
|
reg [15:0] req_addr_b;
|
||||||
|
|
||||||
typedef enum logic [3:0] {
|
typedef enum logic [3:0] {
|
||||||
IDLE,
|
IDLE,
|
||||||
INIT_MEM,
|
INIT_MEM,
|
||||||
@@ -56,84 +58,18 @@ module accumulator
|
|||||||
} wr_state_t;
|
} wr_state_t;
|
||||||
(* MARK_DEBUG="true" *) wr_state_t wr_state;
|
(* MARK_DEBUG="true" *) wr_state_t wr_state;
|
||||||
|
|
||||||
// One word per clock accumulation pipeline
|
|
||||||
// On every sum_valid in ACCUM we launch a BRAM read for cnt_addr
|
|
||||||
// On the next clock the saved sum_data is added to doutb and written back
|
|
||||||
logic accum_pipe_valid;
|
|
||||||
logic [15:0] accum_pipe_addr;
|
|
||||||
logic [ACCUM_WIDTH-1:0] accum_pipe_data;
|
|
||||||
|
|
||||||
// case smp_num // window_size == 1
|
|
||||||
// Then the next sequence can read the same address it is written
|
|
||||||
logic accum_pipe_bypass_valid;
|
|
||||||
logic [ACCUM_WIDTH-1:0] accum_pipe_bypass_data;
|
|
||||||
|
|
||||||
logic accum_accept_last;
|
|
||||||
logic accum_accept_last_all;
|
|
||||||
logic [ACCUM_WIDTH-1:0] accum_write_base;
|
|
||||||
logic [ACCUM_WIDTH-1:0] accum_write_value;
|
|
||||||
|
|
||||||
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
|
||||||
wire start_accept = start && (wr_state == IDLE);
|
|
||||||
|
|
||||||
assign accum_accept_last = (cnt_smp_num + window_size_reg >= smp_num_reg);
|
|
||||||
assign accum_accept_last_all = accum_accept_last && (cnt_seq_num == seq_num_reg - 1);
|
|
||||||
assign accum_write_base = accum_pipe_bypass_valid ? accum_pipe_bypass_data : data_bram_out;
|
|
||||||
assign accum_write_value = accum_pipe_data + accum_write_base;
|
|
||||||
|
|
||||||
// Memory controls to XPM
|
|
||||||
// In accumulation/init states they are driven directly from the current
|
|
||||||
// state and pipeline registers. That avoids an extra register stage
|
|
||||||
logic mem_wea;
|
|
||||||
logic mem_enb;
|
|
||||||
logic [15:0] mem_addra;
|
|
||||||
logic [15:0] mem_addrb;
|
|
||||||
logic [ACCUM_WIDTH-1:0] mem_dina;
|
|
||||||
|
|
||||||
assign mem_wea = (wr_state == INIT_MEM) ? valid_data :
|
|
||||||
(wr_state == ACCUM) ? accum_pipe_valid :
|
|
||||||
1'b0;
|
|
||||||
|
|
||||||
assign mem_addra = (wr_state == INIT_MEM) ? cnt_addr :
|
|
||||||
(wr_state == ACCUM) ? accum_pipe_addr :
|
|
||||||
addra;
|
|
||||||
|
|
||||||
assign mem_dina = (wr_state == INIT_MEM) ? data :
|
|
||||||
(wr_state == ACCUM) ? accum_write_value :
|
|
||||||
data_bram_in;
|
|
||||||
|
|
||||||
assign mem_enb = (wr_state == ACCUM) ? valid_data : enb;
|
|
||||||
assign mem_addrb = (wr_state == ACCUM) ? cnt_addr : addrb;
|
|
||||||
|
|
||||||
// registers for port b data request
|
|
||||||
reg req_data_b;
|
|
||||||
reg [15:0] req_addr_b;
|
|
||||||
|
|
||||||
always @(posedge clk_in) begin
|
always @(posedge clk_in) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
smp_num_reg <= '0;
|
smp_num_reg <= '0;
|
||||||
cnt_smp_num <= '0;
|
cnt_smp_num <= '0;
|
||||||
window_size_reg <= 32'd1;
|
|
||||||
seq_num_reg <= '0;
|
seq_num_reg <= '0;
|
||||||
cnt_seq_num <= '0;
|
cnt_seq_num <= '0;
|
||||||
cnt_addr <= '0;
|
cnt_addr <= '0;
|
||||||
addra <= '0;
|
|
||||||
addrb <= '0;
|
|
||||||
data_bram_in <= '0;
|
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
wr_state <= IDLE;
|
wr_state <= IDLE;
|
||||||
finish_reg <= 0;
|
finish_reg <= 0;
|
||||||
finish_buf <= 0;
|
|
||||||
readout_begin_reg <= 0;
|
|
||||||
out_data_reg <= '0;
|
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
accum_pipe_valid <= 0;
|
|
||||||
accum_pipe_addr <= '0;
|
|
||||||
accum_pipe_data <= '0;
|
|
||||||
accum_pipe_bypass_valid <= 0;
|
|
||||||
accum_pipe_bypass_data <= '0;
|
|
||||||
accum_done <= 0;
|
|
||||||
end else begin
|
end else begin
|
||||||
finish_buf <= finish;
|
finish_buf <= finish;
|
||||||
|
|
||||||
@@ -147,138 +83,83 @@ module accumulator
|
|||||||
readout_begin_reg <= 0;
|
readout_begin_reg <= 0;
|
||||||
finish_reg <= 0;
|
finish_reg <= 0;
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
accum_pipe_valid <= 0;
|
|
||||||
accum_pipe_bypass_valid <= 0;
|
|
||||||
accum_done <= 0;
|
|
||||||
cnt_smp_num <= '0;
|
|
||||||
cnt_seq_num <= '0;
|
|
||||||
cnt_addr <= '0;
|
|
||||||
addrb <= '0;
|
|
||||||
if (start) begin
|
if (start) begin
|
||||||
smp_num_reg <= smp_num;
|
smp_num_reg <= smp_num;
|
||||||
seq_num_reg <= seq_num;
|
seq_num_reg <= seq_num;
|
||||||
window_size_reg <= window_size_safe;
|
|
||||||
wr_state <= INIT_MEM;
|
wr_state <= INIT_MEM;
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
INIT_MEM: begin
|
INIT_MEM: begin
|
||||||
// First sequence
|
// first run to initialize memory with first batch of values
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
enb <= 0;
|
|
||||||
out_valid_reg <= 0;
|
|
||||||
accum_pipe_valid <= 0;
|
|
||||||
accum_pipe_bypass_valid <= 0;
|
|
||||||
accum_done <= 0;
|
|
||||||
|
|
||||||
if (valid_data) begin
|
if (valid_data) begin
|
||||||
// mem_wea/mem_addra/mem_dina do the actual write in this clock
|
|
||||||
data_bram_in <= data;
|
data_bram_in <= data;
|
||||||
addra <= cnt_addr;
|
addra <= cnt_addr;
|
||||||
wea <= 1;
|
wea <= 1;
|
||||||
|
cnt_addr <= cnt_addr + 1;
|
||||||
|
cnt_smp_num <= cnt_smp_num + WINDOW_SIZE;
|
||||||
|
|
||||||
if (cnt_smp_num + window_size_reg >= smp_num_reg) begin
|
end
|
||||||
cnt_smp_num <= '0;
|
if (cnt_smp_num >= smp_num_reg) begin
|
||||||
cnt_addr <= '0;
|
wr_state <= BEGIN_SEQ;
|
||||||
|
|
||||||
if (seq_num_reg <= 16'd1) begin
|
|
||||||
cnt_seq_num <= '0;
|
|
||||||
addrb <= '0;
|
|
||||||
accum_done <= 1;
|
|
||||||
wr_state <= READOUT_START;
|
|
||||||
end else begin
|
|
||||||
// start further accumulation
|
|
||||||
cnt_seq_num <= 16'd1;
|
|
||||||
wr_state <= ACCUM;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
cnt_smp_num <= cnt_smp_num + window_size_reg;
|
|
||||||
cnt_addr <= cnt_addr + 1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
BEGIN_SEQ: begin
|
BEGIN_SEQ: begin
|
||||||
// FIXME: unused
|
// start new acc seq
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
wr_state <= ACCUM;
|
if (cnt_seq_num == seq_num_reg - 1) begin
|
||||||
|
cnt_seq_num <= '0;
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
cnt_addr <= '0;
|
||||||
|
wr_state <= READOUT_START;
|
||||||
|
addrb <= '0;
|
||||||
|
enb <= 0;
|
||||||
|
end else begin
|
||||||
|
// beginning of new data sequence
|
||||||
|
cnt_seq_num <= cnt_seq_num + 1;
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
cnt_addr <= '0;
|
||||||
|
wea <= 0;
|
||||||
|
addrb <= 0;
|
||||||
|
wr_state <= REQ_WORD_B;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
REQ_WORD_B: begin
|
REQ_WORD_B: begin
|
||||||
// FIXME: depr
|
// pre-request data for port b
|
||||||
wea <= 0;
|
wea <= 0;
|
||||||
enb <= 0;
|
enb <= 1;
|
||||||
|
addrb <= cnt_addr;
|
||||||
wr_state <= ACCUM;
|
wr_state <= ACCUM;
|
||||||
end
|
end
|
||||||
|
|
||||||
ACCUM: begin
|
ACCUM: begin
|
||||||
// accum pipeline
|
// sum mem+input
|
||||||
wea <= 0;
|
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
out_valid_reg <= 0;
|
if (valid_data) begin
|
||||||
|
addra <= cnt_addr;
|
||||||
if (accum_pipe_valid) begin
|
|
||||||
// mem_wea/mem_addra/mem_dina do the actual write this clock
|
|
||||||
addra <= accum_pipe_addr;
|
|
||||||
data_bram_in <= accum_write_value;
|
|
||||||
wea <= 1;
|
wea <= 1;
|
||||||
end
|
data_bram_in <= data + data_bram_out;
|
||||||
|
cnt_smp_num <= cnt_smp_num + WINDOW_SIZE;
|
||||||
if (accum_done) begin
|
if (cnt_smp_num + WINDOW_SIZE >= smp_num_reg) begin
|
||||||
// Last input word was accepted on the previous clk
|
wr_state <= BEGIN_SEQ;
|
||||||
accum_pipe_valid <= 0;
|
|
||||||
accum_pipe_bypass_valid <= 0;
|
|
||||||
cnt_smp_num <= '0;
|
|
||||||
cnt_seq_num <= '0;
|
|
||||||
cnt_addr <= '0;
|
|
||||||
addrb <= '0;
|
|
||||||
enb <= 0;
|
|
||||||
wr_state <= READOUT_START;
|
|
||||||
end else if (valid_data) begin
|
|
||||||
// mem_enb/mem_addrb launch the actual read this clock
|
|
||||||
enb <= 1;
|
|
||||||
addrb <= cnt_addr;
|
|
||||||
|
|
||||||
accum_pipe_valid <= 1;
|
|
||||||
accum_pipe_addr <= cnt_addr;
|
|
||||||
accum_pipe_data <= data;
|
|
||||||
|
|
||||||
// case window_size=1 && smp_num is small
|
|
||||||
accum_pipe_bypass_valid <= accum_pipe_valid && (accum_pipe_addr == cnt_addr);
|
|
||||||
accum_pipe_bypass_data <= accum_write_value;
|
|
||||||
|
|
||||||
if (accum_accept_last) begin
|
|
||||||
cnt_smp_num <= '0;
|
|
||||||
cnt_addr <= '0;
|
|
||||||
|
|
||||||
if (cnt_seq_num == seq_num_reg - 1) begin
|
|
||||||
accum_done <= 1;
|
|
||||||
end else begin
|
|
||||||
cnt_seq_num <= cnt_seq_num + 1;
|
|
||||||
end
|
|
||||||
end else begin
|
end else begin
|
||||||
cnt_smp_num <= cnt_smp_num + window_size_reg;
|
|
||||||
cnt_addr <= cnt_addr + 1;
|
cnt_addr <= cnt_addr + 1;
|
||||||
|
wr_state <= REQ_WORD_B;
|
||||||
end
|
end
|
||||||
end else begin
|
|
||||||
accum_pipe_valid <= 0;
|
|
||||||
accum_pipe_bypass_valid <= 0;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
READOUT_START: begin
|
READOUT_START: begin
|
||||||
readout_begin_reg <= 1'b1;
|
readout_begin_reg <= 1'b1;
|
||||||
wr_state <= READOUT_AWAIT;
|
wr_state <= READOUT_AWAIT;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
wea <= 0;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
READOUT_AWAIT: begin
|
READOUT_AWAIT: begin
|
||||||
// req await + delay for every-clock readout
|
// req await + delay for every-clock readout.
|
||||||
wea <= 0;
|
|
||||||
if (batch_req) begin
|
if (batch_req) begin
|
||||||
enb <= 1;
|
enb <= 1;
|
||||||
wr_state <= READOUT_DELAY;
|
wr_state <= READOUT_DELAY;
|
||||||
@@ -292,14 +173,12 @@ module accumulator
|
|||||||
|
|
||||||
READOUT_DELAY: begin
|
READOUT_DELAY: begin
|
||||||
// wait for mem latency
|
// wait for mem latency
|
||||||
wea <= 0;
|
|
||||||
addrb <= addrb + 1;
|
addrb <= addrb + 1;
|
||||||
wr_state <= READOUT_PUT;
|
wr_state <= READOUT_PUT;
|
||||||
end
|
end
|
||||||
|
|
||||||
READOUT_PUT: begin
|
READOUT_PUT: begin
|
||||||
// main data output
|
// main data output
|
||||||
wea <= 0;
|
|
||||||
if ((addrb % READ_BATCH_SIZE) == 0) begin
|
if ((addrb % READ_BATCH_SIZE) == 0) begin
|
||||||
wr_state <= READOUT_LAST;
|
wr_state <= READOUT_LAST;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
@@ -311,7 +190,6 @@ module accumulator
|
|||||||
|
|
||||||
READOUT_LAST: begin
|
READOUT_LAST: begin
|
||||||
// last word of packet
|
// last word of packet
|
||||||
wea <= 0;
|
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
out_data_reg <= data_bram_out;
|
out_data_reg <= data_bram_out;
|
||||||
wr_state <= READOUT_START;
|
wr_state <= READOUT_START;
|
||||||
@@ -320,7 +198,6 @@ module accumulator
|
|||||||
FINISH: begin
|
FINISH: begin
|
||||||
out_valid_reg <= 0;
|
out_valid_reg <= 0;
|
||||||
enb <= 0;
|
enb <= 0;
|
||||||
wea <= 0;
|
|
||||||
wr_state <= IDLE;
|
wr_state <= IDLE;
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -333,13 +210,12 @@ module accumulator
|
|||||||
adder
|
adder
|
||||||
#(
|
#(
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.WINDOW_SIZE(WINDOW_SIZE),
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH)
|
.ACCUM_WIDTH(ACCUM_WIDTH)
|
||||||
) adder_dut
|
) adder_dut
|
||||||
(
|
(
|
||||||
.clk_in(clk_in),
|
.clk_in(clk_in),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
.start(start_accept),
|
|
||||||
.window_size(window_size),
|
|
||||||
.s_axis_tdata(s_axis_tdata),
|
.s_axis_tdata(s_axis_tdata),
|
||||||
.s_axis_tvalid(s_axis_tvalid),
|
.s_axis_tvalid(s_axis_tvalid),
|
||||||
.sum_data(data),
|
.sum_data(data),
|
||||||
@@ -378,14 +254,14 @@ module accumulator
|
|||||||
|
|
||||||
.doutb(data_bram_out),
|
.doutb(data_bram_out),
|
||||||
|
|
||||||
.addra(mem_addra),
|
.addra(addra),
|
||||||
.addrb(mem_addrb),
|
.addrb(addrb),
|
||||||
.clka(clk_in),
|
.clka(clk_in),
|
||||||
.clkb(clk_in),
|
.clkb(clk_in),
|
||||||
.dina(mem_dina),
|
.dina(data_bram_in),
|
||||||
.ena(1'b1),
|
.ena(1'b1),
|
||||||
.enb(mem_enb),
|
.enb(enb),
|
||||||
.wea(mem_wea)
|
.wea(wea)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign readout_begin = readout_begin_reg;
|
assign readout_begin = readout_begin_reg;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ module accumulator_top
|
|||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
parameter ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
parameter N_MAX = 4096,
|
parameter N_MAX = 4096,
|
||||||
|
parameter WINDOW_SIZE = 65,
|
||||||
parameter PACKET_SIZE = 1024,
|
parameter PACKET_SIZE = 1024,
|
||||||
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
parameter READ_BATCH_SIZE =(PACKET_SIZE*8)/(ACCUM_WIDTH)
|
||||||
)
|
)
|
||||||
@@ -21,7 +22,6 @@ module accumulator_top
|
|||||||
input start,
|
input start,
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input [15:0] seq_num,
|
input [15:0] seq_num,
|
||||||
input [31:0] window_size,
|
|
||||||
|
|
||||||
// eth signals
|
// eth signals
|
||||||
input eth_clk_in,
|
input eth_clk_in,
|
||||||
@@ -34,8 +34,7 @@ module accumulator_top
|
|||||||
input logic m_axis_tready,
|
input logic m_axis_tready,
|
||||||
output logic m_axis_tlast,
|
output logic m_axis_tlast,
|
||||||
|
|
||||||
output logic finish,
|
output logic finish
|
||||||
output logic accum_done
|
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [ACCUM_WIDTH-1:0] out_data;
|
wire [ACCUM_WIDTH-1:0] out_data;
|
||||||
@@ -43,68 +42,36 @@ module accumulator_top
|
|||||||
wire readout_begin;
|
wire readout_begin;
|
||||||
wire batch_req;
|
wire batch_req;
|
||||||
|
|
||||||
logic finish_int;
|
|
||||||
logic finish_int_d;
|
|
||||||
logic finish_pulse;
|
|
||||||
logic calc_active;
|
|
||||||
logic start_accept;
|
|
||||||
logic [31:0] window_size_reg;
|
|
||||||
|
|
||||||
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
|
||||||
|
|
||||||
assign finish_pulse = finish_int && !finish_int_d;
|
|
||||||
assign start_accept = start && !calc_active;
|
|
||||||
assign finish = finish_int;
|
|
||||||
|
|
||||||
// Keep the top copy stable for blocks that start later than the accum itself
|
|
||||||
always_ff @(posedge clk_in) begin
|
|
||||||
if (rst) begin
|
|
||||||
calc_active <= 1'b0;
|
|
||||||
finish_int_d <= 1'b0;
|
|
||||||
window_size_reg <= 32'd1;
|
|
||||||
end else begin
|
|
||||||
finish_int_d <= finish_int;
|
|
||||||
|
|
||||||
if (start_accept) begin
|
|
||||||
calc_active <= 1'b1;
|
|
||||||
window_size_reg <= window_size_safe;
|
|
||||||
end else if (finish_pulse) begin
|
|
||||||
calc_active <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
accumulator #(
|
accumulator #(
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||||
.N_MAX(N_MAX),
|
.N_MAX(N_MAX),
|
||||||
|
.WINDOW_SIZE(WINDOW_SIZE),
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
.PACKET_SIZE(PACKET_SIZE)
|
||||||
) accum_main (
|
) accum_main (
|
||||||
.clk_in(clk_in),
|
.clk_in(clk_in),
|
||||||
.rst(rst),
|
.rst(rst),
|
||||||
.s_axis_tdata(s_axis_tdata),
|
.s_axis_tdata(s_axis_tdata),
|
||||||
.s_axis_tvalid(s_axis_tvalid),
|
.s_axis_tvalid(s_axis_tvalid),
|
||||||
.start(start_accept),
|
.start(start),
|
||||||
.smp_num(smp_num),
|
.smp_num(smp_num),
|
||||||
.seq_num(seq_num),
|
.seq_num(seq_num),
|
||||||
.window_size(window_size),
|
|
||||||
.out_data(out_data),
|
.out_data(out_data),
|
||||||
.out_valid(out_valid),
|
.out_valid(out_valid),
|
||||||
.readout_begin(readout_begin),
|
.readout_begin(readout_begin),
|
||||||
.batch_req(batch_req),
|
.batch_req(batch_req),
|
||||||
.finish(finish_int),
|
.finish(finish)
|
||||||
.accum_done(accum_done)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
out_axis_fifo #(
|
out_axis_fifo #(
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||||
|
.WINDOW_SIZE(WINDOW_SIZE),
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
.PACKET_SIZE(PACKET_SIZE)
|
||||||
) output_async_fifo (
|
) output_async_fifo (
|
||||||
.eth_clk_in (eth_clk_in),
|
.eth_clk_in (eth_clk_in),
|
||||||
.acc_clk_in (clk_in),
|
.acc_clk_in (clk_in),
|
||||||
.rst (rst),
|
.rst (rst),
|
||||||
.smp_num (smp_num),
|
.smp_num (smp_num),
|
||||||
.window_size (window_size_reg),
|
|
||||||
|
|
||||||
.m_axis_tdata (m_axis_tdata),
|
.m_axis_tdata (m_axis_tdata),
|
||||||
.m_axis_tvalid (m_axis_tvalid),
|
.m_axis_tvalid (m_axis_tvalid),
|
||||||
@@ -120,6 +87,6 @@ module accumulator_top
|
|||||||
.send_req (send_req),
|
.send_req (send_req),
|
||||||
|
|
||||||
.batch_req (batch_req),
|
.batch_req (batch_req),
|
||||||
.finish (finish_int)
|
.finish (finish)
|
||||||
);
|
);
|
||||||
endmodule
|
endmodule
|
||||||
+13
-30
@@ -4,13 +4,12 @@
|
|||||||
module adder
|
module adder
|
||||||
#(
|
#(
|
||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
|
parameter WINDOW_SIZE = 4,
|
||||||
parameter ACCUM_WIDTH = 32
|
parameter ACCUM_WIDTH = 32
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input clk_in,
|
input clk_in,
|
||||||
input rst,
|
input rst,
|
||||||
input start,
|
|
||||||
input [31:0] window_size,
|
|
||||||
input [DATA_WIDTH-1:0] s_axis_tdata,
|
input [DATA_WIDTH-1:0] s_axis_tdata,
|
||||||
input s_axis_tvalid,
|
input s_axis_tvalid,
|
||||||
|
|
||||||
@@ -21,10 +20,7 @@ module adder
|
|||||||
logic [ACCUM_WIDTH-1:0] accum, res;
|
logic [ACCUM_WIDTH-1:0] accum, res;
|
||||||
logic [DATA_WIDTH-1:0] axis_data;
|
logic [DATA_WIDTH-1:0] axis_data;
|
||||||
logic res_valid, axis_valid;
|
logic res_valid, axis_valid;
|
||||||
(* MARK_DEBUG = "TRUE" *) logic [31:0] cnt;
|
(* MARK_DEBUG = "TRUE" *) logic [15:0] cnt;
|
||||||
logic [31:0] window_size_reg;
|
|
||||||
|
|
||||||
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
|
||||||
|
|
||||||
always @(posedge clk_in) begin
|
always @(posedge clk_in) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
@@ -32,32 +28,19 @@ module adder
|
|||||||
cnt <= '0;
|
cnt <= '0;
|
||||||
res <= '0;
|
res <= '0;
|
||||||
res_valid <= 0;
|
res_valid <= 0;
|
||||||
axis_data <= '0;
|
|
||||||
axis_valid <= 0;
|
|
||||||
window_size_reg <= 32'd1;
|
|
||||||
end else begin
|
end else begin
|
||||||
res_valid <= 0;
|
res_valid <= 0;
|
||||||
|
axis_data <= s_axis_tdata;
|
||||||
if (start) begin
|
axis_valid <= s_axis_tvalid;
|
||||||
accum <= '0;
|
if ( axis_valid) begin
|
||||||
cnt <= '0;
|
if (cnt == WINDOW_SIZE-1) begin
|
||||||
res <= '0;
|
res <= accum + axis_data;
|
||||||
axis_data <= '0;
|
res_valid <= 1;
|
||||||
axis_valid <= 0;
|
accum <= '0;
|
||||||
window_size_reg <= window_size_safe;
|
cnt <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
axis_data <= s_axis_tdata;
|
accum <= accum + axis_data;
|
||||||
axis_valid <= s_axis_tvalid;
|
cnt <= cnt + 1;
|
||||||
if (axis_valid) begin
|
|
||||||
if (cnt == window_size_reg - 1) begin
|
|
||||||
res <= accum + axis_data;
|
|
||||||
res_valid <= 1;
|
|
||||||
accum <= '0;
|
|
||||||
cnt <= '0;
|
|
||||||
end else begin
|
|
||||||
accum <= accum + axis_data;
|
|
||||||
cnt <= cnt + 1;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
module out_axis_fifo #(
|
module out_axis_fifo #(
|
||||||
parameter ACCUM_WIDTH = 32,
|
parameter ACCUM_WIDTH = 32,
|
||||||
|
parameter WINDOW_SIZE = 65,
|
||||||
parameter PACKET_SIZE = 1024
|
parameter PACKET_SIZE = 1024
|
||||||
) (
|
) (
|
||||||
input logic eth_clk_in,
|
input logic eth_clk_in,
|
||||||
input logic acc_clk_in,
|
input logic acc_clk_in,
|
||||||
input logic rst,
|
input logic rst,
|
||||||
input logic [31:0] smp_num,
|
input logic [31:0] smp_num,
|
||||||
input logic [31:0] window_size,
|
|
||||||
|
|
||||||
// AXI stream master for output, eth_clk_in domain
|
// AXI stream master for output, eth_clk_in domain
|
||||||
output logic [7:0] m_axis_tdata,
|
output logic [7:0] m_axis_tdata,
|
||||||
@@ -85,8 +85,6 @@ module out_axis_fifo #(
|
|||||||
reg [31:0] wr_cnt; // current BIT mem ptr
|
reg [31:0] wr_cnt; // current BIT mem ptr
|
||||||
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
reg [31:0] wr_batch_tgt; // next 'target' that should be written from batch
|
||||||
reg [31:0] wr_total; // total BITS to be sent!
|
reg [31:0] wr_total; // total BITS to be sent!
|
||||||
logic [31:0] window_size_reg;
|
|
||||||
wire [31:0] window_size_safe = (window_size == 32'd0) ? 32'd1 : window_size;
|
|
||||||
|
|
||||||
wire empty;
|
wire empty;
|
||||||
|
|
||||||
@@ -94,7 +92,7 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// each written "acc_din" ACCUM_WIDTH word
|
// each written "acc_din" ACCUM_WIDTH word
|
||||||
// is counted as window_size samples actually
|
// is counted as WINDOWS_SIZE samples actually
|
||||||
// because hw division for counters is painful
|
// because hw division for counters is painful
|
||||||
// so we just increased the counter sizes
|
// so we just increased the counter sizes
|
||||||
|
|
||||||
@@ -104,7 +102,6 @@ module out_axis_fifo #(
|
|||||||
wr_cnt <= 32'b0;
|
wr_cnt <= 32'b0;
|
||||||
wr_batch_tgt <= 32'b0;
|
wr_batch_tgt <= 32'b0;
|
||||||
wr_total <= 32'b0;
|
wr_total <= 32'b0;
|
||||||
window_size_reg <= 32'd1;
|
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
finish <= 0;
|
finish <= 0;
|
||||||
|
|
||||||
@@ -118,7 +115,6 @@ module out_axis_fifo #(
|
|||||||
wr_state <= WR_CHECK;
|
wr_state <= WR_CHECK;
|
||||||
wr_total <= smp_num * ACCUM_WIDTH;
|
wr_total <= smp_num * ACCUM_WIDTH;
|
||||||
wr_batch_tgt <= 32'b0;
|
wr_batch_tgt <= 32'b0;
|
||||||
window_size_reg <= window_size_safe;
|
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
finish <= 0;
|
finish <= 0;
|
||||||
end
|
end
|
||||||
@@ -130,9 +126,9 @@ module out_axis_fifo #(
|
|||||||
if ((wr_data_count < (FIFO_WDEPTH - (PACKET_SIZE / (ACCUM_WIDTH / 8)))) && ~wr_rst_busy) begin
|
if ((wr_data_count < (FIFO_WDEPTH - (PACKET_SIZE / (ACCUM_WIDTH / 8)))) && ~wr_rst_busy) begin
|
||||||
batch_req <= 1;
|
batch_req <= 1;
|
||||||
// should give us exactly PACKET_SIZE * 8 bits
|
// should give us exactly PACKET_SIZE * 8 bits
|
||||||
// multiplied by window_size, because we count
|
// multiplied by WINDOW_SIZE, because we count
|
||||||
// each given ACCUM_WIDTH word as window_size samples !!!
|
// each given ACCUM_WIDTH word as WINDOWS_SIZE samples !!!
|
||||||
wr_batch_tgt <= wr_batch_tgt + (8 * window_size_reg * PACKET_SIZE);
|
wr_batch_tgt <= wr_batch_tgt + (8 * WINDOW_SIZE * PACKET_SIZE);
|
||||||
wr_state <= WR_RUN;
|
wr_state <= WR_RUN;
|
||||||
end else begin
|
end else begin
|
||||||
batch_req <= 0;
|
batch_req <= 0;
|
||||||
@@ -154,8 +150,8 @@ module out_axis_fifo #(
|
|||||||
|
|
||||||
if (din_valid) begin
|
if (din_valid) begin
|
||||||
// data supplied
|
// data supplied
|
||||||
// count as we got window_size samples
|
// count as we got WINDOW_SIZE samples
|
||||||
wr_cnt <= wr_cnt + ACCUM_WIDTH * window_size_reg;
|
wr_cnt <= wr_cnt + ACCUM_WIDTH * WINDOW_SIZE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -13,24 +13,20 @@ FPGA_ARCH = artix7
|
|||||||
|
|
||||||
RTL_DIR = ../src
|
RTL_DIR = ../src
|
||||||
|
|
||||||
# Simulation settings
|
|
||||||
SIM_TOP = tb_accumulator_top
|
|
||||||
SIM_RUNTIME ?= 10000 us
|
|
||||||
|
|
||||||
# Design sources only
|
include ../../../scripts/vivado.mk
|
||||||
SYN_FILES += $(filter-out %_tb.sv,$(sort $(shell find $(RTL_DIR) -type f -name '*.v' -o -type f -name '*.sv')))
|
|
||||||
|
|
||||||
# Testbench sources. Vivado puts these into "sim_1", Questa compiles them into "work".
|
SYN_FILES += $(sort $(shell find ../src -type f \( -name '*.v' -o -name '*.sv' \)))
|
||||||
TB_FILES += out_axis_fifo_tb.sv
|
|
||||||
TB_FILES += accum_full_tb.sv
|
|
||||||
|
|
||||||
XCI_FILES = $(sort $(shell find $(RTL_DIR) -type f -name '*.xci'))
|
XCI_FILES = $(sort $(shell find ../src -type f -name '*.xci'))
|
||||||
|
|
||||||
XDC_FILES += ../../../constraints/ax7a035b.xdc
|
XDC_FILES += ../../../constraints/ax7a035b.xdc
|
||||||
XDC_FILES += test_timing.xdc
|
XDC_FILES += test_timing.xdc
|
||||||
|
|
||||||
include ../../../scripts/vivado.mk
|
SYN_FILES += out_axis_fifo_tb.sv
|
||||||
include ../../../scripts/questa.mk
|
SYN_FILES += accum_full_tb.sv
|
||||||
|
SIM_TOP = tb_accumulator_top
|
||||||
|
|
||||||
|
|
||||||
program: $(PROJECT).bit
|
program: $(PROJECT).bit
|
||||||
echo "open_hw_manager" > program.tcl
|
echo "open_hw_manager" > program.tcl
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ module tb_accumulator_top;
|
|||||||
localparam DATA_WIDTH = 12;
|
localparam DATA_WIDTH = 12;
|
||||||
localparam ACCUM_WIDTH = 32;
|
localparam ACCUM_WIDTH = 32;
|
||||||
localparam N_MAX = 4096;
|
localparam N_MAX = 4096;
|
||||||
localparam MAX_WINDOW_SIZE = 65;
|
localparam WINDOW_SIZE = 65;
|
||||||
localparam PACKET_SIZE = 1024;
|
localparam PACKET_SIZE = 1024;
|
||||||
localparam READ_BATCH_SIZE = (PACKET_SIZE*8)/ACCUM_WIDTH;
|
localparam READ_BATCH_SIZE = (PACKET_SIZE*8)/ACCUM_WIDTH;
|
||||||
localparam MAX_WORDS = N_MAX;
|
localparam MAX_WORDS = N_MAX;
|
||||||
@@ -20,7 +20,6 @@ module tb_accumulator_top;
|
|||||||
logic start;
|
logic start;
|
||||||
logic [31:0] smp_num;
|
logic [31:0] smp_num;
|
||||||
logic [15:0] seq_num;
|
logic [15:0] seq_num;
|
||||||
logic [31:0] window_size;
|
|
||||||
|
|
||||||
logic req_ready;
|
logic req_ready;
|
||||||
wire send_req;
|
wire send_req;
|
||||||
@@ -51,6 +50,7 @@ module tb_accumulator_top;
|
|||||||
.DATA_WIDTH(DATA_WIDTH),
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
.ACCUM_WIDTH(ACCUM_WIDTH),
|
.ACCUM_WIDTH(ACCUM_WIDTH),
|
||||||
.N_MAX(N_MAX),
|
.N_MAX(N_MAX),
|
||||||
|
.WINDOW_SIZE(WINDOW_SIZE),
|
||||||
.PACKET_SIZE(PACKET_SIZE)
|
.PACKET_SIZE(PACKET_SIZE)
|
||||||
) dut (
|
) dut (
|
||||||
.clk_in(clk_in),
|
.clk_in(clk_in),
|
||||||
@@ -60,7 +60,6 @@ module tb_accumulator_top;
|
|||||||
.start(start),
|
.start(start),
|
||||||
.smp_num(smp_num),
|
.smp_num(smp_num),
|
||||||
.seq_num(seq_num),
|
.seq_num(seq_num),
|
||||||
.window_size(window_size),
|
|
||||||
.eth_clk_in(eth_clk_in),
|
.eth_clk_in(eth_clk_in),
|
||||||
.req_ready(req_ready),
|
.req_ready(req_ready),
|
||||||
.send_req(send_req),
|
.send_req(send_req),
|
||||||
@@ -105,7 +104,6 @@ module tb_accumulator_top;
|
|||||||
s_axis_tvalid = 1'b0;
|
s_axis_tvalid = 1'b0;
|
||||||
smp_num = '0;
|
smp_num = '0;
|
||||||
seq_num = '0;
|
seq_num = '0;
|
||||||
window_size = 32'd1;
|
|
||||||
req_ready = 1'b0;
|
req_ready = 1'b0;
|
||||||
m_axis_tready = 1'b1;
|
m_axis_tready = 1'b1;
|
||||||
clear_scoreboard();
|
clear_scoreboard();
|
||||||
@@ -143,14 +141,13 @@ module tb_accumulator_top;
|
|||||||
|
|
||||||
task automatic run_test(
|
task automatic run_test(
|
||||||
input integer test_id,
|
input integer test_id,
|
||||||
input integer window_size_i,
|
|
||||||
input integer seq_num_i,
|
input integer seq_num_i,
|
||||||
input integer smp_num_i,
|
input integer smp_num_i,
|
||||||
input bit randomize_data,
|
input bit randomize_data,
|
||||||
input integer base_value,
|
input integer base_value,
|
||||||
input string test_name
|
input string test_name
|
||||||
);
|
);
|
||||||
logic [DATA_WIDTH-1:0] sample_mem [0:MAX_SEQ_NUM-1][0:(N_MAX*MAX_WINDOW_SIZE)-1];
|
logic [DATA_WIDTH-1:0] sample_mem [0:MAX_SEQ_NUM-1][0:(N_MAX*WINDOW_SIZE)-1];
|
||||||
integer seq_idx;
|
integer seq_idx;
|
||||||
integer sample_idx;
|
integer sample_idx;
|
||||||
integer word_idx;
|
integer word_idx;
|
||||||
@@ -168,25 +165,22 @@ module tb_accumulator_top;
|
|||||||
tests_total = tests_total + 1;
|
tests_total = tests_total + 1;
|
||||||
errors_before = total_errors;
|
errors_before = total_errors;
|
||||||
|
|
||||||
if (window_size_i <= 0 || window_size_i > MAX_WINDOW_SIZE)
|
if (smp_num_i <= 0 || smp_num_i > N_MAX * WINDOW_SIZE || (smp_num_i % WINDOW_SIZE) != 0)
|
||||||
$fatal(1, "[%0s] invalid window_size=%0d", test_name, window_size_i);
|
$fatal(1, "[%0s] invalid smp_num=%0d", test_name, smp_num_i);
|
||||||
if (smp_num_i <= 0 || smp_num_i > N_MAX * window_size_i || (smp_num_i % window_size_i) != 0)
|
|
||||||
$fatal(1, "[%0s] invalid smp_num=%0d for window_size=%0d", test_name, smp_num_i, window_size_i);
|
|
||||||
if (seq_num_i <= 0 || seq_num_i > MAX_SEQ_NUM)
|
if (seq_num_i <= 0 || seq_num_i > MAX_SEQ_NUM)
|
||||||
$fatal(1, "[%0s] invalid seq_num=%0d", test_name, seq_num_i);
|
$fatal(1, "[%0s] invalid seq_num=%0d", test_name, seq_num_i);
|
||||||
|
|
||||||
$display("\n========================================");
|
$display("\n========================================");
|
||||||
$display("TEST %0d: %0s", test_id, test_name);
|
$display("TEST %0d: %0s", test_id, test_name);
|
||||||
$display("window_size=%0d seq_num=%0d smp_num=%0d randomize=%0d", window_size_i, seq_num_i, smp_num_i, randomize_data);
|
$display("seq_num=%0d smp_num=%0d randomize=%0d", seq_num_i, smp_num_i, randomize_data);
|
||||||
$display("========================================");
|
$display("========================================");
|
||||||
|
|
||||||
reset_dut();
|
reset_dut();
|
||||||
smp_num = smp_num_i;
|
smp_num = smp_num_i;
|
||||||
seq_num = seq_num_i;
|
seq_num = seq_num_i;
|
||||||
window_size = window_size_i;
|
req_ready = 1'b1; // приемник готов заранее
|
||||||
req_ready = 1'b1; // приемник готов заранее
|
|
||||||
|
|
||||||
exp_word_count = smp_num_i / window_size_i;
|
exp_word_count = smp_num_i / WINDOW_SIZE;
|
||||||
exp_packet_count = (exp_word_count + READ_BATCH_SIZE - 1) / READ_BATCH_SIZE;
|
exp_packet_count = (exp_word_count + READ_BATCH_SIZE - 1) / READ_BATCH_SIZE;
|
||||||
|
|
||||||
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
||||||
@@ -202,8 +196,8 @@ module tb_accumulator_top;
|
|||||||
for (word_idx = 0; word_idx < exp_word_count; word_idx = word_idx + 1) begin
|
for (word_idx = 0; word_idx < exp_word_count; word_idx = word_idx + 1) begin
|
||||||
local_sum = 0;
|
local_sum = 0;
|
||||||
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
for (seq_idx = 0; seq_idx < seq_num_i; seq_idx = seq_idx + 1) begin
|
||||||
for (k = 0; k < window_size_i; k = k + 1)
|
for (k = 0; k < WINDOW_SIZE; k = k + 1)
|
||||||
local_sum = local_sum + sample_mem[seq_idx][word_idx * window_size_i + k];
|
local_sum = local_sum + sample_mem[seq_idx][word_idx * WINDOW_SIZE + k];
|
||||||
end
|
end
|
||||||
expected_words[word_idx] = local_sum[ACCUM_WIDTH-1:0];
|
expected_words[word_idx] = local_sum[ACCUM_WIDTH-1:0];
|
||||||
$display(" expected[%0d] = %0d (0x%08x)", word_idx, expected_words[word_idx], expected_words[word_idx]);
|
$display(" expected[%0d] = %0d (0x%08x)", word_idx, expected_words[word_idx], expected_words[word_idx]);
|
||||||
@@ -324,17 +318,16 @@ module tb_accumulator_top;
|
|||||||
|
|
||||||
reset_dut();
|
reset_dut();
|
||||||
|
|
||||||
run_test(1, 1, 1, 1 * 1, 1'b0, 1, "w1_deterministic_small");
|
run_test(1, 1, 1 * WINDOW_SIZE, 1'b0, 1, "deterministic_small");
|
||||||
run_test(2, 1, 2, 16 * 1, 1'b1, 0, "w1_random_seq2_smp16");
|
// $finish;
|
||||||
run_test(3, 2, 2, 16 * 2, 1'b1, 0, "w2_random_seq2_smp32");
|
run_test(2, 2, 1 * WINDOW_SIZE, 1'b1, 0, "random_seq3_smp8");
|
||||||
run_test(4, 3, 1, 16 * 3, 1'b1, 0, "w3_random_seq1_smp48");
|
run_test(3, 1, 16 * WINDOW_SIZE, 1'b1, 0, "random_seq5_smp16_multi_packet");
|
||||||
run_test(5, 4, 2, 12 * 4, 1'b1, 0, "w4_random_seq2_smp48");
|
run_test(4, 2, 12 * WINDOW_SIZE, 1'b1, 0, "random_seq7_smp12");
|
||||||
run_test(6, 65, 4, 256 * 65, 1'b1, 0, "w65_random_seq4_smp16640");
|
run_test(5, 4, 256 * WINDOW_SIZE, 1'b1, 0, "random_max_smpnum");
|
||||||
run_test(7, 2, 20, 3 * 2, 1'b1, 0, "w2_random_20seqx3");
|
run_test(6, 2, 1500 * WINDOW_SIZE, 1'b1, 0, "random_max_smpnum2");
|
||||||
run_test(8, 65, 20, 3 * 65, 1'b1, 0, "w65_random_20seqx3");
|
run_test(7, 20, 1 * WINDOW_SIZE, 1'b1, 0, "random_20seq");
|
||||||
run_test(9, 1, 200, 1 * 1, 1'b1, 0, "w1_random_200seq");
|
run_test(8, 20, 3 * WINDOW_SIZE, 1'b1, 0, "random_20seqx3");
|
||||||
run_test(10, 2, 200, 2 * 1, 1'b1, 0, "w2_random_200seq");
|
run_test(9, 200, 1 * WINDOW_SIZE, 1'b1, 0, "random_200seq");
|
||||||
run_test(11, 65, 200, 65 * 1, 1'b1, 0, "w1_random_200seq");
|
|
||||||
|
|
||||||
$display("\n========================================");
|
$display("\n========================================");
|
||||||
$display("ALL TESTS COMPLETED");
|
$display("ALL TESTS COMPLETED");
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
module axi4l_reg_map_controller #(
|
||||||
|
parameter int unsigned ADDR_W = 16,
|
||||||
|
parameter int unsigned DATA_W = 32,
|
||||||
|
parameter int unsigned USER_W = 1
|
||||||
|
)(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst_n,
|
||||||
|
axi4l_if.slave s_axil,
|
||||||
|
// dac adc registers
|
||||||
|
output logic start_o,
|
||||||
|
output logic cfg_bus_valid_o,
|
||||||
|
output logic [31:0] pulse_width_o,
|
||||||
|
output logic [31:0] pulse_period_o,
|
||||||
|
output logic [31:0] pulse_num_o,
|
||||||
|
output logic [31:0] pulse_height_raw_o,
|
||||||
|
output logic [31:0] pulse_period_ADC_o,
|
||||||
|
output logic [31:0] window_size_o,
|
||||||
|
|
||||||
|
// DMA CONTROL SIGNALS
|
||||||
|
output logic send_desc_read_o,
|
||||||
|
output logic send_desc_write_o,
|
||||||
|
output logic take_status_read_o,
|
||||||
|
output logic take_status_write_o,
|
||||||
|
|
||||||
|
input logic desc_read_dma_busy_i,
|
||||||
|
input logic desc_write_dma_busy_i,
|
||||||
|
input logic status_read_dma_busy_i,
|
||||||
|
input logic status_write_dma_busy_i,
|
||||||
|
|
||||||
|
input logic desc_read_dma_hs_i,
|
||||||
|
input logic desc_write_dma_hs_i,
|
||||||
|
input logic status_read_dma_hs_i,
|
||||||
|
input logic status_write_dma_hs_i,
|
||||||
|
|
||||||
|
// DMA read descriptors and status register
|
||||||
|
|
||||||
|
output logic [31:0] desc_read_addr_o,
|
||||||
|
output logic [31:0] desc_read_len_o,
|
||||||
|
output logic [31:0] desc_read_config_o,
|
||||||
|
|
||||||
|
input logic [31:0] status_read_i,
|
||||||
|
|
||||||
|
// DMA write descriptors and status register
|
||||||
|
output logic [31:0] desc_write_addr_o,
|
||||||
|
output logic [31:0] desc_write_len_and_tag_o,
|
||||||
|
|
||||||
|
input logic [31:0] status_write_len_i,
|
||||||
|
input logic [31:0] status_write_config_i,
|
||||||
|
|
||||||
|
output logic rst_soft_o,
|
||||||
|
input logic busy_i,
|
||||||
|
input logic [7:0] error_code_i
|
||||||
|
);
|
||||||
|
import axi4l_reg_map_controller_pkg::*;
|
||||||
|
localparam int unsigned N_REGS = CTRL_REG_MAP_N_REGS;
|
||||||
|
|
||||||
|
logic [N_REGS-1:0][31:0] reg_i;
|
||||||
|
logic [N_REGS-1:0][31:0] reg_o;
|
||||||
|
logic [N_REGS-1:0][31:0] reg_pulse;
|
||||||
|
|
||||||
|
axi4l_reg_map #(
|
||||||
|
.ADDR_W (ADDR_W),
|
||||||
|
.DATA_W (DATA_W),
|
||||||
|
.USER_W (USER_W),
|
||||||
|
.N_REGS (N_REGS),
|
||||||
|
.REG_MODE (CTRL_REG_MAP_REG_MODE),
|
||||||
|
.REG_RST (CTRL_REG_MAP_REG_RST)
|
||||||
|
) u_reg_map (
|
||||||
|
.clk (clk),
|
||||||
|
.rst_n (rst_n),
|
||||||
|
.s_axil (s_axil),
|
||||||
|
.reg_i (reg_i),
|
||||||
|
.reg_o (reg_o),
|
||||||
|
.reg_pulse(reg_pulse)
|
||||||
|
);
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
reg_i = '0;
|
||||||
|
|
||||||
|
reg_i[REG_STATUS][0] = busy_i;
|
||||||
|
|
||||||
|
reg_i[REG_STATUS][1] = desc_read_dma_busy_i;
|
||||||
|
reg_i[REG_STATUS][2] = desc_write_dma_busy_i;
|
||||||
|
reg_i[REG_STATUS][3] = status_read_dma_busy_i;
|
||||||
|
reg_i[REG_STATUS][4] = status_write_dma_busy_i;
|
||||||
|
|
||||||
|
reg_i[REG_STATUS][5] = desc_read_dma_hs_i;
|
||||||
|
reg_i[REG_STATUS][6] = desc_write_dma_hs_i;
|
||||||
|
reg_i[REG_STATUS][7] = status_read_dma_hs_i;
|
||||||
|
reg_i[REG_STATUS][8] = status_write_dma_hs_i;
|
||||||
|
|
||||||
|
reg_i[REG_ERROR][7:0] = error_code_i;
|
||||||
|
|
||||||
|
reg_i[REG_READ_STATUS] = status_read_i;
|
||||||
|
reg_i[REG_STATUS_WRITE_LEN] = status_write_len_i;
|
||||||
|
reg_i[REG_STATUS_WRITE_CONFIG] = status_write_config_i;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
assign start_o = reg_pulse[REG_CONTROL][0];
|
||||||
|
assign rst_soft_o = reg_pulse[REG_CONTROL][1];
|
||||||
|
assign cfg_bus_valid_o = reg_pulse[REG_CONTROL][2];
|
||||||
|
|
||||||
|
assign send_desc_read_o = reg_pulse[REG_CONTROL][3];
|
||||||
|
assign send_desc_write_o = reg_pulse[REG_CONTROL][4];
|
||||||
|
assign take_status_read_o = reg_pulse[REG_CONTROL][5];
|
||||||
|
assign take_status_write_o = reg_pulse[REG_CONTROL][6];
|
||||||
|
|
||||||
|
assign pulse_width_o = reg_o[REG_DAC_WIDTH];
|
||||||
|
assign pulse_period_o = reg_o[REG_DAC_PERIOD];
|
||||||
|
assign pulse_num_o = reg_o[REG_DAC_PULSE_NUM];
|
||||||
|
assign pulse_height_raw_o = reg_o[REG_DAC_PULSE_HEIGHT];
|
||||||
|
assign pulse_period_ADC_o = reg_o[REG_ADC_PERIOD];
|
||||||
|
assign window_size_o = reg_o[REG_WINDOW_SIZE];
|
||||||
|
|
||||||
|
assign desc_read_addr_o = reg_o[REG_DESC_READ_ADDR];
|
||||||
|
assign desc_read_len_o = reg_o[REG_DESC_READ_LEN];
|
||||||
|
assign desc_read_config_o = reg_o[REG_DESC_READ_CONFIG];
|
||||||
|
assign desc_write_addr_o = reg_o[REG_DESC_WRITE_ADDR];
|
||||||
|
assign desc_write_len_and_tag_o = reg_o[REG_DESC_WRITE_LEN_AND_TAG];
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package axi4l_reg_map_controller_pkg;
|
||||||
|
|
||||||
|
localparam int unsigned CTRL_REG_MAP_N_REGS = 17;
|
||||||
|
|
||||||
|
/*
|
||||||
|
dac adc configuration registers
|
||||||
|
*/
|
||||||
|
localparam logic [31:0] REG_CONTROL = 32'd0;
|
||||||
|
localparam logic [31:0] REG_STATUS = 32'd1;
|
||||||
|
localparam logic [31:0] REG_DAC_WIDTH = 32'd2;
|
||||||
|
localparam logic [31:0] REG_DAC_PERIOD = 32'd3;
|
||||||
|
localparam logic [31:0] REG_DAC_PULSE_NUM = 32'd4;
|
||||||
|
localparam logic [31:0] REG_DAC_PULSE_HEIGHT = 32'd5;
|
||||||
|
localparam logic [31:0] REG_ADC_PERIOD = 32'd6;
|
||||||
|
localparam logic [31:0] REG_WINDOW_SIZE = 32'd7;
|
||||||
|
localparam logic [31:0] REG_ERROR = 32'd8;
|
||||||
|
|
||||||
|
/*
|
||||||
|
AXI read descriptor input and AXI read descriptor status output configuration registers
|
||||||
|
*/
|
||||||
|
localparam logic [31:0] REG_DESC_READ_ADDR = 32'd9;
|
||||||
|
localparam logic [31:0] REG_DESC_READ_LEN = 32'd10;
|
||||||
|
localparam logic [31:0] REG_DESC_READ_CONFIG = 32'd11;
|
||||||
|
|
||||||
|
localparam logic [31:0] REG_READ_STATUS = 32'd12;
|
||||||
|
|
||||||
|
/*
|
||||||
|
AXI write descriptor input and AXI write descriptor status output configuration registers
|
||||||
|
*/
|
||||||
|
localparam logic [31:0] REG_DESC_WRITE_ADDR = 32'd13;
|
||||||
|
localparam logic [31:0] REG_DESC_WRITE_LEN_AND_TAG = 32'd14;
|
||||||
|
|
||||||
|
localparam logic [31:0] REG_STATUS_WRITE_LEN = 32'd15;
|
||||||
|
localparam logic [31:0] REG_STATUS_WRITE_CONFIG = 32'd16;
|
||||||
|
|
||||||
|
|
||||||
|
localparam logic [2:0] REG_BIT_RSVD = 3'd0;
|
||||||
|
localparam logic [2:0] REG_BIT_RO = 3'd1;
|
||||||
|
localparam logic [2:0] REG_BIT_RW = 3'd2;
|
||||||
|
localparam logic [2:0] REG_BIT_W1S = 3'd3;
|
||||||
|
|
||||||
|
localparam logic [CTRL_REG_MAP_N_REGS-1:0][31:0][2:0] CTRL_REG_MAP_REG_MODE = '{
|
||||||
|
default: '{default: REG_BIT_RSVD},
|
||||||
|
|
||||||
|
REG_CONTROL: '{
|
||||||
|
0 : REG_BIT_W1S,
|
||||||
|
1 : REG_BIT_W1S,
|
||||||
|
2 : REG_BIT_W1S,
|
||||||
|
3 : REG_BIT_W1S,
|
||||||
|
4 : REG_BIT_W1S,
|
||||||
|
5 : REG_BIT_W1S,
|
||||||
|
6 : REG_BIT_W1S,
|
||||||
|
default: REG_BIT_RSVD
|
||||||
|
},
|
||||||
|
|
||||||
|
REG_STATUS: '{
|
||||||
|
0 : REG_BIT_RO,
|
||||||
|
1 : REG_BIT_RO,
|
||||||
|
2 : REG_BIT_RO,
|
||||||
|
3 : REG_BIT_RO,
|
||||||
|
4 : REG_BIT_RO,
|
||||||
|
5 : REG_BIT_RO,
|
||||||
|
6 : REG_BIT_RO,
|
||||||
|
7 : REG_BIT_RO,
|
||||||
|
8 : REG_BIT_RO,
|
||||||
|
default: REG_BIT_RSVD
|
||||||
|
},
|
||||||
|
|
||||||
|
REG_DAC_WIDTH: '{default: REG_BIT_RW},
|
||||||
|
REG_DAC_PERIOD: '{default: REG_BIT_RW},
|
||||||
|
REG_DAC_PULSE_NUM: '{default: REG_BIT_RW},
|
||||||
|
REG_DAC_PULSE_HEIGHT: '{default: REG_BIT_RW},
|
||||||
|
REG_ADC_PERIOD: '{default: REG_BIT_RW},
|
||||||
|
REG_WINDOW_SIZE: '{default: REG_BIT_RW},
|
||||||
|
|
||||||
|
REG_ERROR: '{default: REG_BIT_RO},
|
||||||
|
|
||||||
|
REG_DESC_READ_ADDR: '{default: REG_BIT_RW},
|
||||||
|
REG_DESC_READ_LEN: '{default: REG_BIT_RW},
|
||||||
|
REG_DESC_READ_CONFIG: '{default: REG_BIT_RW},
|
||||||
|
REG_READ_STATUS: '{default: REG_BIT_RO},
|
||||||
|
|
||||||
|
REG_DESC_WRITE_ADDR: '{default: REG_BIT_RW},
|
||||||
|
REG_DESC_WRITE_LEN_AND_TAG: '{default: REG_BIT_RW},
|
||||||
|
REG_STATUS_WRITE_LEN: '{default: REG_BIT_RO},
|
||||||
|
REG_STATUS_WRITE_CONFIG: '{default: REG_BIT_RO}
|
||||||
|
};
|
||||||
|
|
||||||
|
localparam logic [CTRL_REG_MAP_N_REGS-1:0][31:0] CTRL_REG_MAP_REG_RST = '{
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000,
|
||||||
|
32'h0000_0000
|
||||||
|
};
|
||||||
|
|
||||||
|
endpackage
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
module axis_defaults_master
|
||||||
|
(
|
||||||
|
axis_if.master axis
|
||||||
|
);
|
||||||
|
|
||||||
|
assign axis.req.t.keep = '1;
|
||||||
|
assign axis.req.t.strb = '1;
|
||||||
|
assign axis.req.t.last = 1'b1;
|
||||||
|
assign axis.req.t.id = '0;
|
||||||
|
assign axis.req.t.dest = '0;
|
||||||
|
assign axis.req.t.user = '0;
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -1,19 +1,21 @@
|
|||||||
module control #(
|
module control #(
|
||||||
parameter int unsigned DAC_DATA_WIDTH = 12
|
parameter int unsigned DAC_DATA_WIDTH = 12
|
||||||
) (
|
) (
|
||||||
input logic eth_clk_in,
|
input logic ctrl_clk,
|
||||||
input logic dac_clk_in,
|
input logic dac_clk_in,
|
||||||
input logic adc_clk_in,
|
input logic adc_clk_in,
|
||||||
input logic rst_n,
|
|
||||||
|
|
||||||
// AXI stream slave, eth_clk_in domain
|
input logic rst_n,
|
||||||
input logic [7:0] s_axis_tdata,
|
input logic rst_soft,
|
||||||
input logic s_axis_tvalid,
|
|
||||||
output logic s_axis_tready,
|
|
||||||
input logic s_axis_tlast,
|
|
||||||
|
|
||||||
// adc_clk_in domain
|
// adc_clk_in domain
|
||||||
input logic finish,
|
input logic finish,
|
||||||
|
input logic [159:0] cfg_bus_input,
|
||||||
|
input logic cfg_bus_valid,
|
||||||
|
input logic start,
|
||||||
|
|
||||||
|
// status signals
|
||||||
|
output logic busy,
|
||||||
|
|
||||||
// dac_clk_in domain outputs
|
// dac_clk_in domain outputs
|
||||||
output logic [31:0] dac_pulse_width,
|
output logic [31:0] dac_pulse_width,
|
||||||
@@ -24,6 +26,7 @@ module control #(
|
|||||||
// adc_clk_in domain outputs
|
// adc_clk_in domain outputs
|
||||||
output logic [31:0] adc_pulse_period,
|
output logic [31:0] adc_pulse_period,
|
||||||
output logic [15:0] adc_pulse_num,
|
output logic [15:0] adc_pulse_num,
|
||||||
|
output logic [31:0] adc_window_size,
|
||||||
|
|
||||||
// pulse outputs
|
// pulse outputs
|
||||||
output logic dac_start,
|
output logic dac_start,
|
||||||
@@ -42,27 +45,22 @@ module control #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// command constants
|
|
||||||
localparam logic [7:0] CMD_SOFT_RESET = 8'h0F;
|
|
||||||
localparam logic [7:0] CMD_START = 8'hF0;
|
|
||||||
localparam logic [7:0] CMD_SET_DATA = 8'h88;
|
|
||||||
|
|
||||||
// reset synchronizers: async assert, sync deassert in each domain
|
// reset synchronizers: async assert, sync deassert in each domain
|
||||||
logic eth_rst_ff1, eth_rst_ff2;
|
logic rst_ff1, rst_ff2;
|
||||||
logic dac_rst_ff1, dac_rst_ff2;
|
logic dac_rst_ff1, dac_rst_ff2;
|
||||||
logic adc_rst_ff1, adc_rst_ff2;
|
logic adc_rst_ff1, adc_rst_ff2;
|
||||||
|
|
||||||
logic eth_rst;
|
logic ctrl_rst;
|
||||||
logic dac_rst_int;
|
logic dac_rst_int;
|
||||||
logic adc_rst_int;
|
logic adc_rst_int;
|
||||||
|
|
||||||
always_ff @(posedge eth_clk_in or negedge rst_n) begin
|
always_ff @(posedge ctrl_clk or negedge rst_n) begin
|
||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
eth_rst_ff1 <= 1'b1;
|
rst_ff1 <= 1'b1;
|
||||||
eth_rst_ff2 <= 1'b1;
|
rst_ff2 <= 1'b1;
|
||||||
end else begin
|
end else begin
|
||||||
eth_rst_ff1 <= 1'b0;
|
rst_ff1 <= 1'b0;
|
||||||
eth_rst_ff2 <= eth_rst_ff1;
|
rst_ff2 <= rst_ff1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -86,74 +84,34 @@ module control #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
assign eth_rst = eth_rst_ff2;
|
assign ctrl_rst = rst_ff2;
|
||||||
assign dac_rst_int = dac_rst_ff2;
|
assign dac_rst_int = dac_rst_ff2;
|
||||||
assign adc_rst_int = adc_rst_ff2;
|
assign adc_rst_int = adc_rst_ff2;
|
||||||
|
|
||||||
// axi stream is always accepted. If packet is not needed, it is discarded.
|
|
||||||
assign s_axis_tready = 1'b1;
|
|
||||||
|
|
||||||
(* MARK_DEBUG="true" *) wire axis_hs = s_axis_tvalid & s_axis_tready;
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
// Shared 96-bit config bus in ETH domain
|
|
||||||
//
|
|
||||||
// Byte order for SET_DATA payload, little-endian:
|
|
||||||
// payload byte 0 -> cfg_bus_eth[7:0]
|
|
||||||
// payload byte 1 -> cfg_bus_eth[15:8]
|
|
||||||
// ...etc...
|
|
||||||
// payload byte 11 -> cfg_bus_eth[95:88]
|
|
||||||
//
|
|
||||||
// Field layout inside cfg_bus_eth:
|
|
||||||
// [31:0] pulse_width
|
|
||||||
// [63:32] pulse_period
|
|
||||||
// [79:64] pulse_num
|
|
||||||
// [95:80] pulse_height_raw[15:0]
|
|
||||||
// [127:96] pulse_period_ADC
|
|
||||||
//
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
(* MARK_DEBUG="true" *) logic [127:0] cfg_bus_eth;
|
|
||||||
logic [127:0] cfg_shift_eth;
|
|
||||||
|
|
||||||
// ETH-domain parser and control
|
|
||||||
typedef enum logic [2:0] {
|
|
||||||
ST_IDLE = 3'd0,
|
|
||||||
ST_RECV_CFG = 3'd1,
|
|
||||||
ST_WAIT_CFG_ACK = 3'd2,
|
|
||||||
ST_DISCARD = 3'd3
|
|
||||||
} eth_state_t;
|
|
||||||
|
|
||||||
(* MARK_DEBUG="true" *) eth_state_t eth_state;
|
|
||||||
|
|
||||||
logic [3:0] cfg_byte_cnt;
|
|
||||||
|
|
||||||
// Busy flag: set by START command, cleared by finish event from ADC domain
|
|
||||||
(* MARK_DEBUG="true" *) logic busy_flag_eth;
|
|
||||||
|
|
||||||
// Pending ACKs for config delivery
|
// Pending ACKs for config delivery
|
||||||
logic cfg_wait_dac_ack;
|
logic cfg_wait_dac_ack;
|
||||||
logic cfg_wait_adc_ack;
|
logic cfg_wait_adc_ack;
|
||||||
|
|
||||||
// Event toggles ETH -> DAC/ADC
|
// Event toggles cntrl -> DAC/ADC
|
||||||
logic start_toggle_eth;
|
logic start_toggle;
|
||||||
logic rst_toggle_eth;
|
logic rst_toggle;
|
||||||
|
|
||||||
// Config request toggles ETH -> DAC/ADC
|
// Config request toggles cntrl -> DAC/ADC
|
||||||
logic cfg_req_toggle_dac_eth;
|
logic cfg_req_toggle_dac;
|
||||||
logic cfg_req_toggle_adc_eth;
|
logic cfg_req_toggle_adc;
|
||||||
|
|
||||||
// ACK toggles DAC/ADC -> ETH
|
// ACK toggles DAC/ADC -> cntrl
|
||||||
logic cfg_ack_toggle_dac;
|
logic cfg_ack_toggle_dac;
|
||||||
logic cfg_ack_toggle_adc;
|
logic cfg_ack_toggle_adc;
|
||||||
|
|
||||||
(* ASYNC_REG = "TRUE" *) logic cfg_ack_toggle_dac_meta, cfg_ack_toggle_dac_sync, cfg_ack_toggle_dac_sync_d;
|
(* ASYNC_REG = "TRUE" *) logic cfg_ack_toggle_dac_meta, cfg_ack_toggle_dac_sync, cfg_ack_toggle_dac_sync_d;
|
||||||
(* ASYNC_REG = "TRUE" *) logic cfg_ack_toggle_adc_meta, cfg_ack_toggle_adc_sync, cfg_ack_toggle_adc_sync_d;
|
(* ASYNC_REG = "TRUE" *) logic cfg_ack_toggle_adc_meta, cfg_ack_toggle_adc_sync, cfg_ack_toggle_adc_sync_d;
|
||||||
|
|
||||||
wire cfg_ack_pulse_dac_eth = cfg_ack_toggle_dac_sync ^ cfg_ack_toggle_dac_sync_d;
|
wire cfg_ack_pulse_dac = cfg_ack_toggle_dac_sync ^ cfg_ack_toggle_dac_sync_d;
|
||||||
wire cfg_ack_pulse_adc_eth = cfg_ack_toggle_adc_sync ^ cfg_ack_toggle_adc_sync_d;
|
wire cfg_ack_pulse_adc = cfg_ack_toggle_adc_sync ^ cfg_ack_toggle_adc_sync_d;
|
||||||
|
|
||||||
always_ff @(posedge eth_clk_in or posedge eth_rst) begin
|
always_ff @(posedge ctrl_clk or posedge ctrl_rst) begin
|
||||||
if (eth_rst) begin
|
if (ctrl_rst) begin
|
||||||
cfg_ack_toggle_dac_meta <= 1'b0;
|
cfg_ack_toggle_dac_meta <= 1'b0;
|
||||||
cfg_ack_toggle_dac_sync <= 1'b0;
|
cfg_ack_toggle_dac_sync <= 1'b0;
|
||||||
cfg_ack_toggle_dac_sync_d <= 1'b0;
|
cfg_ack_toggle_dac_sync_d <= 1'b0;
|
||||||
@@ -172,11 +130,11 @@ module control #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// finish event: ADC -> ETH via toggle CDC
|
// finish event: ADC -> cntrl via toggle CDC
|
||||||
logic finish_toggle_adc;
|
logic finish_toggle_adc;
|
||||||
logic finish_meta_eth, finish_sync_eth, finish_sync_eth_d;
|
logic finish_meta, finish_sync, finish_sync_d;
|
||||||
|
|
||||||
wire finish_pulse_eth = finish_sync_eth ^ finish_sync_eth_d;
|
wire finish_pulse = finish_sync ^ finish_sync_d;
|
||||||
|
|
||||||
always_ff @(posedge adc_clk_in or posedge adc_rst_int) begin
|
always_ff @(posedge adc_clk_in or posedge adc_rst_int) begin
|
||||||
if (adc_rst_int) begin
|
if (adc_rst_int) begin
|
||||||
@@ -186,152 +144,66 @@ module control #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge eth_clk_in or posedge eth_rst) begin
|
always_ff @(posedge ctrl_clk or posedge ctrl_rst) begin
|
||||||
if (eth_rst) begin
|
if (ctrl_rst) begin
|
||||||
finish_meta_eth <= 1'b0;
|
finish_meta <= 1'b0;
|
||||||
finish_sync_eth <= 1'b0;
|
finish_sync <= 1'b0;
|
||||||
finish_sync_eth_d <= 1'b0;
|
finish_sync_d <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
finish_meta_eth <= finish_toggle_adc;
|
finish_meta <= finish_toggle_adc;
|
||||||
finish_sync_eth <= finish_meta_eth;
|
finish_sync <= finish_meta;
|
||||||
finish_sync_eth_d <= finish_sync_eth;
|
finish_sync_d <= finish_sync;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// ETH FSM
|
logic [159:0] cfg_bus;
|
||||||
always_ff @(posedge eth_clk_in or posedge eth_rst) begin
|
|
||||||
if (eth_rst) begin
|
|
||||||
eth_state <= ST_IDLE;
|
|
||||||
cfg_byte_cnt <= '0;
|
|
||||||
cfg_shift_eth <= '0;
|
|
||||||
cfg_bus_eth <= '0;
|
|
||||||
|
|
||||||
busy_flag_eth <= 1'b0;
|
always_ff @(posedge ctrl_clk or posedge ctrl_rst) begin
|
||||||
|
if (ctrl_rst) begin
|
||||||
|
cfg_bus <= '0;
|
||||||
|
busy <= 0;
|
||||||
|
|
||||||
start_toggle_eth <= 1'b0;
|
start_toggle <= 0;
|
||||||
rst_toggle_eth <= 1'b0;
|
rst_toggle <= 0;
|
||||||
|
|
||||||
cfg_req_toggle_dac_eth <= 1'b0;
|
cfg_req_toggle_dac <= 0;
|
||||||
cfg_req_toggle_adc_eth <= 1'b0;
|
cfg_req_toggle_adc <= 0;
|
||||||
|
|
||||||
cfg_wait_dac_ack <= 1'b0;
|
cfg_wait_dac_ack <= 0;
|
||||||
cfg_wait_adc_ack <= 1'b0;
|
cfg_wait_adc_ack <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
// finish always clears busy
|
if (finish_pulse) begin
|
||||||
if (finish_pulse_eth) begin
|
busy <= 0;
|
||||||
busy_flag_eth <= 1'b0;
|
|
||||||
end
|
end
|
||||||
|
if (cfg_ack_pulse_dac) begin
|
||||||
// config acks
|
|
||||||
if (cfg_ack_pulse_dac_eth) begin
|
|
||||||
cfg_wait_dac_ack <= 1'b0;
|
cfg_wait_dac_ack <= 1'b0;
|
||||||
end
|
end
|
||||||
if (cfg_ack_pulse_adc_eth) begin
|
if (cfg_ack_pulse_adc) begin
|
||||||
cfg_wait_adc_ack <= 1'b0;
|
cfg_wait_adc_ack <= 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
case (eth_state)
|
if (cfg_bus_valid && !busy && !cfg_wait_dac_ack && !cfg_wait_adc_ack) begin
|
||||||
ST_IDLE: begin
|
cfg_bus <= cfg_bus_input;
|
||||||
cfg_byte_cnt <= '0;
|
|
||||||
cfg_shift_eth <= cfg_shift_eth;
|
|
||||||
|
|
||||||
if (axis_hs) begin
|
cfg_req_toggle_dac <= ~cfg_req_toggle_dac;
|
||||||
// if busy, drop the whole packet
|
cfg_req_toggle_adc <= ~cfg_req_toggle_adc;
|
||||||
if (busy_flag_eth) begin
|
|
||||||
if (!s_axis_tlast) begin
|
|
||||||
eth_state <= ST_DISCARD;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
unique case (s_axis_tdata)
|
|
||||||
CMD_SOFT_RESET: begin
|
|
||||||
rst_toggle_eth <= ~rst_toggle_eth;
|
|
||||||
end
|
|
||||||
|
|
||||||
CMD_START: begin
|
cfg_wait_dac_ack <= 1;
|
||||||
start_toggle_eth <= ~start_toggle_eth;
|
cfg_wait_adc_ack <= 1;
|
||||||
busy_flag_eth <= 1'b1;
|
end
|
||||||
end
|
|
||||||
|
|
||||||
CMD_SET_DATA: begin
|
if (start && !busy && !cfg_wait_dac_ack && !cfg_wait_adc_ack) begin
|
||||||
// expect exactly 12 bytes after command
|
start_toggle <= ~start_toggle;
|
||||||
if (s_axis_tlast) begin
|
busy <= 1;
|
||||||
// no payload, invalid packet
|
end
|
||||||
eth_state <= ST_IDLE;
|
if (rst_soft) begin
|
||||||
end else begin
|
rst_toggle <= ~rst_toggle;
|
||||||
cfg_byte_cnt <= 4'd0;
|
end
|
||||||
cfg_shift_eth <= '0;
|
|
||||||
eth_state <= ST_RECV_CFG;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default: begin
|
|
||||||
// unknown command: discard packet remainder if any
|
|
||||||
if (!s_axis_tlast) begin
|
|
||||||
eth_state <= ST_DISCARD;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ST_RECV_CFG: begin
|
|
||||||
if (axis_hs) begin
|
|
||||||
// little endian packing
|
|
||||||
cfg_shift_eth[cfg_byte_cnt*8 +: 8] <= s_axis_tdata;
|
|
||||||
|
|
||||||
if (cfg_byte_cnt == 4'd15) begin
|
|
||||||
// this must be the final payload byte
|
|
||||||
if (s_axis_tlast) begin
|
|
||||||
cfg_bus_eth <= {s_axis_tdata, cfg_shift_eth[119:0]};
|
|
||||||
cfg_req_toggle_dac_eth <= ~cfg_req_toggle_dac_eth;
|
|
||||||
cfg_req_toggle_adc_eth <= ~cfg_req_toggle_adc_eth;
|
|
||||||
cfg_wait_dac_ack <= 1'b1;
|
|
||||||
cfg_wait_adc_ack <= 1'b1;
|
|
||||||
eth_state <= ST_WAIT_CFG_ACK;
|
|
||||||
end else begin
|
|
||||||
// too many bytes in packet
|
|
||||||
eth_state <= ST_DISCARD;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
// early tlast means packet too short!!
|
|
||||||
if (s_axis_tlast) begin
|
|
||||||
eth_state <= ST_IDLE;
|
|
||||||
end else begin
|
|
||||||
cfg_byte_cnt <= cfg_byte_cnt + 4'd1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ST_WAIT_CFG_ACK: begin
|
|
||||||
// any incoming packet while waiting ack is discarded
|
|
||||||
if (cfg_ack_pulse_dac_eth || cfg_ack_pulse_adc_eth) begin
|
|
||||||
if ((~cfg_wait_dac_ack || cfg_ack_pulse_dac_eth) &&
|
|
||||||
(~cfg_wait_adc_ack || cfg_ack_pulse_adc_eth)) begin
|
|
||||||
eth_state <= ST_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (axis_hs && !s_axis_tlast) begin
|
|
||||||
eth_state <= ST_DISCARD;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
ST_DISCARD: begin
|
|
||||||
if (axis_hs && s_axis_tlast) begin
|
|
||||||
eth_state <= ST_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default: begin
|
|
||||||
eth_state <= ST_IDLE;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// ETH -> DAC: start/reset event sync
|
// cntrl -> DAC: start/reset event sync
|
||||||
(* ASYNC_REG = "TRUE" *) logic start_meta_dac, start_sync_dac;
|
(* ASYNC_REG = "TRUE" *) logic start_meta_dac, start_sync_dac;
|
||||||
logic start_sync_dac_d;
|
logic start_sync_dac_d;
|
||||||
(* ASYNC_REG = "TRUE" *) logic rst_meta_dac, rst_sync_dac;
|
(* ASYNC_REG = "TRUE" *) logic rst_meta_dac, rst_sync_dac;
|
||||||
@@ -353,11 +225,11 @@ module control #(
|
|||||||
dac_start <= 1'b0;
|
dac_start <= 1'b0;
|
||||||
dac_rst <= 1'b0;
|
dac_rst <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
start_meta_dac <= start_toggle_eth;
|
start_meta_dac <= start_toggle;
|
||||||
start_sync_dac <= start_meta_dac;
|
start_sync_dac <= start_meta_dac;
|
||||||
start_sync_dac_d <= start_sync_dac;
|
start_sync_dac_d <= start_sync_dac;
|
||||||
|
|
||||||
rst_meta_dac <= rst_toggle_eth;
|
rst_meta_dac <= rst_toggle;
|
||||||
rst_sync_dac <= rst_meta_dac;
|
rst_sync_dac <= rst_meta_dac;
|
||||||
rst_sync_dac_d <= rst_sync_dac;
|
rst_sync_dac_d <= rst_sync_dac;
|
||||||
|
|
||||||
@@ -366,7 +238,7 @@ module control #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// ETH -> ADC: start/reset event sync
|
// cntrl -> ADC: start/reset event sync
|
||||||
(* ASYNC_REG = "TRUE" *) logic start_meta_adc, start_sync_adc;
|
(* ASYNC_REG = "TRUE" *) logic start_meta_adc, start_sync_adc;
|
||||||
logic start_sync_adc_d;
|
logic start_sync_adc_d;
|
||||||
(* ASYNC_REG = "TRUE" *) logic rst_meta_adc, rst_sync_adc;
|
(* ASYNC_REG = "TRUE" *) logic rst_meta_adc, rst_sync_adc;
|
||||||
@@ -388,11 +260,11 @@ module control #(
|
|||||||
adc_start <= 1'b0;
|
adc_start <= 1'b0;
|
||||||
adc_rst <= 1'b0;
|
adc_rst <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
start_meta_adc <= start_toggle_eth;
|
start_meta_adc <= start_toggle;
|
||||||
start_sync_adc <= start_meta_adc;
|
start_sync_adc <= start_meta_adc;
|
||||||
start_sync_adc_d <= start_sync_adc;
|
start_sync_adc_d <= start_sync_adc;
|
||||||
|
|
||||||
rst_meta_adc <= rst_toggle_eth;
|
rst_meta_adc <= rst_toggle;
|
||||||
rst_sync_adc <= rst_meta_adc;
|
rst_sync_adc <= rst_meta_adc;
|
||||||
rst_sync_adc_d <= rst_sync_adc;
|
rst_sync_adc_d <= rst_sync_adc;
|
||||||
|
|
||||||
@@ -401,8 +273,8 @@ module control #(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// ETH -> DAC config CDC
|
// contrl -> DAC config CDC
|
||||||
// cfg_bus_eth is kept stable in ETH domain until DAC and ADC both ACK.
|
// cfg_bus is kept stable in contrl domain until DAC and ADC both ACK.
|
||||||
(* ASYNC_REG = "TRUE" *) logic cfg_req_meta_dac, cfg_req_sync_dac;
|
(* ASYNC_REG = "TRUE" *) logic cfg_req_meta_dac, cfg_req_sync_dac;
|
||||||
logic cfg_req_sync_dac_d;
|
logic cfg_req_sync_dac_d;
|
||||||
wire cfg_req_pulse_dac = cfg_req_sync_dac ^ cfg_req_sync_dac_d;
|
wire cfg_req_pulse_dac = cfg_req_sync_dac ^ cfg_req_sync_dac_d;
|
||||||
@@ -419,22 +291,22 @@ module control #(
|
|||||||
dac_pulse_num <= '0;
|
dac_pulse_num <= '0;
|
||||||
dac_pulse_height <= '0;
|
dac_pulse_height <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
cfg_req_meta_dac <= cfg_req_toggle_dac_eth;
|
cfg_req_meta_dac <= cfg_req_toggle_dac;
|
||||||
cfg_req_sync_dac <= cfg_req_meta_dac;
|
cfg_req_sync_dac <= cfg_req_meta_dac;
|
||||||
cfg_req_sync_dac_d <= cfg_req_sync_dac;
|
cfg_req_sync_dac_d <= cfg_req_sync_dac;
|
||||||
|
|
||||||
if (cfg_req_pulse_dac) begin
|
if (cfg_req_pulse_dac) begin
|
||||||
dac_pulse_width <= cfg_bus_eth[31:0];
|
dac_pulse_width <= cfg_bus[31:0];
|
||||||
dac_pulse_period <= cfg_bus_eth[63:32];
|
dac_pulse_period <= cfg_bus[63:32];
|
||||||
dac_pulse_num <= cfg_bus_eth[79:64];
|
dac_pulse_num <= cfg_bus[79:64];
|
||||||
dac_pulse_height <= cfg_bus_eth[80 +: DAC_DATA_WIDTH];
|
dac_pulse_height <= cfg_bus[80 +: DAC_DATA_WIDTH];
|
||||||
|
|
||||||
cfg_ack_toggle_dac <= ~cfg_ack_toggle_dac;
|
cfg_ack_toggle_dac <= ~cfg_ack_toggle_dac;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// ETH -> ADC config CDC
|
// cntrl -> ADC config CDC
|
||||||
logic cfg_req_meta_adc, cfg_req_sync_adc, cfg_req_sync_adc_d;
|
logic cfg_req_meta_adc, cfg_req_sync_adc, cfg_req_sync_adc_d;
|
||||||
wire cfg_req_pulse_adc = cfg_req_sync_adc ^ cfg_req_sync_adc_d;
|
wire cfg_req_pulse_adc = cfg_req_sync_adc ^ cfg_req_sync_adc_d;
|
||||||
|
|
||||||
@@ -445,16 +317,18 @@ module control #(
|
|||||||
cfg_req_sync_adc_d <= 1'b0;
|
cfg_req_sync_adc_d <= 1'b0;
|
||||||
cfg_ack_toggle_adc <= 1'b0;
|
cfg_ack_toggle_adc <= 1'b0;
|
||||||
|
|
||||||
adc_pulse_period <= '0;
|
adc_pulse_period <= '0;
|
||||||
adc_pulse_num <= '0;
|
adc_pulse_num <= '0;
|
||||||
|
adc_window_size <= '0;
|
||||||
end else begin
|
end else begin
|
||||||
cfg_req_meta_adc <= cfg_req_toggle_adc_eth;
|
cfg_req_meta_adc <= cfg_req_toggle_adc;
|
||||||
cfg_req_sync_adc <= cfg_req_meta_adc;
|
cfg_req_sync_adc <= cfg_req_meta_adc;
|
||||||
cfg_req_sync_adc_d <= cfg_req_sync_adc;
|
cfg_req_sync_adc_d <= cfg_req_sync_adc;
|
||||||
|
|
||||||
if (cfg_req_pulse_adc) begin
|
if (cfg_req_pulse_adc) begin
|
||||||
adc_pulse_period <= cfg_bus_eth[127:96];
|
adc_pulse_period <= cfg_bus[127:96];
|
||||||
adc_pulse_num <= cfg_bus_eth[79:64];
|
adc_pulse_num <= cfg_bus[79:64];
|
||||||
|
adc_window_size <= cfg_bus[159:128];
|
||||||
|
|
||||||
cfg_ack_toggle_adc <= ~cfg_ack_toggle_adc;
|
cfg_ack_toggle_adc <= ~cfg_ack_toggle_adc;
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
import dma_reg_pkg::*;
|
||||||
|
|
||||||
|
module controller_wrapper_axil #(
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input logic ctrl_clk,
|
||||||
|
input logic dac_clk_in,
|
||||||
|
input logic adc_clk_in,
|
||||||
|
input logic rst_n,
|
||||||
|
axi4l_if.slave s_axil,
|
||||||
|
|
||||||
|
// adc_clk_in domain
|
||||||
|
input logic finish,
|
||||||
|
output logic [31:0] adc_window_size,
|
||||||
|
|
||||||
|
// dac_clk_in domain outputs
|
||||||
|
output logic [31:0] dac_pulse_width,
|
||||||
|
output logic [31:0] dac_pulse_period,
|
||||||
|
output logic [DAC_DATA_WIDTH-1:0] dac_pulse_height,
|
||||||
|
output logic [15:0] dac_pulse_num,
|
||||||
|
|
||||||
|
// adc_clk_in domain outputs
|
||||||
|
output logic [31:0] adc_pulse_period,
|
||||||
|
output logic [15:0] adc_pulse_num,
|
||||||
|
|
||||||
|
// pulse outputs
|
||||||
|
output logic dac_start,
|
||||||
|
output logic adc_start,
|
||||||
|
output logic dac_rst,
|
||||||
|
output logic adc_rst,
|
||||||
|
|
||||||
|
// AXIS DMA
|
||||||
|
axis_if.slave s_axis_status_read,
|
||||||
|
axis_if.slave s_axis_status_write,
|
||||||
|
|
||||||
|
axis_if.master m_axis_desc_read,
|
||||||
|
axis_if.master m_axis_desc_write
|
||||||
|
);
|
||||||
|
|
||||||
|
logic start, rst_soft, send_desc_read, send_desc_write, take_status_read, take_status_write, cfg_bus_valid, busy;
|
||||||
|
logic [31:0] pulse_width, pulse_period, pulse_num, pulse_height_raw, pulse_period_ADC, window_size;
|
||||||
|
logic [7:0] error_code;
|
||||||
|
logic [31:0] desc_read_addr, desc_read_len, desc_read_config, status_read;
|
||||||
|
logic [31:0] desc_write_addr, desc_write_len_and_tag, status_write_len, status_write_config;
|
||||||
|
|
||||||
|
logic desc_read_dma_busy, desc_write_dma_busy, status_read_dma_busy, status_write_dma_busy;
|
||||||
|
logic desc_read_dma_hs, desc_write_dma_hs, status_read_dma_hs, status_write_dma_hs;
|
||||||
|
|
||||||
|
axi4l_reg_map_controller #(
|
||||||
|
.ADDR_W(ADDR_W),
|
||||||
|
.DATA_W(DATA_W),
|
||||||
|
.USER_W(USER_W)
|
||||||
|
) axi4l_reg_map_controller_inst (
|
||||||
|
.clk(ctrl_clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.s_axil(s_axil),
|
||||||
|
// CONTROLLER ADC/ DAC
|
||||||
|
.start_o(start),
|
||||||
|
.cfg_bus_valid_o(cfg_bus_valid),
|
||||||
|
|
||||||
|
.pulse_width_o(pulse_width),
|
||||||
|
.pulse_period_o(pulse_period),
|
||||||
|
.pulse_num_o(pulse_num),
|
||||||
|
.pulse_height_raw_o(pulse_height_raw),
|
||||||
|
.pulse_period_ADC_o(pulse_period_ADC),
|
||||||
|
.window_size_o(window_size),
|
||||||
|
|
||||||
|
.rst_soft_o(rst_soft),
|
||||||
|
.busy_i(busy),
|
||||||
|
.error_code_i(error_code),
|
||||||
|
|
||||||
|
// CONTROLLER DMA
|
||||||
|
.send_desc_read_o(send_desc_read),
|
||||||
|
.send_desc_write_o(send_desc_write),
|
||||||
|
.take_status_read_o(take_status_read),
|
||||||
|
.take_status_write_o(take_status_write),
|
||||||
|
|
||||||
|
.desc_read_addr_o(desc_read_addr),
|
||||||
|
.desc_read_len_o(desc_read_len),
|
||||||
|
.desc_read_config_o(desc_read_config),
|
||||||
|
|
||||||
|
.status_read_i(status_read),
|
||||||
|
|
||||||
|
.desc_write_addr_o(desc_write_addr),
|
||||||
|
.desc_write_len_and_tag_o(desc_write_len_and_tag),
|
||||||
|
|
||||||
|
.status_write_len_i(status_write_len),
|
||||||
|
.status_write_config_i(status_write_config),
|
||||||
|
|
||||||
|
.desc_read_dma_busy_i(desc_read_dma_busy),
|
||||||
|
.desc_write_dma_busy_i(desc_write_dma_busy),
|
||||||
|
.status_read_dma_busy_i(status_read_dma_busy),
|
||||||
|
.status_write_dma_busy_i(status_write_dma_busy),
|
||||||
|
|
||||||
|
.desc_read_dma_hs_i(desc_read_dma_hs),
|
||||||
|
.desc_write_dma_hs_i(desc_write_dma_hs),
|
||||||
|
.status_read_dma_hs_i(status_read_dma_hs),
|
||||||
|
.status_write_dma_hs_i(status_write_dma_hs)
|
||||||
|
);
|
||||||
|
|
||||||
|
// CONTROLLER DAC ADC
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// Field layout inside cfg_bus:
|
||||||
|
// [31:0] pulse_width
|
||||||
|
// [63:32] pulse_period
|
||||||
|
// [79:64] pulse_num
|
||||||
|
// [95:80] pulse_height_raw[15:0]
|
||||||
|
// [127:96] pulse_period_ADC
|
||||||
|
// [159:128] window_size
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
(* MARK_DEBUG="true" *) logic [159:0] cfg_bus;
|
||||||
|
assign cfg_bus = {window_size, pulse_period_ADC, pulse_height_raw[15:0], pulse_num[15:0], pulse_period, pulse_width};
|
||||||
|
|
||||||
|
control #(
|
||||||
|
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||||
|
)
|
||||||
|
controller (
|
||||||
|
.ctrl_clk(ctrl_clk),
|
||||||
|
.dac_clk_in(dac_clk_in),
|
||||||
|
.adc_clk_in(adc_clk_in),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.rst_soft(rst_soft),
|
||||||
|
.finish(finish),
|
||||||
|
.cfg_bus_input(cfg_bus),
|
||||||
|
.cfg_bus_valid(cfg_bus_valid),
|
||||||
|
.start(start),
|
||||||
|
|
||||||
|
.busy(busy),
|
||||||
|
|
||||||
|
.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),
|
||||||
|
.adc_window_size(adc_window_size),
|
||||||
|
.dac_start(dac_start),
|
||||||
|
.adc_start(adc_start),
|
||||||
|
.dac_rst(dac_rst),
|
||||||
|
.adc_rst(adc_rst)
|
||||||
|
);
|
||||||
|
|
||||||
|
// CONTROLLER DMA
|
||||||
|
|
||||||
|
dma_read_desc_t desc_read_cmd, desc_read_cmd_out;
|
||||||
|
assign desc_read_cmd.addr = desc_read_addr;
|
||||||
|
assign desc_read_cmd.len = desc_read_len;
|
||||||
|
assign desc_read_cmd.tag = desc_read_config[TAG_WIDTH-1:0];
|
||||||
|
assign desc_read_cmd.id = desc_read_config[TAG_WIDTH +: AXIS_ID_WIDTH];
|
||||||
|
assign desc_read_cmd.dest = desc_read_config[TAG_WIDTH+AXIS_ID_WIDTH +: AXIS_DEST_WIDTH];
|
||||||
|
assign desc_read_cmd.user = desc_read_config[TAG_WIDTH+AXIS_ID_WIDTH+AXIS_DEST_WIDTH +: AXIS_USER_WIDTH];
|
||||||
|
|
||||||
|
dma_write_desc_t desc_write_cmd, desc_write_cmd_out;
|
||||||
|
assign desc_write_cmd.addr = desc_write_addr;
|
||||||
|
assign desc_write_cmd.len = desc_write_len_and_tag[LEN_WIDTH-1:0];
|
||||||
|
assign desc_write_cmd.tag = desc_write_len_and_tag[LEN_WIDTH +: TAG_WIDTH];
|
||||||
|
|
||||||
|
dma_read_status_t status_read_cmd, status_read_cmd_in;
|
||||||
|
assign status_read = { status_read_cmd.error, status_read_cmd.tag};
|
||||||
|
|
||||||
|
dma_write_status_t status_write_cmd, status_write_cmd_in;
|
||||||
|
assign status_write_len = status_write_cmd.len;
|
||||||
|
assign status_write_config = { status_write_cmd.error, status_write_cmd.user,
|
||||||
|
status_write_cmd.dest, status_write_cmd.id, status_write_cmd.tag};
|
||||||
|
|
||||||
|
dma_controller dma_controller_inst
|
||||||
|
(
|
||||||
|
.dma_clk(ctrl_clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
|
||||||
|
.send_desc_read(send_desc_read),
|
||||||
|
.send_desc_write(send_desc_write),
|
||||||
|
.take_status_read(take_status_read),
|
||||||
|
.take_status_write(take_status_write),
|
||||||
|
|
||||||
|
.desc_read_cmd(desc_read_cmd),
|
||||||
|
.desc_write_cmd(desc_write_cmd),
|
||||||
|
.status_read_cmd(status_read_cmd),
|
||||||
|
.status_write_cmd(status_write_cmd),
|
||||||
|
|
||||||
|
.desc_read_cmd_out(desc_read_cmd_out),
|
||||||
|
.desc_write_cmd_out(desc_write_cmd_out),
|
||||||
|
.status_read_cmd_in(status_read_cmd_in),
|
||||||
|
.status_write_cmd_in(status_write_cmd_in),
|
||||||
|
|
||||||
|
.ready_desc_read(m_axis_desc_read.resp.ready),
|
||||||
|
.ready_desc_write(m_axis_desc_write.resp.ready),
|
||||||
|
.ready_status_read(s_axis_status_read.resp.ready),
|
||||||
|
.ready_status_write(s_axis_status_write.resp.ready),
|
||||||
|
|
||||||
|
.valid_desc_read(m_axis_desc_read.req.t.valid),
|
||||||
|
.valid_desc_write(m_axis_desc_write.req.t.valid),
|
||||||
|
.valid_status_read(s_axis_status_read.req.t.valid),
|
||||||
|
.valid_status_write(s_axis_status_write.req.t.valid),
|
||||||
|
|
||||||
|
.desc_read_dma_busy(desc_read_dma_busy),
|
||||||
|
.desc_write_dma_busy(desc_write_dma_busy),
|
||||||
|
.status_read_dma_busy(status_read_dma_busy),
|
||||||
|
.status_write_dma_busy(status_write_dma_busy),
|
||||||
|
|
||||||
|
.desc_read_dma_hs(desc_read_dma_hs),
|
||||||
|
.desc_write_dma_hs(desc_write_dma_hs),
|
||||||
|
.status_read_dma_hs(status_read_dma_hs),
|
||||||
|
.status_write_dma_hs(status_write_dma_hs)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_defaults_master defaults_rd (.axis(m_axis_desc_read));
|
||||||
|
axis_defaults_master defaults_wr (.axis(m_axis_desc_write));
|
||||||
|
|
||||||
|
assign m_axis_desc_read.req.t.data = desc_read_cmd_out;
|
||||||
|
assign m_axis_desc_write.req.t.data = desc_write_cmd_out;
|
||||||
|
assign status_read_cmd_in = s_axis_status_read.req.t.data;
|
||||||
|
assign status_write_cmd_in = s_axis_status_write.req.t.data;
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
import dma_reg_pkg::*;
|
||||||
|
|
||||||
|
module dma_controller
|
||||||
|
(
|
||||||
|
input dma_clk,
|
||||||
|
input rst_n,
|
||||||
|
input logic send_desc_read,
|
||||||
|
input logic send_desc_write,
|
||||||
|
input logic take_status_read,
|
||||||
|
input logic take_status_write,
|
||||||
|
|
||||||
|
input logic ready_desc_read,
|
||||||
|
input logic ready_desc_write,
|
||||||
|
|
||||||
|
output logic ready_status_read,
|
||||||
|
output logic ready_status_write,
|
||||||
|
|
||||||
|
input dma_read_desc_t desc_read_cmd,
|
||||||
|
input dma_write_desc_t desc_write_cmd,
|
||||||
|
|
||||||
|
output dma_read_status_t status_read_cmd,
|
||||||
|
output dma_write_status_t status_write_cmd,
|
||||||
|
|
||||||
|
input dma_read_status_t status_read_cmd_in,
|
||||||
|
input dma_write_status_t status_write_cmd_in,
|
||||||
|
|
||||||
|
output logic desc_read_dma_busy,
|
||||||
|
output logic desc_write_dma_busy,
|
||||||
|
output logic status_read_dma_busy,
|
||||||
|
output logic status_write_dma_busy,
|
||||||
|
|
||||||
|
output logic desc_read_dma_hs,
|
||||||
|
output logic desc_write_dma_hs,
|
||||||
|
output logic status_read_dma_hs,
|
||||||
|
output logic status_write_dma_hs,
|
||||||
|
|
||||||
|
output logic valid_desc_read,
|
||||||
|
output logic valid_desc_write,
|
||||||
|
|
||||||
|
input logic valid_status_read,
|
||||||
|
input logic valid_status_write,
|
||||||
|
|
||||||
|
output dma_read_desc_t desc_read_cmd_out,
|
||||||
|
output dma_write_desc_t desc_write_cmd_out
|
||||||
|
);
|
||||||
|
|
||||||
|
shaper_axis_desc
|
||||||
|
#(
|
||||||
|
.DATA_WIDTH($bits(dma_read_desc_t))
|
||||||
|
) shaper_axis_desc_read
|
||||||
|
(
|
||||||
|
.clk(dma_clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.data_in(desc_read_cmd),
|
||||||
|
.send(send_desc_read),
|
||||||
|
.ready(ready_desc_read),
|
||||||
|
.busy(desc_read_dma_busy),
|
||||||
|
.handshake(desc_read_dma_hs),
|
||||||
|
.data_out(desc_read_cmd_out),
|
||||||
|
.valid(valid_desc_read)
|
||||||
|
);
|
||||||
|
|
||||||
|
shaper_axis_desc
|
||||||
|
#(
|
||||||
|
.DATA_WIDTH($bits(dma_write_desc_t))
|
||||||
|
) shaper_axis_desc_write
|
||||||
|
(
|
||||||
|
.clk(dma_clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.data_in(desc_write_cmd),
|
||||||
|
.send(send_desc_write),
|
||||||
|
.ready(ready_desc_write),
|
||||||
|
.busy(desc_write_dma_busy),
|
||||||
|
.handshake(desc_write_dma_hs),
|
||||||
|
.data_out(desc_write_cmd_out),
|
||||||
|
.valid(valid_desc_write)
|
||||||
|
);
|
||||||
|
|
||||||
|
shaper_axis_status
|
||||||
|
#(
|
||||||
|
.DATA_WIDTH($bits(dma_read_status_t))
|
||||||
|
) shaper_axis_status_read
|
||||||
|
(
|
||||||
|
.clk(dma_clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.data_in(status_read_cmd_in),
|
||||||
|
.take(take_status_read),
|
||||||
|
.valid(valid_status_read),
|
||||||
|
.ready(ready_status_read),
|
||||||
|
.busy(status_read_dma_busy),
|
||||||
|
.handshake(status_read_dma_hs),
|
||||||
|
.data_out(status_read_cmd)
|
||||||
|
);
|
||||||
|
|
||||||
|
shaper_axis_status
|
||||||
|
#(
|
||||||
|
.DATA_WIDTH($bits(dma_write_status_t))
|
||||||
|
) shaper_axis_status_write
|
||||||
|
(
|
||||||
|
.clk(dma_clk),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.data_in(status_write_cmd_in),
|
||||||
|
.take(take_status_write),
|
||||||
|
.valid(valid_status_write),
|
||||||
|
.ready(ready_status_write),
|
||||||
|
.busy(status_write_dma_busy),
|
||||||
|
.handshake(status_write_dma_hs),
|
||||||
|
.data_out(status_write_cmd)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package dma_reg_pkg;
|
||||||
|
parameter int unsigned AXI_ADDR_WIDTH = 16;
|
||||||
|
parameter int unsigned LEN_WIDTH = 20;
|
||||||
|
parameter int unsigned TAG_WIDTH = 8;
|
||||||
|
parameter int unsigned AXIS_ID_WIDTH = 8;
|
||||||
|
parameter int unsigned AXIS_DEST_WIDTH = 8;
|
||||||
|
parameter int unsigned AXIS_USER_WIDTH = 1;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [AXIS_USER_WIDTH-1:0] user;
|
||||||
|
logic [AXIS_DEST_WIDTH-1:0] dest;
|
||||||
|
logic [AXIS_ID_WIDTH-1:0] id;
|
||||||
|
logic [TAG_WIDTH-1:0] tag;
|
||||||
|
logic [LEN_WIDTH-1:0] len;
|
||||||
|
logic [AXI_ADDR_WIDTH-1:0] addr;
|
||||||
|
|
||||||
|
} dma_read_desc_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [TAG_WIDTH-1:0] tag;
|
||||||
|
logic [LEN_WIDTH-1:0] len;
|
||||||
|
logic [AXI_ADDR_WIDTH-1:0] addr;
|
||||||
|
|
||||||
|
} dma_write_desc_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [3:0] error;
|
||||||
|
logic [TAG_WIDTH-1:0] tag;
|
||||||
|
|
||||||
|
} dma_read_status_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [3:0] error;
|
||||||
|
logic [AXIS_USER_WIDTH-1:0] user;
|
||||||
|
logic [AXIS_DEST_WIDTH-1:0] dest;
|
||||||
|
logic [AXIS_ID_WIDTH-1:0] id;
|
||||||
|
logic [TAG_WIDTH-1:0] tag;
|
||||||
|
logic [LEN_WIDTH-1:0] len;
|
||||||
|
|
||||||
|
} dma_write_status_t;
|
||||||
|
|
||||||
|
endpackage
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
module shaper_axis_desc #(
|
||||||
|
parameter DATA_WIDTH = 128
|
||||||
|
) (
|
||||||
|
input clk,
|
||||||
|
input rst_n,
|
||||||
|
input logic [DATA_WIDTH-1:0] data_in,
|
||||||
|
input logic send,
|
||||||
|
input logic ready,
|
||||||
|
|
||||||
|
output logic busy,
|
||||||
|
output logic handshake,
|
||||||
|
output logic [DATA_WIDTH-1:0] data_out,
|
||||||
|
output logic valid
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef enum logic [0:0] {
|
||||||
|
IDLE,
|
||||||
|
WAIT_READY
|
||||||
|
} wr_state;
|
||||||
|
|
||||||
|
wr_state state;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (!rst_n) begin
|
||||||
|
state <= IDLE;
|
||||||
|
busy <= 1'b0;
|
||||||
|
handshake <= 1'b0;
|
||||||
|
data_out <= 1'b0;
|
||||||
|
valid <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
case (state)
|
||||||
|
IDLE: begin
|
||||||
|
handshake <= 1'b0;
|
||||||
|
if (send) begin
|
||||||
|
valid <= 1'b1;
|
||||||
|
data_out <= data_in;
|
||||||
|
busy <= 1'b1;
|
||||||
|
state <= WAIT_READY;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
WAIT_READY: begin
|
||||||
|
if (ready) begin
|
||||||
|
valid <= 1'b0;
|
||||||
|
handshake <= 1'b1;
|
||||||
|
busy <= 1'b0;
|
||||||
|
state <= IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default: state <= IDLE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
module shaper_axis_status #(
|
||||||
|
parameter int unsigned DATA_WIDTH = 128
|
||||||
|
)(
|
||||||
|
input logic clk,
|
||||||
|
input logic rst_n,
|
||||||
|
|
||||||
|
input logic [DATA_WIDTH-1:0] data_in,
|
||||||
|
input logic take,
|
||||||
|
input logic valid,
|
||||||
|
output logic ready,
|
||||||
|
|
||||||
|
output logic busy,
|
||||||
|
output logic handshake,
|
||||||
|
output logic [DATA_WIDTH-1:0] data_out
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef enum logic [0:0] {
|
||||||
|
IDLE,
|
||||||
|
WAIT_TAKE
|
||||||
|
} wr_state;
|
||||||
|
|
||||||
|
wr_state state;
|
||||||
|
|
||||||
|
logic [31:0] data_reg;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (!rst_n) begin
|
||||||
|
state <= IDLE;
|
||||||
|
ready <= 1'b0;
|
||||||
|
busy <= 1'b0;
|
||||||
|
handshake <= 1'b0;
|
||||||
|
data_out <= '0;
|
||||||
|
data_reg <= '0;
|
||||||
|
end else begin
|
||||||
|
case (state)
|
||||||
|
IDLE: begin
|
||||||
|
ready <= 1'b1;
|
||||||
|
if (valid) begin
|
||||||
|
busy <= 1'b0;
|
||||||
|
data_reg <= data_in;
|
||||||
|
handshake <= 1'b1;
|
||||||
|
state <= WAIT_TAKE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
WAIT_TAKE: begin
|
||||||
|
if (take) begin
|
||||||
|
data_out <= data_reg;
|
||||||
|
ready <= 1'b0;
|
||||||
|
handshake <= 1'b0;
|
||||||
|
busy <= 1'b1;
|
||||||
|
state <= IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -1,52 +1,40 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
TOPLEVEL_LANG = verilog
|
||||||
#
|
SIM ?= verilator
|
||||||
# Copyright (c) 2025 FPGA Ninja, LLC
|
|
||||||
#
|
|
||||||
# Authors:
|
|
||||||
# - Alex Forencich
|
|
||||||
#
|
|
||||||
|
|
||||||
# FPGA settings
|
PWD := $(shell pwd)
|
||||||
FPGA_PART = xc7a35tfgg484-1
|
|
||||||
FPGA_TOP = control
|
|
||||||
FPGA_ARCH = artix7
|
|
||||||
|
|
||||||
RTL_DIR = ../src
|
RTL_DIR = $(PWD)/../src
|
||||||
|
LIBS_DIR = $(PWD)/../../../external/rtl_libs
|
||||||
|
|
||||||
|
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi_pkg.sv
|
||||||
|
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi_if.sv
|
||||||
|
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi4l_flat_to_if.sv
|
||||||
|
VERILOG_SOURCES += $(LIBS_DIR)/axi/rtl/axi4l_if_to_flat.sv
|
||||||
|
VERILOG_SOURCES += $(LIBS_DIR)/axi/axi_reg/axi4l_reg_map.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)/axi4l_reg_map_controller.sv
|
||||||
|
VERILOG_SOURCES += $(PWD)/tb_controller_wrapper_axil.sv
|
||||||
|
|
||||||
|
TOPLEVEL = tb_controller_wrapper_axil
|
||||||
|
MODULE = test_controller
|
||||||
|
|
||||||
|
|
||||||
include ../../../scripts/vivado.mk
|
ifeq ($(SIM),verilator)
|
||||||
|
EXTRA_ARGS += --trace --trace-structs
|
||||||
SYN_FILES += $(sort $(shell find ../src -type f \( -name '*.v' -o -name '*.sv' \)))
|
EXTRA_ARGS += -I$(LIBS_DIR)/axi/rtl/
|
||||||
|
COMPILE_ARGS += -Wno-fatal
|
||||||
XCI_FILES = $(sort $(shell find ../src -type f -name '*.xci'))
|
COMPILE_ARGS += -I$(LIBS_DIR)/axi/rtl/
|
||||||
|
EXTRA_ARGS += --trace
|
||||||
XDC_FILES += ../../../constraints/ax7a035b.xdc
|
EXTRA_ARGS += --trace-structs
|
||||||
XDC_FILES += test_timing.xdc
|
EXTRA_ARGS += --public-flat-rw
|
||||||
|
EXTRA_ARGS += -Wno-fatal
|
||||||
SYN_FILES += controller_tb.sv
|
EXTRA_ARGS += --timing
|
||||||
SIM_TOP = control_tb
|
endif
|
||||||
|
|
||||||
|
|
||||||
program: $(PROJECT).bit
|
include $(shell cocotb-config --makefiles)/Makefile.sim
|
||||||
echo "open_hw_manager" > program.tcl
|
|
||||||
echo "connect_hw_server" >> program.tcl
|
|
||||||
echo "open_hw_target" >> program.tcl
|
|
||||||
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
|
|
||||||
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
|
|
||||||
echo "set_property PROGRAM.FILE {$(PROJECT).bit} [current_hw_device]" >> program.tcl
|
|
||||||
echo "program_hw_devices [current_hw_device]" >> program.tcl
|
|
||||||
echo "exit" >> program.tcl
|
|
||||||
vivado -nojournal -nolog -mode batch -source program.tcl
|
|
||||||
|
|
||||||
$(PROJECT).mcs $(PROJECT).prm: $(PROJECT).bit
|
|
||||||
echo "write_cfgmem -force -format mcs -size 16 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
|
|
||||||
echo "exit" >> generate_mcs.tcl
|
|
||||||
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
|
|
||||||
mkdir -p rev
|
|
||||||
COUNT=100; \
|
|
||||||
while [ -e rev/$*_rev$$COUNT.bit ]; \
|
|
||||||
do COUNT=$$((COUNT+1)); done; \
|
|
||||||
COUNT=$$((COUNT-1)); \
|
|
||||||
for x in .mcs .prm; \
|
|
||||||
do cp $*$$x rev/$*_rev$$COUNT$$x; \
|
|
||||||
echo "Output: rev/$*_rev$$COUNT$$x"; done;
|
|
||||||
|
|||||||
@@ -4,72 +4,17 @@ module tb_control;
|
|||||||
|
|
||||||
localparam int unsigned DAC_DATA_WIDTH = 12;
|
localparam int unsigned DAC_DATA_WIDTH = 12;
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
// Clocks / reset
|
// Clocks / reset
|
||||||
logic eth_clk_in;
|
//------------------------------------------------------------
|
||||||
|
logic ctrl_clk;
|
||||||
logic dac_clk_in;
|
logic dac_clk_in;
|
||||||
logic adc_clk_in;
|
logic adc_clk_in;
|
||||||
logic rst_n;
|
logic rst_n;
|
||||||
|
|
||||||
// axi stream (input)
|
|
||||||
logic [7:0] s_axis_tdata;
|
|
||||||
logic s_axis_tvalid;
|
|
||||||
logic s_axis_tready;
|
|
||||||
logic s_axis_tlast;
|
|
||||||
|
|
||||||
// ADC side input
|
|
||||||
logic finish;
|
|
||||||
|
|
||||||
// DUT outputs
|
|
||||||
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;
|
|
||||||
|
|
||||||
logic [31:0] adc_pulse_period;
|
|
||||||
logic [15:0] adc_pulse_num;
|
|
||||||
|
|
||||||
logic dac_start;
|
|
||||||
logic adc_start;
|
|
||||||
logic dac_rst;
|
|
||||||
logic adc_rst;
|
|
||||||
|
|
||||||
|
|
||||||
// DUT
|
|
||||||
control #(
|
|
||||||
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
|
||||||
) dut (
|
|
||||||
.eth_clk_in (eth_clk_in),
|
|
||||||
.dac_clk_in (dac_clk_in),
|
|
||||||
.adc_clk_in (adc_clk_in),
|
|
||||||
.rst_n (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),
|
|
||||||
|
|
||||||
.finish (finish),
|
|
||||||
|
|
||||||
.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)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Clock generation
|
|
||||||
initial begin
|
initial begin
|
||||||
eth_clk_in = 1'b0;
|
ctrl_clk = 1'b0;
|
||||||
forever #(1 * 4.000) eth_clk_in = ~eth_clk_in; // 125 MHz
|
forever #(1 * 4.000) ctrl_clk = ~ctrl_clk; // 125 MHz
|
||||||
end
|
end
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
@@ -82,8 +27,81 @@ module tb_control;
|
|||||||
forever #(1 * 7.692307692) adc_clk_in = ~adc_clk_in; // ~65 MHz
|
forever #(1 * 7.692307692) adc_clk_in = ~adc_clk_in; // ~65 MHz
|
||||||
end
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// DUT inputs
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
logic rst_soft;
|
||||||
|
|
||||||
|
logic finish;
|
||||||
|
|
||||||
|
logic [159:0] cfg_bus_input;
|
||||||
|
logic cfg_bus_valid;
|
||||||
|
|
||||||
|
logic start;
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// DUT outputs
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
logic busy;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
logic [31:0] adc_pulse_period;
|
||||||
|
logic [15:0] adc_pulse_num;
|
||||||
|
logic [31:0] adc_window_size;
|
||||||
|
|
||||||
|
logic dac_start;
|
||||||
|
logic adc_start;
|
||||||
|
logic dac_rst;
|
||||||
|
logic adc_rst;
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// DUT
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
|
control #(
|
||||||
|
.DAC_DATA_WIDTH(DAC_DATA_WIDTH)
|
||||||
|
) dut (
|
||||||
|
.ctrl_clk (ctrl_clk),
|
||||||
|
.dac_clk_in (dac_clk_in),
|
||||||
|
.adc_clk_in (adc_clk_in),
|
||||||
|
|
||||||
|
.rst_n (rst_n),
|
||||||
|
.rst_soft (rst_soft),
|
||||||
|
|
||||||
|
.finish (finish),
|
||||||
|
|
||||||
|
.cfg_bus_input (cfg_bus_input),
|
||||||
|
.cfg_bus_valid (cfg_bus_valid),
|
||||||
|
|
||||||
|
.start (start),
|
||||||
|
|
||||||
|
.busy (busy),
|
||||||
|
|
||||||
|
.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),
|
||||||
|
.adc_window_size (adc_window_size),
|
||||||
|
|
||||||
|
.dac_start (dac_start),
|
||||||
|
.adc_start (adc_start),
|
||||||
|
.dac_rst (dac_rst),
|
||||||
|
.adc_rst (adc_rst)
|
||||||
|
);
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
// pulse counters and monitors for testing
|
// pulse counters and monitors for testing
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
int dac_rst_count;
|
int dac_rst_count;
|
||||||
int adc_rst_count;
|
int adc_rst_count;
|
||||||
int dac_start_count;
|
int dac_start_count;
|
||||||
@@ -93,9 +111,13 @@ module tb_control;
|
|||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
dac_rst_count <= 0;
|
dac_rst_count <= 0;
|
||||||
dac_start_count <= 0;
|
dac_start_count <= 0;
|
||||||
end else begin
|
end
|
||||||
if (dac_rst) dac_rst_count <= dac_rst_count + 1;
|
else begin
|
||||||
if (dac_start) dac_start_count <= dac_start_count + 1;
|
if (dac_rst)
|
||||||
|
dac_rst_count <= dac_rst_count + 1;
|
||||||
|
|
||||||
|
if (dac_start)
|
||||||
|
dac_start_count <= dac_start_count + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -103,84 +125,113 @@ module tb_control;
|
|||||||
if (!rst_n) begin
|
if (!rst_n) begin
|
||||||
adc_rst_count <= 0;
|
adc_rst_count <= 0;
|
||||||
adc_start_count <= 0;
|
adc_start_count <= 0;
|
||||||
end else begin
|
end
|
||||||
if (adc_rst) adc_rst_count <= adc_rst_count + 1;
|
else begin
|
||||||
if (adc_start) adc_start_count <= adc_start_count + 1;
|
if (adc_rst)
|
||||||
|
adc_rst_count <= adc_rst_count + 1;
|
||||||
|
|
||||||
|
if (adc_start)
|
||||||
|
adc_start_count <= adc_start_count + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
// some helpers for axi
|
// helpers
|
||||||
task automatic axis_send_byte(input logic [7:0] data, input logic last);
|
//------------------------------------------------------------
|
||||||
begin
|
|
||||||
@(negedge eth_clk_in);
|
|
||||||
s_axis_tdata <= data;
|
|
||||||
s_axis_tvalid <= 1'b1;
|
|
||||||
s_axis_tlast <= last;
|
|
||||||
|
|
||||||
@(posedge eth_clk_in);
|
|
||||||
while (!s_axis_tready) begin
|
|
||||||
@(posedge eth_clk_in);
|
|
||||||
end
|
|
||||||
|
|
||||||
s_axis_tvalid <= 1'b0;
|
|
||||||
s_axis_tlast <= 1'b0;
|
|
||||||
s_axis_tdata <= '0;
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
task automatic send_cmd(input logic [7:0] cmd);
|
task automatic send_cmd(input logic [7:0] cmd);
|
||||||
begin
|
begin
|
||||||
axis_send_byte(cmd, 1'b1);
|
@(negedge ctrl_clk);
|
||||||
end
|
|
||||||
|
case (cmd)
|
||||||
|
|
||||||
|
8'h0F: begin
|
||||||
|
rst_soft <= 1'b1;
|
||||||
|
|
||||||
|
@(posedge ctrl_clk);
|
||||||
|
|
||||||
|
rst_soft <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
8'hF0: begin
|
||||||
|
start <= 1'b1;
|
||||||
|
|
||||||
|
@(posedge ctrl_clk);
|
||||||
|
|
||||||
|
start <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
default:
|
||||||
|
$fatal(1, "Unsupported command %h", cmd);
|
||||||
|
|
||||||
|
endcase
|
||||||
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
task automatic send_set_data(
|
task automatic send_set_data(
|
||||||
input logic [31:0] pulse_width,
|
input logic [31:0] pulse_width,
|
||||||
input logic [31:0] pulse_period,
|
input logic [31:0] pulse_period,
|
||||||
input logic [15:0] pulse_num,
|
input logic [15:0] pulse_num,
|
||||||
input logic [15:0] pulse_height_raw,
|
input logic [15:0] pulse_height_raw,
|
||||||
input logic [31:0] pulse_period_adc
|
input logic [31:0] pulse_period_adc,
|
||||||
);
|
input logic [31:0] window_size
|
||||||
logic [127:0] payload;
|
);
|
||||||
int i;
|
|
||||||
begin
|
|
||||||
// little-endian payload layout:
|
|
||||||
// [31:0] pulse_width
|
|
||||||
// [63:32] pulse_period
|
|
||||||
// [79:64] pulse_num
|
|
||||||
// [95:80] pulse_height_raw
|
|
||||||
// [127:96] pulse_period_ADC
|
|
||||||
|
|
||||||
payload = {pulse_period_adc, pulse_height_raw, pulse_num, pulse_period, pulse_width};
|
|
||||||
|
|
||||||
axis_send_byte(8'h88, 1'b0); // CMD_SET_DATA
|
logic [159:0] payload;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) begin
|
begin
|
||||||
axis_send_byte(payload[i*8 +: 8], (i == 15));
|
|
||||||
end
|
payload = {
|
||||||
end
|
window_size,
|
||||||
endtask
|
pulse_period_adc,
|
||||||
|
pulse_height_raw,
|
||||||
|
pulse_num,
|
||||||
|
pulse_period,
|
||||||
|
pulse_width
|
||||||
|
};
|
||||||
|
|
||||||
|
@(negedge ctrl_clk);
|
||||||
|
|
||||||
|
cfg_bus_input <= payload;
|
||||||
|
cfg_bus_valid <= 1'b1;
|
||||||
|
|
||||||
|
@(posedge ctrl_clk);
|
||||||
|
|
||||||
|
cfg_bus_valid <= 1'b0;
|
||||||
|
cfg_bus_input <= '0;
|
||||||
|
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
task automatic pulse_finish;
|
task automatic pulse_finish;
|
||||||
begin
|
begin
|
||||||
@(posedge adc_clk_in);
|
@(posedge adc_clk_in);
|
||||||
finish <= 1'b1;
|
finish <= 1'b1;
|
||||||
|
|
||||||
@(posedge adc_clk_in);
|
@(posedge adc_clk_in);
|
||||||
finish <= 1'b0;
|
finish <= 1'b0;
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
// waiters
|
// waiters
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
task automatic wait_dac_rst_count(input int expected, input int max_cycles = 100);
|
task automatic wait_dac_rst_count(input int expected, input int max_cycles = 100);
|
||||||
int i;
|
int i;
|
||||||
begin
|
begin
|
||||||
for (i = 0; i < max_cycles; i++) begin
|
for (i = 0; i < max_cycles; i++) begin
|
||||||
@(posedge dac_clk_in);
|
@(posedge dac_clk_in);
|
||||||
if (dac_rst_count >= expected) return;
|
|
||||||
|
if (dac_rst_count >= expected)
|
||||||
|
return;
|
||||||
end
|
end
|
||||||
$fatal(1, "Timeout waiting for dac_rst_count >= %0d, current=%0d", expected, dac_rst_count);
|
|
||||||
|
$fatal(1,
|
||||||
|
"Timeout waiting for dac_rst_count >= %0d, current=%0d",
|
||||||
|
expected,
|
||||||
|
dac_rst_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
@@ -189,9 +240,16 @@ module tb_control;
|
|||||||
begin
|
begin
|
||||||
for (i = 0; i < max_cycles; i++) begin
|
for (i = 0; i < max_cycles; i++) begin
|
||||||
@(posedge adc_clk_in);
|
@(posedge adc_clk_in);
|
||||||
if (adc_rst_count >= expected) return;
|
|
||||||
|
if (adc_rst_count >= expected)
|
||||||
|
return;
|
||||||
end
|
end
|
||||||
$fatal(1, "Timeout waiting for adc_rst_count >= %0d, current=%0d", expected, adc_rst_count);
|
|
||||||
|
$fatal(1,
|
||||||
|
"Timeout waiting for adc_rst_count >= %0d, current=%0d",
|
||||||
|
expected,
|
||||||
|
adc_rst_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
@@ -200,9 +258,16 @@ module tb_control;
|
|||||||
begin
|
begin
|
||||||
for (i = 0; i < max_cycles; i++) begin
|
for (i = 0; i < max_cycles; i++) begin
|
||||||
@(posedge dac_clk_in);
|
@(posedge dac_clk_in);
|
||||||
if (dac_start_count >= expected) return;
|
|
||||||
|
if (dac_start_count >= expected)
|
||||||
|
return;
|
||||||
end
|
end
|
||||||
$fatal(1, "Timeout waiting for dac_start_count >= %0d, current=%0d", expected, dac_start_count);
|
|
||||||
|
$fatal(1,
|
||||||
|
"Timeout waiting for dac_start_count >= %0d, current=%0d",
|
||||||
|
expected,
|
||||||
|
dac_start_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
@@ -211,165 +276,290 @@ module tb_control;
|
|||||||
begin
|
begin
|
||||||
for (i = 0; i < max_cycles; i++) begin
|
for (i = 0; i < max_cycles; i++) begin
|
||||||
@(posedge adc_clk_in);
|
@(posedge adc_clk_in);
|
||||||
if (adc_start_count >= expected) return;
|
|
||||||
end
|
|
||||||
$fatal(1, "Timeout waiting for adc_start_count >= %0d, current=%0d", expected, adc_start_count);
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
task automatic wait_cfg_applied(
|
if (adc_start_count >= expected)
|
||||||
input logic [31:0] exp_pulse_width,
|
|
||||||
input logic [31:0] exp_pulse_period,
|
|
||||||
input logic [15:0] exp_pulse_num,
|
|
||||||
input logic [15:0] exp_pulse_height_raw,
|
|
||||||
input logic [31:0] exp_pulse_period_adc,
|
|
||||||
input int max_cycles = 200
|
|
||||||
);
|
|
||||||
logic [DAC_DATA_WIDTH-1:0] exp_dac_height;
|
|
||||||
int i;
|
|
||||||
begin
|
|
||||||
exp_dac_height = exp_pulse_height_raw[DAC_DATA_WIDTH-1:0];
|
|
||||||
|
|
||||||
for (i = 0; i < max_cycles; i++) begin
|
|
||||||
@(posedge eth_clk_in);
|
|
||||||
if ((dac_pulse_width === exp_pulse_width ) &&
|
|
||||||
(dac_pulse_period === exp_pulse_period) &&
|
|
||||||
(dac_pulse_num === exp_pulse_num ) &&
|
|
||||||
(dac_pulse_height === exp_dac_height ) &&
|
|
||||||
(adc_pulse_period === exp_pulse_period_adc) &&
|
|
||||||
(adc_pulse_num === exp_pulse_num )) begin
|
|
||||||
return;
|
return;
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
$fatal(1,
|
$fatal(1,
|
||||||
"Timeout waiting config outputs. Got: dac_width=%h dac_period=%h dac_num=%h dac_height=%h adc_period=%h adc_num=%h",
|
"Timeout waiting for adc_start_count >= %0d, current=%0d",
|
||||||
dac_pulse_width, dac_pulse_period, dac_pulse_num, dac_pulse_height,
|
expected,
|
||||||
adc_pulse_period, adc_pulse_num
|
adc_start_count
|
||||||
);
|
);
|
||||||
end
|
end
|
||||||
endtask
|
endtask
|
||||||
|
|
||||||
|
task automatic wait_cfg_applied(
|
||||||
|
|
||||||
|
input logic [31:0] exp_pulse_width,
|
||||||
|
input logic [31:0] exp_pulse_period,
|
||||||
|
input logic [15:0] exp_pulse_num,
|
||||||
|
input logic [15:0] exp_pulse_height_raw,
|
||||||
|
input logic [31:0] exp_pulse_period_adc,
|
||||||
|
input logic [31:0] exp_window_size,
|
||||||
|
input int max_cycles = 200
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [DAC_DATA_WIDTH-1:0] exp_height;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
exp_height = exp_pulse_height_raw[DAC_DATA_WIDTH-1:0];
|
||||||
|
|
||||||
|
for(i=0;i<max_cycles;i++) begin
|
||||||
|
|
||||||
|
@(posedge ctrl_clk);
|
||||||
|
|
||||||
|
if(
|
||||||
|
|
||||||
|
dac_pulse_width == exp_pulse_width &&
|
||||||
|
dac_pulse_period == exp_pulse_period &&
|
||||||
|
dac_pulse_num == exp_pulse_num &&
|
||||||
|
dac_pulse_height == exp_height &&
|
||||||
|
|
||||||
|
adc_pulse_period == exp_pulse_period_adc &&
|
||||||
|
adc_pulse_num == exp_pulse_num &&
|
||||||
|
adc_window_size == exp_window_size
|
||||||
|
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
$fatal("Configuration timeout");
|
||||||
|
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
// Test sequence
|
// Test sequence
|
||||||
|
//------------------------------------------------------------
|
||||||
|
|
||||||
logic [31:0] test_pulse_width;
|
logic [31:0] test_pulse_width;
|
||||||
logic [31:0] test_pulse_period;
|
logic [31:0] test_pulse_period;
|
||||||
logic [15:0] test_pulse_num;
|
logic [15:0] test_pulse_num;
|
||||||
logic [15:0] test_pulse_height_raw;
|
logic [15:0] test_pulse_height_raw;
|
||||||
logic [31:0] test_pulse_period_adc;
|
logic [31:0] test_pulse_period_adc;
|
||||||
|
logic [31:0] test_window_size;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
// defaults
|
// defaults
|
||||||
rst_n = 1'b0;
|
rst_n = 1'b0;
|
||||||
s_axis_tdata = '0;
|
rst_soft = 1'b0;
|
||||||
s_axis_tvalid = 1'b0;
|
|
||||||
s_axis_tlast = 1'b0;
|
start = 1'b0;
|
||||||
finish = 1'b0;
|
finish = 1'b0;
|
||||||
|
|
||||||
|
cfg_bus_input = '0;
|
||||||
|
cfg_bus_valid = 1'b0;
|
||||||
|
|
||||||
test_pulse_width = 32'h11223344;
|
test_pulse_width = 32'h11223344;
|
||||||
test_pulse_period = 32'h55667788;
|
test_pulse_period = 32'h55667788;
|
||||||
test_pulse_num = 16'hA1B2;
|
test_pulse_num = 16'hA1B2;
|
||||||
test_pulse_height_raw = 16'h0CDE; // for DAC_DATA_WIDTH=12 => 12'hCDE
|
test_pulse_height_raw = 16'h0CDE; // for DAC_DATA_WIDTH=12 => 12'hCDE
|
||||||
test_pulse_period_adc = 32'h50607080;
|
test_pulse_period_adc = 32'h50607080;
|
||||||
|
test_window_size = 32'hABCDEF55;
|
||||||
|
|
||||||
repeat (10) @(posedge eth_clk_in);
|
repeat (10) @(posedge ctrl_clk);
|
||||||
rst_n = 1'b1;
|
rst_n = 1'b1;
|
||||||
|
|
||||||
repeat (10) @(posedge eth_clk_in);
|
repeat (10) @(posedge ctrl_clk);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// TEST 1: soft_reset
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
$display("[%0t] TEST 1: soft_reset", $time);
|
$display("[%0t] TEST 1: soft_reset", $time);
|
||||||
|
|
||||||
send_cmd(8'h0F);
|
send_cmd(8'h0F);
|
||||||
|
|
||||||
wait_dac_rst_count(1);
|
wait_dac_rst_count(1);
|
||||||
wait_adc_rst_count(1);
|
wait_adc_rst_count(1);
|
||||||
|
|
||||||
if (dac_rst_count != 1) begin
|
if (dac_rst_count != 1) begin
|
||||||
$fatal(1, "Expected exactly one dac_rst pulse after first soft_reset, got %0d", dac_rst_count);
|
$fatal(1,
|
||||||
|
"Expected exactly one dac_rst pulse after first soft_reset, got %0d",
|
||||||
|
dac_rst_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (adc_rst_count != 1) begin
|
if (adc_rst_count != 1) begin
|
||||||
$fatal(1, "Expected exactly one adc_rst pulse after first soft_reset, got %0d", adc_rst_count);
|
$fatal(1,
|
||||||
|
"Expected exactly one adc_rst pulse after first soft_reset, got %0d",
|
||||||
|
adc_rst_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
$display("[%0t] TEST 1 passed", $time);
|
$display("[%0t] TEST 1 passed", $time);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// TEST 2: set_data
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
$display("[%0t] TEST 2: set_data", $time);
|
$display("[%0t] TEST 2: set_data", $time);
|
||||||
|
|
||||||
send_set_data(
|
send_set_data(
|
||||||
test_pulse_width,
|
|
||||||
test_pulse_period,
|
test_pulse_width,
|
||||||
test_pulse_num,
|
test_pulse_period,
|
||||||
test_pulse_height_raw,
|
test_pulse_num,
|
||||||
test_pulse_period_adc
|
test_pulse_height_raw,
|
||||||
);
|
test_pulse_period_adc,
|
||||||
|
test_window_size
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
wait_cfg_applied(
|
wait_cfg_applied(
|
||||||
test_pulse_width,
|
|
||||||
test_pulse_period,
|
test_pulse_width,
|
||||||
test_pulse_num,
|
test_pulse_period,
|
||||||
test_pulse_height_raw,
|
test_pulse_num,
|
||||||
test_pulse_period_adc
|
test_pulse_height_raw,
|
||||||
);
|
test_pulse_period_adc,
|
||||||
|
test_window_size
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
if (dac_pulse_width !== 32'h11223344) begin
|
if (dac_pulse_width !== 32'h11223344) begin
|
||||||
$fatal(1, "dac_pulse_width mismatch: got %h expected %h", dac_pulse_width, 32'h11223344);
|
$fatal(1,
|
||||||
|
"dac_pulse_width mismatch: got %h expected %h",
|
||||||
|
dac_pulse_width,
|
||||||
|
32'h11223344
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (dac_pulse_period !== 32'h55667788) begin
|
if (dac_pulse_period !== 32'h55667788) begin
|
||||||
$fatal(1, "dac_pulse_period mismatch: got %h expected %h", dac_pulse_period, 32'h55667788);
|
$fatal(1,
|
||||||
|
"dac_pulse_period mismatch: got %h expected %h",
|
||||||
|
dac_pulse_period,
|
||||||
|
32'h55667788
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (dac_pulse_num !== 16'hA1B2) begin
|
if (dac_pulse_num !== 16'hA1B2) begin
|
||||||
$fatal(1, "dac_pulse_num mismatch: got %h expected %h", dac_pulse_num, 16'hA1B2);
|
$fatal(1,
|
||||||
|
"dac_pulse_num mismatch: got %h expected %h",
|
||||||
|
dac_pulse_num,
|
||||||
|
16'hA1B2
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (dac_pulse_height !== 12'hCDE) begin
|
if (dac_pulse_height !== 12'hCDE) begin
|
||||||
$fatal(1, "dac_pulse_height mismatch: got %h expected %h", dac_pulse_height, 12'hCDE);
|
$fatal(1,
|
||||||
|
"dac_pulse_height mismatch: got %h expected %h",
|
||||||
|
dac_pulse_height,
|
||||||
|
12'hCDE
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (adc_pulse_period !== 32'h50607080) begin
|
if (adc_pulse_period !== 32'h50607080) begin
|
||||||
$fatal(1, "adc_pulse_period mismatch: got %h expected %h", adc_pulse_period, 32'h50607080);
|
$fatal(1,
|
||||||
|
"adc_pulse_period mismatch: got %h expected %h",
|
||||||
|
adc_pulse_period,
|
||||||
|
32'h50607080
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (adc_pulse_num !== 16'hA1B2) begin
|
if (adc_pulse_num !== 16'hA1B2) begin
|
||||||
$fatal(1, "adc_pulse_num mismatch: got %h expected %h", adc_pulse_num, 16'hA1B2);
|
$fatal(1,
|
||||||
|
"adc_pulse_num mismatch: got %h expected %h",
|
||||||
|
adc_pulse_num,
|
||||||
|
16'hA1B2
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if(adc_window_size != test_window_size)
|
||||||
|
|
||||||
|
$fatal(
|
||||||
|
"adc_window_size mismatch. got=%h expected=%h",
|
||||||
|
adc_window_size,
|
||||||
|
test_window_size
|
||||||
|
);
|
||||||
|
|
||||||
$display("[%0t] TEST 2 passed", $time);
|
$display("[%0t] TEST 2 passed", $time);
|
||||||
|
|
||||||
repeat (20) @(posedge eth_clk_in);
|
repeat (20) @(posedge ctrl_clk);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// TEST 3: start
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
$display("[%0t] TEST 3: start", $time);
|
$display("[%0t] TEST 3: start", $time);
|
||||||
|
|
||||||
send_cmd(8'hF0);
|
send_cmd(8'hF0);
|
||||||
|
|
||||||
wait_dac_start_count(1);
|
wait_dac_start_count(1);
|
||||||
wait_adc_start_count(1);
|
wait_adc_start_count(1);
|
||||||
|
|
||||||
if (dac_start_count != 1) begin
|
if (dac_start_count != 1) begin
|
||||||
$fatal(1, "Expected exactly one dac_start pulse after first start, got %0d", dac_start_count);
|
$fatal(1,
|
||||||
|
"Expected exactly one dac_start pulse after first start, got %0d",
|
||||||
|
dac_start_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (adc_start_count != 1) begin
|
if (adc_start_count != 1) begin
|
||||||
$fatal(1, "Expected exactly one adc_start pulse after first start, got %0d", adc_start_count);
|
$fatal(1,
|
||||||
|
"Expected exactly one adc_start pulse after first start, got %0d",
|
||||||
|
adc_start_count
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (!busy) begin
|
||||||
|
$fatal(1,
|
||||||
|
"busy must be asserted after start"
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
$display("[%0t] TEST 3 start pulses passed", $time);
|
$display("[%0t] TEST 3 start pulses passed", $time);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
// release busy by finish pulse from ADC domain
|
// release busy by finish pulse from ADC domain
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
$display("[%0t] Sending finish pulse", $time);
|
$display("[%0t] Sending finish pulse", $time);
|
||||||
|
|
||||||
pulse_finish();
|
pulse_finish();
|
||||||
|
|
||||||
// a bit of wait for finish CDC back to ETH
|
repeat (20) @(posedge ctrl_clk);
|
||||||
repeat (20) @(posedge eth_clk_in);
|
|
||||||
|
|
||||||
|
if (busy) begin
|
||||||
|
$fatal(1,
|
||||||
|
"busy was not cleared after finish pulse"
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
// sanity check that commands are accepted again after finish
|
// sanity check that commands are accepted again after finish
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
$display("[%0t] TEST 4: soft_reset after finish", $time);
|
$display("[%0t] TEST 4: soft_reset after finish", $time);
|
||||||
|
|
||||||
send_cmd(8'h0F);
|
send_cmd(8'h0F);
|
||||||
|
|
||||||
wait_dac_rst_count(2);
|
wait_dac_rst_count(2);
|
||||||
wait_adc_rst_count(2);
|
wait_adc_rst_count(2);
|
||||||
|
|
||||||
if (dac_rst_count != 2) begin
|
if (dac_rst_count != 2) begin
|
||||||
$fatal(1, "Expected exactly two dac_rst pulses total, got %0d", dac_rst_count);
|
$fatal(1,
|
||||||
|
"Expected exactly two dac_rst pulses total, got %0d",
|
||||||
|
dac_rst_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
if (adc_rst_count != 2) begin
|
if (adc_rst_count != 2) begin
|
||||||
$fatal(1, "Expected exactly two adc_rst pulses total, got %0d", adc_rst_count);
|
$fatal(1,
|
||||||
|
"Expected exactly two adc_rst pulses total, got %0d",
|
||||||
|
adc_rst_count
|
||||||
|
);
|
||||||
end
|
end
|
||||||
|
|
||||||
$display("[%0t] TEST 4 passed", $time);
|
$display("[%0t] TEST 4 passed", $time);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
$display("==============================================");
|
$display("==============================================");
|
||||||
$display("ALL BASIC TESTS PASSED");
|
$display("ALL BASIC TESTS PASSED");
|
||||||
$display("dac_rst_count = %0d", dac_rst_count);
|
$display("dac_rst_count = %0d", dac_rst_count);
|
||||||
@@ -378,8 +568,170 @@ module tb_control;
|
|||||||
$display("adc_start_count = %0d", adc_start_count);
|
$display("adc_start_count = %0d", adc_start_count);
|
||||||
$display("==============================================");
|
$display("==============================================");
|
||||||
|
|
||||||
#100;
|
#50;
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// TEST 2.1: set_data
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
test_pulse_width = 32'h12121212;
|
||||||
|
test_pulse_period = 32'h34343434;
|
||||||
|
test_pulse_num = 16'h1A2B;
|
||||||
|
test_pulse_height_raw = 16'hC0ED; // for DAC_DATA_WIDTH=12 => 12'hCDE
|
||||||
|
test_pulse_period_adc = 32'h56565656;
|
||||||
|
test_window_size = 32'h01020304;
|
||||||
|
|
||||||
|
$display("[%0t] TEST 2.1: set_data", $time);
|
||||||
|
|
||||||
|
send_set_data(
|
||||||
|
test_pulse_width,
|
||||||
|
test_pulse_period,
|
||||||
|
test_pulse_num,
|
||||||
|
test_pulse_height_raw,
|
||||||
|
test_pulse_period_adc,
|
||||||
|
test_window_size
|
||||||
|
);
|
||||||
|
|
||||||
|
wait_cfg_applied(
|
||||||
|
test_pulse_width,
|
||||||
|
test_pulse_period,
|
||||||
|
test_pulse_num,
|
||||||
|
test_pulse_height_raw,
|
||||||
|
test_pulse_period_adc,
|
||||||
|
test_window_size
|
||||||
|
);
|
||||||
|
|
||||||
|
if (dac_pulse_width !== 32'h12121212) begin
|
||||||
|
$fatal(1,
|
||||||
|
"dac_pulse_width mismatch: got %h expected %h",
|
||||||
|
dac_pulse_width,
|
||||||
|
32'h12121212
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (dac_pulse_period !== 32'h34343434) begin
|
||||||
|
$fatal(1,
|
||||||
|
"dac_pulse_period mismatch: got %h expected %h",
|
||||||
|
dac_pulse_period,
|
||||||
|
32'h34343434
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (dac_pulse_num !== 16'h1A2B) begin
|
||||||
|
$fatal(1,
|
||||||
|
"dac_pulse_num mismatch: got %h expected %h",
|
||||||
|
dac_pulse_num,
|
||||||
|
16'h1A2B
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (dac_pulse_height !== 12'hC0ED) begin
|
||||||
|
$fatal(1,
|
||||||
|
"dac_pulse_height mismatch: got %h expected %h",
|
||||||
|
dac_pulse_height,
|
||||||
|
12'hC0ED
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (adc_pulse_period !== 32'h56565656) begin
|
||||||
|
$fatal(1,
|
||||||
|
"adc_pulse_period mismatch: got %h expected %h",
|
||||||
|
adc_pulse_period,
|
||||||
|
32'h56565656
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
$display("[%0t] TEST 2.1 passed", $time);
|
||||||
|
|
||||||
|
repeat (20) @(posedge ctrl_clk);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// TEST 3.1: start
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
$display("[%0t] TEST 3.1: start", $time);
|
||||||
|
|
||||||
|
send_cmd(8'hF0);
|
||||||
|
|
||||||
|
wait_dac_start_count(2);
|
||||||
|
wait_adc_start_count(2);
|
||||||
|
|
||||||
|
if (dac_start_count != 2) begin
|
||||||
|
$fatal(1,
|
||||||
|
"Expected exactly one dac_start pulse after first start, got %0d",
|
||||||
|
dac_start_count
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (adc_start_count != 2) begin
|
||||||
|
$fatal(1,
|
||||||
|
"Expected exactly one adc_start pulse after first start, got %0d",
|
||||||
|
adc_start_count
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (!busy) begin
|
||||||
|
$fatal(1,
|
||||||
|
"busy must be asserted after start"
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
$display("[%0t] TEST 3.1 start pulses passed", $time);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// release busy by finish pulse from ADC domain
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
$display("[%0t] Sending finish pulse", $time);
|
||||||
|
|
||||||
|
pulse_finish();
|
||||||
|
|
||||||
|
repeat (20) @(posedge ctrl_clk);
|
||||||
|
|
||||||
|
if (busy) begin
|
||||||
|
$fatal(1,
|
||||||
|
"busy was not cleared after finish pulse"
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
// sanity check that commands are accepted again after finish
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
$display("[%0t] TEST 4.1: soft_reset after finish", $time);
|
||||||
|
|
||||||
|
send_cmd(8'h0F);
|
||||||
|
|
||||||
|
wait_dac_rst_count(2);
|
||||||
|
wait_adc_rst_count(2);
|
||||||
|
|
||||||
|
if (dac_rst_count != 2) begin
|
||||||
|
$fatal(1,
|
||||||
|
"Expected exactly two dac_rst pulses total, got %0d",
|
||||||
|
dac_rst_count
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
if (adc_rst_count != 2) begin
|
||||||
|
$fatal(1,
|
||||||
|
"Expected exactly two adc_rst pulses total, got %0d",
|
||||||
|
adc_rst_count
|
||||||
|
);
|
||||||
|
end
|
||||||
|
|
||||||
|
$display("[%0t] TEST 4.1 passed", $time);
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
$display("==============================================");
|
||||||
|
$display("ALL BASIC TESTS PASSED");
|
||||||
|
$display("dac_rst_count = %0d", dac_rst_count);
|
||||||
|
$display("adc_rst_count = %0d", adc_rst_count);
|
||||||
|
$display("dac_start_count = %0d", dac_start_count);
|
||||||
|
$display("adc_start_count = %0d", adc_start_count);
|
||||||
|
$display("==============================================");
|
||||||
$finish;
|
$finish;
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
@@ -11,187 +11,226 @@
|
|||||||
</db_ref>
|
</db_ref>
|
||||||
</db_ref_list>
|
</db_ref_list>
|
||||||
<zoom_setting>
|
<zoom_setting>
|
||||||
<ZoomStartTime time="0.676 ns"></ZoomStartTime>
|
<ZoomStartTime time="160.614 ns"></ZoomStartTime>
|
||||||
<ZoomEndTime time="645.677 ns"></ZoomEndTime>
|
<ZoomEndTime time="1,564.737 ns"></ZoomEndTime>
|
||||||
<Cursor1Time time="349.676 ns"></Cursor1Time>
|
<Cursor1Time time="1,330.716 ns"></Cursor1Time>
|
||||||
</zoom_setting>
|
</zoom_setting>
|
||||||
<column_width_setting>
|
<column_width_setting>
|
||||||
<NameColumnWidth column_width="558"></NameColumnWidth>
|
<NameColumnWidth column_width="479"></NameColumnWidth>
|
||||||
<ValueColumnWidth column_width="61"></ValueColumnWidth>
|
<ValueColumnWidth column_width="116"></ValueColumnWidth>
|
||||||
</column_width_setting>
|
</column_width_setting>
|
||||||
<WVObjectSize size="23" />
|
<WVObjectSize size="34" />
|
||||||
<wvobject type="logic" fp_name="/tb_control/eth_clk_in">
|
<wvobject fp_name="/tb_control/dac_clk_in" type="logic">
|
||||||
<obj_property name="ElementShortName">eth_clk_in</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">eth_clk_in</obj_property>
|
|
||||||
<obj_property name="CustomSignalColor">#008080</obj_property>
|
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/tb_control/dac_clk_in">
|
|
||||||
<obj_property name="ElementShortName">dac_clk_in</obj_property>
|
<obj_property name="ElementShortName">dac_clk_in</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_clk_in</obj_property>
|
<obj_property name="ObjectShortName">dac_clk_in</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/adc_clk_in">
|
<wvobject fp_name="/tb_control/adc_clk_in" type="logic">
|
||||||
<obj_property name="ElementShortName">adc_clk_in</obj_property>
|
<obj_property name="ElementShortName">adc_clk_in</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_clk_in</obj_property>
|
<obj_property name="ObjectShortName">adc_clk_in</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/rst_n">
|
<wvobject fp_name="/tb_control/rst_n" type="logic">
|
||||||
<obj_property name="ElementShortName">rst_n</obj_property>
|
<obj_property name="ElementShortName">rst_n</obj_property>
|
||||||
<obj_property name="ObjectShortName">rst_n</obj_property>
|
<obj_property name="ObjectShortName">rst_n</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#800080</obj_property>
|
<obj_property name="CustomSignalColor">#800080</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/s_axis_tdata">
|
<wvobject fp_name="/tb_control/rst_soft" type="logic">
|
||||||
<obj_property name="ElementShortName">s_axis_tdata[7:0]</obj_property>
|
<obj_property name="ElementShortName">rst_soft</obj_property>
|
||||||
<obj_property name="ObjectShortName">s_axis_tdata[7:0]</obj_property>
|
<obj_property name="ObjectShortName">rst_soft</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#008080</obj_property>
|
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
|
||||||
<obj_property name="Radix">BINARYRADIX</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="logic" fp_name="/tb_control/s_axis_tvalid">
|
|
||||||
<obj_property name="ElementShortName">s_axis_tvalid</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">s_axis_tvalid</obj_property>
|
|
||||||
<obj_property name="CustomSignalColor">#008080</obj_property>
|
<obj_property name="CustomSignalColor">#008080</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/s_axis_tready">
|
<wvobject fp_name="/tb_control/start" type="logic">
|
||||||
<obj_property name="ElementShortName">s_axis_tready</obj_property>
|
<obj_property name="ElementShortName">start</obj_property>
|
||||||
<obj_property name="ObjectShortName">s_axis_tready</obj_property>
|
<obj_property name="ObjectShortName">start</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#008080</obj_property>
|
<obj_property name="CustomSignalColor">#E0FFFF</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/s_axis_tlast">
|
<wvobject fp_name="/tb_control/dut/adc_start_pulse" type="logic">
|
||||||
<obj_property name="ElementShortName">s_axis_tlast</obj_property>
|
<obj_property name="ElementShortName">adc_start_pulse</obj_property>
|
||||||
<obj_property name="ObjectShortName">s_axis_tlast</obj_property>
|
<obj_property name="ObjectShortName">adc_start_pulse</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#008080</obj_property>
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/dac_start_pulse" type="logic">
|
||||||
|
<obj_property name="ElementShortName">dac_start_pulse</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">dac_start_pulse</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/busy" type="logic">
|
||||||
|
<obj_property name="ElementShortName">busy</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">busy</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#E0FFFF</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/finish">
|
<wvobject fp_name="/tb_control/finish" type="logic">
|
||||||
<obj_property name="ElementShortName">finish</obj_property>
|
<obj_property name="ElementShortName">finish</obj_property>
|
||||||
<obj_property name="ObjectShortName">finish</obj_property>
|
<obj_property name="ObjectShortName">finish</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FAAFBE</obj_property>
|
<obj_property name="CustomSignalColor">#FAAFBE</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/dac_pulse_width">
|
<wvobject fp_name="/tb_control/dut/finish_pulse" type="logic">
|
||||||
|
<obj_property name="ElementShortName">finish_pulse</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">finish_pulse</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/cfg_bus_valid" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_bus_valid</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_bus_valid</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#FF0080</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/cfg_bus_input" type="array">
|
||||||
|
<obj_property name="ElementShortName">cfg_bus_input[159:0]</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_bus_input[159:0]</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#FF0080</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dac_pulse_width" type="array">
|
||||||
<obj_property name="ElementShortName">dac_pulse_width[31:0]</obj_property>
|
<obj_property name="ElementShortName">dac_pulse_width[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_pulse_width[31:0]</obj_property>
|
<obj_property name="ObjectShortName">dac_pulse_width[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/dac_pulse_period">
|
<wvobject fp_name="/tb_control/dac_pulse_period" type="array">
|
||||||
<obj_property name="ElementShortName">dac_pulse_period[31:0]</obj_property>
|
<obj_property name="ElementShortName">dac_pulse_period[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_pulse_period[31:0]</obj_property>
|
<obj_property name="ObjectShortName">dac_pulse_period[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/dac_pulse_height">
|
<wvobject fp_name="/tb_control/dac_pulse_height" type="array">
|
||||||
<obj_property name="ElementShortName">dac_pulse_height[11:0]</obj_property>
|
<obj_property name="ElementShortName">dac_pulse_height[11:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_pulse_height[11:0]</obj_property>
|
<obj_property name="ObjectShortName">dac_pulse_height[11:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
<obj_property name="Radix">HEXRADIX</obj_property>
|
<obj_property name="Radix">HEXRADIX</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/dac_pulse_num">
|
<wvobject fp_name="/tb_control/dac_pulse_num" type="array">
|
||||||
<obj_property name="ElementShortName">dac_pulse_num[15:0]</obj_property>
|
<obj_property name="ElementShortName">dac_pulse_num[15:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_pulse_num[15:0]</obj_property>
|
<obj_property name="ObjectShortName">dac_pulse_num[15:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/adc_pulse_period">
|
<wvobject fp_name="/tb_control/adc_pulse_period" type="array">
|
||||||
<obj_property name="ElementShortName">adc_pulse_period[31:0]</obj_property>
|
<obj_property name="ElementShortName">adc_pulse_period[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_pulse_period[31:0]</obj_property>
|
<obj_property name="ObjectShortName">adc_pulse_period[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/adc_pulse_num">
|
<wvobject fp_name="/tb_control/adc_pulse_num" type="array">
|
||||||
<obj_property name="ElementShortName">adc_pulse_num[15:0]</obj_property>
|
<obj_property name="ElementShortName">adc_pulse_num[15:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_pulse_num[15:0]</obj_property>
|
<obj_property name="ObjectShortName">adc_pulse_num[15:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/dac_start">
|
<wvobject fp_name="/tb_control/adc_window_size" type="array">
|
||||||
|
<obj_property name="ElementShortName">adc_window_size[31:0]</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">adc_window_size[31:0]</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dac_start" type="logic">
|
||||||
<obj_property name="ElementShortName">dac_start</obj_property>
|
<obj_property name="ElementShortName">dac_start</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_start</obj_property>
|
<obj_property name="ObjectShortName">dac_start</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/adc_start">
|
<wvobject fp_name="/tb_control/adc_start" type="logic">
|
||||||
<obj_property name="ElementShortName">adc_start</obj_property>
|
<obj_property name="ElementShortName">adc_start</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_start</obj_property>
|
<obj_property name="ObjectShortName">adc_start</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/dac_rst">
|
<wvobject fp_name="/tb_control/dac_rst" type="logic">
|
||||||
<obj_property name="ElementShortName">dac_rst</obj_property>
|
<obj_property name="ElementShortName">dac_rst</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_rst</obj_property>
|
<obj_property name="ObjectShortName">dac_rst</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
<obj_property name="CustomSignalColor">#FFA500</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/adc_rst">
|
<wvobject fp_name="/tb_control/adc_rst" type="logic">
|
||||||
<obj_property name="ElementShortName">adc_rst</obj_property>
|
<obj_property name="ElementShortName">adc_rst</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_rst</obj_property>
|
<obj_property name="ObjectShortName">adc_rst</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="group" fp_name="group499">
|
<wvobject fp_name="group499" type="group">
|
||||||
<obj_property name="label">tb signals</obj_property>
|
<obj_property name="label">tb signals</obj_property>
|
||||||
<obj_property name="DisplayName">label</obj_property>
|
<obj_property name="DisplayName">label</obj_property>
|
||||||
<wvobject type="array" fp_name="/tb_control/dac_rst_count">
|
<wvobject fp_name="/tb_control/dac_rst_count" type="array">
|
||||||
<obj_property name="ElementShortName">dac_rst_count[31:0]</obj_property>
|
<obj_property name="ElementShortName">dac_rst_count[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_rst_count[31:0]</obj_property>
|
<obj_property name="ObjectShortName">dac_rst_count[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/adc_rst_count">
|
<wvobject fp_name="/tb_control/adc_rst_count" type="array">
|
||||||
<obj_property name="ElementShortName">adc_rst_count[31:0]</obj_property>
|
<obj_property name="ElementShortName">adc_rst_count[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_rst_count[31:0]</obj_property>
|
<obj_property name="ObjectShortName">adc_rst_count[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/dac_start_count">
|
<wvobject fp_name="/tb_control/dac_start_count" type="array">
|
||||||
<obj_property name="ElementShortName">dac_start_count[31:0]</obj_property>
|
<obj_property name="ElementShortName">dac_start_count[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">dac_start_count[31:0]</obj_property>
|
<obj_property name="ObjectShortName">dac_start_count[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/adc_start_count">
|
<wvobject fp_name="/tb_control/adc_start_count" type="array">
|
||||||
<obj_property name="ElementShortName">adc_start_count[31:0]</obj_property>
|
<obj_property name="ElementShortName">adc_start_count[31:0]</obj_property>
|
||||||
<obj_property name="ObjectShortName">adc_start_count[31:0]</obj_property>
|
<obj_property name="ObjectShortName">adc_start_count[31:0]</obj_property>
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/test_pulse_width">
|
|
||||||
<obj_property name="ElementShortName">test_pulse_width[31:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">test_pulse_width[31:0]</obj_property>
|
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="array" fp_name="/tb_control/test_pulse_period">
|
|
||||||
<obj_property name="ElementShortName">test_pulse_period[31:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">test_pulse_period[31:0]</obj_property>
|
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="array" fp_name="/tb_control/test_pulse_num">
|
|
||||||
<obj_property name="ElementShortName">test_pulse_num[15:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">test_pulse_num[15:0]</obj_property>
|
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
<wvobject type="array" fp_name="/tb_control/test_pulse_height_raw">
|
|
||||||
<obj_property name="ElementShortName">test_pulse_height_raw[15:0]</obj_property>
|
|
||||||
<obj_property name="ObjectShortName">test_pulse_height_raw[15:0]</obj_property>
|
|
||||||
<obj_property name="CustomSignalColor">#F0E68C</obj_property>
|
|
||||||
<obj_property name="UseCustomSignalColor">true</obj_property>
|
|
||||||
</wvobject>
|
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="array" fp_name="/tb_control/DAC_DATA_WIDTH">
|
<wvobject fp_name="/tb_control/dut/cfg_req_toggle_adc" type="logic">
|
||||||
<obj_property name="ElementShortName">DAC_DATA_WIDTH[31:0]</obj_property>
|
<obj_property name="ElementShortName">cfg_req_toggle_adc</obj_property>
|
||||||
<obj_property name="ObjectShortName">DAC_DATA_WIDTH[31:0]</obj_property>
|
<obj_property name="ObjectShortName">cfg_req_toggle_adc</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#FFFF00</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/dut/cfg_ack_toggle_adc">
|
<wvobject fp_name="/tb_control/dut/cfg_req_toggle_dac" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_req_toggle_dac</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_req_toggle_dac</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#FFFF00</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_ack_toggle_adc" type="logic">
|
||||||
<obj_property name="ElementShortName">cfg_ack_toggle_adc</obj_property>
|
<obj_property name="ElementShortName">cfg_ack_toggle_adc</obj_property>
|
||||||
<obj_property name="ObjectShortName">cfg_ack_toggle_adc</obj_property>
|
<obj_property name="ObjectShortName">cfg_ack_toggle_adc</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#FF00FF</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
<wvobject type="logic" fp_name="/tb_control/dut/cfg_ack_toggle_dac">
|
<wvobject fp_name="/tb_control/dut/cfg_ack_toggle_dac" type="logic">
|
||||||
<obj_property name="ElementShortName">cfg_ack_toggle_dac</obj_property>
|
<obj_property name="ElementShortName">cfg_ack_toggle_dac</obj_property>
|
||||||
<obj_property name="ObjectShortName">cfg_ack_toggle_dac</obj_property>
|
<obj_property name="ObjectShortName">cfg_ack_toggle_dac</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#FF00FF</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_wait_adc_ack" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_wait_adc_ack</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_wait_adc_ack</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#0000FF</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_wait_dac_ack" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_wait_dac_ack</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_wait_dac_ack</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#0000FF</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_req_pulse_adc" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_req_pulse_adc</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_req_pulse_adc</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#808000</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_req_pulse_dac" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_req_pulse_dac</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_req_pulse_dac</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#808000</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_ack_pulse_adc" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_ack_pulse_adc</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_ack_pulse_adc</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#DCDCDC</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
|
</wvobject>
|
||||||
|
<wvobject fp_name="/tb_control/dut/cfg_ack_pulse_dac" type="logic">
|
||||||
|
<obj_property name="ElementShortName">cfg_ack_pulse_dac</obj_property>
|
||||||
|
<obj_property name="ObjectShortName">cfg_ack_pulse_dac</obj_property>
|
||||||
|
<obj_property name="CustomSignalColor">#DCDCDC</obj_property>
|
||||||
|
<obj_property name="UseCustomSignalColor">true</obj_property>
|
||||||
</wvobject>
|
</wvobject>
|
||||||
</wave_config>
|
</wave_config>
|
||||||
|
|||||||
@@ -0,0 +1,338 @@
|
|||||||
|
module tb_controller_wrapper_axil #(
|
||||||
|
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_ADDR_WIDTH = 16,
|
||||||
|
parameter int unsigned AXIS_ID_WIDTH = 8,
|
||||||
|
parameter int unsigned LEN_WIDTH = 20,
|
||||||
|
parameter int unsigned AXIS_USER_WIDTH = 1,
|
||||||
|
parameter int unsigned AXIS_DEST_WIDTH = 8,
|
||||||
|
parameter int unsigned TAG_WIDTH = 8,
|
||||||
|
|
||||||
|
parameter int unsigned READ_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH,
|
||||||
|
parameter int unsigned WRITE_DESC_WIDTH = AXI_ADDR_WIDTH + LEN_WIDTH + TAG_WIDTH,
|
||||||
|
|
||||||
|
parameter int unsigned READ_STATUS_WIDTH = TAG_WIDTH + 4,
|
||||||
|
parameter int unsigned WRITE_STATUS_WIDTH = LEN_WIDTH + TAG_WIDTH + AXIS_ID_WIDTH + AXIS_DEST_WIDTH + AXIS_USER_WIDTH + 4,
|
||||||
|
|
||||||
|
// ceil(width / 8), чтобы keep/strb не стали слишком узкими для нестандартных ширин типа 12/49/61.
|
||||||
|
parameter int unsigned READ_DESC_KEEP_W = (READ_DESC_WIDTH + 7) / 8,
|
||||||
|
parameter int unsigned WRITE_DESC_KEEP_W = (WRITE_DESC_WIDTH + 7) / 8,
|
||||||
|
parameter int unsigned READ_STATUS_KEEP_W = (READ_STATUS_WIDTH + 7) / 8,
|
||||||
|
parameter int unsigned WRITE_STATUS_KEEP_W = (WRITE_STATUS_WIDTH + 7) / 8
|
||||||
|
)(
|
||||||
|
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,
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Минимальный flat-view для DMA AXIS портов.
|
||||||
|
// Наружу оставлены только tdata/tvalid/tready в старом стиле.
|
||||||
|
// Все остальные AXIS поля внутри обёртки завязаны на безопасные значения.
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// DUT master -> testbench: descriptor commands.
|
||||||
|
output logic [READ_DESC_WIDTH-1:0] desc_read_cmd_out,
|
||||||
|
output logic valid_desc_read,
|
||||||
|
input logic ready_desc_read,
|
||||||
|
|
||||||
|
output logic [WRITE_DESC_WIDTH-1:0] desc_write_cmd_out,
|
||||||
|
output logic valid_desc_write,
|
||||||
|
input logic ready_desc_write,
|
||||||
|
|
||||||
|
// testbench -> DUT slave: status commands.
|
||||||
|
input logic [READ_STATUS_WIDTH-1:0] status_read_cmd_in,
|
||||||
|
input logic valid_status_read,
|
||||||
|
output logic ready_status_read,
|
||||||
|
|
||||||
|
input logic [WRITE_STATUS_WIDTH-1:0] status_write_cmd_in,
|
||||||
|
input logic valid_status_write,
|
||||||
|
output logic ready_status_write
|
||||||
|
);
|
||||||
|
|
||||||
|
logic rst_n;
|
||||||
|
assign rst_n = ~rst;
|
||||||
|
|
||||||
|
// Для минимального теста держим все clock domain-ы на одном clock.
|
||||||
|
logic dac_clk_in;
|
||||||
|
logic adc_clk_in;
|
||||||
|
assign dac_clk_in = ctrl_clk;
|
||||||
|
assign adc_clk_in = ctrl_clk;
|
||||||
|
|
||||||
|
logic finish;
|
||||||
|
assign finish = 1'b0;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// AXI-Lite flat -> axi4l_if
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
axi4l_if #(
|
||||||
|
.ADDR_W(ADDR_W),
|
||||||
|
.DATA_W(DATA_W),
|
||||||
|
.USER_W(USER_W)
|
||||||
|
) axil_bus (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
axi4l_flat_to_if #(
|
||||||
|
.ADDR_W(ADDR_W),
|
||||||
|
.DATA_W(DATA_W),
|
||||||
|
.USER_W(USER_W)
|
||||||
|
) u_axil_flat_to_if (
|
||||||
|
.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_axil(axil_bus)
|
||||||
|
);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// AXIS interfaces for the updated controller_wrapper_axil
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
axis_if #(
|
||||||
|
.DATA_W(READ_STATUS_WIDTH),
|
||||||
|
.KEEP_W(READ_STATUS_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) axis_status_read (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_if #(
|
||||||
|
.DATA_W(WRITE_STATUS_WIDTH),
|
||||||
|
.KEEP_W(WRITE_STATUS_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) axis_status_write (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_if #(
|
||||||
|
.DATA_W(READ_DESC_WIDTH),
|
||||||
|
.KEEP_W(READ_DESC_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) axis_desc_read (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_if #(
|
||||||
|
.DATA_W(WRITE_DESC_WIDTH),
|
||||||
|
.KEEP_W(WRITE_DESC_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) axis_desc_write (
|
||||||
|
.aclk(ctrl_clk),
|
||||||
|
.aresetn(rst_n)
|
||||||
|
);
|
||||||
|
|
||||||
|
// testbench flat status -> DUT AXIS slave ports
|
||||||
|
axis_flat_to_if #(
|
||||||
|
.DATA_W(READ_STATUS_WIDTH),
|
||||||
|
.KEEP_W(READ_STATUS_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) u_status_read_flat_to_if (
|
||||||
|
.s_axis_tdata (status_read_cmd_in),
|
||||||
|
.s_axis_tkeep ({READ_STATUS_KEEP_W{1'b1}}),
|
||||||
|
.s_axis_tstrb ({READ_STATUS_KEEP_W{1'b1}}),
|
||||||
|
.s_axis_tlast (1'b1),
|
||||||
|
.s_axis_tid ('0),
|
||||||
|
.s_axis_tdest ('0),
|
||||||
|
.s_axis_tuser ('0),
|
||||||
|
.s_axis_tvalid(valid_status_read),
|
||||||
|
.s_axis_tready(ready_status_read),
|
||||||
|
|
||||||
|
.m_axis(axis_status_read)
|
||||||
|
);
|
||||||
|
|
||||||
|
axis_flat_to_if #(
|
||||||
|
.DATA_W(WRITE_STATUS_WIDTH),
|
||||||
|
.KEEP_W(WRITE_STATUS_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) u_status_write_flat_to_if (
|
||||||
|
.s_axis_tdata (status_write_cmd_in),
|
||||||
|
.s_axis_tkeep ({WRITE_STATUS_KEEP_W{1'b1}}),
|
||||||
|
.s_axis_tstrb ({WRITE_STATUS_KEEP_W{1'b1}}),
|
||||||
|
.s_axis_tlast (1'b1),
|
||||||
|
.s_axis_tid ('0),
|
||||||
|
.s_axis_tdest ('0),
|
||||||
|
.s_axis_tuser ('0),
|
||||||
|
.s_axis_tvalid(valid_status_write),
|
||||||
|
.s_axis_tready(ready_status_write),
|
||||||
|
|
||||||
|
.m_axis(axis_status_write)
|
||||||
|
);
|
||||||
|
|
||||||
|
// DUT AXIS master ports -> testbench flat descriptor outputs
|
||||||
|
logic [READ_DESC_KEEP_W-1:0] unused_desc_read_tkeep;
|
||||||
|
logic [READ_DESC_KEEP_W-1:0] unused_desc_read_tstrb;
|
||||||
|
logic unused_desc_read_tlast;
|
||||||
|
logic [AXIS_ID_WIDTH-1:0] unused_desc_read_tid;
|
||||||
|
logic [AXIS_DEST_WIDTH-1:0] unused_desc_read_tdest;
|
||||||
|
logic [AXIS_USER_WIDTH-1:0] unused_desc_read_tuser;
|
||||||
|
|
||||||
|
axis_if_to_flat #(
|
||||||
|
.DATA_W(READ_DESC_WIDTH),
|
||||||
|
.KEEP_W(READ_DESC_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) u_desc_read_if_to_flat (
|
||||||
|
.s_axis(axis_desc_read),
|
||||||
|
|
||||||
|
.m_axis_tdata (desc_read_cmd_out),
|
||||||
|
.m_axis_tkeep (unused_desc_read_tkeep),
|
||||||
|
.m_axis_tstrb (unused_desc_read_tstrb),
|
||||||
|
.m_axis_tlast (unused_desc_read_tlast),
|
||||||
|
.m_axis_tid (unused_desc_read_tid),
|
||||||
|
.m_axis_tdest (unused_desc_read_tdest),
|
||||||
|
.m_axis_tuser (unused_desc_read_tuser),
|
||||||
|
.m_axis_tvalid(valid_desc_read),
|
||||||
|
.m_axis_tready(ready_desc_read)
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [WRITE_DESC_KEEP_W-1:0] unused_desc_write_tkeep;
|
||||||
|
logic [WRITE_DESC_KEEP_W-1:0] unused_desc_write_tstrb;
|
||||||
|
logic unused_desc_write_tlast;
|
||||||
|
logic [AXIS_ID_WIDTH-1:0] unused_desc_write_tid;
|
||||||
|
logic [AXIS_DEST_WIDTH-1:0] unused_desc_write_tdest;
|
||||||
|
logic [AXIS_USER_WIDTH-1:0] unused_desc_write_tuser;
|
||||||
|
|
||||||
|
axis_if_to_flat #(
|
||||||
|
.DATA_W(WRITE_DESC_WIDTH),
|
||||||
|
.KEEP_W(WRITE_DESC_KEEP_W),
|
||||||
|
.ID_W(AXIS_ID_WIDTH),
|
||||||
|
.DEST_W(AXIS_DEST_WIDTH),
|
||||||
|
.USER_W(AXIS_USER_WIDTH)
|
||||||
|
) u_desc_write_if_to_flat (
|
||||||
|
.s_axis(axis_desc_write),
|
||||||
|
|
||||||
|
.m_axis_tdata (desc_write_cmd_out),
|
||||||
|
.m_axis_tkeep (unused_desc_write_tkeep),
|
||||||
|
.m_axis_tstrb (unused_desc_write_tstrb),
|
||||||
|
.m_axis_tlast (unused_desc_write_tlast),
|
||||||
|
.m_axis_tid (unused_desc_write_tid),
|
||||||
|
.m_axis_tdest (unused_desc_write_tdest),
|
||||||
|
.m_axis_tuser (unused_desc_write_tuser),
|
||||||
|
.m_axis_tvalid(valid_desc_write),
|
||||||
|
.m_axis_tready(ready_desc_write)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Controller ADC/DAC outputs.
|
||||||
|
logic [31:0] adc_window_size;
|
||||||
|
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;
|
||||||
|
logic [31:0] adc_pulse_period;
|
||||||
|
logic [15:0] adc_pulse_num;
|
||||||
|
logic dac_start;
|
||||||
|
logic adc_start;
|
||||||
|
logic dac_rst;
|
||||||
|
logic adc_rst;
|
||||||
|
|
||||||
|
controller_wrapper_axil #(
|
||||||
|
.ADDR_W(ADDR_W),
|
||||||
|
.DATA_W(DATA_W),
|
||||||
|
.USER_W(USER_W),
|
||||||
|
.DAC_DATA_WIDTH(DAC_DATA_WIDTH),
|
||||||
|
.AXI_ADDR_WIDTH(AXI_ADDR_WIDTH),
|
||||||
|
.AXIS_ID_WIDTH(AXIS_ID_WIDTH),
|
||||||
|
.LEN_WIDTH(LEN_WIDTH),
|
||||||
|
.AXIS_USER_WIDTH(AXIS_USER_WIDTH),
|
||||||
|
.AXIS_DEST_WIDTH(AXIS_DEST_WIDTH),
|
||||||
|
.TAG_WIDTH(TAG_WIDTH),
|
||||||
|
.READ_DESC_WIDTH(READ_DESC_WIDTH),
|
||||||
|
.WRITE_DESC_WIDTH(WRITE_DESC_WIDTH),
|
||||||
|
.READ_STATUS_WIDTH(READ_STATUS_WIDTH),
|
||||||
|
.WRITE_STATUS_WIDTH(WRITE_STATUS_WIDTH)
|
||||||
|
) dut (
|
||||||
|
.ctrl_clk(ctrl_clk),
|
||||||
|
.dac_clk_in(dac_clk_in),
|
||||||
|
.adc_clk_in(adc_clk_in),
|
||||||
|
.rst_n(rst_n),
|
||||||
|
.s_axil(axil_bus),
|
||||||
|
|
||||||
|
.finish(finish),
|
||||||
|
.adc_window_size(adc_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(axis_status_read),
|
||||||
|
.s_axis_status_write(axis_status_write),
|
||||||
|
|
||||||
|
.m_axis_desc_read(axis_desc_read),
|
||||||
|
.m_axis_desc_write(axis_desc_write)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule : tb_controller_wrapper_axil
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
import cocotb
|
||||||
|
from cocotb.clock import Clock
|
||||||
|
from cocotb.handle import Immediate
|
||||||
|
from cocotb.triggers import RisingEdge
|
||||||
|
from cocotbext.axi import AxiLiteBus, AxiLiteMaster
|
||||||
|
|
||||||
|
|
||||||
|
# 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 = 0
|
||||||
|
CTRL_RST_SOFT = 1
|
||||||
|
CTRL_CFG_BUS_VALID = 2
|
||||||
|
CTRL_SEND_DESC_READ = 3
|
||||||
|
CTRL_SEND_DESC_WRITE = 4
|
||||||
|
CTRL_TAKE_STATUS_READ = 5
|
||||||
|
CTRL_TAKE_STATUS_WRITE = 6
|
||||||
|
|
||||||
|
|
||||||
|
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, units="ns").start())
|
||||||
|
|
||||||
|
self.axil = AxiLiteMaster(
|
||||||
|
AxiLiteBus.from_prefix(dut, "s_axil"),
|
||||||
|
dut.ctrl_clk,
|
||||||
|
dut.rst,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def reset(self):
|
||||||
|
self.dut.rst.value = 1
|
||||||
|
for _ in range(5):
|
||||||
|
await RisingEdge(self.dut.ctrl_clk)
|
||||||
|
|
||||||
|
self.dut.rst.value = 0
|
||||||
|
for _ in range(5):
|
||||||
|
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")
|
||||||
|
|
||||||
|
|
||||||
|
@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, 1 << CTRL_CFG_BUS_VALID)
|
||||||
|
|
||||||
|
# wait
|
||||||
|
for _ in range(30):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
# check config
|
||||||
|
assert int(dut.dac_pulse_width) == 0x10
|
||||||
|
assert int(dut.dac_pulse_period) == 0x40
|
||||||
|
assert int(dut.dac_pulse_num) == 3
|
||||||
|
assert int(dut.dac_pulse_height) == 0x7FF
|
||||||
|
assert int(dut.adc_pulse_period) == 0x80
|
||||||
|
assert int(dut.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, 1 << CTRL_START)
|
||||||
|
|
||||||
|
await RisingEdge(dut.dac_start)
|
||||||
|
|
||||||
|
|
||||||
|
@cocotb.test()
|
||||||
|
async def simple_dma_desc_status(dut):
|
||||||
|
tb = TB(dut)
|
||||||
|
await tb.reset()
|
||||||
|
|
||||||
|
await tb.write_reg(REG_DESC_READ_ADDR, 0xdead)
|
||||||
|
await tb.write_reg(REG_DESC_READ_LEN, 64)
|
||||||
|
await tb.write_reg(REG_DESC_READ_CONFIG, 0x0000_0001)
|
||||||
|
|
||||||
|
await tb.write_reg(REG_DESC_WRITE_ADDR, 0xbeef)
|
||||||
|
await tb.write_reg(REG_DESC_WRITE_LEN_AND_TAG, 0x0005555)
|
||||||
|
|
||||||
|
# W1S pulse: bit 3 = send_desc_read_o.
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_SEND_DESC_READ)
|
||||||
|
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_SEND_DESC_WRITE)
|
||||||
|
|
||||||
|
for _ in range(20):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
assert int(dut.desc_read_cmd_out.value) == 0x000000100040DEAD
|
||||||
|
assert int(dut.desc_write_cmd_out.value) == 0x0005555BEEF
|
||||||
|
|
||||||
|
# test status
|
||||||
|
dut.status_read_cmd_in.value = Immediate(123)
|
||||||
|
dut.status_write_cmd_in.value = Immediate(0xabcd90012345)
|
||||||
|
dut.valid_status_read.value = Immediate(1)
|
||||||
|
dut.valid_status_write.value = Immediate(1)
|
||||||
|
|
||||||
|
for _ in range(10):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
# read status
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_TAKE_STATUS_READ)
|
||||||
|
await tb.write_reg(REG_CONTROL, 1 << CTRL_TAKE_STATUS_WRITE)
|
||||||
|
|
||||||
|
for _ in range(10):
|
||||||
|
await RisingEdge(dut.ctrl_clk)
|
||||||
|
|
||||||
|
assert await tb.read_reg(REG_READ_STATUS) == 123
|
||||||
|
assert await tb.read_reg(REG_STATUS_WRITE_CONFIG) == 0xABCD900
|
||||||
|
assert await tb.read_reg(REG_STATUS_WRITE_LEN) == 0x12345
|
||||||
+12
-12
@@ -1,7 +1,7 @@
|
|||||||
# Генератор
|
# Генератор
|
||||||
|
|
||||||
Модуль выполняет задачу формирования последовательности импульсов заданной амплитуды, длительности и периода.
|
Модуль выполняет задачу формирования последовательности импульсов заданной амплитуды, длительности и периода.
|
||||||
Дополнительно реализован механизм синхронизации с модулем сэмплера через сигналы `request` и `done`, позволяющий запускать сбор данных для каждого импульса и ожидать подтверждения завершения выборки перед переходом к следующему импульсу.
|
Дополнительно реализован механизм синхронизации с модулем сэмплера через сигналы `sample_req` и `sample_done`, позволяющий запускать сбор данных для каждого импульса и ожидать подтверждения завершения выборки перед переходом к следующему импульсу.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
## Список входных портов
|
## Список входных портов
|
||||||
|
|
||||||
### clk_dac
|
### clk_in
|
||||||
Сигнал тактирования модуля.
|
Сигнал тактирования модуля.
|
||||||
|
|
||||||
### rst
|
### rst
|
||||||
@@ -47,25 +47,25 @@
|
|||||||
### [15:0] pulse_num
|
### [15:0] pulse_num
|
||||||
Количество импульсов, которое необходимо сгенерировать.
|
Количество импульсов, которое необходимо сгенерировать.
|
||||||
|
|
||||||
### request
|
### sample_done
|
||||||
Сигнал запроса на синхронизацию от сэмплера для текущего импульса.
|
Сигнал подтверждения от сэмплера о завершении выборки данных для текущего импульса.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Список выходных портов
|
## Список выходных портов
|
||||||
|
|
||||||
### dac_wrt
|
pulse
|
||||||
Выходной сигнал разрешения записи сигнала
|
Выходной сигнал разрешения записи сигнала
|
||||||
|
|
||||||
### [DATA_WIDTH-1:0] dac_out
|
[DATA_WIDTH-1:0] pulse_height_out
|
||||||
Выходное значение амплитуды сигнала.
|
Выходное значение амплитуды сигнала.
|
||||||
|
|
||||||
Во время активной части импульса равно `pulse_height`, вне импульса — `ZERO_LEVEL`.
|
Во время активной части импульса равно `pulse_height`, вне импульса — `ZERO_LEVEL`.
|
||||||
|
|
||||||
### done
|
sample_req
|
||||||
Сигнал запроса на запуск синхронизации с сэмплером для текущего импульса.
|
Сигнал запроса на запуск выборки в модуле сэмплера.
|
||||||
|
|
||||||
Поднимается в начале каждого нового импульса и снимается после получения `request`.
|
Поднимается в начале каждого нового импульса и снимается после получения `sample_done`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -74,11 +74,11 @@
|
|||||||
После прихода сигнала `start` модуль:
|
После прихода сигнала `start` модуль:
|
||||||
|
|
||||||
- фиксирует входные параметры генерации
|
- фиксирует входные параметры генерации
|
||||||
|
- сбрасывает внутренние счетчики
|
||||||
- поднимает `enable = 1`
|
- поднимает `enable = 1`
|
||||||
- выполняет `pulse_num` циклов работы
|
- формирует первый `sample_req`
|
||||||
- - типичный цикл состоит в ожидании синхронизации (`synced`), после чего запуск генерации импульса
|
|
||||||
|
|
||||||
Синхронизация представляет из себя простое рукопожатие с внешним модулем, имеющим сигналы `request`/`done` работающими в соответствии с этими сигналами генератора. Один из модулей, входит в ожидание и ставит на свой done активный уровень, после чего ждет, пока второй, запаздывающий модуль не войдет в свой режим ожидания, и не выставит для своего done активный уровень. Для каждого из модулей, на следующий такт после выставления активного уровня, производится проверка своего request. Так, при получении активного request (иными словами активного done от внешнего модуля), модуль незамедлительно опускает уровень своего done и начинает работать. Done подымается до активного уровня хотя-бы на один такт работы соответствующего модуля.
|
После этого начинается последовательная генерация импульсов.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,95 +1,105 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
|
||||||
module generator
|
module generator
|
||||||
#(
|
#(
|
||||||
parameter DATA_WIDTH = 14,
|
parameter DATA_WIDTH = 14,
|
||||||
parameter ZERO_LEVEL = 8192 // 8192 or 0
|
parameter ZERO_LEVEL = 8192 // 8192 or 0
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input clk_dac,
|
input clk_in,
|
||||||
input rst,
|
input rst,
|
||||||
input start,
|
input start,
|
||||||
input [31:0] pulse_width,
|
input [31:0] pulse_width,
|
||||||
input [31:0] pulse_period,
|
input [31:0] pulse_period,
|
||||||
input [DATA_WIDTH-1:0] pulse_height,
|
input [DATA_WIDTH-1:0] pulse_height,
|
||||||
input [15:0] pulse_num,
|
input [15:0] pulse_num,
|
||||||
input request,
|
input sample_done,
|
||||||
|
|
||||||
output logic [DATA_WIDTH-1:0] dac_out,
|
output pulse,
|
||||||
output logic done
|
output[DATA_WIDTH-1:0] pulse_height_out,
|
||||||
);
|
output logic sample_req
|
||||||
logic [DATA_WIDTH-1:0] pulse_height_reg;
|
|
||||||
logic [31:0] pulse_width_reg, pulse_period_reg;
|
|
||||||
logic [15:0] pulse_num_reg;
|
|
||||||
|
|
||||||
logic [15:0] cnt_pulse_num;
|
);
|
||||||
logic [31:0] cnt_pulse_period;
|
|
||||||
|
(* MARK_DEBUG="true" *) logic [DATA_WIDTH-1:0] pulse_height_reg, pulse_height_out_reg;
|
||||||
|
|
||||||
|
(* MARK_DEBUG="true" *) logic [31:0] pulse_width_reg, pulse_period_reg;
|
||||||
|
(* MARK_DEBUG="true" *) logic [15:0] pulse_num_reg;
|
||||||
|
|
||||||
|
(* MARK_DEBUG="true" *) logic enable;
|
||||||
|
(* MARK_DEBUG="true" *) logic [15:0] cnt_pulse_num;
|
||||||
|
(* MARK_DEBUG="true" *) logic [31:0] cnt_period;
|
||||||
|
|
||||||
logic enable, synced;
|
|
||||||
|
always @(posedge clk_in) begin
|
||||||
initial begin
|
|
||||||
cnt_pulse_period = '0;
|
|
||||||
cnt_pulse_num = '0;
|
|
||||||
enable = 0;
|
|
||||||
synced = 0;
|
|
||||||
dac_out = ZERO_LEVEL;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk_dac) begin
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
pulse_height_reg <= ZERO_LEVEL;
|
pulse_height_reg <= ZERO_LEVEL;
|
||||||
pulse_width_reg <= 0;
|
pulse_height_out_reg <= ZERO_LEVEL;
|
||||||
pulse_period_reg <= 0;
|
pulse_width_reg <= '0;
|
||||||
pulse_num_reg <= 0;
|
pulse_period_reg <= '0;
|
||||||
cnt_pulse_num <= 0;
|
pulse_num_reg <= '0;
|
||||||
cnt_pulse_period <= 0;
|
enable <= 0;
|
||||||
dac_out <= ZERO_LEVEL;
|
cnt_pulse_num <= '0;
|
||||||
done <= 0;
|
cnt_period <= '0;
|
||||||
enable <= 0;
|
sample_req <= 0;
|
||||||
synced <= 0;
|
end else begin
|
||||||
end
|
|
||||||
else begin
|
|
||||||
// wait start for updating registers
|
|
||||||
if (start & !enable) begin
|
if (start & !enable) begin
|
||||||
enable <= 1;
|
enable <= 1'b1;
|
||||||
pulse_width_reg <= pulse_width;
|
cnt_pulse_num <= '0;
|
||||||
pulse_period_reg <= pulse_period;
|
cnt_period <= '0;
|
||||||
pulse_num_reg <= pulse_num;
|
|
||||||
pulse_height_reg <= pulse_height;
|
sample_req <= 1;
|
||||||
end
|
|
||||||
// main work cycle
|
pulse_width_reg <= pulse_width;
|
||||||
|
pulse_period_reg <= pulse_period;
|
||||||
|
pulse_num_reg <= pulse_num;
|
||||||
|
pulse_height_reg <= pulse_height;
|
||||||
|
end
|
||||||
if (enable) begin
|
if (enable) begin
|
||||||
if (cnt_pulse_num != pulse_num_reg) begin
|
|
||||||
// wait for synchronization with sampler
|
if (!sample_req && (cnt_period == 0)) begin
|
||||||
if (!synced) begin
|
pulse_height_out_reg <= ZERO_LEVEL;
|
||||||
if (request & done) begin
|
if (sample_done) begin
|
||||||
synced <= 1;
|
sample_req <= 1'b0;
|
||||||
done <= 0;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
done <= 1;
|
|
||||||
end
|
end
|
||||||
else begin
|
|
||||||
if (cnt_pulse_period != pulse_period_reg) begin
|
if (!sample_done) begin
|
||||||
if (cnt_pulse_period < pulse_width_reg)
|
if (cnt_pulse_num == pulse_num_reg - 1) begin
|
||||||
dac_out <= pulse_height_reg;
|
enable <= 1'b0;
|
||||||
else
|
|
||||||
dac_out <= ZERO_LEVEL;
|
|
||||||
cnt_pulse_period++;
|
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
cnt_pulse_num++;
|
cnt_pulse_num <= cnt_pulse_num + 1;
|
||||||
cnt_pulse_period <= 0;
|
sample_req <= 1'b1;
|
||||||
synced <= 0;
|
cnt_period <= 1;
|
||||||
dac_out <= ZERO_LEVEL;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
cnt_pulse_num <= 0;
|
|
||||||
enable <= 0;
|
if (cnt_period <= pulse_width_reg) begin
|
||||||
|
pulse_height_out_reg <= pulse_height_reg;
|
||||||
|
end else begin
|
||||||
|
pulse_height_out_reg <= ZERO_LEVEL;
|
||||||
|
end
|
||||||
|
if (cnt_period == pulse_period_reg) begin
|
||||||
|
cnt_period <= 0;
|
||||||
|
end else begin
|
||||||
|
cnt_period <= cnt_period + 1;
|
||||||
|
end
|
||||||
|
if (sample_req && sample_done) begin
|
||||||
|
sample_req <= 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
OBUF OBUF_pulse_clk (
|
||||||
|
.I(clk_in),
|
||||||
|
.O(pulse)
|
||||||
|
);
|
||||||
|
|
||||||
|
assign pulse_height_out = pulse_height_out_reg;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -1,360 +1,114 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module generator_tb;
|
module generator_tb;
|
||||||
// === Параметры ===
|
|
||||||
localparam DATA_WIDTH = 14;
|
|
||||||
localparam LOGIC_ZERO_LEVEL = 0; // DAC -5V for logic zero
|
|
||||||
localparam VOLTAGE_ZERO_LEVEL = 2**(DATA_WIDTH-1); // DAC 0V for logic zero
|
|
||||||
localparam CLK_PERIOD = 8;
|
|
||||||
parameter string ZERO_LEVEL = "logic"; // "logic" VS "true"
|
|
||||||
|
|
||||||
// === Сигналы ===
|
parameter DATA_WIDTH = 14;
|
||||||
// Системные сигналы
|
parameter ZERO_LEVEL = 8192;
|
||||||
|
parameter CLK_PERIOD = 16;
|
||||||
|
|
||||||
logic clk;
|
logic clk;
|
||||||
logic rst;
|
logic rst;
|
||||||
logic start;
|
logic start;
|
||||||
// Входные сигналы
|
|
||||||
logic [31:0] pulse_width; // config reg
|
|
||||||
logic [31:0] pulse_period; // config reg
|
|
||||||
logic [DATA_WIDTH-1:0] pulse_height; // config reg
|
|
||||||
logic [15:0] pulse_num; // config reg
|
|
||||||
logic sampler_done; // sampler request for synchronization
|
|
||||||
// Выходные сигналы
|
|
||||||
wire [DATA_WIDTH-1:0] dac_out; // DAC input logic signal
|
|
||||||
wire generator_done; // generator request for synchronization
|
|
||||||
|
|
||||||
// === Переменные ===
|
logic [31:0] pulse_width;
|
||||||
int current_zero_level;
|
logic [31:0] pulse_period;
|
||||||
initial begin
|
logic [DATA_WIDTH-1:0] pulse_height;
|
||||||
if (ZERO_LEVEL == "true")
|
logic [15:0] pulse_num;
|
||||||
current_zero_level = VOLTAGE_ZERO_LEVEL;
|
|
||||||
else
|
logic pulse;
|
||||||
current_zero_level = LOGIC_ZERO_LEVEL;
|
logic [DATA_WIDTH-1:0] pulse_height_out;
|
||||||
end
|
|
||||||
|
|
||||||
// DUT
|
// DUT
|
||||||
generate
|
generator #(
|
||||||
if (ZERO_LEVEL == "true") begin : gen_dut_true
|
.DATA_WIDTH(DATA_WIDTH)
|
||||||
generator #(
|
) dut (
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
.clk_in(clk),
|
||||||
.ZERO_LEVEL(VOLTAGE_ZERO_LEVEL)
|
.rst(rst),
|
||||||
) dut (
|
.start(start),
|
||||||
.clk_dac(clk),
|
.pulse_width(pulse_width),
|
||||||
.rst(rst),
|
.pulse_period(pulse_period),
|
||||||
.start(start),
|
.pulse_height(pulse_height),
|
||||||
.pulse_width(pulse_width),
|
.pulse_num(pulse_num),
|
||||||
.pulse_period(pulse_period),
|
.pulse(pulse),
|
||||||
.pulse_height(pulse_height),
|
.pulse_height_out(pulse_height_out)
|
||||||
.pulse_num(pulse_num),
|
);
|
||||||
.dac_out(dac_out),
|
|
||||||
.done(generator_done),
|
|
||||||
.request(sampler_done)
|
|
||||||
);
|
|
||||||
initial $display("[TB] Generator compiled. ZERO_LEVEL: TRUE");
|
|
||||||
end
|
|
||||||
else if (ZERO_LEVEL == "logic") begin : gen_dut_logic
|
|
||||||
generator #(
|
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
|
||||||
.ZERO_LEVEL(LOGIC_ZERO_LEVEL)
|
|
||||||
) dut (
|
|
||||||
.clk_dac(clk),
|
|
||||||
.rst(rst),
|
|
||||||
.start(start),
|
|
||||||
.pulse_width(pulse_width),
|
|
||||||
.pulse_period(pulse_period),
|
|
||||||
.pulse_height(pulse_height),
|
|
||||||
.pulse_num(pulse_num),
|
|
||||||
.dac_out(dac_out),
|
|
||||||
.done(generator_done),
|
|
||||||
.request(sampler_done)
|
|
||||||
);
|
|
||||||
initial $display("[TB] Generator compiled. ZERO_LEVEL: LOGIC");
|
|
||||||
end
|
|
||||||
else begin : gen_dut_error
|
|
||||||
// Защита от дурака
|
|
||||||
initial begin
|
|
||||||
$display("[ERROR] Unknown value ZERO_LEVEL: %s", ZERO_LEVEL);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
// Тактовые сигналы
|
// Clock
|
||||||
initial begin
|
initial begin
|
||||||
clk = 0;
|
clk = 0;
|
||||||
forever #(CLK_PERIOD/2) clk = ~clk;
|
forever #(CLK_PERIOD/2) clk = ~clk;
|
||||||
end
|
end
|
||||||
|
|
||||||
// === Таски для тестипрования ===
|
|
||||||
// Таска синхронизации, одно рукопожатие
|
|
||||||
task automatic synchronize(
|
|
||||||
input bit sampler_first, // 1 - выставить sampler_done ДО генератора, 0 - ПОСЛЕ
|
|
||||||
input int delay_before_ack, // Если sampler_first=0: задержка ПОСЛЕ gen_done. Если 1: задержка от НАЧАЛА цикла.
|
|
||||||
input int ack_duration // сколько тактов удерживать sampler_done после встречи сигналов
|
|
||||||
);
|
|
||||||
if (sampler_first) begin
|
|
||||||
// --- сэмплер готов до генератора ---
|
|
||||||
repeat(delay_before_ack) @(posedge clk);
|
|
||||||
sampler_done <= 1;
|
|
||||||
wait(generator_done == 1);
|
|
||||||
repeat(ack_duration) @(posedge clk);
|
|
||||||
sampler_done <= 0;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
// --- генератора готов до сэмплер ---
|
|
||||||
wait(generator_done == 1);
|
|
||||||
repeat(delay_before_ack) @(posedge clk);
|
|
||||||
sampler_done <= 1;
|
|
||||||
repeat(ack_duration) @(posedge clk);
|
|
||||||
sampler_done <= 0;
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска сброса DUT
|
|
||||||
task automatic reset_dut(
|
|
||||||
input int rst_duration // сколько тактов держать сброс
|
|
||||||
);
|
|
||||||
rst <= 1;
|
|
||||||
repeat(rst_duration) @(posedge clk);
|
|
||||||
rst <= 0;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска запуска DUT
|
|
||||||
task automatic start_dut(
|
|
||||||
input int start_duration // сколько тактов держать импульс
|
|
||||||
);
|
|
||||||
start <= 1;
|
|
||||||
repeat(start_duration) @(posedge clk);
|
|
||||||
start <= 0;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска конфигурации DUT
|
|
||||||
task automatic set_config(
|
|
||||||
input logic [31:0] w, // ширина импульса
|
|
||||||
input logic [31:0] p, // период импульса
|
|
||||||
input logic [15:0] n, // количество импульсов
|
|
||||||
input logic [DATA_WIDTH-1:0] h // высота импульса
|
|
||||||
);
|
|
||||||
// Задаем конфигурационные регистры
|
|
||||||
@(posedge clk);
|
|
||||||
pulse_width <= w;
|
|
||||||
pulse_period <= p;
|
|
||||||
pulse_num <= n;
|
|
||||||
pulse_height <= h;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// Таска проверки устойчивости к долгим управляющим импульсам
|
|
||||||
task automatic check_impulses;
|
|
||||||
// Локальные переменные для хранения случайных параметров
|
|
||||||
int rand_start_duration;
|
|
||||||
int rand_delay;
|
|
||||||
int rand_ack;
|
|
||||||
bit rand_first;
|
|
||||||
int total_impulse_cycles = 0;
|
|
||||||
|
|
||||||
int pulse_w = 11;
|
|
||||||
int pulse_p = 31;
|
|
||||||
int pulse_n = 5;
|
|
||||||
int pulse_h = 1024;
|
|
||||||
|
|
||||||
$display("[TB] -check_impulses- Check system stability under random latencies");
|
|
||||||
|
|
||||||
// Установка конфигурации
|
|
||||||
set_config(
|
|
||||||
.w(pulse_w),
|
|
||||||
.p(pulse_p),
|
|
||||||
.n(pulse_n),
|
|
||||||
.h(pulse_h)
|
|
||||||
);
|
|
||||||
|
|
||||||
reset_dut(5);
|
|
||||||
repeat(2) @(posedge clk);
|
|
||||||
|
|
||||||
// Старт норме 1 такт. Сделаем случайным от 5 до 25 тактов.
|
|
||||||
rand_start_duration = $urandom_range(5, 25);
|
|
||||||
$display("[TB] Long start: %0d clocks", rand_start_duration);
|
|
||||||
|
|
||||||
// Фоновый процесс подсчета тактов импульса
|
|
||||||
fork
|
|
||||||
begin : counter_proc
|
|
||||||
forever begin
|
|
||||||
@(negedge clk); // 180 deg. phase shift for "DAC strobing signal"
|
|
||||||
if (dac_out == pulse_h) begin
|
|
||||||
total_impulse_cycles++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
join_none
|
|
||||||
|
|
||||||
// Параллельный запуск длинного старта и обработки синхронизации
|
|
||||||
fork
|
|
||||||
// Поток 1: Удерживаем старт аномально долго
|
|
||||||
begin
|
|
||||||
start_dut(rand_start_duration);
|
|
||||||
end
|
|
||||||
// Поток 2: Обслуживаем n=4 циклов синхронизации со случайными задержками
|
|
||||||
begin
|
|
||||||
repeat(pulse_n) begin
|
|
||||||
// Рандомизируем параметры для каждого из 4-х рукопожатий
|
|
||||||
rand_first = $urandom; // Случайно: Самплер первый (1) или Генератор первый (0)
|
|
||||||
rand_delay = $urandom_range(1, 8); // Случайная задержка ожидания (1..8 тактов)
|
|
||||||
rand_ack = $urandom_range(5, 10); // Аномально долгий удерживаемый импульс sampler_done (10..30 тактов)
|
|
||||||
|
|
||||||
synchronize(
|
|
||||||
.sampler_first(rand_first),
|
|
||||||
.delay_before_ack(rand_delay),
|
|
||||||
.ack_duration(rand_ack)
|
|
||||||
);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
join
|
|
||||||
repeat(pulse_p+5) @(posedge clk);
|
|
||||||
disable counter_proc;
|
|
||||||
// Ожидание завершения переходных процессов
|
|
||||||
repeat(10) @(posedge clk);
|
|
||||||
if (total_impulse_cycles == pulse_w*pulse_n)
|
|
||||||
$display("[TB] -check_impulses- Pulse generation CORRECT");
|
|
||||||
else begin
|
|
||||||
$display("[ERROR] -check_impulses- Pulse generation INCORRECT. Total number of pulses: %d, must be: %d", total_impulse_cycles, pulse_w*pulse_n);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
$display("[TB] -check_impulses- Done");
|
|
||||||
endtask
|
|
||||||
|
|
||||||
task automatic run_test_case(
|
|
||||||
input int pulse_w,
|
|
||||||
input int pulse_p,
|
|
||||||
input int pulse_n,
|
|
||||||
input int pulse_h,
|
|
||||||
input bit skip_reset, // skip reset sequence on demand
|
|
||||||
input bit count_level // count ticks of amplitude == pulse_h or amplitude != pulse_h
|
|
||||||
);
|
|
||||||
int total_impulse_cycles = 0;
|
|
||||||
|
|
||||||
if (!skip_reset) begin
|
|
||||||
reset_dut(1);
|
|
||||||
@(posedge clk);
|
|
||||||
end
|
|
||||||
|
|
||||||
set_config(
|
|
||||||
.w(pulse_w),
|
|
||||||
.p(pulse_p),
|
|
||||||
.n(pulse_n),
|
|
||||||
.h(pulse_h)
|
|
||||||
);
|
|
||||||
@(posedge clk);
|
|
||||||
|
|
||||||
start_dut(1);
|
|
||||||
|
|
||||||
// Фоновый процесс подсчета тактов импульса
|
|
||||||
fork
|
|
||||||
begin : counter_proc
|
|
||||||
forever begin
|
|
||||||
@(negedge clk); // 180 deg. phase shift for "DAC strobing signal"
|
|
||||||
if (count_level) begin
|
|
||||||
if (dac_out == pulse_h) begin
|
|
||||||
total_impulse_cycles++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if (dac_out != current_zero_level) begin
|
|
||||||
total_impulse_cycles++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
join_none
|
|
||||||
|
|
||||||
repeat(pulse_n) begin
|
|
||||||
synchronize(
|
|
||||||
.sampler_first(0),
|
|
||||||
.delay_before_ack(1),
|
|
||||||
.ack_duration(2)
|
|
||||||
);
|
|
||||||
end
|
|
||||||
repeat(pulse_p+5) @(posedge clk);
|
|
||||||
disable counter_proc;
|
|
||||||
repeat(10) @(posedge clk);
|
|
||||||
|
|
||||||
if (count_level) begin
|
|
||||||
if (total_impulse_cycles == pulse_w*pulse_n)
|
|
||||||
$display("[TB] -run_test_case- Pulse generation CORRECT");
|
|
||||||
else begin
|
|
||||||
$display("[ERROR] -run_test_case- Pulse generation INCORRECT. Total number of pulses: %d, must be: %d", total_impulse_cycles, pulse_w*pulse_n);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
if (total_impulse_cycles == 0)
|
|
||||||
$display("[TB] -run_test_case- Pulse generation CORRECT");
|
|
||||||
else begin
|
|
||||||
$display("[ERROR] -run_test_case- Pulse generation INCORRECT. Total number of pulses: %d, must be: %d", total_impulse_cycles, 0);
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// --- ОСНОВНОЙ ПРОЦЕСС ТЕСТИРОВАНИЯ ---
|
|
||||||
initial begin
|
initial begin
|
||||||
$display("[TB] Tests start");
|
$display("\n=== GENERATOR TEST ===\n");
|
||||||
|
|
||||||
// Инициализация
|
|
||||||
rst = 1;
|
rst = 1;
|
||||||
start = 0;
|
start = 0;
|
||||||
|
|
||||||
pulse_width = 0;
|
pulse_width = 0;
|
||||||
pulse_period = 0;
|
pulse_period = 0;
|
||||||
pulse_height = 0;
|
pulse_height = 0;
|
||||||
pulse_num = 0;
|
pulse_num = 0;
|
||||||
sampler_done = 0;
|
|
||||||
|
|
||||||
$display("[TB] Test 1. Random latency for control signals");
|
repeat(5) @(posedge clk);
|
||||||
check_impulses();
|
rst = 0;
|
||||||
$display("[TB] Test 1 complete");
|
|
||||||
|
|
||||||
$display("[TB] Test 2. Random configs");
|
// --- Test 1 ---
|
||||||
for (int i = 0; i < 25; i++) begin
|
// 3 clk 1, 5 clk 0, 4 pulses
|
||||||
int r_w, r_p, r_n, r_h;
|
repeat(2) @(posedge clk);
|
||||||
bit r_skip;
|
pulse_width = 3;
|
||||||
|
pulse_period = 8;
|
||||||
|
pulse_num = 4;
|
||||||
|
pulse_height = 14'h3FF;
|
||||||
|
start = 1;
|
||||||
|
|
||||||
// Генерируем параметры
|
repeat(1) @(posedge clk);
|
||||||
r_p = $urandom_range(5, 50); // Период от 5 до 50
|
start = 0;
|
||||||
r_w = $urandom_range(0, r_p); // Ширина не больше периода
|
|
||||||
r_n = $urandom_range(1, 10); // Количество импульсов
|
|
||||||
r_h = $urandom_range(1, 2**DATA_WIDTH-1); // Высота (для 14 бит)
|
|
||||||
r_skip = $urandom_range(0, 1); // Случайный сброс (0 - сброс, 1 - пропуск)
|
|
||||||
|
|
||||||
// Защита от "нулевого" импульса. Невозможно проверить длительность.
|
repeat(50) @(posedge clk);
|
||||||
if (r_h == current_zero_level) begin
|
|
||||||
r_h += $urandom_range(1, 10);
|
|
||||||
end
|
|
||||||
|
|
||||||
$display("[TB] --- Test #%0d (Config: W=%0d, P=%0d, N=%0d, H=%0d, SkipReset=%0b) ---",
|
// --- Test 2 ---
|
||||||
i+1, r_w, r_p, r_n, r_h, r_skip);
|
$display("\n--- SECOND RUN ---\n");
|
||||||
|
|
||||||
run_test_case(
|
@(posedge clk);
|
||||||
.pulse_w(r_w),
|
pulse_width = 2;
|
||||||
.pulse_p(r_p),
|
pulse_period = 5;
|
||||||
.pulse_n(r_n),
|
pulse_num = 3;
|
||||||
.pulse_h(r_h),
|
pulse_height = 14'h155;
|
||||||
.skip_reset(r_skip),
|
start = 1;
|
||||||
.count_level(1)
|
|
||||||
);
|
|
||||||
end
|
|
||||||
$display("[TB] Test 2 complete");
|
|
||||||
|
|
||||||
$display("[TB] Test 3. Zero level of pulse height");
|
@(posedge clk);
|
||||||
run_test_case(
|
start = 0;
|
||||||
.pulse_w(77),
|
|
||||||
.pulse_p(131),
|
|
||||||
.pulse_n(13),
|
|
||||||
.pulse_h(current_zero_level),
|
|
||||||
.skip_reset(0),
|
|
||||||
.count_level(0)
|
|
||||||
);
|
|
||||||
$display("[TB] Test 3 complete");
|
|
||||||
|
|
||||||
$display("[TB] ALL PASSED");
|
repeat(40) @(posedge clk);
|
||||||
|
|
||||||
|
pulse_width = 3;
|
||||||
|
pulse_period = 8;
|
||||||
|
pulse_num = 4;
|
||||||
|
pulse_height = 14'h3FF;
|
||||||
|
start = 1;
|
||||||
|
|
||||||
|
repeat(1) @(posedge clk);
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
repeat(5) @(posedge clk);
|
||||||
|
start = 1;
|
||||||
|
pulse_height = 14'h155;
|
||||||
|
|
||||||
|
repeat(1) @(posedge clk);
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
repeat(50) @(posedge clk);
|
||||||
|
|
||||||
|
|
||||||
|
$display("\n=== TEST FINISHED ===");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// Display
|
||||||
|
always @(posedge clk) begin
|
||||||
|
$display("t=%0t | pulse=%0b | height=%h",
|
||||||
|
$time, pulse, pulse_height_out);
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
+11
-11
@@ -1,7 +1,7 @@
|
|||||||
# Сэмплер
|
# Сэмплер
|
||||||
|
|
||||||
Модуль выполняет задачу сбора данных с выхода АЦП, их обработки, упаковки и передачи дальше с помощью AXI Stream интерфейса.
|
Модуль выполняет задачу сбора данных с выхода АЦП, их обработки, упаковки и передачи дальше с помощью AXI Stream интерфейса.
|
||||||
Дополнительно реализован механизм синхронизации с внешним генератором через сигналы `request` и `done`, позволяющий запускать сбор строго по запросу и подтверждать завершение выборки.
|
Дополнительно реализован механизм синхронизации с внешним генератором через сигналы `sample_req` и `sample_done`, позволяющий запускать сбор строго по запросу и подтверждать завершение выборки.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -41,8 +41,9 @@ out_of_range
|
|||||||
[31:0] smp_num
|
[31:0] smp_num
|
||||||
Количество валидных отсчетов, которое необходимо собрать после получения запроса на выборку.
|
Количество валидных отсчетов, которое необходимо собрать после получения запроса на выборку.
|
||||||
|
|
||||||
request
|
sample_req
|
||||||
Сигнал запроса на синхронизацию от генератора для текущего импульса.
|
Сигнал запроса на запуск выборки.
|
||||||
|
При его активации модуль начинает сбор данных и переходит в активное состояние (`enable = 1`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -56,10 +57,9 @@ m_axis_tvalid
|
|||||||
Урезанный AXI Stream формат, сигнал валидности выходных данных.
|
Урезанный AXI Stream формат, сигнал валидности выходных данных.
|
||||||
Формируется при готовности очередного пакета.
|
Формируется при готовности очередного пакета.
|
||||||
|
|
||||||
done
|
sample_done
|
||||||
Сигнал запроса на запуск синхронизации с генератором для текущего импульса.
|
Сигнал завершения выборки.
|
||||||
|
Поднимается после того, как модуль собрал количество валидных отсчетов, равное `smp_num`.
|
||||||
Поднимается в начале каждого нового импульса и снимается после получения `request`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ done
|
|||||||
|
|
||||||
### Запуск выборки
|
### Запуск выборки
|
||||||
|
|
||||||
Сбор данных начинается только после прихода сигнала `request`.
|
Сбор данных начинается только после прихода сигнала `sample_req`.
|
||||||
|
|
||||||
При этом:
|
При этом:
|
||||||
|
|
||||||
@@ -94,9 +94,7 @@ done
|
|||||||
- внутренний счетчик собранных отсчетов обнуляется
|
- внутренний счетчик собранных отсчетов обнуляется
|
||||||
- модуль переходит в активное состояние (`enable = 1`)
|
- модуль переходит в активное состояние (`enable = 1`)
|
||||||
|
|
||||||
Пока `enable = 1`, модуль принимает только валидные отсчеты.
|
Пока `enable = 1`, модуль принимает только валидные отсчеты и считает их.
|
||||||
|
|
||||||
Синхронизация представляет из себя простое рукопожатие с внешним модулем, имеющим сигналы `request`/`done` работающими в соответствии с этими сигналами сэмплера. Один из модулей, входит в ожидание и ставит на свой done активный уровень, после чего ждет, пока второй, запаздывающий модуль не войдет в свой режим ожидания, и не выставит для своего done активный уровень. Для каждого из модулей, на следующий такт после выставления активного уровня, производится проверка своего request. Так, при получении активного request (иными словами активного done от внешнего модуля), модуль незамедлительно опускает уровень своего done и начинает работать. Done подымается до активного уровня хотя-бы на один такт работы соответствующего модуля.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -128,6 +126,7 @@ done
|
|||||||
|
|
||||||
Когда количество собранных валидных отсчетов достигает значения `smp_num`:
|
Когда количество собранных валидных отсчетов достигает значения `smp_num`:
|
||||||
|
|
||||||
|
- поднимается сигнал `sample_done`
|
||||||
- внутренние счетчики сбрасываются
|
- внутренние счетчики сбрасываются
|
||||||
- буфер очищается
|
- буфер очищается
|
||||||
- `enable` сбрасывается в `0`
|
- `enable` сбрасывается в `0`
|
||||||
@@ -142,3 +141,4 @@ done
|
|||||||
cd tests
|
cd tests
|
||||||
make sim
|
make sim
|
||||||
```
|
```
|
||||||
|
При успешном завершении теста высвечивается "ALL PASSED".
|
||||||
+129
-62
@@ -1,87 +1,154 @@
|
|||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module sampler
|
module sampler
|
||||||
#(
|
#(
|
||||||
parameter DATA_WIDTH = 12,
|
parameter DATA_WIDTH = 12,
|
||||||
parameter PACK_FACTOR = 1,
|
parameter PACK_FACTOR = 1,
|
||||||
parameter PROCESS_MODE = 0
|
parameter PROCESS_MODE = 0
|
||||||
) (
|
)
|
||||||
|
(
|
||||||
input clk_in,
|
input clk_in,
|
||||||
input rst,
|
input rst,
|
||||||
input [DATA_WIDTH-1:0] data_in,
|
input [DATA_WIDTH-1:0] data_in,
|
||||||
input out_of_range,
|
input out_of_range,
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num,
|
||||||
input request,
|
input sample_req,
|
||||||
|
|
||||||
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
output logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||||
output logic m_axis_tvalid,
|
output logic m_axis_tvalid,
|
||||||
output logic done
|
output logic sample_done
|
||||||
);
|
);
|
||||||
// WARNING: number of samples smp_num must be multiple of PACK_FACTOR
|
(* MARK_DEBUG="true" *) logic [DATA_WIDTH-1:0] data_converted;
|
||||||
// Last (smp_num % PACK_FACTOR) will be lost and not transmitted
|
(* MARK_DEBUG="true" *) logic out_of_range_reg;
|
||||||
logic [DATA_WIDTH-1:0] data_converted;
|
(* MARK_DEBUG="true" *) logic [31:0] smp_num_reg, cnt_smp_num;
|
||||||
logic [31:0] smp_num_reg, cnt_smp_num;
|
(* MARK_DEBUG="true" *) logic enable;
|
||||||
logic synced;
|
|
||||||
logic [$clog2(PACK_FACTOR):0] pack_cnt;
|
|
||||||
|
|
||||||
always_comb begin
|
generate
|
||||||
if (PROCESS_MODE) begin
|
if (PROCESS_MODE) begin
|
||||||
if (out_of_range) begin
|
|
||||||
data_converted = {~data_in[DATA_WIDTH-1], {(DATA_WIDTH-1){data_in[DATA_WIDTH-1]}}};
|
|
||||||
end else begin
|
|
||||||
data_converted = {~data_in[DATA_WIDTH-1], data_in[DATA_WIDTH-2:0]};
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
if (out_of_range) begin
|
|
||||||
data_converted = {DATA_WIDTH{data_in[DATA_WIDTH-1]}};
|
|
||||||
end else begin
|
|
||||||
data_converted = data_in;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
initial begin
|
always @(posedge clk_in) begin
|
||||||
synced = 0;
|
if (rst) begin
|
||||||
m_axis_tdata = '0;
|
data_converted <= '0;
|
||||||
m_axis_tvalid = 0;
|
out_of_range_reg <= 0;
|
||||||
end
|
end
|
||||||
|
else begin
|
||||||
|
out_of_range_reg <= out_of_range;
|
||||||
|
if (data_in == {1'b1, {(DATA_WIDTH-1){1'b0}}})
|
||||||
|
data_converted <= data_in;
|
||||||
|
else
|
||||||
|
data_converted <= data_in[DATA_WIDTH-1] ?{1'b1, (~data_in[DATA_WIDTH-2:0] + 1'b1)}:data_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
always @(posedge clk_in) begin
|
||||||
|
if (rst) begin
|
||||||
|
data_converted <= '0;
|
||||||
|
out_of_range_reg <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
out_of_range_reg <= out_of_range;
|
||||||
|
data_converted <= data_in;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
(* MARK_DEBUG="true" *) logic [DATA_WIDTH*PACK_FACTOR-1:0] buffer;
|
||||||
|
(* MARK_DEBUG="true" *) logic buffer_ready;
|
||||||
|
|
||||||
|
logic [$clog2(PACK_FACTOR):0] cnt;
|
||||||
|
|
||||||
always_ff @(posedge clk_in) begin
|
generate
|
||||||
if (rst) begin
|
if (PACK_FACTOR == 1) begin
|
||||||
m_axis_tdata <= '0;
|
always @(posedge clk_in) begin
|
||||||
m_axis_tvalid <= 0;
|
if (rst) begin
|
||||||
cnt_smp_num <= '0;
|
buffer <= '0;
|
||||||
smp_num_reg <= '0;
|
buffer_ready <= 0;
|
||||||
pack_cnt <= '0;
|
cnt_smp_num <= '0;
|
||||||
synced <= 0;
|
smp_num_reg <= '0;
|
||||||
done <= 0;
|
enable <= '0;
|
||||||
end else begin
|
sample_done <= 0;
|
||||||
if (!synced) begin
|
end
|
||||||
if (done && request) begin
|
else begin
|
||||||
synced <= 1;
|
buffer_ready <= 0;
|
||||||
done <= 0;
|
if (sample_done && !sample_req) begin
|
||||||
|
sample_done <= 1'b0;
|
||||||
|
end
|
||||||
|
if (!enable && sample_req && !sample_done) begin
|
||||||
|
enable <= 1;
|
||||||
cnt_smp_num <= 0;
|
cnt_smp_num <= 0;
|
||||||
smp_num_reg <= smp_num;
|
smp_num_reg <= smp_num;
|
||||||
end else begin
|
|
||||||
done <= 1;
|
|
||||||
end
|
end
|
||||||
end else begin
|
if (enable) begin
|
||||||
if (cnt_smp_num != smp_num_reg) begin
|
if (!out_of_range_reg) begin
|
||||||
cnt_smp_num++;
|
if (cnt_smp_num != smp_num_reg) begin
|
||||||
m_axis_tdata[pack_cnt*DATA_WIDTH +: DATA_WIDTH] <= data_converted;
|
buffer <= data_converted;
|
||||||
if (pack_cnt == PACK_FACTOR-1) begin
|
buffer_ready <= 1;
|
||||||
pack_cnt <= 0;
|
cnt_smp_num <= cnt_smp_num +1;
|
||||||
m_axis_tvalid <= 1;
|
end
|
||||||
end else begin
|
else begin
|
||||||
pack_cnt++;
|
cnt_smp_num <= '0;
|
||||||
m_axis_tvalid <= 0;
|
sample_done <= 1'b1;
|
||||||
|
buffer_ready <= 0;
|
||||||
|
buffer <= '0;
|
||||||
|
enable <= 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end else begin
|
|
||||||
pack_cnt <= '0;
|
|
||||||
synced <= 0;
|
|
||||||
m_axis_tvalid <= 0;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end else begin
|
||||||
|
always @(posedge clk_in) begin
|
||||||
|
if (rst) begin
|
||||||
|
buffer <= '0;
|
||||||
|
cnt <= '0; //
|
||||||
|
buffer_ready <= 0;
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
smp_num_reg <= '0;
|
||||||
|
enable <= 0;
|
||||||
|
sample_done <= 0;
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
buffer_ready <= 0;
|
||||||
|
if (sample_done && !sample_req) begin
|
||||||
|
sample_done <= 1'b0;
|
||||||
|
end
|
||||||
|
if (!enable && sample_req && !sample_done) begin
|
||||||
|
enable <= 1;
|
||||||
|
cnt_smp_num <= 0;
|
||||||
|
smp_num_reg <= smp_num;
|
||||||
|
end
|
||||||
|
if (enable) begin
|
||||||
|
if (!out_of_range_reg) begin
|
||||||
|
if (cnt_smp_num != smp_num_reg) begin
|
||||||
|
cnt_smp_num <= cnt_smp_num +1;
|
||||||
|
buffer <= {buffer[DATA_WIDTH*(PACK_FACTOR-1)-1:0], data_converted};
|
||||||
|
if (cnt == PACK_FACTOR-1) begin
|
||||||
|
cnt <= 0;
|
||||||
|
buffer_ready <= 1;
|
||||||
|
buffer <= {buffer[DATA_WIDTH*(PACK_FACTOR-1)-1:0], data_converted};
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
cnt <= cnt + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
sample_done <= 1'b1;
|
||||||
|
cnt_smp_num <= '0;
|
||||||
|
buffer_ready <= 0;
|
||||||
|
buffer <= '0;
|
||||||
|
enable <= 0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
assign m_axis_tdata = buffer;
|
||||||
|
assign m_axis_tvalid = buffer_ready;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# Copyright (c) 2025 FPGA Ninja, LLC
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# - Alex Forencich
|
||||||
|
#
|
||||||
|
|
||||||
|
# FPGA settings
|
||||||
|
FPGA_PART = xc7a35tfgg484-1
|
||||||
|
FPGA_TOP = sampler
|
||||||
|
FPGA_ARCH = artix7
|
||||||
|
|
||||||
|
RTL_DIR = ../src
|
||||||
|
|
||||||
|
|
||||||
|
include ../../../scripts/vivado.mk
|
||||||
|
|
||||||
|
SYN_FILES += $(sort $(shell find ../src -type f \( -name '*.v' -o -name '*.sv' \)))
|
||||||
|
|
||||||
|
XCI_FILES = $(sort $(shell find ../src -type f -name '*.xci'))
|
||||||
|
|
||||||
|
XDC_FILES += ../../../constraints/ax7a035b.xdc
|
||||||
|
|
||||||
|
SYN_FILES += sampler_main_tb.sv
|
||||||
|
SIM_TOP = sampler_tb
|
||||||
|
|
||||||
|
|
||||||
|
program: $(PROJECT).bit
|
||||||
|
echo "open_hw_manager" > program.tcl
|
||||||
|
echo "connect_hw_server" >> program.tcl
|
||||||
|
echo "open_hw_target" >> program.tcl
|
||||||
|
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
|
||||||
|
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
|
||||||
|
echo "set_property PROGRAM.FILE {$(PROJECT).bit} [current_hw_device]" >> program.tcl
|
||||||
|
echo "program_hw_devices [current_hw_device]" >> program.tcl
|
||||||
|
echo "exit" >> program.tcl
|
||||||
|
vivado -nojournal -nolog -mode batch -source program.tcl
|
||||||
|
|
||||||
|
$(PROJECT).mcs $(PROJECT).prm: $(PROJECT).bit
|
||||||
|
echo "write_cfgmem -force -format mcs -size 16 -interface SPIx4 -loadbit {up 0x0000000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
|
||||||
|
echo "exit" >> generate_mcs.tcl
|
||||||
|
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
|
||||||
|
mkdir -p rev
|
||||||
|
COUNT=100; \
|
||||||
|
while [ -e rev/$*_rev$$COUNT.bit ]; \
|
||||||
|
do COUNT=$$((COUNT+1)); done; \
|
||||||
|
COUNT=$$((COUNT-1)); \
|
||||||
|
for x in .mcs .prm; \
|
||||||
|
do cp $*$$x rev/$*_rev$$COUNT$$x; \
|
||||||
|
echo "Output: rev/$*_rev$$COUNT$$x"; done;
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
|
module sampler_tb;
|
||||||
|
|
||||||
|
parameter DATA_WIDTH = 12;
|
||||||
|
parameter PROCESS_MODE = 0;
|
||||||
|
parameter CLK_PERIOD = 15.3846;
|
||||||
|
parameter TEST_NUM = 1000;
|
||||||
|
|
||||||
|
logic clk;
|
||||||
|
logic rst;
|
||||||
|
|
||||||
|
logic [DATA_WIDTH-1:0] data_in;
|
||||||
|
logic out_of_range;
|
||||||
|
|
||||||
|
logic [DATA_WIDTH-1:0] m_axis_tdata;
|
||||||
|
logic m_axis_tvalid;
|
||||||
|
|
||||||
|
integer errors = 0;
|
||||||
|
|
||||||
|
sampler #(
|
||||||
|
.DATA_WIDTH(DATA_WIDTH),
|
||||||
|
.PROCESS_MODE(PROCESS_MODE)
|
||||||
|
) dut (
|
||||||
|
.clk_in(clk),
|
||||||
|
.rst(rst),
|
||||||
|
.data_in(data_in),
|
||||||
|
.out_of_range(out_of_range),
|
||||||
|
.m_axis_tdata(m_axis_tdata),
|
||||||
|
.m_axis_tvalid(m_axis_tvalid)
|
||||||
|
);
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
clk = 0;
|
||||||
|
forever #(CLK_PERIOD/2) clk = ~clk;
|
||||||
|
end
|
||||||
|
|
||||||
|
function automatic [DATA_WIDTH-1:0] ref_convert(input [DATA_WIDTH-1:0] din);
|
||||||
|
if (PROCESS_MODE == 0)
|
||||||
|
return din;
|
||||||
|
else if (din == {1'b1, {(DATA_WIDTH-1){1'b0}}})
|
||||||
|
return din;
|
||||||
|
else
|
||||||
|
return din[DATA_WIDTH-1] ?
|
||||||
|
{1'b1, (~din[DATA_WIDTH-2:0] + 1'b1)} :
|
||||||
|
din;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
task send(input [DATA_WIDTH-1:0] word, input bit oor);
|
||||||
|
@(posedge clk);
|
||||||
|
data_in <= word;
|
||||||
|
out_of_range <= oor;
|
||||||
|
endtask
|
||||||
|
|
||||||
|
logic [DATA_WIDTH-1:0] exp_d0, exp_d1, exp_d2;
|
||||||
|
logic oor_d0, oor_d1, oor_d2;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
$display("\n=== RANDOM SAMPLER TEST===\n");
|
||||||
|
|
||||||
|
rst = 1;
|
||||||
|
data_in = 0;
|
||||||
|
out_of_range = 0;
|
||||||
|
|
||||||
|
exp_d0 = 0;
|
||||||
|
exp_d1 = 0;
|
||||||
|
exp_d2 = 0;
|
||||||
|
|
||||||
|
oor_d0 = 1;
|
||||||
|
oor_d1 = 1;
|
||||||
|
oor_d2 = 1;
|
||||||
|
|
||||||
|
repeat(5) @(posedge clk);
|
||||||
|
rst = 0;
|
||||||
|
repeat(2) @(posedge clk);
|
||||||
|
|
||||||
|
repeat (TEST_NUM) begin
|
||||||
|
logic [DATA_WIDTH-1:0] rand_data;
|
||||||
|
bit rand_oor;
|
||||||
|
|
||||||
|
rand_data = $urandom_range(0, (1 << DATA_WIDTH) - 1);
|
||||||
|
rand_oor = ($urandom_range(0, 99) < 20);
|
||||||
|
|
||||||
|
@(negedge clk);
|
||||||
|
|
||||||
|
if (!oor_d2) begin
|
||||||
|
if (m_axis_tvalid !== 1) begin
|
||||||
|
$display("ERROR: valid=0");
|
||||||
|
errors++;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (m_axis_tdata !== exp_d2) begin
|
||||||
|
$display("ERROR: data mismatch");
|
||||||
|
$display(" expected = %h", exp_d2);
|
||||||
|
$display(" got = %h", m_axis_tdata);
|
||||||
|
errors++;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
send(rand_data, rand_oor);
|
||||||
|
|
||||||
|
exp_d2 = exp_d1;
|
||||||
|
exp_d1 = exp_d0;
|
||||||
|
exp_d0 = ref_convert(rand_data);
|
||||||
|
|
||||||
|
oor_d2 = oor_d1;
|
||||||
|
oor_d1 = oor_d0;
|
||||||
|
oor_d0 = rand_oor;
|
||||||
|
end
|
||||||
|
|
||||||
|
@(posedge clk);
|
||||||
|
|
||||||
|
|
||||||
|
if (!oor_d2) begin
|
||||||
|
|
||||||
|
if (m_axis_tdata !== exp_d2) begin
|
||||||
|
$display("ERROR: final mismatch");
|
||||||
|
$display(" expected = %h", exp_d2);
|
||||||
|
$display(" got = %h", m_axis_tdata);
|
||||||
|
errors++;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (errors == 0)
|
||||||
|
$display("\n========== ALL PASSED ==========\n");
|
||||||
|
else
|
||||||
|
$display("\n========== FAILED: %0d errors ==========\n", errors);
|
||||||
|
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
module sampler_tb #(
|
|
||||||
// Параметры тестбенча
|
|
||||||
parameter int DATA_WIDTH = 12, // bitwidth of sampled data. Equal to ADC bitwidth
|
|
||||||
parameter int PACK_FACTOR = 1, // packing of several numbers in one axi-stream tdata transaction
|
|
||||||
parameter bit PROCESS_MODE = 0, // signed (1) / unsigned (0)
|
|
||||||
parameter real CLK_PERIOD = 15.3846,
|
|
||||||
parameter int OTR_OFFSET = 0 // Out of Range offset number clipping
|
|
||||||
);
|
|
||||||
// Вычислимые константы
|
|
||||||
// Диапазон значений семплера
|
|
||||||
localparam int MIN_VALUE = PROCESS_MODE ? -2**(DATA_WIDTH-1) : 0;
|
|
||||||
localparam int MAX_VALUE = PROCESS_MODE ? 2**(DATA_WIDTH-1)-1 : (2**DATA_WIDTH)-1;
|
|
||||||
|
|
||||||
logic clk;
|
|
||||||
logic rst_dut;
|
|
||||||
logic rst_gen;
|
|
||||||
|
|
||||||
wire [DATA_WIDTH-1:0] data_in;
|
|
||||||
wire out_of_range;
|
|
||||||
|
|
||||||
logic [31:0] smp_num;
|
|
||||||
|
|
||||||
logic done;
|
|
||||||
logic request;
|
|
||||||
|
|
||||||
logic [DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
|
||||||
logic m_axis_tvalid;
|
|
||||||
|
|
||||||
sampler #(
|
|
||||||
.DATA_WIDTH (DATA_WIDTH),
|
|
||||||
.PACK_FACTOR (PACK_FACTOR),
|
|
||||||
.PROCESS_MODE(PROCESS_MODE)
|
|
||||||
) dut (
|
|
||||||
.clk_in (clk),
|
|
||||||
.rst (rst_dut),
|
|
||||||
|
|
||||||
.data_in (data_in),
|
|
||||||
.out_of_range (out_of_range),
|
|
||||||
|
|
||||||
.smp_num (smp_num),
|
|
||||||
.done (done),
|
|
||||||
|
|
||||||
.m_axis_tdata (m_axis_tdata),
|
|
||||||
.m_axis_tvalid(m_axis_tvalid),
|
|
||||||
|
|
||||||
.request (request)
|
|
||||||
);
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// CLOCK
|
|
||||||
// =====================================================
|
|
||||||
initial begin
|
|
||||||
clk = 0;
|
|
||||||
forever #(CLK_PERIOD/2) clk = ~clk;
|
|
||||||
end
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// RESET
|
|
||||||
// =====================================================
|
|
||||||
task automatic reset_dut();
|
|
||||||
@(posedge clk);
|
|
||||||
rst_dut = 1;
|
|
||||||
@(posedge clk);
|
|
||||||
rst_dut = 0;
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// FEED DATA
|
|
||||||
// =====================================================
|
|
||||||
triangle_wave_gen #(
|
|
||||||
.DATA_WIDTH(DATA_WIDTH),
|
|
||||||
.OFFSET(OTR_OFFSET), // offset of bits from '0 and '1 for OTR
|
|
||||||
.STEP(1) // LSB bit per clock
|
|
||||||
) signal_gen (
|
|
||||||
.clk(clk),
|
|
||||||
.rst(rst_gen),
|
|
||||||
.signal(data_in),
|
|
||||||
.otr(out_of_range)
|
|
||||||
);
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// TEST TASKS
|
|
||||||
// =====================================================
|
|
||||||
task automatic run_test_case(
|
|
||||||
input int sample_num
|
|
||||||
);
|
|
||||||
logic [DATA_WIDTH-1:0] input_values[$];
|
|
||||||
logic [DATA_WIDTH-1:0] output_values[$];
|
|
||||||
bit flag;
|
|
||||||
int tmp_input_val, tmp_output_val;
|
|
||||||
|
|
||||||
// Startup sequence
|
|
||||||
rst_gen <= 1;
|
|
||||||
smp_num <= sample_num;
|
|
||||||
request <= 1;
|
|
||||||
@(posedge clk);
|
|
||||||
|
|
||||||
// syncronize
|
|
||||||
while (!done)
|
|
||||||
@(posedge clk);
|
|
||||||
request <= 0;
|
|
||||||
|
|
||||||
// Wait for sync and start signal generator
|
|
||||||
// while (!dut.synced)
|
|
||||||
// @(posedge clk);
|
|
||||||
wait(dut.synced === 1);
|
|
||||||
rst_gen <= 0;
|
|
||||||
|
|
||||||
// Wait for valid data
|
|
||||||
fork
|
|
||||||
begin : stat_mon_proc
|
|
||||||
forever begin
|
|
||||||
@(posedge clk);
|
|
||||||
input_values.push_back(data_in);
|
|
||||||
if (m_axis_tvalid) begin
|
|
||||||
for (int i = 0; i < PACK_FACTOR; i++)
|
|
||||||
output_values.push_back(m_axis_tdata[DATA_WIDTH*i +: DATA_WIDTH]);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
join_none
|
|
||||||
|
|
||||||
// Wait until end
|
|
||||||
// while (dut.synced)
|
|
||||||
// @(posedge clk);
|
|
||||||
wait(dut.synced === 0);
|
|
||||||
|
|
||||||
disable stat_mon_proc;
|
|
||||||
// Pop last input value. Signal is ahead of tdata for 1 cycle
|
|
||||||
input_values.pop_back();
|
|
||||||
|
|
||||||
// check data length correct
|
|
||||||
if ((input_values.size() - (input_values.size() % PACK_FACTOR)) != output_values.size()) begin
|
|
||||||
$display("[ERROR] -run_test_case- Input queue size don't equal to output queue size: %0d vs %0d", input_values.size(), output_values.size());
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
flag = 0;
|
|
||||||
for (int i = 0; i < output_values.size(); i++) begin
|
|
||||||
// clip value for OTR
|
|
||||||
tmp_input_val = int'(input_values[i]) + MIN_VALUE;
|
|
||||||
tmp_output_val = PROCESS_MODE ?
|
|
||||||
int'($signed({output_values[i][DATA_WIDTH-1], output_values[i]})) :
|
|
||||||
int'(output_values[i]);
|
|
||||||
|
|
||||||
if ((tmp_input_val < MIN_VALUE + OTR_OFFSET) ||
|
|
||||||
(tmp_input_val > MAX_VALUE - OTR_OFFSET)) begin
|
|
||||||
// need clipping
|
|
||||||
tmp_input_val = ((tmp_input_val - MIN_VALUE) < 2**(DATA_WIDTH-1)) ?
|
|
||||||
MIN_VALUE : MAX_VALUE;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (tmp_input_val != tmp_output_val)
|
|
||||||
flag = 1;
|
|
||||||
end
|
|
||||||
// $display("Total: %0d", output_values.size());
|
|
||||||
if (flag) begin
|
|
||||||
$display("[ERROR] -run_test_case- Sampled data not correct and not equal to generated signal.");
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
endtask
|
|
||||||
|
|
||||||
// =====================================================
|
|
||||||
// MAIN
|
|
||||||
// =====================================================
|
|
||||||
initial begin
|
|
||||||
int random_number;
|
|
||||||
|
|
||||||
$display("\n=== BASIC TEST ===");
|
|
||||||
|
|
||||||
rst_dut = 1;
|
|
||||||
rst_gen = 1;
|
|
||||||
smp_num = 0;
|
|
||||||
repeat(2) @(posedge clk);
|
|
||||||
rst_dut = 0;
|
|
||||||
repeat(2) @(posedge clk);
|
|
||||||
|
|
||||||
$display("basic test #1");
|
|
||||||
run_test_case(10);
|
|
||||||
run_test_case(100);
|
|
||||||
run_test_case(10000);
|
|
||||||
$display("basic test #2");
|
|
||||||
run_test_case(0);
|
|
||||||
|
|
||||||
$display("\n=== RANDOM STRESS TEST ===");
|
|
||||||
for (int i = 0; i < 10; i++) begin
|
|
||||||
$display("Random test #%0d", i);
|
|
||||||
random_number = $urandom_range(0, 3 * 2**(DATA_WIDTH)); // up to 1.5 triangle waves
|
|
||||||
run_test_case(random_number);
|
|
||||||
end
|
|
||||||
|
|
||||||
$display("\n=== TEST FINISHED ===");
|
|
||||||
$finish;
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module triangle_wave_gen #(
|
|
||||||
parameter DATA_WIDTH = 12,
|
|
||||||
parameter OFFSET = 100, // offset of bits from '0 and '1 for OTR
|
|
||||||
parameter STEP = 1 // LSB bit per clock
|
|
||||||
) (
|
|
||||||
input clk,
|
|
||||||
input rst,
|
|
||||||
output logic [DATA_WIDTH-1:0] signal,
|
|
||||||
output logic otr
|
|
||||||
);
|
|
||||||
logic [DATA_WIDTH:0] counter;
|
|
||||||
logic direction;
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
counter = '0;
|
|
||||||
direction = 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
assign signal = counter > (2**DATA_WIDTH-1) ? (2**DATA_WIDTH-1) : counter;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
if (signal < OFFSET || (2**DATA_WIDTH - signal) <= OFFSET)
|
|
||||||
otr <= 1;
|
|
||||||
else
|
|
||||||
otr <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge clk) begin
|
|
||||||
if (rst) begin
|
|
||||||
counter = 0;
|
|
||||||
direction = 1;
|
|
||||||
end else begin
|
|
||||||
if (direction)
|
|
||||||
counter += STEP;
|
|
||||||
else
|
|
||||||
counter -= STEP;
|
|
||||||
|
|
||||||
if (counter >= 2**DATA_WIDTH-1 || counter <= 0)
|
|
||||||
direction <= ~direction;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
|
||||||
###################################################################
|
|
||||||
# Questa/ModelSim simulation helper
|
|
||||||
#
|
|
||||||
# Expected variables from the project Makefile:
|
|
||||||
# SYN_FILES - RTL sources
|
|
||||||
# TB_FILES - testbench sources
|
|
||||||
# INC_FILES - include files, optional
|
|
||||||
# SIM_TOP - simulation top module
|
|
||||||
# SIM_DEFS - defines, optional
|
|
||||||
# SIM_RUNTIME - run time, for example "10000 us" or "-all"
|
|
||||||
#
|
|
||||||
# Useful overrides:
|
|
||||||
# make sim-questa XILINX_VIVADO=/opt/Xilinx/Vivado/2024.2
|
|
||||||
# make sim-questa-gui
|
|
||||||
###################################################################
|
|
||||||
|
|
||||||
.PHONY: sim-questa sim-questa-gui questa-clean questa-xpm-clean
|
|
||||||
|
|
||||||
VLIB ?= vlib
|
|
||||||
VMAP ?= vmap
|
|
||||||
VLOG ?= vlog
|
|
||||||
VSIM ?= vsim
|
|
||||||
|
|
||||||
QUESTA_WORK_LIB ?= work
|
|
||||||
QUESTA_XPM_LIB ?= xpm
|
|
||||||
QUESTA_DIR ?= questa_build
|
|
||||||
QUESTA_TRANSCRIPT ?= transcript
|
|
||||||
XILINX_VIVADO=/tools/Xilinx/2025.1/Vivado
|
|
||||||
SIM_RUNTIME ?= 10000 us
|
|
||||||
QUESTA_RUN ?= run $(SIM_RUNTIME)
|
|
||||||
|
|
||||||
# XPM is needed by this design because accum.sv uses xpm_memory_sdpram and
|
|
||||||
# out_axis_fifo.sv uses xpm_fifo_async. Point XILINX_VIVADO to your Vivado
|
|
||||||
# install if it is not already exported by settings64.sh.
|
|
||||||
QUESTA_USE_XPM ?= 1
|
|
||||||
|
|
||||||
QUESTA_XPM_SRC = \
|
|
||||||
$(XILINX_VIVADO)/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv \
|
|
||||||
$(XILINX_VIVADO)/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv \
|
|
||||||
$(XILINX_VIVADO)/data/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv
|
|
||||||
|
|
||||||
QUESTA_GLBL_SRC = $(XILINX_VIVADO)/data/verilog/src/glbl.v
|
|
||||||
|
|
||||||
QUESTA_DEFS = $(foreach d,$(SIM_DEFS),+define+$(d))
|
|
||||||
QUESTA_INC_DIRS = $(sort $(dir $(SYN_FILES) $(TB_FILES) $(INC_FILES)))
|
|
||||||
QUESTA_INCS = $(foreach d,$(QUESTA_INC_DIRS),+incdir+$(d))
|
|
||||||
QUESTA_LIBS = $(if $(filter 1,$(QUESTA_USE_XPM)),-L $(QUESTA_XPM_LIB),)
|
|
||||||
QUESTA_SOURCES = $(SYN_FILES) $(TB_FILES) $(if $(wildcard $(QUESTA_GLBL_SRC)),$(QUESTA_GLBL_SRC),)
|
|
||||||
|
|
||||||
QUESTA_GLBL_TOP = $(if $(wildcard $(QUESTA_GLBL_SRC)),$(QUESTA_WORK_LIB).glbl,)
|
|
||||||
|
|
||||||
|
|
||||||
$(QUESTA_DIR):
|
|
||||||
mkdir -p $@
|
|
||||||
|
|
||||||
$(QUESTA_DIR)/sources.f: Makefile | $(QUESTA_DIR)
|
|
||||||
@rm -f $@
|
|
||||||
@for inc in $(QUESTA_INCS); do echo $$inc >> $@; done
|
|
||||||
@for src in $(QUESTA_SOURCES); do echo $$src >> $@; done
|
|
||||||
|
|
||||||
$(QUESTA_DIR)/xpm.stamp: | $(QUESTA_DIR)
|
|
||||||
@if [ "$(QUESTA_USE_XPM)" = "1" ]; then \
|
|
||||||
if [ -z "$(XILINX_VIVADO)" ]; then \
|
|
||||||
echo "ERROR: XILINX_VIVADO is not set. Source Vivado settings64.sh or pass XILINX_VIVADO=/path/to/Vivado/<version>."; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
for src in $(QUESTA_XPM_SRC); do \
|
|
||||||
if [ ! -f $$src ]; then \
|
|
||||||
echo "ERROR: XPM source not found: $$src"; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
done; \
|
|
||||||
$(VLIB) $(QUESTA_XPM_LIB); \
|
|
||||||
$(VMAP) $(QUESTA_XPM_LIB) $(QUESTA_XPM_LIB); \
|
|
||||||
$(VLOG) -sv -work $(QUESTA_XPM_LIB) $(QUESTA_XPM_SRC); \
|
|
||||||
fi
|
|
||||||
@touch $@
|
|
||||||
|
|
||||||
$(QUESTA_DIR)/compile.stamp: $(QUESTA_DIR)/sources.f $(SYN_FILES) $(TB_FILES) $(INC_FILES) $(QUESTA_DIR)/xpm.stamp
|
|
||||||
$(VLIB) $(QUESTA_WORK_LIB)
|
|
||||||
$(VMAP) $(QUESTA_WORK_LIB) $(QUESTA_WORK_LIB)
|
|
||||||
$(VLOG) -sv -work $(QUESTA_WORK_LIB) $(QUESTA_DEFS) -timescale 1ns/1ps $(QUESTA_INCS) -f $(QUESTA_DIR)/sources.f
|
|
||||||
@touch $@
|
|
||||||
|
|
||||||
sim-questa: $(QUESTA_DIR)/compile.stamp
|
|
||||||
$(VSIM) -c $(QUESTA_LIBS) $(QUESTA_WORK_LIB).$(SIM_TOP) $(QUESTA_GLBL_TOP) -do "$(QUESTA_RUN); quit -f"
|
|
||||||
|
|
||||||
sim-questa-gui: $(QUESTA_DIR)/compile.stamp
|
|
||||||
$(VSIM) $(QUESTA_LIBS) -voptargs="+acc" $(QUESTA_WORK_LIB).$(SIM_TOP) $(QUESTA_GLBL_TOP)
|
|
||||||
|
|
||||||
questa-clean:
|
|
||||||
-rm -rf $(QUESTA_DIR) $(QUESTA_WORK_LIB) $(QUESTA_TRANSCRIPT) vsim.wlf *.wlf
|
|
||||||
|
|
||||||
questa-xpm-clean: questa-clean
|
|
||||||
-rm -rf $(QUESTA_XPM_LIB)
|
|
||||||
Reference in New Issue
Block a user