草庐IT

Xilinx IOBUF 的用法

财不外漏_ 2023-12-06 原文

Xilinx IOBUF 的用法

文章目录

一、概念

1. 基本概念

应用场景: 在vivado中,连接的管脚的信号一般都会自动添加OBUF或IBUF。但是对于inout类型的接口,不会主动添加IOBUF,因为in/out切换需要控制信号,需要用户自己分配好。

Xilinx官网原文: The IOBUF primitive is needed when bidirectional signals require both an input buffer and a 3-state output buffer with an active-High 3-state T pin. The IOBUF is a generic IOBUF. A logic-High on the T pin disables the output buffer. When the output buffer is 3-stated (T = High), the input buffer and any on-die receiver termination (uncalibrated or DCI) are ON. When the output buffer is not 3-stated (T = Low), any on-die receiver termination (uncalibrated or DCI) is disabled.

I/O attributes that do not impact the logic function of the component such as IOSTANDARD, DRIVE and SLEW should be supplied to the top-level port via an appropriate property. For details on applying such properties to the associated port, see the Vivado Design Suite Properties Reference Guide (UG912).

个人翻译: 当双向信号需要输入缓冲区和带active-High 3态T引脚的3态输出缓冲区时,需要IOBUF原语。IOBUF是一个通用的IOBUF。T为高电平时关闭output buffer(I端口)。当output buffer为3-state (T = High)时,input buffer和任何固定接收器终端(未校准或DCI)均为有效。当输出缓冲区不是3-state (T = Low)时,任何固定接收器终端(未校准或DCI)都是禁用的。

不影响组件逻辑功能的I/O属性(如IOSTANDARD、DRIVE和kill)应该通过适当的属性提供给顶级端口。有关将这些属性应用到相关端口的详细信息,请参见Vivado设计套件属性参考指南(UG912)。

Vivado原语:

// IOBUF: Single-ended Bi-directional Buffer
//        All devices
// Xilinx HDL Language Template, version 2017.2
    
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),   // 1-bit output: Buffer output
      .I(I),   // 1-bit input: Buffer input
      .IO(IO), // 1-bit inout: Buffer inout (connect directly to top-level port)
      .T(T)    // 1-bit input: 3-state enable input
   );

个人理解: 这玩意儿的解释有点绕,我们结合结构图原文原语来总结一下,大致是这么个意思:

首先,我为什么说它绕,因为IOBUF的O指的是IO_pin >> FPGA,也就是说这里的Output输出的主语是IO_pin,而不是FPGA;这里的 I 指的是IO_Pin << FPGA,同样主语是IO_pin,这里指的是输入到IO_pin。所以第一次使用的时候容易弄混。

再与结构图结合就很容易理解了,三态门T控制的是I端口能否有效输入:

  • T拉高时,I端口停止工作,O端口向FPGA内部输出信号;
  • T拉低时,I端口向IO_pin输入来自FPGA内部的信号,此时 O = I(因为O端口从这个方向上来说也是 I 的分支);

2. 硬件结构

2.1 IOBUF

官网原图:

Vivado综合后的RTL视图:

真值表:

Inputs
Bidirectional
Outputs
T
I
IO
O
1
X
Z
IO
0
1
1
1
0
0
0
0

接口描述:

PortDirectionWidthFunction带有个人情感色彩的翻译
IInput1Input of OBUF. Connect to the logic driving the output port.OBUF的输入端,连接到Output端口的逻辑驱动
IOInout1Bidirectional port to be connected directly to top-level inout port.双向端口被直接连接到顶层的inout端口
OOutput1Output path of the buffer.IOBUF的输出路径
TInput13-state enable input signifying whether the buffer acts as an input or output.3态门启用输入,表示IOBUF是作为输入还是作为输出。

2.2 OBUFT

真值表:

Inputs
Outputs
T
I
O
1
X
Z
0
1
1
0
0
0

接口描述:

PortDirectionWidthFunction带有个人偏见的翻译
IInput1Input of OBUF. Connect to the logic driving the output port.OBUF的输入端,连接到Output端口的逻辑驱动
OOutput1Output of OBUF to be connected directly to top-level output port.OBUF的输出端被直接连接到顶层的output端口
TInput13-state enable input.三态门使能输入

二、实例

