AXI-Taffric-Generator IP核的使用(System Test模式)

Scroll Down

前言

最近学习到了也用到了很多AXI接口的IP核,很多时候参考xilinx仿真示例工程时都会看到(AXI-Taffric-Generator)ATG这个IP,于是出于兴趣就阅读了《PG-125 AXI Traffic Generator》了解了一下这个IP核。ATG起到了生成多种AXI数据类型的主机端数据流的作用。我对其中的System Init/System Test模式了解比较多一点,该模式可以提供AXI4-LITE接口的数据产生,个人觉得非常方便。在使用该模式时碰到了关于COE文件配置的问题,网上找到的答案比较模糊,手册上也没有详细说明,自己搞清楚之后觉得可以写出来分享分享。

IP核的配置

IP核的配置还是十分简单的,看一下手册就明白了,可以配置操作长度(最多256个)等。
image.png

COE文件的配置

在该IP核的System Test模式下需要使用COE(Coefficient)文件来传递参数。
COE文件是一种ASCII文本文件,文件头部定义数据基数(Radix),可以是2、10或16。数据以向量的形式给出,每个向量以分号结尾。Vivado会解析COE文件格式,并在生成IP核时导出相关的MIF格式文件,用于行为级仿真。

ATG核需要配置四种COE文件,分别是ADDRESS.COE用于配置读写地址、DATA.COE用于配置写入数据、MASK.COE用于配置数据掩码、CONTROL.COE用于配置读写操作。由于每个配置文件的格式都有稍许不同,下面分开说明。

Address.coe的配置

memory_initialization_radix=16;
memory_initialization_vector=40 44 48 4c 50 54 58 5c 40 44 48 4c 50 54 58 5c ffffffff;

第一行表示参数为16进制,第二行中的地址参数的FFFFFFFF表示结束标志。
每一次的读/写地址用逗号或者空格隔开。

DATA.coe的配置

memory_initialization_radix=16;
memory_initialization_vector=1 2 3 4 a b c d 1 2 3 4 a b c d f;

数据的配置就没什么好说的了,注意一点无论该次是读或者写操作都需要在对应位置上填上数据。

MASK.coe的配置

memory_initialization_radix=16;
memory_initialization_vector=00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000;

image.png
掩码的配置也没什么好说的,掩码的1bit对应数据的4bit。

Control.coe的配置

memory_initialization_radix=16;
memory_initialization_vector=10100 10200 10300 10400 10500 10600 10700 10800 00900 00a00 00b00 00c00 00d00 00e00 00f00 01000 01100;

重点讲一下Control.coe的配置
image.png

image.png

结合上面这个示意图能方便说明。可以把每次读或者写操作称为一次"Transaction",配置中的"Transaction"按照先后顺序排列成序列。Control参数的bit[16]为读/写操作控制、bit[15:8]表示如果当次读写操作成功,则跳转到下一次操作序列的编号、bit[7:0]表示如果当次读写操作失败,则跳转到下一次操作序列的编号,如下图所示。
image
至此,ATG核的配置差不多就到这里了,如果要产生的AXI4-LITE数据比较多的话据说是可以利用MATLAB来产生,这个可以后续再了解一下。

ATG核的使用

输入信号时序说明

以下几个输入信号:awready wready bvalid arready rready需要与其对应的valid/ready信号满足一定时序关系。比如可以使ready信号默认拉高,当接收到其对应的valid信号为高时,ready信号拉低,完成一次握手。在查阅资料时发现大部分的AXI接口IP核都有这样的时序要求,这点需要注意一下。
image.png

