<!– SPDX-FileCopyrightText: 2026 Ahmed Imamović SPDX-FileCopyrightText: 2026 Tarik Hamedović SPDX-License-Identifier: CC-BY-SA-4.0 –>
ADC
The ADC interface is the entry point of the sampled signal path. It captures incoming converter data and presents it in the internal format used by the rest of the design.
adc/adc.v
This module is the board-facing ADC wrapper. It forwards the sampling clock to two ADC channels and captures incoming parallel data using DDR input registers. In the current implementation, only the rising-edge samples are propagated to the internal datapath.
Responsibilities
The block performs three main tasks:
forwards
sys_clkto the external ADC channels asadc_clk_ch0andadc_clk_ch1,captures DDR input data from
adc_data_ch0andadc_data_ch1using vendorIDDRprimitives,outputs the rising-edge samples on
ad_data_ch0andad_data_ch1.
Interface summary
System signals:
sys_clk– system clock used for ADC clock forwarding and input capture,rst_n– active-low reset input, currently unused by the implementation.
ADC-side signals:
adc_clk_ch0– forwarded ADC clock for channel 0,adc_clk_ch1– forwarded ADC clock for channel 1,adc_data_ch0[11:0]– 12-bit ADC data bus for channel 0,adc_data_ch1[11:0]– 12-bit ADC data bus for channel 1,ad_data_ch0[11:0]– captured output data for channel 0,ad_data_ch1[11:0]– captured output data for channel 1.
Implementation notes
Each ADC input bit is connected to an IDDR primitive configured with
DDR_CLK_EDGE = "SAME_EDGE_PIPELINED". This produces two sampled values:
Q1– rising-edge sampled data,Q2– falling-edge sampled data.
Although both rising-edge and falling-edge samples are captured internally, the current module exports only the rising-edge values:
assign ad_data_ch0 = adc0_rising;
assign ad_data_ch1 = adc1_rising;
The forwarded ADC clocks are generated using ODDR primitives configured to
emit a 50% duty-cycle clock derived from sys_clk.
RTL source
// SPDX-FileCopyrightText: 2026 Ahmed Imamovic Tarik Hamedovic
// SPDX-License-Identifier: CC-BY-SA-4.0
`timescale 1ns/1ps
`default_nettype none
module adc(
// sys
input wire sys_clk, // system clock
input wire rst_n, // active-low reset (unused here)
// ADC
output wire adc_clk_ch0, // AD channel 0 sampling clock
output wire adc_clk_ch1, // AD channel 1 sampling clock
input wire [11:0] adc_data_ch0, // AD channel 0 data
input wire [11:0] adc_data_ch1, // AD channel 1 data
output wire [11:0] ad_data_ch0, // single-edge (rising) captured data
output wire [11:0] ad_data_ch1
);
wire [11:0] adc0_rising, adc0_falling;
wire [11:0] adc1_rising, adc1_falling;
genvar i;
generate
for (i = 0; i < 12; i = i + 1) begin : gen_iddr_ch0
IDDR #(
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0)
) iddr_ch0_i (
.Q1 (adc0_rising[i]),
.Q2 (adc0_falling[i]),
.C (sys_clk),
.CE (1'b1),
.D (adc_data_ch0[i]),
.R (1'b0),
.S (1'b0)
);
end
for (i = 0; i < 12; i = i + 1) begin : gen_iddr_ch1
IDDR #(
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0)
) iddr_ch1_i (
.Q1 (adc1_rising[i]),
.Q2 (adc1_falling[i]),
.C (sys_clk),
.CE (1'b1),
.D (adc_data_ch1[i]),
.R (1'b0),
.S (1'b0)
);
end
endgenerate
// Generate forwarded ADC clocks (50% duty) from sys_clk
ODDR #(.DDR_CLK_EDGE("SAME_EDGE")) ODDR_clk_ch0 (
.Q (adc_clk_ch0), .C(sys_clk), .CE(1'b1),
.D1(1'b1), .D2(1'b0), .R(1'b0), .S(1'b0)
);
ODDR #(.DDR_CLK_EDGE("SAME_EDGE")) ODDR_clk_ch1 (
.Q (adc_clk_ch1), .C(sys_clk), .CE(1'b1),
.D1(1'b1), .D2(1'b0), .R(1'b0), .S(1'b0)
);
// Choose rising-edge samples (or combine rising/falling if desired)
assign ad_data_ch0 = adc0_rising;
assign ad_data_ch1 = adc1_rising;
endmodule
`default_nettype wire