Vivado BD模式下导入RTL,如何实现聚合自定义的AXI接口?

文章来源:FPGA入门到精通

AXI(Advanced eXtensible Interface)是Xilinx FPGA中常用的接口协议,Vivado中很多IP都是采用AXI接口,特别是在Block Design模式下,添加AXI接口类的IP,可以发现AXI接口都是合并聚拢在一起的,连接同类型接口,只需连接一根线即可实现接口整体连接,非常方便。

1.png

那么对于我们自定义verilog模块,带AXI接口时,如何在导入Block Design后,也一样实现聚合在一起?

一、如何在Block Design模式下添加RTL代码?

打开Block Design,在Diagram界面中,鼠标右击,打开右键菜单下,鼠标点击找到的“Add Module”。

2.png

弹出“Add Module”,鼠标单击要选择要导入的RTL代码,再点击OK,或者直接双击要导入的RTL代码。

3.png

二、如何将导入的RTL代码接口聚合在一起?

1、创建一个示例模块接口

module axi_test(    input s_axi_clk,    input s_axi_resetn,       input valid_i,    input last_i,    input [31:0] data_i,    output ready_o,      output valid_o,    output last_o,    output [31:0] data_o,    input ready_i    );     endmodule

导入BD后的效果如下图,所有接口都是分开的。

4.png

这里分享两个解决办法。

2、遵循AXI4接口的命名方式

这里需要遵循AXI4接口的命名方式,导入BD中后,会自动聚合在一起,但这个方式的缺点是不可控,可能出现聚合混乱的情况。

(1)AXI4-Stream

