首页 > 其他分享 >03 AXI4总线axi-lite-master

03 AXI4总线axi-lite-master

时间:2023-12-30 14:56:25浏览次数:30  
标签:03 begin axi end read write master lite AXI

软件版本:vitis2021.1(vivado2021.1)

操作系统:WIN10 64bit

硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA

登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!

2.1概述

使用XILINX 的软件工具VIVADO以及XILINX的7代以上的FPGA或者SOC掌握AXI-4总线结束,并且可以灵活使用AXI-4总线技术完成数据的交换,可以让我们在构建强大的FPGA内部总线数据互联通信方面取得高效、高速、标准化的优势。

关于AXI4总线协议的部分介绍请阅读"01AXI4总线axi-lite-slave"。

本文实验目的:

1:掌握基于VIVADO工具产生AXI协议模板

2:掌握通过VIVADO工具产生AXI-lite-master代码

3:理解AXI-lite-master中自定义寄存器的地址分配

4:掌握通过VIVADO封装AXI-lite-master图形化IP

5:通过仿真验证AXI-lite-master IP的工作是否正常。

2.2创建axi4-lite-master总线接口IP

新建fpga工程,过程省略

新建完成工程后,单击菜单栏Tools->Create and Package New IP,开始创建一个AXI4-Lite接口总线IP

选择使用vivado自带的AXI总线模板创建一个AXI4-Lite接口IP

设置IP的名字为maxi_lite

模板支持3种协议,分别是AXI4-Full ,AXI4-Lite ,AXI4-Stream

总线包括Master和Slave两种模式,这里选择Master模式

这里选择Verify Peripheral IP using AXI4 VIP 可以对AXI4-Lite快速验证

单击Finish 后展开VIVADO自动产生的demo,单击Block Design的工程,可以看到如下2个IP。其中maxi_lite_0就是我们自定义的IP,另外一个slave_0是用来验证maxi_lite_0正确性。

采用默认地址分配即可

 

继续再看代码看看里面有什么东西

路径uisrc/03_ip/ maxi_lite_1.0/hdl路径下的maxi_lite_v1_0_M00_AXI.v就是我们的源码。另外一个maxi_lite_v1_0.v是软件产生了一个接口文件,如果我们自己定义IP可有可无。

2.3程序分析

axi总线信号的关键无非是地址和数据,而写地址的有效取决于AXI_AWVALID和AXI_AWREADY,写数据的有效取决于S_AXI_WVALID和S_AXI_WREADY。同理,读地址的有效取决于AXI_ARVALID和AXI_ARREADY,读数据的有效取决于S_AXI_RVALID和S_AXI_RREADY。所以以下代码的阅读分析注意也是围绕以上4个信号的有效时序。

以下程序我们把关键信号的代码拆分阅读

1:产生初始化信号

    always @(posedge M_AXI_ACLK)                                              

      begin                                                                        

        // Initiates AXI transaction delay    

        if (M_AXI_ARESETN == 0 )                                                  

          begin                                                                    

            init_txn_ff <= 1'b0;                                                  

            init_txn_ff2 <= 1'b0;                                                  

          end                                                                              

        else                                                                      

          begin  

            init_txn_ff <= INIT_AXI_TXN;

            init_txn_ff2 <= init_txn_ff;                                                                

          end                                                                      

      end  

2:axi-lite-master的axi_awvalid

当start_single_write有效,开始一次写传输,设置axi_awvalid有效。

      always @(posedge M_AXI_ACLK)                                            

      begin                                                                        

        //Only VALID signals must be deasserted during reset per AXI spec          

        //Consider inverting then registering active-low reset for higher fmax    

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                  

          begin                                                                    

            axi_awvalid <= 1'b0;                                                  

          end                                                                      

          //用户逻辑发出新地址/数据命令的信号         

        else                                                                      

          begin                                                                    

            if (start_single_write)                                                

              begin                                                                

                axi_awvalid <= 1'b1;                                              

              end                                                                  

         //Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave)

            else if (M_AXI_AWREADY && axi_awvalid)                                

              begin                                                                

                axi_awvalid <= 1'b0;                                              

              end                                                                  

          end                                                                      

      end

3:axi-lite-master的axi_awaddr

      always @(posedge M_AXI_ACLK)                                  

          begin                                                    

            if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                

              begin                                                

                axi_awaddr <= 0;                                    

              end                                                  

              // Signals a new write address/ write data is        

              // available by user logic                            

            else if (M_AXI_AWREADY && axi_awvalid)                  

              begin                                                

                axi_awaddr <= axi_awaddr + 32'h00000004;            

                                                                     

              end                                                  

          end  

