基于Verilog HDL的axi

您所在的位置:网站首页 axi4总线实现ddr读写verilog 基于Verilog HDL的axi

基于Verilog HDL的axi

2024-06-13 20:14| 来源: 网络整理| 查看: 265

  前文对axi_lite接口协议的各个信号做了详细讲解,本文通过Verilog Hdl编写一个通用接口转axi_lite接口协议的模块。

1、生成xilinx官方提供axi源码

  Xilinx其实给用户提供了axi相关模块,获取方式如下,首先打开vivado软件,然后点击Manage IP,之后选择New IP Location,如下图所示。

在这里插入图片描述

图1 创建IP

  直接点击下一步。

在这里插入图片描述

图2 向导界面

  之后需要选择器件型号,然后确定工程路径,之后点击Finish。

在这里插入图片描述

图3 Manage IP Settings

  进入工程后,在Tools选项卡下点击Create and Package New IP,如下图所示。

在这里插入图片描述

图4 生成IP

  进入向导界面后直接点击下一步。

在这里插入图片描述

图5 Create and Package New IP

  然后选择创建AXI外围设备,如下图所示。

在这里插入图片描述

图6 创建AXI 外围设备

  根据需求修改一下IP名,然后点击下一步,如下图所示。

在这里插入图片描述

图7 修改IP名

  然后选择生成IP的协议类型,此处选择lite协议,然后选择主机,数据位宽只能固定为32位。之后点击下一步,如下图所示。

在这里插入图片描述

图8 生成axi_lite主机模块

  通过修改上图设置,可以生成axi_lite、axi_full、axi_stream协议的主机和从机模块,后文会使用其余模块,就不再详细讲解。

  最后需要选择Edit IP,才会生成IP的源文件,如下图所示。

在这里插入图片描述

图9 生成IP

  之后会生成一个工程,生成的工程会包含axi_lite_master_v1_0_M00_AXI的一个模块,这个模块就是生成的axi_lite_master模块。

在这里插入图片描述

图10 生成文件

  本文只是告诉读者vivado能够生成一个axi协议的相关模块,但是该模块的代码不够简洁,其实使用起来没那么方便。

  后文不会对生成的模块进行解读和使用,后文会根据前文所讲协议内容自己编写一个axi_lite_master模块,而该模块的axi_lite端口信号与生成的模块保持一致。

2、axi_lite_master模块设计

  用户端口肯定会设计的比较简单,只包括读写使能、地址、数据信号,由于axi_lite接口需要和从机进行应答,那么用户端口写入的数据和地址就不能立即写入,需要等待。

  解决这个问题的方法有两种思路,第一种是在写和读部分都给用户输出一个模块忙闲指示信号,只有当模块对应功能空闲时,才能进行下次操作。

  第二种就是在写数据、写地址、读地址端口处加一个FIFO,用来存储用户的数据和指令,当FIFO不为空,就读出FIFO中的数据通过axi_lite发送给从机。这种方式的优点是用户不需要等待模块空闲,直接将需要发送的指令、数据输入即可,简化逻辑,但是FIFO会消耗更多资源。

  本文采用第二种设计方式,整个模块通过检测三个FIFO是否为空,向从机发起读写时序。

  端口信号如下所示,首先是axi_lite的时钟、复位和五个通道的信号,然后是用户的端口信号,用户的写使能信号与写数据、写地址信号对齐,读使能与读地址信号对齐。用户的地址信号位宽默认为8位,而axi_lite的地址和数据信号一般均为32位,可以根据实际情况进行拼接。

module axi_lite_master #( parameter UADDR_W = 8 ,//用户地址位宽; parameter UDATA_W = 32 ,//用户数据位宽; parameter ADATA_W = 32 //AXI_LITE的地址和数据位宽; )( input M_AXI_ACLK ,//AXI接口时钟信号; input M_AXI_ARESETN ,//AXI接口复位信号,低电平有效; //AXI写地址通道信号; output reg [ADATA_W - 1 : 0] M_AXI_AWADDR ,//AXI地址信号; output [2 : 0] M_AXI_AWPROT ,//AXI地址端口信号; output reg M_AXI_AWVALID ,//AIX地址数据有效指示信号,高电平有效; input M_AXI_AWREADY ,//AXI地址数据应答信号。 //AXI写数据通道信号; output reg [ADATA_W - 1 : 0] M_AXI_WDATA ,//AXI写数据信号; output [ADATA_W / 8 - 1 : 0] M_AXI_WSTRB ,//AXI写数据掩码信号,低电平有效; output reg M_AXI_WVALID ,//AXI写入数据有效指示信号,高电平有效; input M_AXI_WREADY ,//AXI写入数据应答信号,高电平有效; //AXI写应答通道信号; input [1 : 0] M_AXI_BRESP ,//AXI写应答信号,为0时表示写入正确; input M_AXI_BVALID ,//AXI写应答有效指示信号,高电平有效; output reg M_AXI_BREADY ,//AXI写应答响应信号,高电平有效; //AXI读地址通道信号; output reg [ADATA_W - 1 : 0] M_AXI_ARADDR ,//AXI读地址信号; output [2 : 0] M_AXI_ARPROT ,//AXI读地址端口信号; output reg M_AXI_ARVALID ,//AXI读地址有效指示信号,高电平有效; input M_AXI_ARREADY ,//AXI读地址应答信号,高电平有效; //AXI读数据通道信号; input [ADATA_W - 1 : 0] M_AXI_RDATA ,//AXI读数据信号; input [1 : 0] M_AXI_RRESP ,//AXI读数据状态应答信号,为0表示读数据正确; input M_AXI_RVALID ,//读数据有效指示信号,高电平有效; output reg M_AXI_RREADY ,//主机接收从机读出数据的应答信号,高电平有效; //用户写数据信号; input wr_en ,//写使能信号,高电平有效; input [UADDR_W - 1 : 0] waddr ,//写地址信号,与写使能对齐; input [UDATA_W - 1 : 0] wdata ,//写数据信号,与写使能对齐; //用户读数据信号; input rd_en ,//读使能信号,高电平有效; input [UADDR_W - 1 : 0] raddr ,//读地址信号,与读使能对齐; output reg [UDATA_W - 1 : 0] rdata ,//读数据信号; output reg rdata_vld ,//读数据有效指示信号,高电平有效; output reg error //错误指示信号,当写入错误或读出错误时为1,正常为0; );

  axi_lite的读、写地址端口类型信号一般为0,且写入数据不会加掩码,因此这几个信号直接连接对应电平输出即可。

