Xilinx原语详解——IBUFDS OBUFDS

2023-12-10 09:45

本文主要是介绍Xilinx原语详解——IBUFDS OBUFDS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  在使用FPGA时,往往会用到一些差分信号,比如HDMI接口,LVDS接口的ADC、显示器等等设备,而FPGA内部往往只会使用单端信号,就需要完成单端信号和差分信号的相互转换,xilinx提供了两个原语对所有IO信号实现差分和单端的转换,IBUFDS将FPGA输入的差分信号转换为单端信号,而OBUFDS负责把FPGA内部的单端信号转换为差分信号输出。

1、IBUFDS

  IBUFDS是一个支持低电压差分信号的输入缓冲器,图1是IBUFDS的框图。在IBUFDS中,有两个输入接口,一个是差分输入的正极端口I,另一个是差分输入的负极端口IB,两个端口的信号极性必须相反才能正常工作,输出端O将输入的差分信号转换为单端信号输出。

在这里插入图片描述

图1 IBUFDS框图

  IBUFDS的真值表如图2所示(直接从UG768中截图),注意只有当I和IB极性相反的时候才能表示两个信号互为差分对,此时才能正常工作,输出I端口的电平。一般是不会出现均为高电平或低电平状态的,除非差分走线没有做等长处理,此时是硬件设计的问题。

在这里插入图片描述

图2 IBUFDS真值表

  IBUFDS的Verilog HDL原语模板如下所示:

   IBUFDS #(.DIFF_TERM("FALSE"),       // Differential Termination.IBUF_LOW_PWR("TRUE"),     // Low power="TRUE", Highest performance="FALSE" .IOSTANDARD("DEFAULT")     // Specify the input I/O standard) IBUFDS_inst (.O(O),  // Buffer output.I(I),  // Diff_p buffer input (connect directly to top-level port).IB(IB) // Diff_n buffer input (connect directly to top-level port));

2、OBUFDS

  IBUFDS是在FPGA的输入管脚使用,将外部的差分信号转为单端信号供内部使用。 OBUFDS刚好相反,其在输出管脚使用,将内部的单端信号转换为差分信号输出FPGA。图3是OBUFDS的框图,I为单端输入信号,O为差分输出正极,OB是差分输出负极。

在这里插入图片描述

图3 OBUFDS框图

  OBUFDS功能比较简单,对应真值表(可以从UG768手册直接获取)如图4所示。

在这里插入图片描述

图4 OBUFDS真值表

  OBUFDS对应的Verilog HDL原语模板如下所示:

   OBUFDS #(.IOSTANDARD("DEFAULT"), // Specify the output I/O standard.SLEW("SLOW")           // Specify the output slew rate) OBUFDS_inst (.O(O),     // Diff_p output (connect directly to top-level port).OB(OB),   // Diff_n output (connect directly to top-level port).I(I)      // Buffer input);

3、IOBUFDS

  除了上述单向的差分信号外,可以利用三态差分转换器件IOBUFDS实现双向差分转换,对应的框图如图5所示,T是三态的使能信号,低电平有效(图中少画了圈),T为低电平时,I作为FPGA输出的单端信号,IO和IOB作为转换后的差分输出引脚。当T为高电平时,三态门关闭,此时IO作为差分输入的正极,IOB作为差分输入的负极,O作为差分输入转换后的单端输入信号。

在这里插入图片描述

图5 IOBUFDS框图

  对应的真值表如图6所示,

在这里插入图片描述

图6 IOBUFDS真值表

  IOBUFDS对应的Verilog HDL原语模板如下所示:

   IOBUFDS #(.DIFF_TERM("FALSE"),     // Differential Termination ("TRUE"/"FALSE").IBUF_LOW_PWR("TRUE"),   // Low Power - "TRUE", High Performance = "FALSE" .IOSTANDARD("BLVDS_25"), // Specify the I/O standard.SLEW("SLOW")            // Specify the output slew rate) IOBUFDS_inst (.O(O),     // Buffer output.IO(IO),   // Diff_p inout (connect directly to top-level port).IOB(IOB), // Diff_n inout (connect directly to top-level port).I(I),     // Buffer input.T(T)      // 3-state enable input, high=input, low=output);

4、仿真

  这几个原语功能比较简单,使用一个工程完成三个原语的仿真,设计文件如下所示,外部输入的差分信号ibufds_p和ibufds_n,经过IBUFDS转为单端信号ibufds_o,该信号经过触发器延迟一个时钟得到ibufds_o_r,通过OBUFDS转换为差分信号obufds_p和obufds_n输出。外部输入一个三态控制信号t,用于控制IOBUFDS的三态使能端口,使能有效时,将IBUFDS寄存后的信号ibufds_o_r输出。

