AD4134 Verilog驱动
`timescale 1ns / 1ps
module ad4134 (
// Physical Interface
input wire ADC_DCLK_I, // ADC Clock Input
input wire ADC_ODR_I, // ADC Output Data Rate input
input wire [ 3:0] ADC_DOUT_I, // ADC Data Output
// User Interface
input wire sys_clk_200mhz, // System Clock
input wire sys_rst_n, // System Reset (active low)
output wire [23:0] adc_data0, // Channel 0 Data Output
output wire [23:0] adc_data1, // Channel 1 Data Output
output wire [23:0] adc_data2, // Channel 2 Data Output
output wire [23:0] adc_data3, // Channel 3 Data Output
output reg adc_data_vld // Data Valid Output
);
// Internal Signals
reg [23:0] temp_data[3:0]; // Temporary storage for each channel data
reg [23:0]
adc_data0_reg1,
adc_data1_reg1,
adc_data2_reg1,
adc_data3_reg1; // The purpose of the two-stage delay of the multi bit signal here is to synchronize with the effective signal, rather than weaken the metastable state
reg [23:0]
adc_data0_reg2,
adc_data1_reg2,
adc_data2_reg2,
adc_data3_reg2; // The purpose of the two-stage delay of the multi bit signal here is to synchronize with the effective signal, rather than weaken the metastable state
assign adc_data0 = adc_data0_reg2;
assign adc_data1 = adc_data1_reg2;
assign adc_data2 = adc_data2_reg2;
assign adc_data3 = adc_data3_reg2;
wire adc_clk; // Buffer for ADC Clock
wire adc_odr; // Buffer for ADC ODR
// Buffering ADC Clock and ODR
BUFG BUFG_ADC_CLK (
.I(ADC_DCLK_I),
.O(adc_clk)
);
BUFG BUFG_ADC_ODR (
.I(ADC_ODR_I),
.O(adc_odr)
);
// Initialization and Reset Logic
always @(posedge adc_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
// Reset all registers to initial values
adc_data_vld <= 1'b0;
temp_data[0] <= 24'b0;
temp_data[1] <= 24'b0;
temp_data[2] <= 24'b0;
temp_data[3] <= 24'b0;
end else begin
// Shift in data on DCLK rising edge
temp_data[0] <= {temp_data[0][22:0], ADC_DOUT_I[0]};
temp_data[1] <= {temp_data[1][22:0], ADC_DOUT_I[1]};
temp_data[2] <= {temp_data[2][22:0], ADC_DOUT_I[2]};
temp_data[3] <= {temp_data[3][22:0], ADC_DOUT_I[3]};
end
end
// Two-stage synchronization for adc_odr signal
reg adc_odr_sync1;
reg adc_odr_sync2;
always @(posedge sys_clk_200mhz or negedge sys_rst_n) begin
if (!sys_rst_n) begin
adc_odr_sync1 <= 1'b0;
adc_odr_sync2 <= 1'b0;
end else begin
adc_odr_sync1 <= adc_odr; // First stage synchronization
adc_odr_sync2 <= adc_odr_sync1; // Second stage synchronization
end
end
// Output Logic on ODR Rising Edge
always @(posedge sys_clk_200mhz) begin
if (adc_odr_sync1 != adc_odr_sync2 && adc_odr_sync2 == 1'b0) begin
adc_data_vld <= 1'b1; // Set data valid signal
end else begin
adc_data_vld <= 1'b0;
end
end
always @(posedge sys_clk_200mhz) begin // The purpose of the two-stage delay of the multi bit signal here is to synchronize with the effective signal, rather than weaken the metastable state
adc_data0_reg1 <= temp_data[0];
adc_data1_reg1 <= temp_data[1];
adc_data2_reg1 <= temp_data[2];
adc_data3_reg1 <= temp_data[3];
adc_data0_reg2 <= adc_data0_reg1;
adc_data1_reg2 <= adc_data1_reg1;
adc_data2_reg2 <= adc_data2_reg1;
adc_data3_reg2 <= adc_data3_reg1;
end
endmodule

仿真文件:
`timescale 1ns / 1ps
module tb_ad4134;
// Testbench Signals
reg ADC_DCLK_I; // ADC Clock Input
reg ADC_ODR_I; // ADC Output Data Rate Input
reg [ 3:0] ADC_DOUT_I; // ADC Data Output
reg sys_clk_200mhz; // System Clock
reg sys_rst_n;
wire [23:0] adc_data0; // Channel 0 Data Output
wire [23:0] adc_data1; // Channel 1 Data Output
wire [23:0] adc_data2; // Channel 2 Data Output
wire [23:0] adc_data3; // Channel 3 Data Output
wire adc_data_vld; // Data Valid Output
// Instantiate the Device Under Test (DUT)
ad4134 dut (
.ADC_DCLK_I(ADC_DCLK_I),
.ADC_ODR_I(ADC_ODR_I),
.ADC_DOUT_I(ADC_DOUT_I),
.sys_clk_200mhz(sys_clk_200mhz),
.sys_rst_n(sys_rst_n),
.adc_data0(adc_data0),
.adc_data1(adc_data1),
.adc_data2(adc_data2),
.adc_data3(adc_data3),
.adc_data_vld(adc_data_vld)
);
// Clock Generation for System Clock (200 MHz)
initial begin
sys_clk_200mhz = 0;
forever #2.5 sys_clk_200mhz = ~sys_clk_200mhz; // 200 MHz
end
initial begin
sys_rst_n = 1'b0;
#5;
sys_rst_n = 1'b1;
end
parameter DCLK_PERIOD = 10.416666666667; // 1000/48/2,half period
// DCLK Generation and Data Simulation
initial begin
// Initialize signals
ADC_DCLK_I = 0;
ADC_ODR_I = 0;
ADC_DOUT_I = 4'b0;
// Simulation process
#5;
repeat (1000000) generate_data;
end
task generate_data; // Master Mode
integer i;
reg [23:0] expected_data[0:3]; // To store expected data
// Generate expected data
expected_data[0] = $urandom_range(0, 24'hFFFFFF);
expected_data[1] = $urandom_range(0, 24'hFFFFFF);
expected_data[2] = $urandom_range(0, 24'hFFFFFF);
expected_data[3] = $urandom_range(0, 24'hFFFFFF);
ADC_ODR_I = 1;
repeat (6) #DCLK_PERIOD; // t1 ODR high time
ADC_ODR_I = 0;
repeat (2) #DCLK_PERIOD; // t3 ODR falling edge to DCLK rising edge
for (i = 23; i >= 0; i = i - 1) begin
ADC_DCLK_I = 1;
ADC_DOUT_I[0] = expected_data[0][i];
ADC_DOUT_I[1] = expected_data[1][i];
ADC_DOUT_I[2] = expected_data[2][i];
ADC_DOUT_I[3] = expected_data[3][i];
#DCLK_PERIOD;
ADC_DCLK_I = 0;
#DCLK_PERIOD;
end
repeat (4) #DCLK_PERIOD; // t4 Last data DCLK falling edge to ODR rising edge
// Check for mismatches and throw exceptions
if (adc_data0 !== expected_data[0]) begin
$display("Mismatch on Channel 0: Expected %h, Got %h", expected_data[0], adc_data0);
$fatal("Error: Mismatch on Channel 0!");
end
if (adc_data1 !== expected_data[1]) begin
$display("Mismatch on Channel 1: Expected %h, Got %h", expected_data[1], adc_data1);
$fatal("Error: Mismatch on Channel 1!");
end
if (adc_data2 !== expected_data[2]) begin
$display("Mismatch on Channel 2: Expected %h, Got %h", expected_data[2], adc_data2);
$fatal("Error: Mismatch on Channel 2!");
end
if (adc_data3 !== expected_data[3]) begin
$display("Mismatch on Channel 3: Expected %h, Got %h", expected_data[3], adc_data3);
$fatal("Error: Mismatch on Channel 3!");
end
endtask
endmodule


