Files
reflectometer_fpga_project/designs/adc_dac_synchoronizer/sync_top.sv

157 lines
5.6 KiB
Systemverilog
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

`timescale 1ns / 1ps
module sync_top
#(
parameter int unsigned DAC_DATA_WIDTH = 14, // DAC bit-width
parameter int unsigned ADC_DATA_WIDTH = 12, // ADC bit-width
parameter int unsigned PACK_FACTOR = 1, // number of ADC readings per transaction
parameter int unsigned PROCESS_MODE = 0, // representation format of ADC readings (0 - direct code, 1 - 2's completment)
parameter int unsigned ZERO_LEVEL = 0,
parameter int unsigned USE_DELAY_LINE = 0
)
(
input clk_adc,
input rst_adc,
input clk_dac,
input rst_dac,
input start,
input out_of_range,
input [31:0] pulse_width,
input [31:0] pulse_period, // DAC counter limit
input [DAC_DATA_WIDTH-1:0] pulse_height,
input [15:0] pulse_num,
input [31:0] smp_num, // ADC counter limit
output [ADC_DATA_WIDTH*PACK_FACTOR-1:0] m_axis_tdata,
output m_axis_tvalid
);
//------------------------------------------------------------
// 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. Адаптация разрядности и «заземление» лишних бит
generate
if (ADC_DATA_WIDTH > DAC_DATA_WIDTH) begin : g_pad_zeros
// АЦП шире ЦАП: добиваем нулями старшие биты
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
if (USE_DELAY_LINE > 0) begin : g_delay_line
localparam int DELAY_LENGTH = USE_DELAY_LINE;
// Двумерный массив для линии задержки
logic [DELAY_LENGTH-1:0][ADC_DATA_WIDTH-1:0] signal_delay_line;
always_ff @(posedge clk_dac) begin
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];
end
end
// ИСПРАВЛЕНО: читаем из последнего элемента массива
assign adc_signal = signal_delay_line[DELAY_LENGTH-1];
end
else begin : g_no_delay
assign adc_signal = internal_wire_signal;
end
endgenerate
//------------------------------------------------------------
// DAC -> ADC CDC
//------------------------------------------------------------
logic [2:0] stretch; // 125/65~=2. Чтобы поймать единичный импульс, растянем его во времени
logic [1:0] sync_DA;
wire dac_done_stretched;
always_ff @(posedge clk_dac or posedge rst_dac)
begin
if (rst_dac)
stretch <= 0;
else begin
stretch[0] <= dac_done;
stretch[1] <= stretch[0];
stretch[2] <= stretch[1];
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
//------------------------------------------------------------
logic [1:0] sync_AD;
always_ff @(posedge clk_dac or posedge rst_dac) begin
if (rst_dac)
sync_AD <= 0;
else begin
sync_AD[0] <= adc_done;
sync_AD[1] <= sync_AD[0];
end
end
assign dac_request = sync_AD[1];
//------------------------------------------------------------
// Generator
//------------------------------------------------------------
generator #(
.DATA_WIDTH(DAC_DATA_WIDTH),
.ZERO_LEVEL(ZERO_LEVEL)
) generator_inst (
.clk_dac(clk_dac),
.rst(rst_dac),
.start(start),
.pulse_width(pulse_width),
.pulse_period(pulse_period),
.pulse_height(pulse_height),
.pulse_num(pulse_num),
.dac_out(dac_signal),
.request(dac_request),
.done(dac_done)
);
//------------------------------------------------------------
// Sampler
//------------------------------------------------------------
sampler #(
.DATA_WIDTH(ADC_DATA_WIDTH),
.PACK_FACTOR(PACK_FACTOR),
.PROCESS_MODE(PROCESS_MODE)
) sampler_inst (
.clk_in(clk_adc),
.rst(rst_adc),
.data_in(adc_signal),
.out_of_range(out_of_range),
.smp_num(smp_num),
.m_axis_tdata(m_axis_tdata),
.m_axis_tvalid(m_axis_tvalid),
.request(adc_request),
.done(adc_done)
);
endmodule