module buf_ctrl(input       clk      ,//系统时钟信号;input       rst      ,//系统复位信号,高电平有效;input       iobufds_t,//iobufds使能控制端;input       ibufds_p ,//ibufds正极输入;input       ibufds_n ,//ibufds负极输入;output      obufds_p ,//obufds正极输出;output      obufds_n ,//obufds负极输出;inout       iobufds_p,//iobufds正极输出;inout       iobufds_n,//iobufds负极输出;output      iobufds_i //将IOBUFDS输入的数据输出,防止倍优化掉;
); reg         ibufds_o_r;wire        ibufds_o ;//例化IBUFDS原语IBUFDS #(.DIFF_TERM     ( "FALSE"   ),// Differential Termination.IBUF_LOW_PWR  ( "TRUE"    ),// Low power="TRUE", Highest performance="FALSE" .IOSTANDARD    ( "DEFAULT" ) // Specify the input I/O standard)u_IBUFDS (.O    (ibufds_o   ),// Buffer output.I    (ibufds_p   ),// Diff_p buffer input (connect directly to top-level port).IB   (ibufds_n   ) // Diff_n buffer input (connect directly to top-level port));always@(posedge clk)beginibufds_o_r <= ibufds_o;end//例化OBUFDS原语OBUFDS #(.IOSTANDARD ( "DEFAULT" ),// Specify the output I/O standard.SLEW       ( "SLOW"    ) // Specify the output slew rate)u_OBUFDS (.O    (obufds_p   ),// Diff_p output (connect directly to top-level port).OB   (obufds_n   ),// Diff_n output (connect directly to top-level port).I    (ibufds_o_r ) // Buffer input);//例化IOBUFDS原语IOBUFDS #(.DIFF_TERM     ("FALSE"    ),// Differential Termination ("TRUE"/"FALSE").IBUF_LOW_PWR  ("TRUE"     ),// Low Power - "TRUE", High Performance = "FALSE" .IOSTANDARD    ("BLVDS_25" ),// Specify the I/O standard.SLEW          ("SLOW"     ) // Specify the output slew rate)u_IOBUFDS (.O    (iobufds_i     ),// Buffer output.IO   (iobufds_p     ),// Diff_p inout (connect directly to top-level port).IOB  (iobufds_n     ),// Diff_n inout (connect directly to top-level port).I    (ibufds_o_r    ),// Buffer input.T    (iobufds_t     ) // 3-state enable input, high=input, low=output);endmodule

  对应的TestBench文件如下所示:

