Files
PLFM_RADAR/9_Firmware/9_2_FPGA/ad9484_interface_400m.v
T
Jason eefaf94e9e Fix 6 RTL files + add xfft_32 stub for successful Vivado synthesis
Resolves all synthesis errors across attempts 3-11, achieving clean
Vivado 2025.2 synthesis on XC7A100T (0 errors, 831 LUTs, 320 FFs, 2 DSPs).

radar_receiver_final.v:
- reg clk_400m -> wire; output reg -> output wire (x4)
- Replace ad9484_lvds_to_cmos_400m with ad9484_interface_400m
- Remove duplicate IBUFDS lvds_to_cmos_400m instantiation
- Remove non-existent ref_i/ref_q port connections on matched filter
- Connect adc_dco_bufg as 400MHz clock source

ad9484_interface_400m.v:
- Add adc_dco_bufg output port with BUFG instance
- Route all internal logic through buffered DCO clock

cic_decimator_4x_enhanced.v:
- Move reset_monitors handling inside else branch (fixes Vivado
  ambiguous clock error in both integrator and comb always blocks)
- Add separate comb_overflow_latched/comb_saturation_detected regs
  to eliminate multi-driven nets between integrator and comb blocks
- Remove standalone always @(posedge reset_monitors) block
- Add output_counter to async reset branch

matched_filter_processing_chain.v:
- Wrap behavioral FFT body (uses $cos/$sin/$rtoi) in ifdef SIMULATION
- Add synthesis stub tying outputs to safe defaults

chirp_memory_loader_param.v:
- Replace hardcoded Windows paths with relative filenames for all
  10 $readmem default parameters

latency_buffer_2159.v:
- Split single always block into separate BRAM write (synchronous
  only) and control logic (with async reset) blocks
- Fixes Vivado Synth 8-3391: BRAM cannot infer with async reset

xfft_32.v (NEW):
- Synthesis stub for Xilinx 32-point FFT IP core
- AXI-Stream interface with pass-through and 1-cycle latency
- Placeholder until real xfft IP is generated
2026-03-15 17:37:59 +02:00

107 lines
3.0 KiB
Verilog

module ad9484_interface_400m (
// ADC Physical Interface (LVDS)
input wire [7:0] adc_d_p, // ADC Data P
input wire [7:0] adc_d_n, // ADC Data N
input wire adc_dco_p, // Data Clock Output P (400MHz)
input wire adc_dco_n, // Data Clock Output N (400MHz)
// System Interface
input wire sys_clk, // 100MHz system clock (for control only)
input wire reset_n,
// Output at 400MHz domain
output wire [7:0] adc_data_400m, // ADC data at 400MHz
output wire adc_data_valid_400m, // Valid at 400MHz
output wire adc_dco_bufg // Buffered 400MHz DCO clock for downstream use
);
// LVDS to single-ended conversion
wire [7:0] adc_data;
wire adc_dco;
// IBUFDS for each data bit
genvar i;
generate
for (i = 0; i < 8; i = i + 1) begin : data_buffers
IBUFDS #(
.DIFF_TERM("TRUE"),
.IOSTANDARD("LVDS_25")
) ibufds_data (
.O(adc_data[i]),
.I(adc_d_p[i]),
.IB(adc_d_n[i])
);
end
endgenerate
// IBUFDS for DCO
IBUFDS #(
.DIFF_TERM("TRUE"),
.IOSTANDARD("LVDS_25")
) ibufds_dco (
.O(adc_dco),
.I(adc_dco_p),
.IB(adc_dco_n)
);
// Global clock buffer for DCO — used as 400MHz clock throughout receiver
wire adc_dco_buffered;
BUFG bufg_dco (
.I(adc_dco),
.O(adc_dco_buffered)
);
assign adc_dco_bufg = adc_dco_buffered;
// IDDR for capturing DDR data
wire [7:0] adc_data_rise; // Data on rising edge
wire [7:0] adc_data_fall; // Data on falling edge
genvar j;
generate
for (j = 0; j < 8; j = j + 1) begin : iddr_gen
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"),
.INIT_Q1(1'b0),
.INIT_Q2(1'b0),
.SRTYPE("SYNC")
) iddr_inst (
.Q1(adc_data_rise[j]), // Rising edge data
.Q2(adc_data_fall[j]), // Falling edge data
.C(adc_dco_buffered), // 400MHz DCO (buffered)
.CE(1'b1),
.D(adc_data[j]),
.R(1'b0),
.S(1'b0)
);
end
endgenerate
// Combine rising and falling edge data to get 400MSPS stream
reg [7:0] adc_data_400m_reg;
reg adc_data_valid_400m_reg;
reg dco_phase;
always @(posedge adc_dco_buffered or negedge reset_n) begin
if (!reset_n) begin
adc_data_400m_reg <= 8'b0;
adc_data_valid_400m_reg <= 1'b0;
dco_phase <= 1'b0;
end else begin
dco_phase <= ~dco_phase;
if (dco_phase) begin
// Output falling edge data (completes the 400MSPS stream)
adc_data_400m_reg <= adc_data_fall;
end else begin
// Output rising edge data
adc_data_400m_reg <= adc_data_rise;
end
adc_data_valid_400m_reg <= 1'b1; // Always valid when ADC is running
end
end
assign adc_data_400m = adc_data_400m_reg;
assign adc_data_valid_400m = adc_data_valid_400m_reg;
endmodule