module axi4_stream_test(    input wire clk,    input wire reset,    // Slave side    input wire [31:0] s_axis_tdata,    input wire s_axis_tkeep,    input wire s_axis_tlast,    input wire [2:0] s_axis_tid,    input wire [1:0] s_axis_tqos,    input wire s_axis_tvalid,    output wire s_axis_tready,    // Master side    output wire [31:0] m_axis_tdata,    output wire m_axis_tkeep,    output wire m_axis_tlast,    output wire [2:0] m_axis_tid,    output wire [1:0] m_axis_tqos,    output wire m_axis_tvalid,    input wire m_axis_tready    ); endmodule

导入效果如下:

5.png

(2)AXI4 Memory Mapped(也称为AXI4-MM)

module axi4_mm(    input wire clk,    input wire reset,    // Address and data signals    output wire [31:0] awaddr,    output wire [2:0] awprot,    output wire awvalid,    input wire awready,    output wire [31:0] wdata,    output wire [3:0] wstrb,    output wire wvalid,    input wire wready,    // Response signals    input wire [1:0] bresp,    input wire bvalid,    output wire bready,    // Address and data signals for read    input wire [31:0] araddr,    input wire [2:0] arprot,    input wire arvalid,    output wire arready,    input wire [31:0] rdata,    input wire [1:0] rresp,    input wire rvalid,    output wire rready    );endmodule

导入效果:

6.png

二、使用IP Integrator HDL语言

1、什么是IP Integrator HDL?

IP Integrator HDL并不是一个特定的硬件描述语言(HDL),而是一个概念或工具,可以让用VHDL或Verilog编写的RTL模块,定义的接口更清晰明确,包括接口的类型和聚合后的名称。

2、如何使用?

在vivado中,点击菜单栏“Tools”-》“Language Templates”,再点开Verilog下的IP Integrator HDL代码示例,如下图:

7.png

这里面有详细的示例,这里介绍AXI接口。

(1)AXI Memory Mapped

module my_module (  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWID" *)  // Uncomment the following to set interface specific parameter on the bus interface.  //  (* X_INTERFACE_PARAMETER = "CLK_DOMAIN <value>,PHASE <value>,MAX_BURST_LENGTH <value>,NUM_WRITE_OUTSTANDING <value>,NUM_READ_OUTSTANDING <value>,SUPPORTS_NARROW_BURST <value>,READ_WRITE_MODE <value>,BUSER_WIDTH <value>,RUSER_WIDTH <value>,WUSER_WIDTH <value>,ARUSER_WIDTH <value>,AWUSER_WIDTH <value>,ADDR_WIDTH <value>,ID_WIDTH <value>,FREQ_HZ <value>,PROTOCOL <value>,DATA_WIDTH <value>,HAS_BURST <value>,HAS_CACHE <value>,HAS_LOCK <value>,HAS_PROT <value>,HAS_QOS <value>,HAS_REGION <value>,HAS_WSTRB <value>,HAS_BRESP <value>,HAS_RRESP <value>" *)  input [<left_bound>:0] <s_awid>, // Write address ID (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWADDR" *)  input [<left_bound>:0] <s_awaddr>, // Write address (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWLEN" *)  input [<left_bound>:0] <s_awlen>, // Burst length (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWSIZE" *)  input [2:0] <s_awsize>, // Burst size (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWBURST" *)  input [1:0] <s_awburst>, // Burst type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWLOCK" *)  input [<left_bound>:0] <s_awlock>, // Lock type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWCACHE" *)  input [3:0] <s_awcache>, // Cache type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWPROT" *)  input [2:0] <s_awprot>, // Protection type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWREGION" *)  input [3:0] <s_awregion>, // Write address slave region (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWQOS" *)  input [3:0] <s_awqos>, // Transaction Quality of Service token (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWUSER" *)  input [<left_bound>:0] <s_awuser>, // Write address user sideband (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWVALID" *)  input <s_awvalid>, // Write address valid (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> AWREADY" *)  output <s_awready>, // Write address ready (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WID" *)  input [<left_bound>:0] <s_wid>, // Write ID tag (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WDATA" *)  input [<left_bound>:0] <s_wdata>, // Write data (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WSTRB" *)  input [<left_bound>:0] <s_wstrb>, // Write strobes (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WLAST" *)  input <s_wlast>, // Write last beat (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WUSER" *)  input [<left_bound>:0] <s_wuser>, // Write data user sideband (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WVALID" *)  input <s_wvalid>, // Write valid (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> WREADY" *)  output <s_wready>, // Write ready (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> BID" *)  output [<left_bound>:0] <s_bid>, // Response ID (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> BRESP" *)  output [1:0] <s_bresp>, // Write response (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> BUSER" *)  output [<left_bound>:0] <s_buser>, // Write response user sideband (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> BVALID" *)  output <s_bvalid>, // Write response valid (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> BREADY" *)  input <s_bready>, // Write response ready (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARID" *)  input [<left_bound>:0] <s_arid>, // Read address ID (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARADDR" *)  input [<left_bound>:0] <s_araddr>, // Read address (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARLEN" *)  input [<left_bound>:0] <s_arlen>, // Burst length (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARSIZE" *)  input [2:0] <s_arsize>, // Burst size (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARBURST" *)  input [1:0] <s_arburst>, // Burst type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARLOCK" *)  input [<left_bound>:0] <s_arlock>, // Lock type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARCACHE" *)  input [3:0] <s_arcache>, // Cache type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARPROT" *)  input [2:0] <s_arprot>, // Protection type (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARREGION" *)  input [3:0] <s_arregion>, // Read address slave region (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARQOS" *)  input [3:0] <s_arqos>, // Quality of service token (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARUSER" *)  input [<left_bound>:0] <s_aruser>, // Read address user sideband (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARVALID" *)  input <s_arvalid>, // Read address valid (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> ARREADY" *)  output <s_arready>, // Read address ready (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RID" *)  output [<left_bound>:0] <s_rid>, // Read ID tag (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RDATA" *)  output [<left_bound>:0] <s_rdata>, // Read data (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RRESP" *)  output [1:0] <s_rresp>, // Read response (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RLAST" *)  output <s_rlast>, // Read last beat (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RUSER" *)  output [<left_bound>:0] <s_ruser>, // Read user sideband (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RVALID" *)  output <s_rvalid>, // Read valid (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:aximm:1.0 <interface_name> RREADY" *)  input <s_rready>, // Read ready (optional)//  additional ports here);
//  user logic here
endmodule

(2)AXI Stream

module my_module (  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TID" *)  // Uncomment the following to set interface specific parameter on the bus interface.  //  (* X_INTERFACE_PARAMETER = "CLK_DOMAIN <value>,PHASE <value>,FREQ_HZ <value>,LAYERED_METADATA <value>,HAS_TLAST <value>,HAS_TKEEP <value>,HAS_TSTRB <value>,HAS_TREADY <value>,TUSER_WIDTH <value>,TID_WIDTH <value>,TDEST_WIDTH <value>,TDATA_NUM_BYTES <value>" *)  input [<left_bound>:0] <s_tid>, // Transfer ID tag (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TDEST" *)  input [<left_bound>:0] <s_tdest>, // Transfer Destination (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TDATA" *)  input [<left_bound>:0] <s_tdata>, // Transfer Data (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TSTRB" *)  input [<left_bound>:0] <s_tstrb>, // Transfer Data Byte Strobes (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TKEEP" *)  input [<left_bound>:0] <s_tkeep>, // Transfer Null Byte Indicators (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TLAST" *)  input <s_tlast>, // Packet Boundary Indicator (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TUSER" *)  input [<left_bound>:0] <s_tuser>, // Transfer user sideband (optional)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TVALID" *)  input <s_tvalid>, // Transfer valid (required)  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TREADY" *)  output <s_tready>, // Transfer ready (optional)//  additional ports here);
//  user logic here
endmodule

其中“<interface_name>”是定义聚合后的接口名称。

只需要在每个参数接口前,添加对应的IP Integrator HDL属性语句。

未加IP Integrator HDL代码示例:

module axi_test(    input wire clk,    input wire reset,    // Slave side    input wire [31:0] s_tdata,    input wire s_tkeep,    input wire s_tlast,    input wire s_tvalid,    output wire s_tready,    // Master side    output wire [31:0] m_tdata,    output wire m_tkeep,    output wire m_tlast,    output wire m_tvalid,    input wire m_tready    ); endmodule

导入效果图:

8.png

添加IP Integrator HDL代码示例:

module axi_test(    input wire clk,    input wire reset,    // Slave side    (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_test TDATA" *)    input wire [31:0] s_tdata,    (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_test TKEEP" *)    input wire s_tkeep,    (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_test TLAST" *)    input wire s_tlast,    (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_test TVALID" *)    input wire s_tvalid,     (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_test TREADY" *)    output wire s_tready,    // Master side     (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_test TDATA" *)    output wire [31:0] m_tdata,     (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_test TKEEP" *)    output wire m_tkeep,     (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_test TLAST" *)    output wire m_tlast,     (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_test TVALID" *)    output wire m_tvalid,     (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_test TREADY" *)    input wire m_tready    ); endmodule

导入效果图:

9.png

最新文章

最新文章