首页 > 代码库 > ZYNQ GPIO 缓冲实现方法

ZYNQ GPIO 缓冲实现方法

在Vivado中,EMIO IP(system和AXI扩展部分)引出实际上有3个管脚,分别是gpio_i,gpio_o,gpio_t,

技术分享

 

要把它们转化为标准的GPIO,要外加缓冲器,步骤如下

技术分享

在顶层模块中,会生成如下代码

IOBUF gpio_0_tri_iobuf_0
(.I(gpio_0_tri_o_0),
.IO(gpio_0_tri_io[0]),
.O(gpio_0_tri_i_0),
.T(gpio_0_tri_t_0));
IOBUF gpio_0_tri_iobuf_1
(.I(gpio_0_tri_o_1),
.IO(gpio_0_tri_io[1]),
.O(gpio_0_tri_i_1),
.T(gpio_0_tri_t_1));
IOBUF gpio_0_tri_iobuf_10
(.I(gpio_0_tri_o_10),
.IO(gpio_0_tri_io[10]),
.O(gpio_0_tri_i_10),
.T(gpio_0_tri_t_10));
IOBUF gpio_0_tri_iobuf_11
(.I(gpio_0_tri_o_11),
.IO(gpio_0_tri_io[11]),
.O(gpio_0_tri_i_11),
.T(gpio_0_tri_t_11));

有多少IO,就会有多少个缓冲器。

缓冲器内部结构如图所示

技术分享

 

这个缓冲器其实也可以自己写得更加简洁一些,比如adi官方的例子

module ad_iobuf (

  dio_t,
  dio_i,
  dio_o,
  dio_p);

  parameter     DATA_WIDTH = 1;

  input   [(DATA_WIDTH-1):0]  dio_t;
  input   [(DATA_WIDTH-1):0]  dio_i;
  output  [(DATA_WIDTH-1):0]  dio_o;
  inout   [(DATA_WIDTH-1):0]  dio_p;

  genvar n;
  generate                         #循环例化   
  for (n = 0; n < DATA_WIDTH; n = n + 1) begin: g_iobuf
  assign dio_o[n] = dio_p[n];
  assign dio_p[n] = (dio_t[n] == 1b1) ? 1bz : dio_i[n];
  end
  endgenerate

endmodule

调用

  ad_iobuf #(
    .DATA_WIDTH(32)                    #参数输入,例化32个
  ) i_iobuf (
    .dio_t(gpio_t[31:0]),
    .dio_i(gpio_o[31:0]),
    .dio_o(gpio_i[31:0]),
    .dio_p(gpio_bd));

当然,这样一来更新稍有不便,而且需要手工增加3个线,有点复杂。

如没有特殊要求推荐第一种方法。

ZYNQ GPIO 缓冲实现方法