always @ (posedge clk_100m or negedge rst_n)
begin
	if(rst_n == 1'b0)
	arready <= U_DLY 1'b0;
	else if (awvalid == 1'b1)
	arready <= U_DLY 1'b0;
	else
	arready <= U_DLY 1'b1;
end

Example Design

Xilinx给出的Example Design是ATG核往AXI Bram中读写数据来进行仿真测试的,需要将Bram核配置成AXI-LITE接口。
连接模块和TestBench如下。

module axi_traffic_test_top #(
    parameter   U_DLY               = 1'b1          
)(
    input                           rst_n                       , 
    input                           clk_100m                    , 
    output                          done                          
);

//Wire Define
wire                       [31 : 0] m_axi_lite_ch1_awaddr       ; 
wire                       [2 : 0 ] m_axi_lite_ch1_awprot       ; 
wire                                m_axi_lite_ch1_awvalid      ; 
wire                                m_axi_lite_ch1_awready      ; 
wire                       [31 : 0] m_axi_lite_ch1_wdata        ; 
wire                       [3 : 0 ] m_axi_lite_ch1_wstrb        ; 
wire                                m_axi_lite_ch1_wvalid       ; 
wire                                m_axi_lite_ch1_wready       ; 
wire                       [1 : 0 ] m_axi_lite_ch1_bresp        ; 
wire                                m_axi_lite_ch1_bvalid       ; 
wire                                m_axi_lite_ch1_bready       ; 
wire                       [31 : 0] m_axi_lite_ch1_araddr       ; 
wire                                m_axi_lite_ch1_arvalid      ; 
wire                                m_axi_lite_ch1_arready      ; 
wire                       [31 : 0] m_axi_lite_ch1_rdata        ; 
wire                                m_axi_lite_ch1_rvalid       ; 
wire                                m_axi_lite_ch1_rready       ; 
wire                       [1 : 0 ] m_axi_lite_ch1_rresp        ; 
wire                                m_axi_lite_ch1_rlast        ; 
wire                         [31:0] status_i                    ; 

axi_traffic_gen
u_axi_traffic_gen
(
    .s_axi_aclk                     (clk_100m                   ), //(input) 
    .s_axi_aresetn                  (rst_n                      ), //(input) 
    .m_axi_lite_ch1_awaddr          (m_axi_lite_ch1_awaddr      ), //(output) 
    .m_axi_lite_ch1_awprot          (m_axi_lite_ch1_awprot      ), //(output) 
    .m_axi_lite_ch1_awvalid         (m_axi_lite_ch1_awvalid     ), //(output) 
    .m_axi_lite_ch1_awready         (m_axi_lite_ch1_awready     ), //(input) 
    .m_axi_lite_ch1_wdata           (m_axi_lite_ch1_wdata       ), //(output) 
    .m_axi_lite_ch1_wstrb           (m_axi_lite_ch1_wstrb       ), //(output) 
    .m_axi_lite_ch1_wvalid          (m_axi_lite_ch1_wvalid      ), //(output) 
    .m_axi_lite_ch1_wready          (m_axi_lite_ch1_wready      ), //(input) 
    .m_axi_lite_ch1_bresp           (m_axi_lite_ch1_bresp       ), //(input) 
    .m_axi_lite_ch1_bvalid          (m_axi_lite_ch1_bvalid      ), //(input) 
    .m_axi_lite_ch1_bready          (m_axi_lite_ch1_bready      ), //(output) 
    .m_axi_lite_ch1_araddr          (m_axi_lite_ch1_araddr      ), //(output) 
    .m_axi_lite_ch1_arvalid         (m_axi_lite_ch1_arvalid     ), //(output) 
    .m_axi_lite_ch1_arready         (m_axi_lite_ch1_arready     ), //(input),
    .m_axi_lite_ch1_rdata           (m_axi_lite_ch1_rdata       ), //(input) 
    .m_axi_lite_ch1_rvalid          (m_axi_lite_ch1_rvalid      ), //(output) 
    .m_axi_lite_ch1_rready          (m_axi_lite_ch1_rready      ), //(output) 
    .m_axi_lite_ch1_rresp           (m_axi_lite_ch1_rresp       ), //(input) 
    .done                           (done                       ), //(output) 
    .status                         (status_i                   )  //(output) 
);

axi4lite_bram 
u_responder 
(
    .s_axi_aclk                     (clk_100m                   ), 
    .s_axi_aresetn                  (rst_n                      ), 
    .s_axi_awaddr                   (m_axi_lite_ch1_awaddr[11 :0]), 
    .s_axi_awprot                   (m_axi_lite_ch1_awprot      ), 
    .s_axi_awvalid                  (m_axi_lite_ch1_awvalid     ), 
    .s_axi_awready                  (m_axi_lite_ch1_awready     ), 
    .s_axi_wdata                    (m_axi_lite_ch1_wdata       ), 
    .s_axi_wstrb                    (m_axi_lite_ch1_wstrb       ), 
    .s_axi_wvalid                   (m_axi_lite_ch1_wvalid      ), 
    .s_axi_wready                   (m_axi_lite_ch1_wready      ), 
    .s_axi_bresp                    (m_axi_lite_ch1_bresp       ), 
    .s_axi_bvalid                   (m_axi_lite_ch1_bvalid      ), 
    .s_axi_bready                   (m_axi_lite_ch1_bready      ), 
    .s_axi_arprot                   (3'd0                       ), 
    .s_axi_araddr                   (m_axi_lite_ch1_araddr[11 : 0]), 
    .s_axi_arvalid                  (m_axi_lite_ch1_arvalid     ), 
    .s_axi_arready                  (m_axi_lite_ch1_arready     ), 
    .s_axi_rdata                    (m_axi_lite_ch1_rdata       ), 
    .s_axi_rresp                    (m_axi_lite_ch1_rresp       ), 
    .s_axi_rvalid                   (m_axi_lite_ch1_rvalid      ), 
    .s_axi_rready                   (m_axi_lite_ch1_rready      )  
);
endmodule

module sim_atg_top #(
    parameter   U_DLY               = 1'b1          
)(


);
//Local Parameter Define

//Register Define
reg                                 rst_n                       ; 
reg                                 clk_100m                  ; 

//Wire Define

initial begin
clk_100m = 0;
forever clk_100m = #5 ~clk_100m;
end

initial begin
    rst_n = 1'b0;
    #1500 rst_n =1'b1;
    #4000 rst_n = 1'b0;
    #10 rst_n = 1'b1;
end

axi_traffic_test_top
u_test_top
(
    .rst_n                          (rst_n                      ), 
    .clk_100m                       (clk_100m                   ), 
    .done                           (done                       )  
);

endmodule