Xilinx IDDR及ODDR使用和仿真

平台: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;
	generate
	for (i = 0; i<=(WIDTH-1); i = i +1) begin : adc_ch_di
		adc_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]                )
			);
	end
	endgenerate 

	genvar j;
	generate
	for (j = 0; j<=(WIDTH-1); j = j +1) begin : adc_ch_do
		adc_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                    ));
	end
	endgenerate 
//-----------------------------------------------------------
//-----------------------------------------------------------
initial
begin
        adc_clock   =0;
        adc_reset   =1;
        data_clk    =0;
        #100;
        adc_reset   =0;
end

reg [11:0]   data_cnt;

always@(posedge data_clk or posedge adc_reset)
begin
        if(adc_reset == 1'b1)begin
                data_cnt  <= 12'h0;
        end
        else begin
                data_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。

相关推荐
DS小龙哥8 小时前
基于Zynq FPGA的雷龙SD NAND存储芯片性能测试
fpga开发·sd nand·雷龙·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
上理考研周导师17 小时前
第二章 虚拟仪器及其构成原理
fpga开发
FPGA技术实战19 小时前
《探索Zynq MPSoC》学习笔记(二)
fpga开发·mpsoc
bigbig猩猩1 天前
FPGA(现场可编程门阵列)的时序分析
fpga开发
Terasic友晶科技1 天前
第2篇 使用Intel FPGA Monitor Program创建基于ARM处理器的汇编或C语言工程<二>
fpga开发·汇编语言和c语言
码农阿豪1 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发·sd nand·spi nand·spi nand flash·工业级tf卡·嵌入式tf卡
江山如画,佳人北望1 天前
EDA技术简介
fpga开发
淘晶驰AK1 天前
电子设计竞赛准备经历分享
嵌入式硬件·fpga开发
最好有梦想~1 天前
FPGA时序分析和约束学习笔记(4、IO传输模型)
笔记·学习·fpga开发