在FPGA的设计过程中,有时候会遇到双向信号(既能作为输出,也能作为输入的信号叫双向信号)。比如,IIC总线中的SDA信号就是一个双向信号,QSPI Flash的四线操作的时候四根信号线均为双向信号。在Verilog中用关键字inout定义双向信号,这里总结一下双向信号的处理方法。

  实际上,双向信号的本质是由一个三态门组成的,三态门可以输出高电平,低电平和高阻态三种状态,在FPGA中,一个三态门的结构如下图所示:

    

  描述这个逻辑的Verilog代码如下:

module inout_top
(
input I_data_in ,
inout IO_data ,
output O_data_out ,
input Control
); assign IO_data = Control ? I_data_in : 'bz ;
assign O_data_out = IO_data ; endmodule

  当Control为1时,IO_data为输出,输出I_data_in的值

  当Control为0时,IO_data为输入,把输入的信号赋值给O_data_out

  这段代码在Vivado2015.4.2编译环境下的RTL图如下图所示

  在ISE14.7的编译环境下的RTL图如下图所示

  

  可以发现在Vivado2015.4.2环境的Control信号的IBUF后面居然还综合出了一个LUT,在ISE14.7环境下Control信号后面综合出了一个反向器,出现这个LUT和反向器的原因是Control为1才把IO_data设置成输出,而在Xilinx中一个IOBUF资源默认T端为0时IO端才为输出,T端为1时,IO端为输入,所以把

  assign IO_data = Control ? I_data_in : 1'bz ;

  改为

  assign IO_data = (Control == 1’b0) ? I_data_in : 1'bz ;

  在Vivado2015.4.2环境下综合出的RTL图为下图

  

  在ISE14.7的环境下综合出的RTL图如下图所示

  

  显然,Vivado环境中LUT和ISE环境中的反相器不见了,节省了1个Cell资源。

  以上是处理inout的第一种方法,第二种处理inout信号的方法是调用Xilinx的IOBUF原语,IOBUF的原语可以在Vivado2015.4.2的Language Templates中找到

  

  调用这个原语的Verilog代码如下:

module inout_top
(
input I_data_in,
inout IO_data ,
output O_data_out ,
input Control
); IOBUF #(
.DRIVE(), // Specify the output drive strength
.IBUF_LOW_PWR("TRUE"), // Low Power - "TRUE", High Performance = "FALSE"
.IOSTANDARD("DEFAULT"), // Specify the I/O standard
.SLEW("SLOW") // Specify the output slew rate
) IOBUF_inst (
.O(O_data_out), // Buffer output
.IO(IO_data), // Buffer inout port (connect directly to top-level port)
.I(I_data_in), // Buffer input
.T(Control) // 3-state enable input, high=input, low=output
); endmodule

  在Vivado2015.4.2环境下综合出的RTL图如下图所示

  

  在ISE14.7环境下综合出的RTL图如下图所示

  

  显然和  assign IO_data = (Control == 1’b0) ? I_data_in : 1'bz ;这种情况下综合出的RTL完全一样。

总结,利用Verilog处理双向信号有两种方式:

  1、写代码

    assign IO_data = (Control == 1’b0)? I_data_in : 1'bz ;

    assign O_data_out = IO_data ;

  2、例化IOBUF原语

    IOBUF #(

     .DRIVE(12), // Specify the output drive strength

    .IBUF_LOW_PWR("TRUE"),  // Low Power - "TRUE", High Performance = "FALSE"

    .IOSTANDARD("DEFAULT"), // Specify the I/O standard

    .SLEW("SLOW") // Specify the output slew rate

    ) IOBUF_inst (

    .O(O_data_out),     // Buffer output

    .IO(IO_data),   // Buffer inout port (connect directly to top-level port)

     .I(I_data_in),     // Buffer input

    .T(Control)      // 3-state enable input, high=input, low=output

    );

题外话:

  最近调一套代码,代码是前辈写的,之前都是用ISE开发,那套代码用ISE编译出的bit文件可以正常运行,但是最新的项目由于要添加更多的功能,所以选用了K7系列的FPGA,在Vivado下开发,结果发现原来正常运行的代码在Vivado下就不能运行了,通过反复检查与定位,发现原来的那套代码对inout信号的处理十分不规范,而且没有加Control这个控制信号来控制inout的方向,直接想当然的作为输入或者输出来使用。最后我们把inout信号全部采用上面两种规范的处理方法处理以后,代码正常运行。所以平时在设计的过程中一定要多注意细节,力求规范。

欢迎关注我的公众号:FPGA之禅

