axi4-lite verilog源码以及注释

`timescale 1 ns / 1 ps

      modulemyip_v1_0_S00_AXI #
      (
            //Users to add parameters here

            //User parameters ends
            //Do not modify the parameters beyond this line

            //Width of S_AXI data bus
            parameterinteger C_S_AXI_DATA_WIDTH = 32,
            //Width of S_AXI address bus
            parameterinteger C_S_AXI_ADDR_WIDTH = 4
      )
      (
            //Users to add ports here

            //User ports ends
            //Do not modify the ports beyond this line

            //Global Clock Signal
            inputwire  S_AXI_ACLK,
            //Global Reset Signal. This Signal is Active LOW
            inputwire  S_AXI_ARESETN, //复位,低有效
            //Write address (issued by master, acceped by Slave)
            inputwire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR, //写地址,给出一次写突发传输的写地址
            //Write channel Protection type. This signal indicates the
                // privilege and security level ofthe transaction, and whether
                // the transaction is a data accessor an instruction access.
            inputwire [2 : 0] S_AXI_AWPROT,  //写通道保护类型。此信号表示事务的特权和安全级别,以及事务是数据访问还是指令访问。
            //Write address valid. This signal indicates that the master signaling
                // valid write address and controlinformation.
            inputwire  S_AXI_AWVALID, //写地址有效信号。此信号表示主信号有效的写入地址和控制信息
            //Write address ready. This signal indicates that the slave is ready
                // to accept an address and associatedcontrol signals.
            outputwire  S_AXI_AWREADY, //表明“从”可以接收地址和对应的控制信号
            //Write data (issued by master, acceped by Slave)
            inputwire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA, //写数据
            //Write strobes. This signal indicates which byte lanes hold
                // valid data. There is one writestrobe bit for each eight
                // bits of the write data bus.   
            inputwire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB, //写选通信号。 此信号指示哪个字节(8个wire)线保存有效数据。写入数据总线的每个八位有一个写选通位。
            //Write valid. This signal indicates that valid write
                // data and strobes are available.
            inputwire  S_AXI_WVALID, //写有效,表明此次写有效
            //Write ready. This signal indicates that the slave
                // can accept the write data.
            outputwire  S_AXI_WREADY,//表明从机可以接收写数据
            //Write response. This signal indicates the status
                // of the write transaction.
            outputwire [1 : 0] S_AXI_BRESP,//写响应,表明写传输的状态
            //Write response valid. This signal indicates that the channel
                // is signaling a valid writeresponse.
            outputwire  S_AXI_BVALID,//写响应有效
            //Response ready. This signal indicates that the master
                // can accept a write response.
            inputwire  S_AXI_BREADY,//表明主机能够接收写响应
            //Read address (issued by master, acceped by Slave)
            inputwire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,//      读地址,给出一次写突发传输的读地址
            //Protection type. This signal indicates the privilege
                // and security level of thetransaction, and whether the
                // transaction is a data access oran instruction access.
            inputwire [2 : 0] S_AXI_ARPROT,//保护类型,表明一次传输的特权级及安全等级,以及事务是数据访问还是指令访问。
            //Read address valid. This signal indicates that the channel
                // is signaling valid read addressand control information.
            inputwire  S_AXI_ARVALID,//读地址有效信号,此信号通道的地址和控制信号有效。
            //Read address ready. This signal indicates that the slave is
                // ready to accept an address andassociated control signals.
            outputwire  S_AXI_ARREADY,//表明从机可以接受地址和控制信号
            //Read data (issued by slave)
            outputwire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,//读数据
            //Read response. This signal indicates the status of the
                // read transfer.
            outputwire [1 : 0] S_AXI_RRESP,//读响应,处于读传输状态
            //Read valid. This signal indicates that the channel is
                // signaling the required read data.
            outputwire  S_AXI_RVALID,//读有效,表明此次读有效
            //Read ready. This signal indicates that the master can
                // accept the read data and responseinformation.
            inputwire  S_AXI_RREADY //读主机可以接收到读数据和响应信息
      );

      //AXI4LITE signals
      reg[C_S_AXI_ADDR_WIDTH-1 : 0]     axi_awaddr;//写地址
      reg      axi_awready;//写地址就绪信号
      reg      axi_wready;//写就绪信号
      reg[1 : 0]   axi_bresp;//写响应信号,处于写状态
      reg      axi_bvalid;//写响应有效信号
      reg[C_S_AXI_ADDR_WIDTH-1 : 0]     axi_araddr;//读地址
      reg      axi_arready;//读地址就绪信号
      reg[C_S_AXI_DATA_WIDTH-1 : 0]     axi_rdata;//读数据信号
      reg[1 : 0]   axi_rresp;//读响应信号,处于读状态
      reg      axi_rvalid;//读有效信号

      //Example-specific design signals
      //local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
      //ADDR_LSB is used for addressing 32/64 bit registers/memories
      //ADDR_LSB = 2 for 32 bits (n downto 2)
      //ADDR_LSB = 3 for 64 bits (n downto 3)
      localparaminteger ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
      localparaminteger OPT_MEM_ADDR_BITS = 1;
      //----------------------------------------------
      //--Signals for user logic register space example
      //------------------------------------------------
      //--Number of Slave Registers 4
      reg[C_S_AXI_DATA_WIDTH-1:0] slv_reg0;
      reg[C_S_AXI_DATA_WIDTH-1:0] slv_reg1;
      reg[C_S_AXI_DATA_WIDTH-1:0] slv_reg2;
      reg[C_S_AXI_DATA_WIDTH-1:0] slv_reg3;
      wire       slv_reg_rden;
      wire       slv_reg_wren;
      reg[C_S_AXI_DATA_WIDTH-1:0]  reg_data_out;
      integer   byte_index;
      reg  aw_en;

      //I/O Connections assignments

      assignS_AXI_AWREADY   = axi_awready;
      assignS_AXI_WREADY     = axi_wready;
      assignS_AXI_BRESP  = axi_bresp;
      assignS_AXI_BVALID      = axi_bvalid;
      assignS_AXI_ARREADY    = axi_arready;
      assignS_AXI_RDATA = axi_rdata;
      assignS_AXI_RRESP  = axi_rresp;
      assignS_AXI_RVALID      = axi_rvalid;
      //Implement axi_awready generation
      //axi_awready is asserted for one S_AXI_ACLK clock cycle when both
      //S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
      //de-asserted when reset is low.


      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_awready <= 1'b0;
            aw_en <= 1'b1;
          end
        else
          begin   
            if (~axi_awready && S_AXI_AWVALID&& S_AXI_WVALID && aw_en) //写地址未完成,写地址有效,写数据有效,写使能为1
              begin
                // slave is ready to accept write addresswhen  ‘
                // there is a valid write address andwrite data
                // on the write address and data bus.This design
                // expects no outstandingtransactions.
                axi_awready <= 1'b1;
                aw_en <= 1'b0;       //aw_en为1时表明还没有写数据可以写,即进入此条件,进入后改为0,表明正在写数据,外部不能再往里面写完数据了。
              end
              else if (S_AXI_BREADY &&axi_bvalid)//写响应完成,写响应有效,即写完了将写使能和写就绪信号恢复为初始状态
                  begin
                    aw_en <= 1'b1;
                    axi_awready <= 1'b0;
                  end
            else          
              begin
                axi_awready <= 1'b0;
              end
          end
      end      

      //Implement axi_awaddr latching
      //This process is used to latch the address when both
      //S_AXI_AWVALID and S_AXI_WVALID are valid.
   //当S_AXI_AWVALID和 S_AXI_WVALID 信号均有效时,将地址锁存。
      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_awaddr <= 0;
          end
        else
          begin   
            if (~axi_awready && S_AXI_AWVALID&& S_AXI_WVALID && aw_en)//写地址未完成,写地址有效,写使能有效时将地址写入
              begin
                // Write Address latching
                axi_awaddr <= S_AXI_AWADDR;
              end
          end
      end      

      //Implement axi_wready generation
      //axi_wready is asserted for one S_AXI_ACLK clock cycle when both
      //S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is
      //de-asserted when reset is low.

      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_wready <= 1'b0;
          end
        else
          begin   
            if (~axi_wready && S_AXI_WVALID&& S_AXI_AWVALID && aw_en )//写就未完成,写有效,写地址有效,写使能为1,将写完成状态改为完成
              begin
                // slave is ready to accept writedata when
                // there is a valid write address andwrite data
                // on the write address and data bus.This design
                // expects no outstandingtransactions.
                axi_wready <= 1'b1;
              end
            else
              begin
                axi_wready <= 1'b0;
              end
          end
      end      

      //Implement memory mapped register select and write logic generation
      //The write data is accepted and written to memory mapped registers when
      //axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Writestrobes are used to
      //select byte enables of slave registers while writing.
      //These registers are cleared when reset (active low) is applied.
      //Slave register write enable is asserted when valid address and data areavailable
      //and the slave is ready to accept the write address and write data.
      assignslv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready&& S_AXI_AWVALID;//写完成,写有效,写地址完成,写地址有效

      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            slv_reg0 <= 0;
            slv_reg1 <= 0;
            slv_reg2 <= 0;
            slv_reg3 <= 0;
          end
        else begin
          if (slv_reg_wren)
            begin
              case (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )/*这段程序的作用是,当PS那边向AXI4-Lite总线写数据时,PS这边负责将数据接收到寄存器slv_reg。而slv_reg寄存器有0~3共4个。至于赋值给哪一个由

         axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]决定,根据宏定义其实就是由axi_awaddr[3:2] (写地址中不仅包含地址,而且包含了控制位,这里的[3:2]就是控制位)决定赋值给哪个slv_reg。PS调用写函数时,如果不做地址偏移的话,axi_awaddr[3:2]的值默认是为0的,举个例子,如果我们自定义的IP的地址被映射为0x43C00000,那么我们Xil_Out32(0x43C00000,Value)写的就是slv_reg0的值。如果地址偏移4位,如

         Xil_Out32(0x43C00000 + 4,Value) 写的就是slv_reg1的值,依次类推*/
                2'h0:
                  for ( byte_index = 0; byte_index<= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
                    if ( S_AXI_WSTRB[byte_index] == 1) begin    //S_AXI_WSTRB的每一位信号都对应一个字节数据,当该位有效则代表这个字节数据有效
                      // Respective byte enables areasserted as per write strobes
                      // Slave register 0
                      slv_reg0[(byte_index*8) +: 8]<= S_AXI_WDATA[(byte_index*8) +: 8];
                    end 
                2'h1:
                  for ( byte_index = 0; byte_index<= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
                    if ( S_AXI_WSTRB[byte_index] == 1) begin
                      // Respective byte enables areasserted as per write strobes
                      // Slave register 1
                      slv_reg1[(byte_index*8) +: 8]<= S_AXI_WDATA[(byte_index*8) +: 8];
                    end 
                2'h2:
                  for ( byte_index = 0; byte_index<= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
                    if ( S_AXI_WSTRB[byte_index] == 1) begin
                      // Respective byte enables areasserted as per write strobes
                      // Slave register 2
                      slv_reg2[(byte_index*8) +: 8]<= S_AXI_WDATA[(byte_index*8) +: 8];
                    end 
                2'h3:
                  for ( byte_index = 0; byte_index<= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
                    if ( S_AXI_WSTRB[byte_index] == 1) begin
                      // Respective byte enables areasserted as per write strobes
                      // Slave register 3
                      slv_reg3[(byte_index*8) +: 8]<= S_AXI_WDATA[(byte_index*8) +: 8];
                    end 
                default : begin
                            slv_reg0 <= slv_reg0;
                            slv_reg1 <= slv_reg1;
                            slv_reg2 <= slv_reg2;
                            slv_reg3 <= slv_reg3;
                          end
              endcase
            end
        end
      end   

      //Implement write response logic generation
      //The write response and response valid signals are asserted by the slave
      //when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. 
      //This marks the acceptance of address and indicates the status of
      //write transaction.

      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_bvalid  <= 0;
            axi_bresp   <= 2'b0;
          end
        else
          begin   
            if (axi_awready && S_AXI_AWVALID&& ~axi_bvalid && axi_wready && S_AXI_WVALID)//写地址有效,写数据有效,写地址完成,写完成,写响应无效,
              begin                                                                     //即,将数据已经成功写入,此时应将写响应改为有效,写传输状态置0
                // indicates a valid write responseis available
                axi_bvalid <= 1'b1;
                axi_bresp  <= 2'b0; // 'OKAY' response
              end                   // work error responses infuture
            else
              begin
                if (S_AXI_BREADY &&axi_bvalid)   //主机传来写响应完成,自身处于写响应有效
                  //check if bready is asserted whilebvalid is high)
                  //(there is a possibility thatbready is always asserted high)  
                  begin
                    axi_bvalid <= 1'b0;
                  end 
              end
          end
      end  

      //Implement axi_arready generation
      //axi_arready is asserted for one S_AXI_ACLK clock cycle when
      //S_AXI_ARVALID is asserted. axi_awready is
      //de-asserted when reset (active low) is asserted.
      //The read address is also latched when S_AXI_ARVALID is
      //asserted. axi_araddr is reset to zero on reset assertion.


      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_arready <= 1'b0;
            axi_araddr  <= 32'b0;
          end
        else
          begin   
            if (~axi_arready &&S_AXI_ARVALID)//读地址未完成,读地址有效
              begin
                // indicates that the slave hasacceped the valid read address
                axi_arready <= 1'b1;
                // Read address latching
                axi_araddr  <= S_AXI_ARADDR;
              end
            else
              begin
                axi_arready <= 1'b0;
              end
          end
      end      

      //Implement axi_arvalid generation
      //axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both
      //S_AXI_ARVALID and axi_arready are asserted. The slave registers
      //data are available on the axi_rdata bus at this instance. The
      //assertion of axi_rvalid marks the validity of read data on the
      //bus and axi_rresp indicates the status of read transaction.axi_rvalid
      //is deasserted on reset (active low). axi_rresp and axi_rdata are
      //cleared to zero on reset (active low). 
      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_rvalid <= 0;
            axi_rresp <= 0;
          end
        else
          begin   
            if (axi_arready && S_AXI_ARVALID&& ~axi_rvalid)//读地址完成,读地址有效,读未完成,此时将读改为有效,将读状态改为未处于读状态
              begin
                // Valid read data is available atthe read data bus
                axi_rvalid <= 1'b1;
                axi_rresp  <= 2'b0; // 'OKAY' response
              end  
            else if (axi_rvalid &&S_AXI_RREADY)//读有效,读完成,此时将读改为无效
              begin
                // Read data is accepted by themaster
                axi_rvalid <= 1'b0;
              end               
          end
      end   

      //Implement memory mapped register select and read logic generation
      //Slave register read enable is asserted when valid address is available
      //and the slave is ready to accept the read address.
      assignslv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;//读地址完成,读地址有效,读无效,即此时成功拿到主机给的地址但读数据还未完成
      always@(*)
      begin
            // Address decoding for reading registers
            case (axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
              2'h0  : reg_data_out <= slv_reg0;
              2'h1  : reg_data_out <= slv_reg1;
              2'h2  : reg_data_out <= slv_reg2;
              2'h3  : reg_data_out <= slv_reg3;
              default : reg_data_out <= 0;
            endcase
      end

      //Output register or memory read data
      always@( posedge S_AXI_ACLK )
      begin
        if ( S_AXI_ARESETN == 1'b0 )
          begin
            axi_rdata <= 0;
          end
        else
          begin   
            // When there is a valid read address(S_AXI_ARVALID) with
            // acceptance of read address by theslave (axi_arready),
            // output the read dada
            if (slv_reg_rden)//当需要读出数据时
              begin
                axi_rdata <= reg_data_out;     // register read data
              end  
          end
      end   

      //Add user logic here

      //User logic ends

      endmodule
编辑 重设标签(回车键确认) 标为违禁 关闭 合并 删除

提问于 2019-04-27 08:23:29 +0800

这个帖子被标记为一个社区wiki

这个帖子是一个wiki(维基). 任何一个积分 >500的人都可以完善它