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