最终是想在zynq7000系类的fpga上实现yolo系类,以及其他轻量型网络,第一阶段主要是学习AXI总线相关的知识,并在fpga上实现,第二阶段主要是卷积神经网络的相关函数如何映射到fpga上去,第三阶段主要是写驱动应用程序,并上板调试。

axi读写架构

一.AXI总线协议规范:

1.无论写操作和读操作,地址信息和控制信息将在数据传输之前进行信息传输
2.支持多种数据的传输
3.支持乱序传输
信息源通过VALID信号显示数据信息或者控制信息的有效性;
而接受方则利用READY信号表示可以接收相应的数据;
还有一个LAST信号表示在读数据通道或者写数据通道中最后一个有效数据的到达
在这里插入图片描述
在这里插入图片描述

二.AXI总线的握手机制

1.五个单向通道体系结构均采用同样的VALID/READY两个握手信号来进行地址信息,控制信息,写/读数据信息,以及应答信息的传输。

2.信息源产生的高电平有效的VALID信号标志出地址信息,控制信息以及数据信息,应答信息等多种信息的有效传输或接收;

3.目标源产生的同样为高电平有效的READY信号则表明了可以接收相对应的信息。
VALID和READY信号均为高电平有效,也只有两个信号都为高电平时,传输才能完成。
4.AXI总线协议同时也规范了在AXI maste与AXI slave主从设备的输入输出信号之间不允许存在任何组合逻辑

5.握手信号之间存在的相关性:在握手中死锁会发生带来信号传输的崩溃,不同模块之间的握手信号不存在任何相关性
在这里插入图片描述

三.工程搭建