4:axi-lite-master的axi_wvalid

当M_AXI_WREADY && axi_wvalid同时有效的时候,数据才是有效的,对于axi-lite_master接口,M_AXI_WREADY && axi_wvalid同时有效的时间窗口是一个时钟周期。

       always @(posedge M_AXI_ACLK)                                        

       begin                                                                        

         if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                                    

           begin                                                                    

             axi_wvalid <= 1'b0;                                                    

           end                                                                      

         //Signal a new address/data command is available by user logic              

         else if (start_single_write)                                                

           begin                                                                    

             axi_wvalid <= 1'b1;                                                    

           end                                                                      

         //Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave)      

         else if (M_AXI_WREADY && axi_wvalid)                                        

           begin                                                                    

            axi_wvalid <= 1'b0;                                                      

           end                                                                      

       end  

5:axi-lite-master的axi_wdata

产生写测试用的测试数据

      always @(posedge M_AXI_ACLK)                                  

          begin                                                    

            if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                

              begin                                                

                axi_wdata <= C_M_START_DATA_VALUE;                  

              end                                                  

            // Signals a new write address/ write data is          

            // available by user logic                              

            else if (M_AXI_WREADY && axi_wvalid)                    

              begin                                                

                axi_wdata <= C_M_START_DATA_VALUE + write_index;    

              end                                                  

            end

6:写次数记录write_index计数器

这个demo中以start_single_wirte信号作为统计的,如果我们完全自定axi-lite_master代码可以自行优化,可以写出更好的代码。我们这里是用vivado模板产生的代码主要是教会大家如何使用现有的手段和软件工具学习axi4总线。

      always @(posedge M_AXI_ACLK)                                                

      begin                                                                        

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                  

          begin                                                                    

            write_index <= 0;                                                      

          end                                                                      

          // Signals a new write address/ write data is                            

          // available by user logic                                              

        else if (start_single_write)                                              

          begin                                                                    

            write_index <= write_index + 1;                                        

          end                                                                      

      end

7:axi-lite-master的axi_bready

当收到写通道的axi-lite-slave发回的M_AXI_BVALDI应答信号,设置axi_bready为1,BRESP返回AXI写操作是否有错误。

      always @(posedge M_AXI_ACLK)                                    

      begin                                                                

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                          

          begin                                                            

            axi_bready <= 1'b0;                                            

          end                                                              

        // accept/acknowledge bresp with axi_bready by the master          

        // when M_AXI_BVALID is asserted by slave                          

        else if (M_AXI_BVALID && ~axi_bready)                              

          begin                                                            

            axi_bready <= 1'b1;                                            

          end                                                              

        // deassert after one clock cycle                                  

        else if (axi_bready)                                              

          begin                                                            

            axi_bready <= 1'b0;                                            

          end                                                              

        // retain the previous value                                      

        else                                                              

          axi_bready <= axi_bready;                                        

      end                                                                  

                                                                             

    //Flag write errors                                                    

    assign write_resp_error = (axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]);

8:axi-lite-master的axi_arvalid

      always @(posedge M_AXI_ACLK)                                                    

      begin                                                                            

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                      

          begin                                                                        

            axi_arvalid <= 1'b0;                                                      

          end                                                                          

        //Signal a new read address command is available by user logic                

        else if (start_single_read)                                                    

          begin                                                                        

            axi_arvalid <= 1'b1;                                                      

          end                                                                          

        //RAddress accepted by interconnect/slave (issue of M_AXI_ARREADY by slave)    

        else if (M_AXI_ARREADY && axi_arvalid)                                        

          begin                                                                        

            axi_arvalid <= 1'b0;                                                      

          end                                                                          

        // retain the previous value                                                  

      end    

9:axi-lite-master的axi_araddr

      always @(posedge M_AXI_ACLK)                                  

          begin                                                    

            if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                

              begin                                                

                axi_awaddr <= 0;                                    

              end                                                  

              // Signals a new write address/ write data is        

              // available by user logic                            

            else if (M_AXI_AWREADY && axi_awvalid)                  

              begin                                                

                axi_awaddr <= axi_awaddr + 32'h00000004;            

                                                                     

              end                                                  

          end

10:axi-lite-master的axi_rready