assign M_AXI_AWPROT = 3'd0 ;//写地址端口信号始终为0; assign M_AXI_ARPROT = 3'd0 ;//读地址端口信号始终为0; assign M_AXI_WSTRB = {{ADATA_W/8}{1'b1}};//写数据掩码信号,本模块写入数据全部有效,因此全为高电平; assign wfifo_empty = wa_fifo_empty & wa_fifo_empty;//由于写地址和写数据可以同时进行,所以将两个写FIFO空指示信号合并;

  由于用户端口的写地址信号、写数据信号都与写使能对齐,且前文分析axi_lite的写数据和写地址信号可以对齐(隐含意思:两个FIFO可以一起读出数据)。因此可以把两个FIFO的空标志信号整理为一个空标志信号。

  下面是写地址FIFO、读地址FIFO、写数据FIFO的例化,地址FIFO的数据位宽为8,数据FIFO的数据位宽为32,FIFO深度均为32。FIFO输出数据会滞后读使能一个时钟。

//用于存储写地址的FIFO; addr_fifo_8x32 u_waddr_fifo ( .clk ( M_AXI_ACLK ),//input wire clk; .din ( waddr ),//input wire [7 : 0] din; .wr_en ( wr_en ),//input wire wr_en; .rd_en ( wfifo_rd_en ),//input wire rd_en; .dout ( wa_fifo_dout ),//output wire [7 : 0] dout; .full ( wa_fifo_full ),//output wire full; .empty ( wa_fifo_empty ) //output wire empty; ); //用于存储读地址的FIFO; addr_fifo_8x32 u_raddr_fifo ( .clk ( M_AXI_ACLK ),//input wire clk; .din ( raddr ),//input wire [7 : 0] din; .wr_en ( rd_en ),//input wire wr_en; .rd_en ( ra_fifo_rd_en ),//input wire rd_en; .dout ( ra_fifo_dout ),//output wire [7 : 0] dout; .full ( ra_fifo_full ),//output wire full; .empty ( ra_fifo_empty ) //output wire empty; ); //用于存储写数据的FIFO; data_fifo_32x32 u_wdata_fifo ( .clk ( M_AXI_ACLK ),//input wire clk; .din ( wdata ),//input wire [31 : 0] din; .wr_en ( wr_en ),//input wire wr_en; .rd_en ( wfifo_rd_en ),//input wire rd_en; .dout ( wd_fifo_dout ),//output wire [31 : 0] dout; .full ( wd_fifo_full ),//output wire full; .empty ( wd_fifo_empty ) //output wire empty; );

  写地址FIFO和写数据FIFO的读使能采用一个信号,即同时输出信号。

  然后下面是一个写标志信号wr_flag,该信号为高电平表示正在进行axi_lite写操作。当写地址、写数据FIFO均有数据且不处于写状态时拉高,当写应答通道响应时拉低。

//写标志信号,初始值为0,当写入数据时拉高,一次写入完成后拉低; always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN==1'b0)begin//初始值为0; wr_flag {{ADATA_W - UADDR_W}{1'b0}},wa_fifo_dout[UADDR_W - 1 : 0]}; M_AXI_WDATA {ADATA_W - UDATA_W}{1'b0}},wd_fifo_dout[UDATA_W - 1 : 0]}; end end

  之后需要生成axi_lite写地址、写数据通道的有效指示信号,当FIFO读出数据后拉高,各自应答信号为高电平时拉低。

//生成AXI写地址有效指示信号,与写地址信号对齐; always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN==1'b0)begin//初始值为0; M_AXI_AWVALID {ADATA_W - UADDR_W}{1'b0}},ra_fifo_dout[UADDR_W - 1 : 0]}; end end //生成AXI读地址有效指示信号,与读地址信号对齐; always@(posedge M_AXI_ACLK)begin if(M_AXI_ARESETN==1'b0)begin//初始值为0; M_AXI_ARVALID


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3