`timescale 1 ns / 1 ps

module axi_lite_slave #
(
	parameter integer C_S_AXI_DATA_WIDTH	= 32,
	parameter integer C_S_AXI_ADDR_WIDTH	= 6   //地址位宽
)
(
	input wire  S_AXI_ACLK,
	input wire  S_AXI_ARESETN,
	input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
	input wire [2 : 0] S_AXI_AWPROT,
	input wire  S_AXI_AWVALID,
	output wire  S_AXI_AWREADY,
	input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
	input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
	input wire  S_AXI_WVALID,
	output wire  S_AXI_WREADY,
	output wire [1 : 0] S_AXI_BRESP,
	output wire  S_AXI_BVALID,
	input wire  S_AXI_BREADY,
	input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
	input wire [2 : 0] S_AXI_ARPROT,
	input wire  S_AXI_ARVALID,
	output wire  S_AXI_ARREADY,
	output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
	output wire [1 : 0] S_AXI_RRESP,
	output wire  S_AXI_RVALID,
	input wire  S_AXI_RREADY
);

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;

localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 4-1;

wire	 slv_reg_rden;
wire	 slv_reg_wren;
reg [C_S_AXI_DATA_WIDTH-1:0]	 reg_data_out;
integer	 byte_index;

assign S_AXI_AWREADY	= axi_awready;
assign S_AXI_WREADY	= axi_wready;
assign S_AXI_BRESP	= axi_bresp;
assign S_AXI_BVALID	= axi_bvalid;
assign S_AXI_ARREADY	= axi_arready;
assign S_AXI_RDATA	= axi_rdata;
assign S_AXI_RRESP	= axi_rresp;
assign S_AXI_RVALID	= axi_rvalid;

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_awready <= 1'b0;
    end 
  else
    begin    
      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID)
        begin
          axi_awready <= 1'b1;
        end
      else           
        begin
          axi_awready <= 1'b0;
        end
    end 
end       

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)
        begin
          axi_awaddr <= S_AXI_AWADDR;
        end
    end 
end       

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)
        begin
          axi_wready <= 1'b1;
        end
      else
        begin
          axi_wready <= 1'b0;
        end
    end 
end       

assign slv_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
      axi_bvalid  <= 0;
      axi_bresp   <= 2'b0;
    end 
  else
    begin    
      if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
        begin
          axi_bvalid <= 1'b1;
          axi_bresp  <= 2'b0;  
        end                   
      else
        begin
          if (S_AXI_BREADY && axi_bvalid) 
            begin
              axi_bvalid <= 1'b0; 
            end  
        end
    end
end   

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
          axi_arready <= 1'b1;
          axi_araddr  <= S_AXI_ARADDR;
        end
      else
        begin
          axi_arready <= 1'b0;
        end
    end 
end       

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
          axi_rvalid <= 1'b1;
          axi_rresp  <= 2'b0;
        end   
      else if (axi_rvalid && S_AXI_RREADY)
        begin
          axi_rvalid <= 1'b0;
        end                
    end
end    

always @( posedge S_AXI_ACLK )
begin
  if ( S_AXI_ARESETN == 1'b0 )
    begin
      axi_rdata  <= 0;
    end 
  else
    begin    
      if (slv_reg_rden)
        begin
          axi_rdata <= reg_data_out; 
        end   
    end
end    

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg0;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg0 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d0) )
		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
					slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg1;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg1 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d1) )
		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
					slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg2;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg2 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d2) )
		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
					slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg3;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg3 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d3) )
		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
					slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg4;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg4 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d4) )
		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
					slv_reg4[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg5;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg5 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d5) )
		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
					slv_reg5[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg6;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg6 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d6) )
		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
					slv_reg6[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg7;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg7 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d7) )
		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
					slv_reg7[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg8;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg8 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d8) )
		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
					slv_reg8[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg9;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg9 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d9) )
		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
					slv_reg9[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg10;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg10 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d10) )
		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
					slv_reg10[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg11;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg11 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d11) )
		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
					slv_reg11[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg12;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg12 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d12) )
		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
					slv_reg12[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg13;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg13 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d13) )
		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
					slv_reg13[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg14;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg14 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d14) )
		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
					slv_reg14[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

reg [C_S_AXI_DATA_WIDTH-1:0]slv_reg15;
always @( posedge S_AXI_ACLK )
if ( S_AXI_ARESETN == 1'b0 )
	begin
		slv_reg15 <= 0;
	end
else
	if(slv_reg_wren & (axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]=='d15) )
		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
					slv_reg15[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
				end

assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
always @(*)
begin
	case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
		'd0:reg_data_out<=slv_reg0;
		'd1:reg_data_out<=slv_reg1;
		'd2:reg_data_out<=slv_reg2;
		'd3:reg_data_out<=slv_reg3;
		'd4:reg_data_out<=slv_reg4;
		'd5:reg_data_out<=slv_reg5;
		'd6:reg_data_out<=slv_reg6;
		'd7:reg_data_out<=slv_reg7;
		'd8:reg_data_out<=slv_reg8;
		'd9:reg_data_out<=slv_reg9;
		'd10:reg_data_out<=slv_reg10;
		'd11:reg_data_out<=slv_reg11;
		'd12:reg_data_out<=slv_reg12;
		'd13:reg_data_out<=slv_reg13;
		'd14:reg_data_out<=slv_reg14;
		'd15:reg_data_out<=slv_reg15;
        default : reg_data_out <= 0;
	endcase
end

endmodule

1.利用vivado工具封装成ip核

在这里插入图片描述

2.新建一个工程,添加ip核,搭建bd,添加ila片内逻辑分析仪

在这里插入图片描述

3.生成bit流

4.export hardware启动sdk,勾选include bit选项,准备编写驱动程序在这里插入图片描述

5.创建一个新的app——hello world创建一个新的app——hello world

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里选helloworld 模板
在这里插入图片描述
6.下载bit流文件到fpga
在这里插入图片描述
在这里插入图片描述

修改驱动的c代码

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"


int main()
{
    init_platform();

    print("Hello World\n\r");
    	*(unsigned int *)0x43C00000 = 100;//定义一个指针,指向第一个寄存器并赋值
    	xil_printf("reg0=%d\r\n",*(unsigned int *) 0x43C00000);//打印第一个寄存器的值
    	*(unsigned int *)0x43C00004 = 200;
    	xil_printf("reg1=%d\r\n",*(unsigned int *) 0x43C00004);
    cleanup_platform();
    return 0;
}

运行run as 结果如下:
在这里插入图片描述

7.使用ila在线抓波形

修改hellword.c代码如下:加一个循环让arm启动

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"


int main()
{
    init_platform();

    print("Hello World\n\r");
    while(1){
    	*(unsigned int *)0x43C00000 = 100;
    	xil_printf("reg0=%d\r\n",*(unsigned int *) 0x43C00000);

    	*(unsigned int *)0x43C00004 = 200;
    	xil_printf("reg1=%d\r\n",*(unsigned int *) 0x43C00004);
    }
    cleanup_platform();
    return 0;
}

这里串口一直打印数据,表示arm正常启动了

在这里插入图片描述

8.打开vivado下载程序的界面

点击抓波形(三角形)按钮,发现没有抓到数据,是因为读写都很短,大约只需要1us,而串口打印需要100us,所以很难抓到读写的那一部分数据,所以要设置触发条件。
在这里插入图片描述

9.用axi_master模型进行仿真

`timescale 1ns / 1ps
module AXI_GP_M_BFM #
(
    parameter C_M_AXI_DATA_WIDTH=32,
    parameter C_M_AXI_ADDR_WIDTH=6 
)
(
    input M_AXI_ACLK,
    input M_AXI_ARESETN,
    
    //AR channel
    output reg M_AXI_ARVALID,
    input M_AXI_ARREADY,
    output reg [C_M_AXI_ADDR_WIDTH-1:0]M_AXI_ARADDR,
    output [2:0]M_AXI_ARPROT,//=3'b0

    //Rd channel
    input [C_M_AXI_DATA_WIDTH-1:0]M_AXI_RDATA,
    input [1:0]M_AXI_RRESP,//ignore
    input M_AXI_RVALID,
    output reg M_AXI_RREADY,

    //AW channel
    output reg M_AXI_AWVALID,
    input M_AXI_AWREADY,
    output reg [C_M_AXI_ADDR_WIDTH-1:0]M_AXI_AWADDR,
    output [2:0]M_AXI_AWPROT,//=3'h0

    //Wr channel
    output reg [C_M_AXI_DATA_WIDTH-1:0]M_AXI_WDATA,
    output reg M_AXI_WVALID,
    input M_AXI_WREADY,
    output [C_M_AXI_DATA_WIDTH/8-1:0]M_AXI_WSTRB,//={(C_M_AXI_DATA_WIDTH/8){1'b1}}        

    //Wr Resp
    input [1:0]M_AXI_BRESP,//ignore
    input M_AXI_BVALID,
    output reg M_AXI_BREADY
);