【设计经验】1、Verilog中如何规范的处理inout信号的更多相关文章

  1. 硬件描述语言Verilog设计经验总结

    一.硬件描述语言Verilog 粗略地看Verilog与C语言有许多相似之处.分号用于结束每个语句,注释符也是相同的(/* ... */和// 都是熟悉的),运算符"=="也用来测 ...

  2. 【设计经验】5、Verilog对数据进行四舍五入(round)与饱和(saturation)截位

    一.软件平台与硬件平台 软件平台: 操作系统:Windows 8.1 64-bit 开发套件:Vivado2015.4.2  Matlab2016a 仿真工具:Vivado自带仿真器 二.引言 在利用 ...

  3. 【设计经验】2、ISE中ChipScope使用教程

    一.软件与硬件平台 软件平台: 操作系统:Windows 8.1 开发套件:ISE14.7 硬件平台: FPGA型号:XC6SLX45-CSG324 二.ChipScope介绍 ChipScope是X ...

  4. 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣

    建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...

  5. 《设计模式之美》 <03>面向对象、设计原则、设计模式、编程规范、重构,这五者有何关系?

    面向对象 现在,主流的编程范式或者是编程风格有三种,它们分别是面向过程.面向对象和函数式编程.面向对象这种编程风格又是这其中最主流的.现在比较流行的编程语言大部分都是面向对象编程语言.大部分项目也都是 ...

  6. Web API接口设计经验总结

    在Web API接口的开发过程中,我们可能会碰到各种各样的问题,我在前面两篇随笔<Web API应用架构在Winform混合框架中的应用(1)>.<Web API应用架构在Winfo ...

  7. web设计经验<三>值得你深入了解的交互设计5大支柱

    随着单页式设计和移动端的兴起,网页中的交互设计越来越重要了.为了打造流畅而可靠的用户体验,你需要对交互设计有更加深入的了解. 正如同我们在<交互设计最佳实践(卷1)>中所述,要做好交互设计 ...

  8. web设计经验<一> 提升移动设备响应式设计的8个建议

    今天看到一些关于web设计的一些建议和设计经验,拿出来分享分享. 第一篇: 提升移动设备响应式设计的8个建议 一.直观性和易用性 在使用移动设备时,对于杂乱.复杂或者不直观的设计造成的混乱不佳的用户体 ...

  9. 关于Verilog 中的for语句的探讨

    在C语言中,经常用到for循环语句,但在硬件描述语言中for语句的使用较C语言等软件描述语言有较大的区别. 在Verilog中除了在Testbench(仿真测试激励)中使用for循环语句外,在Test ...

随机推荐

  1. halcon批量读取图片

    以前这个代码都是自己写,不仅繁琐,而且容易忘记.其实Halcon中提供了相关的方法.记录一下吧,其实很简单. 读取一个文件夹下的所有图片[助手]>[打开新的image acquisition ] ...

  2. Docekr 挂在卷之后访问目录时异常 cannot open directory '.': Permission denied 的解决办法

    1,原因,原因是CentOS7 中的安全模块 selinux 把权限禁掉了 2,解决办法如下 2.1,运行容器是加参数在 --privileged=true   (个人认为这是最佳方式,推荐使用) 如 ...

  3. eclipse 启动 闪退

    eclipse启动闪退 打开eclipse安装文件夹中的eclipse.ini文件. 把Xmx1024m修改为Xmx512m,可以解决闪退问题.

  4. JAVA程序调试

    调试 步骤1:设置断点(不能在空白处设置断点) 步骤2:启动调试 步骤3:调试代码(F6单步跳过)笔记本Fn+F6(F5) 步骤4:结束调试 掌握调试的好处? l  很清晰的看到,代码执行的顺序 l  ...

  5. springmvc controller方法返回值

  6. aio,nio ,io 心得

    1.nio 流的过程有几个,连接,可读,读 ,返回 :连接了不一定可读,等待浪费时间,这些时间可以去读其他的连接,selector是管理,管理全部测一下可不可读,只对可读的连接进行读取.同时,nio有 ...

  7. Java学习笔记(二十一):类型转换和instanceof关键字

    基本数据类型转换: 自动类型转换:把大类型的数据赋值给大类型的变量(此时的大小指的是容量的范围) byte b = 12; //byte是一个字节 int i = b; //int是四个字节 强制类型 ...

  8. 第一个只出现一次的字符字符(python)

    题目描述 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).   # -*- codin ...

  9. object references an unsaved transient instance save the transient instance before flushing

    object references an unsaved transient instance save the transient instance before flushing 对象引用未保存的 ...

  10. 【python原理解析】gc原理初步解析

    python的gc是会用到:引用计数.标记-清除和分代收集,首先说明一下什么是引用计数 可以通过sys模块中的getrefcount()方法获取某个对象的引用计数 python本身的数据类型有基础类型 ...