update: new synchronizer + half-baked TB
This commit is contained in:
@ -1,10 +1,3 @@
|
|||||||
# Primary clocks
|
# Primary clocks
|
||||||
create_clock -name eth_clk -period 8.000 [get_ports dac_clk_in]
|
create_clock -name eth_clk -period 8.000 [get_ports dac_clk_in]
|
||||||
create_clock -name acc_clk -period 15.385 [get_ports adc_clk_in]
|
create_clock -name acc_clk -period 15.385 [get_ports adc_clk_in]
|
||||||
|
|
||||||
|
|
||||||
# Asynchronous clock groups
|
|
||||||
|
|
||||||
set_clock_groups -name ASYNC_ETH_ACC -asynchronous \
|
|
||||||
-group [get_clocks eth_clk] \
|
|
||||||
-group [get_clocks acc_clk]
|
|
||||||
@ -2,113 +2,104 @@
|
|||||||
|
|
||||||
module sync_top
|
module sync_top
|
||||||
#(
|
#(
|
||||||
parameter int unsigned DAC_DATA_WIDTH = 14,
|
parameter int unsigned DAC_DATA_WIDTH = 14, // DAC bit-width
|
||||||
parameter int unsigned ADC_DATA_WIDTH = 12,
|
parameter int unsigned ADC_DATA_WIDTH = 12, // ADC bit-width
|
||||||
parameter int unsigned PACK_FACTOR = 1,
|
parameter int unsigned PACK_FACTOR = 1, // number of ADC readings per transaction
|
||||||
parameter int unsigned PROCESS_MODE = 0
|
parameter int unsigned PROCESS_MODE = 0, // representation format of ADC readings (0 - direct code, 1 - 2's completment)
|
||||||
|
parameter int unsigned ZERO_LEVEL = 0
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
input adc_clk_in,
|
input clk_adc,
|
||||||
input adc_rst,
|
input rst_adc,
|
||||||
|
input clk_dac,
|
||||||
input dac_clk_in,
|
input rst_dac,
|
||||||
input dac_rst,
|
input start,
|
||||||
|
input out_of_range,
|
||||||
input dac_start,
|
|
||||||
|
|
||||||
input [31:0] pulse_width,
|
input [31:0] pulse_width,
|
||||||
input [31:0] pulse_period,
|
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, // DAC counter limit
|
||||||
input [31:0] smp_num,
|
input [31:0] smp_num, // ADC counter limit
|
||||||
|
output [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
||||||
output logic [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
|
output m_axis_tvalid
|
||||||
output logic m_axis_tvalid
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// Internal signals
|
// Internal signals
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
|
wire dac_done, dac_request, adc_done, adc_request;
|
||||||
(* MARK_DEBUG="true" *) logic sample_req;
|
wire [DAC_DATA_WIDTH-1:0] dac_signal;
|
||||||
(* MARK_DEBUG="true" *) logic sample_req_sync1;
|
wire [ADC_DATA_WIDTH-1:0] adc_singnal;
|
||||||
(* MARK_DEBUG="true" *) logic sample_req_sync2;
|
generate
|
||||||
(* MARK_DEBUG="true" *) logic sample_req_sync3;
|
if (ADC_DATA_WIDTH > DAC_DATA_WIDTH) begin : g_pad_zeros
|
||||||
|
assign adc_singnal = { {(ADC_DATA_WIDTH - DAC_DATA_WIDTH){1'b0}}, dac_signal };
|
||||||
(* MARK_DEBUG="true" *) logic sample_done;
|
end
|
||||||
(* MARK_DEBUG="true" *) logic sample_done_sync1;
|
else begin : g_truncate
|
||||||
(* MARK_DEBUG="true" *) logic sample_done_sync2;
|
assign adc_singnal = dac_signal[ADC_DATA_WIDTH-1:0];
|
||||||
(* MARK_DEBUG="true" *) logic sample_done_sync3;
|
end
|
||||||
|
endgenerate
|
||||||
(* MARK_DEBUG="true" *) logic pulse;
|
|
||||||
(* MARK_DEBUG="true" *) logic [DAC_DATA_WIDTH-1:0] pulse_height_out;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Simple DAC -> ADC test source
|
|
||||||
//
|
|
||||||
// generator output is directly connected to sampler input
|
|
||||||
// with width truncation:
|
|
||||||
//
|
|
||||||
// pulse_height_out[13:0] -> data_in[11:0]
|
|
||||||
//------------------------------------------------------------
|
|
||||||
(* MARK_DEBUG="true" *) logic [ADC_DATA_WIDTH-1:0] data_in;
|
|
||||||
(* MARK_DEBUG="true" *) logic out_of_range;
|
|
||||||
|
|
||||||
assign data_in = pulse_height_out[ADC_DATA_WIDTH-1:0];
|
|
||||||
assign out_of_range = 1'b0;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// DAC -> ADC CDC
|
// DAC -> ADC CDC
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
always_ff @(posedge adc_clk_in or posedge adc_rst) begin
|
logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
|
||||||
if (adc_rst) begin
|
logic [1:0] sync_DA;
|
||||||
sample_req <= 1'b0;
|
wire dac_done_stretched;
|
||||||
sample_req_sync2 <= 1'b0;
|
|
||||||
sample_req_sync3 <= 1'b0;
|
always_ff @(posedge clk_dac or posedge rst_dac)
|
||||||
end
|
begin
|
||||||
|
if (rst_dac)
|
||||||
|
stretch <= 0;
|
||||||
else begin
|
else begin
|
||||||
sample_req_sync2 <= sample_req_sync1;
|
stretch[0] <= dac_done;
|
||||||
sample_req_sync3 <= sample_req_sync2;
|
stretch[1] <= stretch[0];
|
||||||
sample_req <= sample_req_sync3;
|
stretch[2] <= stretch[1];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
assign dac_done_stretched = |stretch;
|
||||||
|
|
||||||
|
always_ff @(posedge clk_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
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
always_ff @(posedge dac_clk_in or posedge dac_rst) begin
|
logic [1:0] sync_AD;
|
||||||
if (dac_rst) begin
|
|
||||||
sample_done <= 1'b0;
|
always_ff @(posedge clk_dac or posedge rst_dac) begin
|
||||||
sample_done_sync2 <= 1'b0;
|
if (rst_dac)
|
||||||
sample_done_sync3 <= 1'b0;
|
sync_AD <= 0;
|
||||||
end
|
|
||||||
else begin
|
else begin
|
||||||
sample_done_sync2 <= sample_done_sync1;
|
sync_AD[0] <= adc_done;
|
||||||
sample_done_sync3 <= sample_done_sync2;
|
sync_AD[1] <= sync_AD[0];
|
||||||
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_in(dac_clk_in),
|
.clk_dac(clk_dac),
|
||||||
.rst(dac_rst),
|
.rst(rst_dac),
|
||||||
.start(dac_start),
|
.start(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),
|
||||||
.sample_done(sample_done),
|
.request(dac_request),
|
||||||
|
.done(dac_done)
|
||||||
.pulse(pulse),
|
|
||||||
.pulse_height_out(pulse_height_out),
|
|
||||||
.sample_req(sample_req_sync1)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
@ -119,18 +110,15 @@ 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(adc_clk_in),
|
.clk_in(clk_adc),
|
||||||
.rst(adc_rst),
|
.rst(rst_adc),
|
||||||
|
.data_in(adc_singnal),
|
||||||
.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),
|
||||||
.sample_done(sample_done_sync1)
|
.request(adc_request),
|
||||||
|
.done(adc_done)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
@ -2,39 +2,45 @@
|
|||||||
|
|
||||||
module tb_top;
|
module tb_top;
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Параметры
|
||||||
|
//------------------------------------------------------------
|
||||||
localparam DAC_DATA_WIDTH = 14;
|
localparam DAC_DATA_WIDTH = 14;
|
||||||
localparam ADC_DATA_WIDTH = 12;
|
localparam ADC_DATA_WIDTH = 12;
|
||||||
localparam PACK_FACTOR = 1;
|
localparam PACK_FACTOR = 1;
|
||||||
localparam PROCESS_MODE = 0;
|
localparam PROCESS_MODE = 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 CLK_DAC_PERIOD = 8;
|
||||||
|
localparam CLK_ADC_PERIOD = 15.385;
|
||||||
|
|
||||||
|
localparam ZERO_LEVEL = LOGIC_ZERO_LEVEL; // "logic" VS "true"
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// clocks / reset
|
// Тактовые сигналы и сброс
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic adc_clk_in;
|
logic clk_dac;
|
||||||
logic adc_rst;
|
logic rst_dac;
|
||||||
|
logic clk_adc;
|
||||||
logic dac_clk_in;
|
logic rst_adc;
|
||||||
logic dac_rst;
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// control
|
// Управление и конфиг
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic dac_start;
|
logic dac_start;
|
||||||
|
|
||||||
logic [31:0] pulse_width;
|
logic [31:0] pulse_width;
|
||||||
logic [31:0] pulse_period;
|
logic [31:0] pulse_period;
|
||||||
logic [DAC_DATA_WIDTH-1:0] pulse_height;
|
logic [DAC_DATA_WIDTH-1:0] pulse_height;
|
||||||
logic [15:0] pulse_num;
|
logic [15:0] pulse_num;
|
||||||
logic [31:0] smp_num;
|
logic [31:0] smp_num;
|
||||||
|
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// outputs
|
// Входы
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
logic [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
reg out_of_range;
|
||||||
logic m_axis_tvalid;
|
//------------------------------------------------------------
|
||||||
|
// Выходы
|
||||||
integer valid_count;
|
//------------------------------------------------------------
|
||||||
|
wire [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata;
|
||||||
|
wire m_axis_tvalid;
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
// DUT
|
// DUT
|
||||||
//------------------------------------------------------------
|
//------------------------------------------------------------
|
||||||
@ -42,127 +48,260 @@ 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)
|
||||||
) dut (
|
) dut (
|
||||||
.adc_clk_in(adc_clk_in),
|
.clk_adc(clk_adc),
|
||||||
.adc_rst(adc_rst),
|
.clk_dac(clk_dac),
|
||||||
|
.rst_adc(rst_adc),
|
||||||
.dac_clk_in(dac_clk_in),
|
.rst_dac(rst_dac),
|
||||||
.dac_rst(dac_rst),
|
.start(dac_start),
|
||||||
|
|
||||||
.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
|
||||||
adc_clk_in = 1'b0;
|
clk_adc = 0;
|
||||||
forever #5 adc_clk_in = ~adc_clk_in; // 100 MHz
|
forever #(CLK_ADC_PERIOD/2) clk_adc = ~clk_adc;
|
||||||
end
|
end
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// DAC clock
|
|
||||||
//------------------------------------------------------------
|
|
||||||
initial begin
|
initial begin
|
||||||
dac_clk_in = 1'b0;
|
clk_dac = 0;
|
||||||
forever #8 dac_clk_in = ~dac_clk_in; // slower domain
|
forever #(CLK_DAC_PERIOD/2) clk_dac = ~clk_dac;
|
||||||
end
|
end
|
||||||
|
|
||||||
//------------------------------------------------------------
|
// === Таски для тестипрования ===
|
||||||
// monitor output stream
|
// Таска сброса DAC DUT
|
||||||
//------------------------------------------------------------
|
task automatic reset_dut_dac(
|
||||||
always @(posedge adc_clk_in) begin
|
input int rst_duration // сколько тактов держать сброс
|
||||||
if (m_axis_tvalid) begin
|
);
|
||||||
valid_count = valid_count + 1;
|
rst_dac <= 1;
|
||||||
|
repeat(rst_duration) @(posedge clk_dac);
|
||||||
|
rst_dac <= 0;
|
||||||
|
endtask
|
||||||
|
|
||||||
$display("[%0t] VALID: data=%0d",
|
// Таска сброса ADC DUT
|
||||||
$time,
|
task automatic reset_dut_adc(
|
||||||
m_axis_tdata);
|
input int rst_duration // сколько тактов держать сброс
|
||||||
end
|
);
|
||||||
end
|
rst_adc <= 1;
|
||||||
|
repeat(rst_duration) @(posedge clk_adc);
|
||||||
|
rst_adc <= 0;
|
||||||
|
endtask
|
||||||
|
|
||||||
//------------------------------------------------------------
|
// Таска запуска DUT
|
||||||
// test
|
task automatic start_dut(
|
||||||
//------------------------------------------------------------
|
input int start_duration // сколько тактов держать импульс
|
||||||
|
);
|
||||||
|
dac_start <= 1;
|
||||||
|
repeat(start_duration) @(posedge 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 // число сэмплов
|
||||||
|
);
|
||||||
|
// Задаем конфигурационные регистры
|
||||||
|
@(posedge clk_dac);
|
||||||
|
pulse_width <= w;
|
||||||
|
pulse_period <= p;
|
||||||
|
pulse_num <= n;
|
||||||
|
pulse_height <= h;
|
||||||
|
smp_num <= sn;
|
||||||
|
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");
|
||||||
|
|
||||||
adc_rst = 1'b1;
|
// Инициализация
|
||||||
dac_rst = 1'b1;
|
dac_start = 0;
|
||||||
|
|
||||||
dac_start = 1'b0;
|
|
||||||
|
|
||||||
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;
|
||||||
|
fork
|
||||||
|
reset_dut_adc(3);
|
||||||
|
reset_dut_dac(6);
|
||||||
|
join
|
||||||
|
@(posedge clk_dac);
|
||||||
|
@(posedge clk_adc);
|
||||||
|
set_config(
|
||||||
|
.w(50),
|
||||||
|
.p(125),
|
||||||
|
.n(5),
|
||||||
|
.h(1024),
|
||||||
|
.sn(65)
|
||||||
|
);
|
||||||
|
start_dut(1);
|
||||||
|
|
||||||
valid_count = 0;
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// reset
|
|
||||||
//--------------------------------------------------------
|
|
||||||
repeat (10) @(posedge adc_clk_in);
|
|
||||||
repeat (10) @(posedge dac_clk_in);
|
|
||||||
|
|
||||||
adc_rst = 1'b0;
|
|
||||||
dac_rst = 1'b0;
|
|
||||||
|
|
||||||
repeat (5) @(posedge dac_clk_in);
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// config
|
|
||||||
//--------------------------------------------------------
|
|
||||||
pulse_width = 32'd3;
|
|
||||||
pulse_period = 32'd8;
|
|
||||||
pulse_height = 14'd200;
|
|
||||||
pulse_num = 16'd4;
|
|
||||||
smp_num = 32'd8;
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// start
|
|
||||||
//--------------------------------------------------------
|
|
||||||
@(posedge dac_clk_in);
|
|
||||||
dac_start = 1'b1;
|
|
||||||
|
|
||||||
@(posedge dac_clk_in);
|
|
||||||
dac_start = 1'b0;
|
|
||||||
|
|
||||||
$display("==================================");
|
|
||||||
$display("TEST START");
|
|
||||||
$display("==================================");
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// wait
|
|
||||||
//--------------------------------------------------------
|
|
||||||
repeat (600) @(posedge adc_clk_in);
|
|
||||||
|
|
||||||
//--------------------------------------------------------
|
|
||||||
// check
|
|
||||||
//--------------------------------------------------------
|
|
||||||
if (valid_count > 0) begin
|
|
||||||
$display("==================================");
|
|
||||||
$display("TEST PASSED");
|
|
||||||
$display("valid_count = %0d", valid_count);
|
|
||||||
$display("==================================");
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
$display("==================================");
|
|
||||||
$display("TEST FAILED");
|
|
||||||
$display("No valid output detected");
|
|
||||||
$display("==================================");
|
|
||||||
end
|
|
||||||
|
|
||||||
|
$display("[TB] ALL PASSED");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user