基于Axi4_lite协议的自定义IP仿真平台的搭建

  做FPGA开发离不开仿真,仿真对于FPGA的调试开发起到了很好的辅助作用。对于新手而言仿真就更加重要了,老练的FPGA开发者时序了然于胸,对于简单的IP核开发是可以省略仿真的步骤,但是对于绝大多数的情况而言,仿真不仅能提高工作效率,而且能够提高开发者的时序分析能力。仿真是验证最常用的手段,虽说现在很多FPGA里头集成了逻辑分析,但是直接上板调试还是会损耗不少的时间,一方面是跑综合需要足够的时间,另一方面板上调试的资源有限,很多的错误并不能合理的排查。以此在写完代码后最好是先做仿真,仿真没问题了再上板调试。

  正常情况下仿真都会用到仿真工具,我一般用的仿真工具是modelsim,vivado虽说也有自带的仿真,但是使用起来不仅麻烦,而且时序会跟modelsim的有些偏差。目前使用的modelsim版本为ModelSim SE-64 10.5,这是比较专业的仿真软件。对IP核进行仿真,除了以下的这种方式其实还可以使用更高级的仿真,那就是UVM,UVM对IP核的验证会更加专业及全面,不过UVM更像面向对象的语言,使用的是System Verilog,是一门方法学,比较难入门。它自带了完整的流程,IC验证方面用得可能更频繁,FPGA设计的仿真也可以使用这种方式。

  下面的仿真平台的搭建就是基于前面所讲的axi4_lite协议,对自定义IP核GPIO进行仿真。仿真代码是用System Verilog语言来完成,学过C或C++的应该能比较容易看懂,会Verilog语言的看SV语言应该难度也不大。

  一般封装好的IP会在一个文件夹下:

  文件夹下会放doc文件及ip文件,doc用来存放IP核的寄存器说明及操作文档,ip则用来放IP核的相关代码。

  ip文件下存放if,rtl,sim文件,if放封装时可能需自定义的接口,rtl放IP核源码,sim放仿真代码。

  rtl:

 

  sim:

  使用的时候直接双击run.bat文件即可,modelsim自动打开并仿真。

  run.bat代码:

1 modelsim -do sim.do

  sim.do代码:

 1 #删除work工作目录
 2 file delete -force work
 3     
 4 #设置uvm环境变量,指定uvm的dpi位置
 5 set UVM_DPI_HOME D:/modeltech64_10.5/uvm-1.1d/win64
 6 
 7 #创建work工作目录
 8 vlib work
 9 