当M_AXI_RVALID && axi_rready同时有效的时候,数据才是有效的,对于axi-lite_master接口,M_AXI_RVALID && ~axi_rready==1的时候设置axi_rready=1,当axi_rready==1,再设置axi_rready=0

      always @(posedge M_AXI_ACLK)                                    

      begin                                                                

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                            

          begin                                                            

            axi_rready <= 1'b0;                                            

          end                                                              

        // accept/acknowledge rdata/rresp with axi_rready by the master    

        // when M_AXI_RVALID is asserted by slave                          

        else if (M_AXI_RVALID && ~axi_rready)                              

          begin                                                            

            axi_rready <= 1'b1;                                            

          end                                                              

        // deassert after one clock cycle                                  

        else if (axi_rready)                                                

          begin                                                            

            axi_rready <= 1'b0;                                            

          end                                                              

        // retain the previous value                                        

      end                                                                  

                                                                             

    //Flag write errors                                                    

    assign read_resp_error = (axi_rready & M_AXI_RVALID & M_AXI_RRESP[1]);  

11:axi-lite-master的M_AXI_RDATA

当M_AXI_RVALID && axi_rready都有效的时候,对读取的M_AXI_RDATA数据和expected_rdata数据进行比较。

      always @(posedge M_AXI_ACLK)                                                      

      begin                                                                            

        if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                                        

        read_mismatch <= 1'b0;                                                          

                                                                                         

        //The read data when available (on axi_rready) is compared with the expected data

        else if ((M_AXI_RVALID && axi_rready) && (M_AXI_RDATA != expected_rdata))        

          read_mismatch <= 1'b1;                                                        

        else                                                                            

          read_mismatch <= read_mismatch;                                              

      end  

12:产生对比数据expected_rdata

数据expected_rdata用于和读出的M_AXI_RDATA进行对比以此验证数据的正确性。

      always @(posedge M_AXI_ACLK)                                  

          begin                                                    

            if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                

              begin                                                

                axi_wdata <= C_M_START_DATA_VALUE;                  

              end                                                  

            // Signals a new write address/ write data is          

            // available by user logic                              

            else if (M_AXI_WREADY && axi_wvalid)                    

              begin                                                

                axi_wdata <= C_M_START_DATA_VALUE + write_index;    

              end                                                  

            end                                                    

13:读次数记录read_index计数器

这个demo中以start_single_read信号作为统计的,如果我们完全自定axi-lite_master代码可以自行优化,可以写出更好的代码。我们这里是用vivado模板产生的代码主要线教会大家如何使用现有的手段和软件工具学习axi4总线。

      always @(posedge M_AXI_ACLK)                                                    

      begin                                                                            

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                      

          begin                                                                        

            read_index <= 0;                                                          

          end                                                                          

        // Signals a new read address is                                              

        // available by user logic                                                    

        else if (start_single_read)                                                    

          begin                                                                        

            read_index <= read_index + 1;                                              

          end                                                                          

      end  