首先我们想象这样一个应用场景:

因为某些原因,ARM不能直接连接到PHY芯片上,所以需要通过FPGA间接与PHY芯片相连接,这个时候我们就有以下引脚:

input  i_arm_mdc,
inout  io_arm_mdio,
output o_phy_mdc,
inout  io_phy_mdio

而根据MDIO协议:

IO端口切换输入输出模式的根据是OP位,所以我们可以先设置一系列寄存器来存储io_arm_mdio的input内容,以及读写变化使能。

reg      	        s_mdio_rd_en;
reg      [35:00]    s_mdio_word ;
reg      [01:00]    s_mdio_op   ;	
reg      [05:00]    s_cnt_mdio  ;
reg                 s_add_mdio  ;
wire				s_arm_out	;
wire                s_phy_out	;

assign o_phy_mdc = i_arm_mdc	;

always @(posedge i_arm_mdc or negedge i_rst_n)begin   
    if(!i_rst_n) begin
	    s_mdio_word <= 36'b0;
	end
	else begin
		s_mdio_word <= {s_mdio_word[34:00],s_arm_out};
	end
end

/* ---- mdio contrl ---- */
always @(posedge i_arm_mdc or negedge i_rst_n) begin
    if (!i_rst_n) begin
        s_add_mdio <= 1'b0;
        s_mdio_op  <= 1'b0;
    end 
    else begin
		if((s_mdio_word==36'hffffffff6||s_mdio_word==36'hffffffff5) && s_mdio_trans_cnt == 8'd35)
            s_add_mdio <= 1'b1;
		else if(s_cnt_mdio >= 16'd27)
            s_add_mdio <= 1'b0;
        else 
            s_add_mdio <= s_add_mdio;
        if (s_add_mdio) 
            s_cnt_mdio <= s_cnt_mdio + 1'b1;
        else
            s_cnt_mdio <= 1'b0;
		if(s_mdio_word==36'hffffffff6 && s_mdio_trans_cnt == 8'd35)
            s_mdio_op <= Read_bits;
        else if (s_mdio_word==36'hffffffff5 && s_mdio_trans_cnt == 8'd35)
            s_mdio_op <= Write_bits;
		else
			s_mdio_op <= s_mdio_op;
	end
end

always @(posedge i_arm_mdc or negedge i_rst_n)begin   
    if(!i_rst_n)begin
		s_mdio_rd_en <= 1'b0;
	end
	else begin
		if(s_cnt_mdio>=6'd9 && s_mdio_op == Read_bits)/* 5-bit PHY_ADDR + 5-bit Reg_ADDR = 10-bit */
			s_mdio_rd_en <= 1'b1;
		else
			s_mdio_rd_en <= 1'b0;
	end
end

在需要的参数都准备好后,就可以开始使用原语了:

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_arm (
            .O (s_arm_out      ),    // 
            .IO(io_arm_mdio    ),    // 
            .I (s_phy_out     ),    // 
            .T (!s_mdio_rd_en )     // 3-state enable input, high=input, low=output
    );
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_phy (
            .O (s_phy_out      ),    // 
            .IO(io_phy_mdio    ),    // 
            .I (s_arm_out      ),    // 
            .T (s_mdio_rd_en  )     // 3-state enable input, high=input, low=output
    );

最后综合出来的结果就是这个样子:

三、参考文献

Xilinx: IOBUF English

Xilinx: OBUFT English

KevinChase:【FPGA】xilinx IOBUF的用法

有关Xilinx IOBUF 的用法的更多相关文章

  1. ruby - 有人可以解释一下在 Ruby 中注入(inject)的真实、通俗易懂的用法吗? - 2

    我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有

  2. ruby - 使用法拉第上传文件 - 2

    我在尝试使用Faraday将文件上传到网络服务时遇到问题。我的代码:conn=Faraday.new('http://myapi')do|f|f.request:multipartendpayload={:file=>Faraday::UploadIO.new('...','image/jpeg')}conn.post('/',payload)尝试发布后似乎没有任何反应。当我检查响应时this是我所看到的:#:post,:body=>#,#,@opts={}>,#],@index=0>>,#>],@ios=[#,#,@opts={}>,#],@index=0>,#],@index=0>

  3. ruby - rspec: raise_error 用法来匹配错误信息 - 2

    我使用raise(ConfigurationError.new(msg))引发错误我试着用rspec测试一下:expect{Base.configuration.username}.toraise_error(ConfigurationError,message)但这行不通。我该如何测试呢?目标是匹配message。 最佳答案 您可以使用正则表达式匹配错误消息:it{expect{Foo.bar}.toraise_error(NoMethodError,/private/)}这将检查NoMethodError是否由privateme

  4. 【ChatGPT】ChatGPT 的 N 种用法 - 2

    目录ChatGPT简介技术原理应用未来发展ChatGPT的10 种用法ChatGPT简介ChatGPT是一种基于深度学习的大型语言模型,由OpenAI公司开发。技术原理GPT是GenerativePre-trainedTransformer的缩写,意为生成式预训练变压器。它的技术原理是使用了一个基于注意力机制的变压器(Trans

  5. ruby - 是否有 Rack::Session::Cookie 用法的基本示例? - 2

    我找不到任何使用Rack::Session::Cookie的简单示例,并且希望能够将信息存储在cookie中,并在以后的请求中访问它并让它过期.这些是我能找到的唯一示例:HowdoIset/getsessionvarsinaRackapp?http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html这是我得到的:useRack::Session::Cookie,:key=>'rack.session',:domain=>'foo.com',:path=>'/',:expire_after=>2592000,:secret=

  6. ruby - Ruby 方法的双冒号(双列或::)语法的惯用用法 - 2

    我是Ruby的新手,发现以下几对令人困惑示例同样有效:File.included_modulesFile::included_modulesFile.stat('mbox')#Returnsa'#'objectFile::stat('mbox')File.new("foo.txt","w")File::new("foo.txt","w")"asdf".size#Aninstancemethod"asdf"::size2+32::send(:+,3)#AnextremeexampleFile::new,尤其是我经常遇到的东西。我的问题:如果我永远避免使用::运算符来限定除类、模块和常量之

  7. ruby-on-rails - 如果只有一个存在,是否有用于返回第一个数组元素的 ruby​​ 习惯用法? - 2

    如果数组只包含一个值,我想返回数组的第一个元素。目前,我使用:vals.one??vals.first:vals.presence因此:vals=[];vals.one??vals.first:vals.presence#=>nilvals=[2];vals.one??vals.first:vals.presence#=>2vals=[2,'Z'];vals.one??vals.first:vals.presence#=>[2,"Z"]是否有内置的东西可以做到这一点,或者是否有更好的设计考虑?我的用例是特定的,涉及知道从方法(将实现上述代码)中期望什么的演示者。如果这些演示者将所有返回

  8. ruby - 这是 &&= 在 Ruby 中的合理用法吗? - 2

    在SOquestion2068165一个答案提出了使用这样的东西的想法:params[:task][:completed_at]&&=Time.parse(params[:task][:completed_at])作为DRYer的说法params[:task][:completed_at]=Time.parse(params[:task][:completed_at])ifparams[:task][:completed_at]paramsHash将来自(Rails/ActionView)表单。这是众所周知的||=习语的一种推论,如果LHS不是nil/false则设置值。像这样使用&&

  9. ruby - Head 用法未知选项 -1/-n 错误。可能与 ruby 有关 - 2

    我在OSX10.9.1中启动终端时反复出现问题。每次启动终端时,我都会重复以下至少30次Unknownoption:1Usage:head[-options]...-musemethodfortherequest(defaultis'HEAD')-fmakerequestevenifheadbelievesmethodisillegal-bUsethespecifiedURLasbase-tSettimeoutvalue-iSettheIf-Modified-Sinceheaderontherequest-cusethiscontent-typeforPOST,PUT,CHECKIN-

  10. ruby-on-rails - rails 中是否内置了对默认值替换习惯用法的支持? - 2

    我经常编写代码以在遇到nil/空值时提供默认值。例如:category=order.category||"Any"#ORcategory=order.category.empty??"Any":order.category我即将扩展try方法来处理这个习语。category=order.try(:category,:on_nill=>"Any")#ORcategory=order.try(:category,:on_empty=>"Any")我想知道Rails/Ruby是否有一些方法来处理这个习惯用法?注意:我正在尝试消除||的重复/或/?基于运算符的习语。本质上,我正在寻找与try方

随机推荐