10 #vlog表示编译 *.sv表示do文件同级路径下所有.sv文件 -L表示添加库文件
11 vlog -L mtiAvm -L mtiOvm -L mtiUvm -L mtiUPF *.sv
12 
13 #编译源文件,包含覆盖率测试
14 vlog -cover sbctf -coveropt 3 ../rtl/*.v
15 
16 #执行仿真,打开覆盖率窗口,不使能优化,调用uvm库uvm_dpi,利用UVM_TEST_NAME从命令行中寻找测试用例的名字,创建它的实例并运行
17 vsim -coverage -novopt -c -sv_lib $UVM_DPI_HOME/uvm_dpi work.Gpio_sim +UVM_TESTNAME=case0
18 
19 #观察DUT的信号波形
20 add wave -position insertpoint sim:/Gpio_sim/u_Axi4_Gpio/*
21 
22 run 10ms

  顶层仿真文件Gpio_sim.sv:

  1 //**************************************************************************
  2 // *** file name      : Gpio_sim.sv
  3 // *** version        : 1.0
  4 // *** Description    : Gpio IP core testbech
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.4.7        
  8 // *** Changes        :       
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 `define GPIO_NUM 32
 12 
 13 module Gpio_sim();
 14     
 15 /******************************************************************************\   
 16 Define AXI4-lite interface port
 17 \******************************************************************************/        
 18     wire                w_axi_aclk       ;
 19     wire                w_axi_aresetn    ;
 20     
 21     wire    [31:0]      w_axi_awaddr     ;
 22     wire                w_axi_awvalid    ;
 23     wire                w_axi_awready    ;
 24     
 25     wire    [31:0]      w_axi_wdata      ;
 26     wire    [3:0]       w_axi_wstrb      ;
 27     wire                w_axi_wvalid     ;
 28     wire                w_axi_wready     ;
 29     
 30     wire    [1:0]       w_axi_bresp      ;
 31     wire                w_axi_bvalid     ;
 32     wire                w_axi_bready     ;
 33     
 34     wire    [31:0]      w_axi_araddr     ;
 35     wire                w_axi_arvalid    ;
 36     wire                w_axi_arready    ;
 37     
 38     wire    [31:0]      w_axi_rdata      ;
 39     wire    [1:0]       w_axi_rresp      ;
 40     wire                w_axi_rvalid     ;
 41     wire                w_axi_rready     ;
 42     
 43 /******************************************************************************\   
 44 Instantiate AXI4-lite master module
 45 \******************************************************************************/
 46     m_axi4_lite_if u_m_axi4_lite_if
 47     (
 48         .o_sys_clk                 (w_axi_aclk                ),
 49         .o_sys_rstn                (w_axi_aresetn             ),
 50         .o_m_axi_awaddr            (w_axi_awaddr              ),
 51         .o_m_axi_awvalid           (w_axi_awvalid             ),
 52         .i_m_axi_awready           (w_axi_awready             ),
 53         .o_m_axi_wdata             (w_axi_wdata               ),
 54         .o_m_axi_wstrb             (w_axi_wstrb               ),
 55         .o_m_axi_wvalid            (w_axi_wvalid              ),
 56         .i_m_axi_wready            (w_axi_wready              ),
 57         .i_m_axi_bresp             (w_axi_bresp               ),
 58         .i_m_axi_bvalid            (w_axi_bvalid              ),
 59         .o_m_axi_bready            (w_axi_bready              ),
 60         .o_m_axi_araddr            (w_axi_araddr              ),
 61         .o_m_axi_arvalid           (w_axi_arvalid             ),
 62         .i_m_axi_arready           (w_axi_arready             ),
 63         .i_m_axi_rdata             (w_axi_rdata               ),
 64         .i_m_axi_rresp             (w_axi_rresp               ),
 65         .i_m_axi_rvalid            (w_axi_rvalid              ),
 66         .o_m_axi_rready            (w_axi_rready              )
 67     );
 68     
 69 /******************************************************************************\   
 70 Instantiate AXI4-lite slave IP core
 71 \******************************************************************************/
 72     reg        [31:0]        r_gpio_i;
 73     Axi4_Gpio    
 74     #( 
 75         .IO_NUM    (`GPIO_NUM)                
 76     )    
 77     u_Axi4_Gpio
 78     (
 79         .i_s_axi_aclk              (w_axi_aclk                ),    
 80         .i_s_axi_aresetn           (w_axi_aresetn             ),   
 81         .i_s_axi_awaddr            (w_axi_awaddr              ),     
 82         .i_s_axi_awprot            ('d0                       ),     
 83         .i_s_axi_awvalid           (w_axi_awvalid             ),  
 84         .o_s_axi_awready           (w_axi_awready             ),  
 85         .i_s_axi_wdata             (w_axi_wdata               ),    
 86         .i_s_axi_wstrb             (w_axi_wstrb               ),    
 87         .i_s_axi_wvalid            (w_axi_wvalid              ),     
 88         .o_s_axi_wready            (w_axi_wready              ),     
 89         .o_s_axi_bresp             (w_axi_bresp               ),    
 90         .o_s_axi_bvalid            (w_axi_bvalid              ),     
 91         .i_s_axi_bready            (w_axi_bready              ),     
 92         .i_s_axi_araddr            (w_axi_araddr              ),     
 93         .i_s_axi_arprot            ('d0                       ),     
 94         .i_s_axi_arvalid        (w_axi_arvalid             ),  
 95         .o_s_axi_arready           (w_axi_arready             ),  
 96         .o_s_axi_rdata             (w_axi_rdata               ),    
 97         .o_s_axi_rresp             (w_axi_rresp               ),    
 98         .o_s_axi_rvalid            (w_axi_rvalid              ),     
 99         .i_s_axi_rready            (w_axi_rready              ),      
100         
101         .i_gpio_if_i               (r_gpio_i                  ),
102         .o_gpio_if_o               (                          ),
103         .o_gpio_if_t               (                          )  
104     ); 
105     
106 
107     
108 /******************************************************************************\   
109 Perform the steps of IP core in sequence
110 \******************************************************************************/    
111     reg  [31:0] r_cpu_rd_data;
112     initial r_cpu_rd_data = 0;
113 
114 
115     initial
116     begin  
117         $display("start"); 
118         #2000;
119         u_m_axi4_lite_if.arm_write_data(32'h00000000,32'h5aa5a55a,4'hf);
120         #200;
121         u_m_axi4_lite_if.arm_write_data(32'h00000004,32'h5a00005a,4'hf);
122         #200;
123         u_m_axi4_lite_if.arm_read_data(32'h00000000,r_cpu_rd_data);
124         #200;
125         u_m_axi4_lite_if.arm_read_data(32'h00000004,r_cpu_rd_data);
126         #200;
127         r_gpio_i = 32'h1234567;
128         u_m_axi4_lite_if.arm_read_data(32'h00000008,r_cpu_rd_data);
129         $display("sim complete"); 
130     end
131 
132 endmodule

     产生激励模块m_axi4_lite_if.sv:

  1 //**************************************************************************
  2 // *** file name      : m_axi4_lite_if.sv
  3 // *** version        : 1.0
  4 // *** Description    : axi4_lite_if master
  5 // *** Blogs          : https://www.cnblogs.com/WenGalois123/
  6 // *** Author         : Galois_V
  7 // *** Date           : 2022.4.7        
  8 // *** Changes        :       
  9 //**************************************************************************
 10 `timescale 1ns/1ps
 11 
 12 module m_axi4_lite_if
 13 (
 14     output    reg                    o_sys_clk,
 15     output    reg                    o_sys_rstn,
 16     
 17     output    reg    [31:0]          o_m_axi_awaddr,
 18     output    reg                    o_m_axi_awvalid,
 19     input                            i_m_axi_awready,
 20     
 21     output    reg    [31:0]          o_m_axi_wdata,
 22     output    reg    [3:0]           o_m_axi_wstrb,
 23     output    reg                    o_m_axi_wvalid,
 24     input                            i_m_axi_wready,
 25     
 26     input        [1:0]               i_m_axi_bresp,
 27     input                            i_m_axi_bvalid,
 28     output    reg                    o_m_axi_bready,
 29     
 30     output    reg    [31:0]          o_m_axi_araddr,
 31     output    reg                    o_m_axi_arvalid,
 32     input                            i_m_axi_arready,
 33     
 34     input        [31:0]              i_m_axi_rdata,
 35     input        [1:0]               i_m_axi_rresp,
 36     input                            i_m_axi_rvalid,
 37     output    reg                    o_m_axi_rready
 38 );
 39 
 40     parameter               SYS_CLK = 100_000_000  ,
 41                             TIME_1S = 1000_000_000 ;
 42     
 43     
 44     real clk_cnt = TIME_1S/SYS_CLK;
 45 /******************************************************************************\   
 46 产生仿真环境需要的时钟与复位信号,这里的时钟信号为100MHz                                                      
 47 \******************************************************************************/    
 48     initial//所有的initial模块都是并行的,initial模块的语句是按顺序执行的。
 49     begin 
 50         o_sys_clk = 0;
 51         o_sys_rstn = 0;
 52         #1000;
 53         o_sys_rstn = 1;
 54     end
 55     
 56     always #(clk_cnt/2) o_sys_clk = ~o_sys_clk;
 57 
 58 /******************************************************************************\   
 59 先初始化axi4-lite的输出量信号                                                      
 60 \******************************************************************************/    
 61     initial
 62     begin 
 63         o_m_axi_awaddr         = 'd0;
 64         o_m_axi_awvalid        = 'd0;
 65         o_m_axi_wdata          = 'd0;
 66         o_m_axi_wstrb          = 'd0;
 67         o_m_axi_wvalid         = 'd0;
 68         o_m_axi_bready         = 'd0;
 69         o_m_axi_araddr         = 'd0;
 70         o_m_axi_arvalid        = 'd0;
 71         o_m_axi_rready         = 'd0;
 72     end
 73 /******************************************************************************\   
 74 通过axi4-lite总线写数据,写task                                                     
 75 \******************************************************************************/        
 76     task arm_write_data
 77     ( 
 78         input    [31:0]    i_addr , 
 79         input    [31:0]    i_data ,
 80         input    [3:0]     i_byte_en
 81     );
 82     begin
 83         @(posedge o_sys_clk)
 84         begin 
 85             o_m_axi_awaddr  = i_addr;
 86             o_m_axi_awvalid = 1'b1;
 87             o_m_axi_wdata   = i_data;
 88             o_m_axi_wstrb   = i_byte_en;
 89             o_m_axi_wvalid  = 1'b1;
 90             o_m_axi_bready  = 1'b1;
 91         end
 92         @(posedge o_sys_clk); 
 93         begin
 94             while(~(i_m_axi_awready & i_m_axi_wready))    //
 95             begin
 96                 @(posedge o_sys_clk)
 97                 begin
 98                     o_m_axi_awvalid = 1'b0;
 99                     o_m_axi_wvalid = 1'b0;
100                 end
101             end
102         end
103         
104         @(posedge o_sys_clk)
105         begin
106             while(~i_m_axi_bvalid)
107             begin
108                 @(posedge o_sys_clk)
109                 begin
110                     if(i_m_axi_bresp != 2'b00)
111                     begin
112                         $display("write fail");
113                     end
114                 end
115             end
116         end
117         
118         o_m_axi_bready = 1'b0;
119     end
120     endtask
121 
122 
123 /******************************************************************************\   
124 通过axi4-lite总线读数据,读task                                                  
125 \******************************************************************************/    
126     task arm_read_data
127     ( 
128         input    [31:0]    i_addr,
129         output    [31:0]    o_rdata
130     );
131     begin
132         @(posedge o_sys_clk)
133         begin
134             o_m_axi_araddr = i_addr;
135             o_m_axi_arvalid = 1'b1;
136             o_m_axi_rready = 1'b1;
137         end
138         
139         @(posedge o_sys_clk)
140         begin
141             while(~i_m_axi_arready)
142             begin
143                 @(posedge o_sys_clk)
144                 begin
145                     o_m_axi_arvalid = 1'b0;
146                 end
147             end
148         end
149         @(posedge o_sys_clk)
150         begin
151             o_rdata = i_m_axi_rdata;
152             while(~i_m_axi_rvalid)
153             begin
154                 if(i_m_axi_rresp!=2'b00)
155                 $display("read fail");
156             end
157         end
158         
159         o_m_axi_rready = 1'b0;
160     end
161     endtask
162 
163 endmodule

  以上便是整个axi4_lite 的仿真平台搭建,可以根据实际需要增加新的接口功能,比如axi4_stream接口这些等等。

  仿真的结果如下图:

 

posted on 2022-04-07 14:40  Galois_V  阅读(870)  评论(0编辑  收藏  举报