`timescale 1 ns/1 ns
module test();parameter	CYCLE		=   10          ;//系统时钟周期,单位ns,默认10ns;reg			                clk         ;//系统时钟,默认100MHz;reg			                rst         ;//系统复位,默认高电平有效;reg                         iobufds_t   ;reg                         ibufds_p    ;reg                         ibufds_n    ;wire                        obufds_p    ;wire                        obufds_n    ;wire                        iobufds_i   ;wire                        iobufds_p   ;wire                        iobufds_n   ;buf_ctrl  u_buf_ctrl (.clk            ( clk       ),.rst            ( rst       ),.iobufds_t      ( iobufds_t ),.ibufds_p       ( ibufds_p  ),.ibufds_n       ( ibufds_n  ),.obufds_p       ( obufds_p  ),.obufds_n       ( obufds_n  ),.iobufds_i      ( iobufds_i ),.iobufds_p      ( iobufds_p ),.iobufds_n      ( iobufds_n ));reg  iobufds_p_i;reg  iobufds_n_i;assign iobufds_p = (iobufds_t) ? iobufds_p_i : 1'bz;assign iobufds_n = (iobufds_t) ? iobufds_n_i : 1'bz;//生成周期为CYCLE数值的系统时钟;initial beginclk = 1;forever #(CYCLE/2) clk = ~clk;end//生成复位信号;initial beginrst = 0;#2;rst = 1;//开始时复位10个时钟;#(10*CYCLE);rst = 0;repeat(220) @(posedge clk);$stop;//停止仿真;endinitial begin#1;ibufds_p = 1'b0;ibufds_n = 1'b1;iobufds_t = 1'b1;iobufds_p_i = 1'b0;iobufds_n_i = 1'b1;#(CYCLE*12);ibufds_n = ibufds_p;#(CYCLE*2);ibufds_p = ~ibufds_p;#(CYCLE*2);ibufds_n = ibufds_p;#(CYCLE*2);repeat(200)beginibufds_p = ({$random} % 2);ibufds_n = ~ibufds_p;#(CYCLE);iobufds_t = ({$random} % 2);#(CYCLE);iobufds_p_i = ({$random} % 2);iobufds_n_i = ~iobufds_p_i;#(CYCLE);endendendmodule

  仿真结果如图7所示,图中对IBUFDS的四种输入取值做了仿真,当IBUFDS的输入同时为高电平或者低电平时,IBUFDS转换的输出信号会保持之前的状态不变。在实际情况下应该避免这种情况出现,其余情况IBUFDS与真值表结果一致,不再赘述。

在这里插入图片描述

图7 IBUFDS输入转换仿真

  下图主要关注OBUFDS相关信号,如图黄色信号为OBUFDS输入单端数据,而红色信号为OBUFDS输出差分信号,由图可知仿真正确。

在这里插入图片描述

图8 OBUFDS转换仿真

  IOBUFDS的仿真如图9所示,红色信号为IOBUFDS的三态使能信号,橙色信号是IOBUFDS的单端输出信号,对应真值表中的I,天蓝色信号表示IOBUFDS的双向差分信号,紫色信号是IOBUFDS的单端输入信号,对应真值表中的O。

在这里插入图片描述

图9 IOBUFDS转换仿真

  当使能信号为高电平时,IOBUFDS的三态门关闭,此时两路天蓝色差分信号为输入信号,紫色信号是两路差分输入转换为单端的结果,紫色信号与差分正极的逻辑保持一致,与橙色信号无关,所以正确。

  当使能信号为低电平时,IOBUFDS的三态门打开,此时IOBUFDS把橙色单端信号转换为两路天蓝色的差分信号输出,紫色信号此时与橙色信号是一致的,与普通三态门逻辑一致,仿真正确。

5、FPGA如何实现差分输入\输出

  通过上文仿真可以知道逻辑实现,但是FPGA是如何实现差分输入和输出的呢?将上述工程分配管脚,然后实现,生产比特流文件,最后查看信号在芯片中的走线及布局。

  如图10所示,是IBUFDS两个差分输入管脚的布局,Xilinx把两个相邻的管脚作为差分信号的两个管脚,通过两个IOB模块实现IOBUFDS的转换功能。

在这里插入图片描述

图10 IOBUFDS管脚分布

  图11是OBUFDS的实现情况,把两个管脚组合成差分信号,通过OBUFDS位于P脚的IOB之中,也就是单端引脚OBUF的位置,该结构可以作为OBUFDS使用,如图12所示。

在这里插入图片描述

图11 差分引脚布局

在这里插入图片描述

图12 OBUFDS位置

  IOBUFDS的情况稍微复杂一点,因为是双向信号,所以会同时使用ILOGIC和OLOGIC,并且因为有三态使能信号,所以OLOGIC需要同时使用上下两条路径,如图13所示,ILOGIC和OLOGIC在IDDR和ODDR文中已经详细分析过,此处不再赘述。

在这里插入图片描述

图13 IOBUFDS布局

  综上,FPGA会将相邻两个管脚配置为差分对,保证两路信号足够近,延时足够小,IBUF和OBUF的位置根据功能不同可能实现IBUFDS、OBUFDS、IOBUFDS等功能,在FPGA中经常可以看见同一器件可以复用多种功能,OLOGCI被作为ODDR,OFB等功能。

  参考资料:UG768 Xilinx 7 Series FPGA and Zynq-7000 All Programmable SoC Libraries Guide for HDL Designs

  本文工程在后台回复“BUF”(不包括引号)即可,UG768直接回复”xilinx手册”即可,包含前文用到xilinx相关所有手册。

这篇关于Xilinx原语详解——IBUFDS OBUFDS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/476749

相关文章

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Linux内核之内核裁剪详解

《Linux内核之内核裁剪详解》Linux内核裁剪是通过移除不必要的功能和模块,调整配置参数来优化内核,以满足特定需求,裁剪的方法包括使用配置选项、模块化设计和优化配置参数,图形裁剪工具如makeme... 目录简介一、 裁剪的原因二、裁剪的方法三、图形裁剪工具四、操作说明五、make menuconfig

详解Java中的敏感信息处理

《详解Java中的敏感信息处理》平时开发中常常会遇到像用户的手机号、姓名、身份证等敏感信息需要处理,这篇文章主要为大家整理了一些常用的方法,希望对大家有所帮助... 目录前后端传输AES 对称加密RSA 非对称加密混合加密数据库加密MD5 + Salt/SHA + SaltAES 加密平时开发中遇到像用户的

Springboot使用RabbitMQ实现关闭超时订单(示例详解)

《Springboot使用RabbitMQ实现关闭超时订单(示例详解)》介绍了如何在SpringBoot项目中使用RabbitMQ实现订单的延时处理和超时关闭,通过配置RabbitMQ的交换机、队列和... 目录1.maven中引入rabbitmq的依赖:2.application.yml中进行rabbit

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

SpringBoot使用Apache POI库读取Excel文件的操作详解

《SpringBoot使用ApachePOI库读取Excel文件的操作详解》在日常开发中,我们经常需要处理Excel文件中的数据,无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到... 目录项目背景依赖导入读取Excel模板的实现代码实现代码解析ExcelDemoInfoDTO 数据传输

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab