eefaf94e9e
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
110 lines
3.3 KiB
Verilog
110 lines
3.3 KiB
Verilog
`timescale 1ns / 1ps
|
|
|
|
// latency_buffer_2159_fixed.v
|
|
module latency_buffer_2159 #(
|
|
parameter DATA_WIDTH = 32,
|
|
parameter LATENCY = 3187
|
|
) (
|
|
input wire clk,
|
|
input wire reset_n,
|
|
input wire [DATA_WIDTH-1:0] data_in,
|
|
input wire valid_in,
|
|
output wire [DATA_WIDTH-1:0] data_out,
|
|
output wire valid_out
|
|
);
|
|
|
|
// ========== FIXED PARAMETERS ==========
|
|
localparam ADDR_WIDTH = 12; // Enough for 4096 entries (>2159)
|
|
|
|
// ========== FIXED LOGIC ==========
|
|
(* ram_style = "block" *) reg [DATA_WIDTH-1:0] bram [0:4095];
|
|
reg [ADDR_WIDTH-1:0] write_ptr;
|
|
reg [ADDR_WIDTH-1:0] read_ptr;
|
|
reg valid_out_reg;
|
|
|
|
// Delay counter to track when LATENCY cycles have passed
|
|
reg [ADDR_WIDTH-1:0] delay_counter;
|
|
reg buffer_has_data; // Flag when buffer has accumulated LATENCY samples
|
|
|
|
// ========== FIXED INITIALIZATION ==========
|
|
integer k;
|
|
initial begin
|
|
for (k = 0; k < 4096; k = k + 1) begin
|
|
bram[k] = {DATA_WIDTH{1'b0}};
|
|
end
|
|
write_ptr = 0;
|
|
read_ptr = 0;
|
|
valid_out_reg = 0;
|
|
delay_counter = 0;
|
|
buffer_has_data = 0;
|
|
end
|
|
|
|
// ========== BRAM WRITE (synchronous only, no async reset) ==========
|
|
// Xilinx Block RAMs do not support asynchronous resets.
|
|
// Separating the BRAM write into its own always block avoids Synth 8-3391.
|
|
// The initial block above handles power-on initialization for FPGA.
|
|
always @(posedge clk) begin
|
|
if (valid_in) begin
|
|
bram[write_ptr] <= data_in;
|
|
end
|
|
end
|
|
|
|
// ========== CONTROL LOGIC (with async reset) ==========
|
|
always @(posedge clk or negedge reset_n) begin
|
|
if (!reset_n) begin
|
|
write_ptr <= 0;
|
|
read_ptr <= 0;
|
|
valid_out_reg <= 0;
|
|
delay_counter <= 0;
|
|
buffer_has_data <= 0;
|
|
end else begin
|
|
// Default: no valid output
|
|
valid_out_reg <= 0;
|
|
|
|
// ===== WRITE SIDE =====
|
|
if (valid_in) begin
|
|
// Increment write pointer (wrap at 4095)
|
|
if (write_ptr == 4095) begin
|
|
write_ptr <= 0;
|
|
end else begin
|
|
write_ptr <= write_ptr + 1;
|
|
end
|
|
|
|
// Count how many samples we've written
|
|
if (delay_counter < LATENCY) begin
|
|
delay_counter <= delay_counter + 1;
|
|
|
|
// When we've written LATENCY samples, buffer is "primed"
|
|
if (delay_counter == LATENCY - 1) begin
|
|
buffer_has_data <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
// ===== READ SIDE =====
|
|
// Only start reading after we have LATENCY samples in buffer
|
|
if (buffer_has_data && valid_in) begin
|
|
// Read pointer follows write pointer with LATENCY delay
|
|
// Calculate: read_ptr = (write_ptr - LATENCY) mod 4096
|
|
|
|
// Handle wrap-around correctly
|
|
if (write_ptr >= LATENCY) begin
|
|
read_ptr <= write_ptr - LATENCY;
|
|
end else begin
|
|
// Wrap around: 4096 + write_ptr - LATENCY
|
|
read_ptr <= 4096 + write_ptr - LATENCY;
|
|
end
|
|
|
|
// Output is valid
|
|
valid_out_reg <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
// ========== OUTPUTS ==========
|
|
assign data_out = bram[read_ptr];
|
|
assign valid_out = valid_out_reg;
|
|
|
|
|
|
|
|
endmodule |