assign M_AXI_AWPROT=3'h0;
assign M_AXI_WSTRB={(C_M_AXI_DATA_WIDTH/8){1'b1}};
assign M_AXI_ARPROT=3'b0;

always @(negedge M_AXI_ARESETN)
begin
    M_AXI_AWVALID<=0;
    M_AXI_AWADDR<=0;
    M_AXI_WDATA<=0;
    M_AXI_WVALID<=0;
    M_AXI_ARVALID<=0;
    M_AXI_ARADDR<=0;
    M_AXI_RREADY<=0;
end

always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN)                                                                                                     
if(~M_AXI_ARESETN)                                                           
    M_AXI_BREADY<=1'b0;                                                                                                                          
else
    if(M_AXI_BVALID & ~M_AXI_BREADY)                                                                               
        M_AXI_BREADY<=1'b1;                                                                                                                                       
    else
        if(M_AXI_BVALID & M_AXI_BREADY)
            M_AXI_BREADY<=1'b0;

task write(input int unsigned addr,data);
begin
    @(posedge M_AXI_ACLK) M_AXI_AWVALID<=1;M_AXI_AWADDR<=addr;M_AXI_WVALID<=1;M_AXI_WDATA<=data;
    @(posedge M_AXI_ACLK);
    while((M_AXI_WVALID|M_AXI_AWVALID)==1)
        begin
            if(M_AXI_AWREADY)
                M_AXI_AWVALID<=0;
            if(M_AXI_WREADY)
                M_AXI_WVALID<=0;
            @(posedge M_AXI_ACLK);
        end
    while(~(M_AXI_BVALID && M_AXI_BREADY)) @(posedge M_AXI_ACLK);
end
endtask

task read(input int unsigned addr,output int unsigned data);
begin
    M_AXI_ARADDR<=addr;
    @(posedge M_AXI_ACLK) M_AXI_ARVALID<=1;
    @(posedge M_AXI_ACLK);
    while(~(M_AXI_ARVALID && M_AXI_ARREADY)) @(posedge M_AXI_ACLK);
    M_AXI_ARVALID<=0;
    @(posedge M_AXI_ACLK);
    while(~M_AXI_RVALID) @(posedge M_AXI_ACLK);
    M_AXI_RREADY<=1;
    @(posedge M_AXI_ACLK) M_AXI_RREADY<=0;
    data=M_AXI_RDATA;
end
endtask

endmodule

testbench文件采用system verilog来写的,在testbench中将axi_lite和axi_master例化,然后再将其对应的端口连接到一起,上代码

`timescale 1ns / 1ps

module testbench;

bit M_AXI_ACLK;always #5 M_AXI_ACLK=~M_AXI_ACLK;
bit M_AXI_ARESETN;

    parameter C_M_AXI_DATA_WIDTH=32;
    parameter C_M_AXI_ADDR_WIDTH=6;

//AR channel
wire M_AXI_ARVALID;
wire M_AXI_ARREADY;
wire [C_M_AXI_ADDR_WIDTH-1:0]M_AXI_ARADDR;
wire [2:0]M_AXI_ARPROT;//=3'b0

//Rd channel
wire [C_M_AXI_DATA_WIDTH-1:0]M_AXI_RDATA;
wire [1:0]M_AXI_RRESP;//ignore
wire M_AXI_RVALID;
wire M_AXI_RREADY;

//AW channel
wire M_AXI_AWVALID;
wire M_AXI_AWREADY;
wire [C_M_AXI_ADDR_WIDTH-1:0]M_AXI_AWADDR;
wire [2:0]M_AXI_AWPROT;//=3'h0

//Wr channel
wire [C_M_AXI_DATA_WIDTH-1:0]M_AXI_WDATA;
wire M_AXI_WVALID;
wire M_AXI_WREADY;
wire [C_M_AXI_DATA_WIDTH/8-1:0]M_AXI_WSTRB;//={(C_M_AXI_DATA_WIDTH/8){1'b1}}        

//Wr Resp
wire [1:0]M_AXI_BRESP;//ignore
wire M_AXI_BVALID;
wire M_AXI_BREADY;

int unsigned rdata;
initial
begin
M_AXI_ARESETN=1;
#30 M_AXI_ARESETN=0;
#30 M_AXI_ARESETN=1;
repeat(30) @(posedge M_AXI_ACLK);
u_AXI_GP_M_BFM.write(16,20);	//这里写地址为0x16,写的数据为0d20
u_AXI_GP_M_BFM.read(16,rdata);	//这里读地址为0X16
#100 $stop;

end

dut_axi_lite_slave u_dut_axi_lite_slave
(
M_AXI_ACLK,
M_AXI_ARESETN,
M_AXI_AWADDR,
 M_AXI_AWPROT,
M_AXI_AWVALID,
 M_AXI_AWREADY,
M_AXI_WDATA,
 M_AXI_WSTRB,
  M_AXI_WVALID,
 M_AXI_WREADY,
M_AXI_BRESP,
M_AXI_BVALID,
M_AXI_BREADY,
M_AXI_ARADDR,
M_AXI_ARPROT,
M_AXI_ARVALID,
M_AXI_ARREADY,
M_AXI_RDATA,
M_AXI_RRESP,
M_AXI_RVALID,
M_AXI_RREADY
);

AXI_GP_M_BFM u_AXI_GP_M_BFM
(
M_AXI_ACLK,
M_AXI_ARESETN,
    
    //AR channel
M_AXI_ARVALID,
M_AXI_ARREADY,
M_AXI_ARADDR,
M_AXI_ARPROT,//=3'b0

    //Rd channel
M_AXI_RDATA,
M_AXI_RRESP,//ignore
 M_AXI_RVALID,
M_AXI_RREADY,

    //AW channel
M_AXI_AWVALID,
M_AXI_AWREADY,
M_AXI_AWADDR,
M_AXI_AWPROT,//=3'h0

    //Wr channel
M_AXI_WDATA,
M_AXI_WVALID,
M_AXI_WREADY,
M_AXI_WSTRB,//={(C_M_AXI_DATA_WIDTH/8){1'b1}}        

    //Wr Resp
M_AXI_BRESP,//ignore
M_AXI_BVALID,
M_AXI_BREADY
);

endmodule

读写仿真均正确
在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