ad9248的最高时钟频率65mhz,采用cmos3.3v电压的并行io接口,做成电子模块后一般为双通道adc,有两个对外输出时钟cha_clk与chb_clk,一个并行输入端口,14分辨率的ddr_data,其模块逻辑如下,首先向adc发送一对差分时钟作为cha_clk和chb_clk,然后adc返回给fpga一个双沿数据ddr_data,通过iddr原语进行数据解析并将解析后的数据作为cha_data和chb_data输出,同时处理解析后数据的时钟为user_clk,而差分时钟由ad_clk产生。cha_over和chb_over表示接收到的外部电压是否超过量程+-5v。同时参数代表单极性输出还是双极性输出。
MMCM IP配置如下,需要注意user_clk与ad_clk相位差90

module ad9248_driver#(
parameter UNIPOLAR = 1
)(
input i_ad_clk50m ,
input i_user_clk50m ,
input [13:0] i_ddr_data ,
input i_cha_over ,
input i_chb_over ,
output o_cha_clk ,
output o_chb_clk ,
output reg [13:0] o_cha_data ,
output reg [13:0] o_chb_data
);
assign o_cha_clk = i_ad_clk50m ;
assign o_chb_clk = !i_ad_clk50m;
wire [13:0] w_cha_data ;
wire [13:0] w_chb_data ;
//超量程则将前一刻输出作为有效值
always@(posedge i_user_clk50m) begin
o_cha_data <= w_cha_data;
o_chb_data <= w_chb_data;
end
genvar i;
generate
for(i = 0; i < 14; i = i + 1) begin
IDDR #(
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED" ),
.INIT_Q1 (1'b0 ),
.INIT_Q2 (1'b0 ),
.SRTYPE ("SYNC" )
) IDDR_inst (
.Q1 (w_cha_data[i] ), // 上升沿数据
.Q2 (w_chb_data[i] ), // 下降沿数据
.C (i_ad_clk50m ), // 时钟输入
.CE (1'b1 ), // 时钟使能
.D (i_ddr_data[i] ), // 输入数据
.R (1'b0 ), // 复位(可选)
.S (1'b0 ) // 置位(可选)
);
end
endgenerate
reg [15:0] r_cnt ;
always@(posedge i_user_clk50m) begin
if(r_cnt < 1)
r_cnt <= r_cnt + 1;
else
r_cnt <= 0;
end
reg r_vld ;
always@(posedge i_user_clk50m) begin
if(r_cnt == 1)
r_vld <= 1;
else
r_vld <= 0;
end
ila_0 your_instance_name (
.clk(i_user_clk50m), // input wire clk
.probe0(i_cha_over), // input wire [0:0] probe0
.probe1(i_chb_over), // input wire [0:0] probe1
.probe2(o_cha_data), // input wire [13:0] probe2
.probe3(o_chb_data), // input wire [13:0] probe3
.probe4(r_vld ) // input wire [0:0] probe4
);
endmodule
测试用的顶层文件
module ad_sample(
input i_clk50m ,
input i_rst_n ,
input [13:0] i_ddr_data ,
input i_cha_over ,
input i_chb_over ,
output o_cha_clk ,
output o_chb_clk
);
wire w_ad_clk ;
wire w_usr_clk ;
clk_wiz_0
mmcm(
.clk_out1 (w_ad_clk ),
.clk_out2 (w_usr_clk ),
.resetn (i_rst_n ), // input resetn
.locked (), // output locked
.clk_in1 (i_clk50m )
);
wire [13:0] w_cha_data ;
wire [13:0] w_chb_data ;
ad9248_driver
ad9248_driver_u(
.i_ad_clk50m (w_ad_clk ),
.i_user_clk50m (w_usr_clk ),
.i_ddr_data (i_ddr_data ),
.i_cha_over (i_cha_over ),
.i_chb_over (i_chb_over ),
.o_cha_clk (o_cha_clk ),
.o_chb_clk (o_chb_clk ),
.o_cha_data (w_cha_data ),
.o_chb_data (w_chb_data )
);
endmodule