在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] == 1‘b1) ? 1‘bz : 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个线,有点复杂。
如没有特殊要求推荐第一种方法。