平台:Vivado2018
官方相关文档,ug471_7Series_SelectIO.pdf
关于IDDR与ODDR
Input DDR Resource(IDDR)
外部的数据在时钟的上下沿同时传输数据,我们可以使用IDDR原语将输入的单bit数据转化为2bit的数据输出。同时数据速率变为原来的二分之一。
端口介绍
Q1,Q2 | 数据输出 |
C | 时钟输入 |
CE | 时钟使能 |
D | 数据输入(DDR) |
S/R | 同步、异步和复位引脚 |
IDDR属性
DDR_CLK_EDGE | 设置相对于时钟边沿的 IDDR 工作模式,拥有OPPOSITE_EDGE (default), SAME_EDGE, SAME_EDGE_PIPELINED三种模式 |
INIT_Q1、INIT_Q2 | 设置Q1、Q2初始值 |
SRTYPE | 相对于时钟 (C) 的设置/复位类型 |
模式介绍
OPPOSITE_EDGE Mode模式
通过时钟上升沿输出Q1下降沿输出Q2。
SAME_EDGE模式
数据呈现到同一时钟边沿上的FPGA逻辑中。先输出D0A,在输出一对D1A和D2A。
SAME_EDGE_PIPELINED模式
数据呈现到相同时钟边沿的FPGA逻辑中。与SAME_EDGE模式不同的是,数据在第二个时钟周期输出一对数据。
Output DDR Overview (ODDR)
与IDDR相反的是,ODDR将内部的2bit数据,转换为单bit数据输出。数据速率变为原来的二倍。
端口介绍
Q | 数据输出(DDR) |
C | 时钟输入 |
CE | 时钟使能 |
D | 数据输入 |
S/R | 同步、异步和复位引脚 |
ODDR属性
DDR_CLK_EDGE | 设置相对于时钟边沿的 ODDR 工作模式,拥有O OPPOSITE_EDGE (default), SAME_EDGE两种模式 |
INIT | 设置 Q 端口的初始值 |
SRTYPE | 相对于时钟 (C) 的设置/复位类型 |
模式介绍
OPPOSITE_EDGE Mode
时钟的两个边沿 (CLK) 都用于以两倍的吞吐量从 FPGA 逻辑捕获数据。
SAME_EDGE Mode
数据可以呈现给同一时钟边沿。
参考代码IDDR
// *********************************************************************************/
// Project Name :
// Author : i_huyi
// Email : i_huyi@qq.com
// Creat Time : 2024/3/27 11:27:39
// File Name : .v
// Module Name :
// Called By :
// Abstract :
//
// CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
// All Rights Reserved
//
// *********************************************************************************/
// Modification History:
// 1. initial
// *********************************************************************************/
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module adc_interface_iob_dly#(
parameter U_DLY = 1)(
//
input wire adc_data_n ,
input wire adc_data_p ,
output wire adc_data_rise ,
output wire adc_data_fall ,
output wire data_lvds_out ,
//system
input wire adc_clock ,
input wire adc_reset );
//--------------------------------------
// localparam
//--------------------------------------//--------------------------------------
// register
//--------------------------------------//--------------------------------------
// wire
//--------------------------------------//--------------------------------------
// assign
//--------------------------------------//------------------------------------------------------------
//------------------------------------------------------------
IBUFDS #(.DIFF_TERM ("TRUE" ),// Differential Termination.IBUF_LOW_PWR ("FALSE" ),// Low power="TRUE", Highest performance="FALSE" .IOSTANDARD ("LVDS" )// Specify the input I/O standard
) IBUFDS_inst (.O (data_lvds_out ),// Buffer output.I (adc_data_p ),// Diff_p buffer input (connect directly to top-level port).IB (adc_data_n )// Diff_n buffer input (connect directly to top-level port)
);
//------------------------------------------------------------
//------------------------------------------------------------
IDDR #(.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED" ),// "OPPOSITE_EDGE", "SAME_EDGE"// or "SAME_EDGE_PIPELINED".INIT_Q1 (1'b0 ),// Initial value of Q1: 1'b0 or 1'b1.INIT_Q2 (1'b0 ),// Initial value of Q2: 1'b0 or 1'b1.SRTYPE ("SYNC" )// Set/Reset type: "SYNC" or "ASYNC")
IDDR_i(.Q1 (adc_data_rise ),// 1-bit output for positive edge of clock.Q2 (adc_data_fall ),// 1-bit output for negative edge of clock.C (adc_clock ),// 1-bit clock input.CE (1'b1 ),// 1-bit clock enable input.D (data_lvds_out ),// 1-bit DDR data input.R (adc_reset ),// 1-bit reset.S (1'b0 )// 1-bit set);
//------------------------------------------------------------
//------------------------------------------------------------
endmodule
参考代码ODDR
// *********************************************************************************/
// Project Name :
// Author : i_huyi
// Email : i_huyi@qq.com
// Creat Time : 2024/3/27 11:40:24
// File Name : .v
// Module Name :
// Called By :
// Abstract :
//
// CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
// All Rights Reserved
//
// *********************************************************************************/
// Modification History:
// 1. initial
// *********************************************************************************/
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module adc_interface_out#(
parameter U_DLY = 1)(
//
input wire adc_data_n ,
input wire adc_data_p ,
output wire adc_dq_p ,
output wire adc_dq_n ,
//system
input wire adc_clock ,
input wire adc_reset );
//--------------------------------------
// localparam
//--------------------------------------//--------------------------------------
// register
//--------------------------------------//--------------------------------------
// wire
//--------------------------------------
wire Q ;
//--------------------------------------
// assign
//--------------------------------------
OBUFDS #(.IOSTANDARD ("LVDS18" ),// Specify the output I/O standard.SLEW ("SLOW" )// Specify the output slew rate) OBUFDS_inst (.O (adc_dq_p ),// Diff_p output (connect directly to top-level port).OB (adc_dq_n ),// Diff_n output (connect directly to top-level port).I (Q )// Buffer input );//------------------------------------------------------------
//------------------------------------------------------------
ODDR #(.DDR_CLK_EDGE ("SAME_EDGE" ),// "OPPOSITE_EDGE" or "SAME_EDGE" .INIT (1'b0 ),// Initial value of Q: 1'b0 or 1'b1.SRTYPE ("SYNC" )// Set/Reset type: "SYNC" or "ASYNC"
) ODDR_inst (.Q (Q ),// 1-bit DDR output.C (adc_clock ),// 1-bit clock input.CE (1'b1 ),// 1-bit clock enable input.D1 (adc_data_p ),// 1-bit data input (positive edge).D2 (adc_data_n ),// 1-bit data input (negative edge).R (adc_reset ),// 1-bit reset.S (1'b0 )// 1-bit set
);
//------------------------------------------------------------
//------------------------------------------------------------//------------------------------------------------------------
//------------------------------------------------------------
endmodule
仿真tb
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2024/03/27 10:25:26
// Design Name:
// Module Name: vtf_adc_interface_iob_dly
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module vtf_adc_interface_iob_dly;reg adc_clock ;
reg adc_reset ;
wire [11:0] ADC_A_I_P ;
wire [11:0] ADC_A_I_N ;
wire [11:0] ADC_A_I_r ;
wire [11:0] ADC_A_I_f ;
reg data_clk ;wire [11:0] adc_dq_p ;
wire [11:0] adc_dq_n ;//-----------------------------------------------------------
//-----------------------------------------------------------
parameter WIDTH = 12;
//-----------------------------------------------------------
//-----------------------------------------------------------genvar i;generatefor (i = 0; i<=(WIDTH-1); i = i +1) begin : adc_ch_diadc_interface_iob_dly u_iddr(.adc_clock ( adc_clock ),.adc_reset ( adc_reset ),.adc_data_n ( ADC_A_I_N[i] ),.adc_data_p ( ADC_A_I_P[i] ),.adc_data_rise ( ADC_A_I_r[i] ),.adc_data_fall ( ADC_A_I_f[i] ));endendgenerate genvar j;generatefor (j = 0; j<=(WIDTH-1); j = j +1) begin : adc_ch_doadc_interface_out u_oddr(.adc_data_n (ADC_A_I_f[j] ),.adc_data_p (ADC_A_I_r[j] ),.adc_dq_p (adc_dq_p[j] ),.adc_dq_n (adc_dq_n[j] ),.adc_clock (adc_clock ),.adc_reset (adc_reset ));endendgenerate
//-----------------------------------------------------------
//-----------------------------------------------------------
initial
beginadc_clock =0;adc_reset =1;data_clk =0;#100;adc_reset =0;
endreg [11:0] data_cnt;always@(posedge data_clk or posedge adc_reset)
beginif(adc_reset == 1'b1)begindata_cnt <= 12'h0;endelse begindata_cnt <= data_cnt + 11'h1;end
end//-----------------------------------------------------------
//-----------------------------------------------------------
//产生数据
assign ADC_A_I_P[0] = data_cnt[0];
assign ADC_A_I_P[1] = data_cnt[1];
assign ADC_A_I_P[2] = data_cnt[2];
assign ADC_A_I_P[3] = data_cnt[3];
assign ADC_A_I_P[4] = data_cnt[4];
assign ADC_A_I_P[5] = data_cnt[5];
assign ADC_A_I_P[6] = data_cnt[6];
assign ADC_A_I_P[7] = data_cnt[7];
assign ADC_A_I_P[8] = data_cnt[8];
assign ADC_A_I_P[9] = data_cnt[9];
assign ADC_A_I_P[10] = data_cnt[10];
assign ADC_A_I_P[11] = data_cnt[11];
assign ADC_A_I_N[0] =~ADC_A_I_P[0];
assign ADC_A_I_N[1] =~ADC_A_I_P[1];
assign ADC_A_I_N[2] =~ADC_A_I_P[2];
assign ADC_A_I_N[3] =~ADC_A_I_P[3];
assign ADC_A_I_N[4] =~ADC_A_I_P[4];
assign ADC_A_I_N[5] =~ADC_A_I_P[5];
assign ADC_A_I_N[6] =~ADC_A_I_P[6];
assign ADC_A_I_N[7] =~ADC_A_I_P[7];
assign ADC_A_I_N[8] =~ADC_A_I_P[8];
assign ADC_A_I_N[9] =~ADC_A_I_P[9];
assign ADC_A_I_N[10] =~ADC_A_I_P[10];
assign ADC_A_I_N[11] =~ADC_A_I_P[11];//时钟
always #2 adc_clock = ~adc_clock;
always #1 data_clk = ~data_clk;endmodule
关于IDDR的模式
SAME_EDGE_PIPELINED
SAME_EDGE
OPPOSITE_EDGE
关于ODDR
输出adc_dq_p,adc_dq_n。