14:axi-lite-master的状态机

      always @(posedge M_AXI_ACLK)                                  

          begin                                                    

            if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                

              begin                                                

                expected_rdata <= C_M_START_DATA_VALUE;            

              end                                                  

              // Signals a new write address/ write data is        

              // available by user logic                            

            else if (M_AXI_RVALID && axi_rready)                    

              begin                                                

                expected_rdata <= C_M_START_DATA_VALUE + read_index;

              end                                                  

          end                                                      

      //implement master command interface state machine                        

      always @ ( posedge M_AXI_ACLK)                                                    

      begin                                                                            

        if (M_AXI_ARESETN == 1'b0)                                                    

          begin                                                                        

          // reset condition                                                            

          // All the signals are assigned default values under reset condition          

            mst_exec_state  <= IDLE;                                            

            start_single_write <= 1'b0;                                                

            write_issued  <= 1'b0;                                                      

            start_single_read  <= 1'b0;                                                

            read_issued   <= 1'b0;                                                      

            compare_done  <= 1'b0;                                                      

            ERROR <= 1'b0;

          end                                                                          

        else                                                                            

          begin                                                                        

           // state transition                                                          

            case (mst_exec_state)                                                      

                                                                                         

              IDLE:                                                            

              // This state is responsible to initiate

              // AXI transaction when init_txn_pulse is asserted

                if ( init_txn_pulse == 1'b1 )                                    

                  begin                                                                

                    mst_exec_state  <= INIT_WRITE;                                      

                    ERROR <= 1'b0;

                    compare_done <= 1'b0;

                  end                                                                  

                else                                                                    

                  begin                                                                

                    mst_exec_state  <= IDLE;                                    

                  end                                                                  

                                                                                         

              INIT_WRITE:                                                              

                // This state is responsible to issue start_single_write pulse to      

                // initiate a write transaction. Write transactions will be            

                // issued until last_write signal is asserted.                          

                // write controller                                                    

                if (writes_done)                                                        

                  begin                                                                

                    mst_exec_state <= INIT_READ;//                                      

                  end                                                                  

                else                                                                    

                  begin                                                                

                    mst_exec_state  <= INIT_WRITE;                                      

                                                                                         

                      if (~axi_awvalid && ~axi_wvalid && ~M_AXI_BVALID && ~last_write && ~start_single_write && ~write_issued)

                        begin                                                          

                          start_single_write <= 1'b1;                                  

                          write_issued  <= 1'b1;                                        

                        end                                                            

                      else if (axi_bready)                                              

                        begin                                                          

                          write_issued  <= 1'b0;                                        

                        end                                                            

                      else                                                              

                        begin                                                          

                          start_single_write <= 1'b0; //Negate to generate a pulse      

                        end                                                            

                  end                                                                  

                                                                                         

              INIT_READ:                                                                

                // This state is responsible to issue start_single_read pulse to        

                // initiate a read transaction. Read transactions will be              

                // issued until last_read signal is asserted.                          

                 // read controller                                                    

                 if (reads_done)                                                        

                   begin                                                                

                     mst_exec_state <= INIT_COMPARE;                                    

                   end                                                                  

                 else                                                                  

                   begin                                                                

                     mst_exec_state  <= INIT_READ;                                      

                                                                                         

                     if (~axi_arvalid && ~M_AXI_RVALID && ~last_read && ~start_single_read && ~read_issued)

                       begin                                                            

                         start_single_read <= 1'b1;                                    

                         read_issued  <= 1'b1;                                          

                       end                                                              

                     else if (axi_rready)                                              

                       begin                                                            

                         read_issued  <= 1'b0;                                          

                       end                                                              

                     else                                                              

                       begin                                                            

                         start_single_read <= 1'b0; //Negate to generate a pulse        

                       end                                                              

                   end                                                                  

                                                                                         

               INIT_COMPARE:                                                            

                 begin

                     // This state is responsible to issue the state of comparison          

                     // of written data with the read data. If no error flags are set,      

                     // compare_done signal will be asseted to indicate success.            

                     ERROR <= error_reg;

                     mst_exec_state <= IDLE;                                    

                     compare_done <= 1'b1;                                              

                 end                                                                  

               default :                                                                

                 begin                                                                  

                   mst_exec_state  <= IDLE;                                    

                 end                                                                    

            endcase                                                                    

        end                                                                            

      end //MASTER_EXECUTION_PROC                    

 

整理成流程图,更加容易理解:

15:最后一个写数据

      always @(posedge M_AXI_ACLK)                                                      

      begin                                                                            

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                        

          last_write <= 1'b0;                                                                                                                                          

        //The last write should be associated with a write address ready response      

        else if ((write_index == C_M_TRANSACTIONS_NUM) && M_AXI_AWREADY)                

          last_write <= 1'b1;                                                          

        else                                                                            

          last_write <= last_write;                                                    

      end                                                                              

                                                                                         

      //Check for last write completion.                                                                                                                           

      //This logic is to qualify the last write count with the final write              

      //response. This demonstrates how to confirm that a write has been                

      //committed.                                                                      

                                                                                         

      always @(posedge M_AXI_ACLK)                                                      

      begin                                                                            

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                        

          writes_done <= 1'b0;                                                          

                                                                                         

          //The writes_done should be associated with a bready response                

        else if (last_write && M_AXI_BVALID && axi_bready)                              

          writes_done <= 1'b1;                                                          

        else                                                                            

          writes_done <= writes_done;                                                  

      end      

16:最后一个读数据

      always @(posedge M_AXI_ACLK)                                                      

      begin                                                                            

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                        

          last_read <= 1'b0;                                                            

                                                                                         

        //The last read should be associated with a read address ready response        

        else if ((read_index == C_M_TRANSACTIONS_NUM) && (M_AXI_ARREADY) )              

          last_read <= 1'b1;                                                            

        else                                                                            

          last_read <= last_read;                                                      

      end                                                                              

                                                                                         

    /*   Check for last read completion.                                                                                                                                 

     This logic is to qualify the last read count with the final read response/data.   */                

                                                                                 

      always @(posedge M_AXI_ACLK)                                                      

      begin                                                                            

        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                        

          reads_done <= 1'b0;                                                                                                                              

        //The reads_done should be associated with a read ready response                

        else if (last_read && M_AXI_RVALID && axi_rready)                              

          reads_done <= 1'b1;                                                          

        else                                                                            

          reads_done <= reads_done;                                                    

        end    

2.4实验结果

具体的仿真方法省略,以下是仿真结果。

 

标签:03,begin,axi,end,read,write,master,lite,AXI
From: https://www.cnblogs.com/milianke/p/17936357.html

相关文章

  • 05 AXI4总线axi-full-master
    软件版本:vitis2021.1(vivado2021.1)操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!1概述使用XILINX的软件工具VIVADO以及XILINX的7代以上的FPGA或者SOC掌握AXI-4总线结束,并且可以灵活使用AXI-4总线技......
  • 02 AXI4总线axi-lite-slave
    软件版本:vitis2021.1(vivado2021.1)操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!1概述使用XILINX的软件工具VIVADO以及XILINX的7代以上的FPGA或者SOC掌握AXI-4总线协议,并且可以灵活使用AXI-4总线技......
  • 03使用fdma读写axi-bram测试
    软件版本:vitis2021.1(vivado2021.1)操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!3.1概述    FDMA是米联客基于AXI4总线协议定制的一个DMA控制器。有了这个IP我们可以统一实现用FPGA代码直接读写P......
  • 3-1-01 AXI4-FULL-MASTER IP FDMA介绍
    件版本:vitis2021.1(vivado2021.1)操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!1.1概述    FDMA是米联客的基于AXI4总线协议定制的一个DMA控制器。本文对AXI4-FULL总线接口进行了封装,同时定义了简......
  • check the manual that corresponds to your MySQL server version for the right syn
    form:{repairstatus:0,name:'',//负责人maintenancetime:newDate().toISOString().split('T')[0],//保修时间equipmentid:'',equipment:'',describe:'',finfishtime:'',repairname:'�......
  • 1-1-03 XILINX JTAG开发工具usb-jtag驱动安装
    1.1概述    一般安装vitis(vivado)的过程中勾选了安装jtagcable驱动就会默认安装好jtag驱动,但是如果vivado无法正确识别到JTAG,那么可以试下重新手动安装驱动1.2准备工作安装驱动前,必须关闭所有的vivado,vitis-sdk并且拔掉USBJTAG以免导致安装失败1.3usb-jtag驱动安装......
  • 代码随想录day03 链表删除 链表类的实现 反转链表
    首先是链表的删除操作热身题这里使用了一个新的头指针这样在删除头指针的时候就不需要进行额外的判断然后是链表类的实现需要一点背诵加上深刻理解有时候理解了但是写起来还是会有些指针边界的小问题应该多写写多记一下就会好了还有就是手写链表要常复习吧学习新......
  • 用python打开文件获取文件属性时,运行报错PermissionError: [Errno 13] Permission den
    一:概述在开发中我们经常会使用python程序去对物理主机平台上的文件进行操作,在这里说明一下,python中获取文件属性时,运行出现的错误。二:具体说明<1>获取文件属性的代码importos#创建一个临时目录temp_dir='temp'os.mkdir(temp_dir)#在临时目录中创建一个文件temp_file=o......
  • OpenEuler22.03安装PostgreSQL15.5并配置一主二从
    环境准备序号IP标识(hostname)CPU/内存配置系统盘数据盘1192.168.8.190pg018C+16G80G500G2192.168.8.191pg028C+16G80G500G3192.168.8.192pg038C+16G80G500G规划的文件夹目录(所有主机):##以下目录为本文规划的目录,可以提前创建,也可以跟着......
  • 【五期李伟平】CCF-B(TFS'23)Consensus Reaching Process With Multiobjective Optimiza
    PengWu,FengenLi,JieZhao,etal.ConsensusReachingProcessWithMultiobjectiveOptimizationforLarge-ScaleGroupDecisionMakingWithCooperativeGame[J].IEEETransactionsonFuzzySystems2023:293-306.  本文针对大规模群体决策(LSGDM)中的共识达成......