基于Verilog HDL的axi |
您所在的位置:网站首页 › axi4总线实现ddr读写verilog › 基于Verilog HDL的axi |
前文对axi_lite接口协议的各个信号做了详细讲解,本文通过Verilog Hdl编写一个通用接口转axi_lite接口协议的模块。 1、生成xilinx官方提供axi源码Xilinx其实给用户提供了axi相关模块,获取方式如下,首先打开vivado软件,然后点击Manage IP,之后选择New IP Location,如下图所示。 直接点击下一步。 之后需要选择器件型号,然后确定工程路径,之后点击Finish。 进入工程后,在Tools选项卡下点击Create and Package New IP,如下图所示。 进入向导界面后直接点击下一步。 然后选择创建AXI外围设备,如下图所示。 根据需求修改一下IP名,然后点击下一步,如下图所示。 然后选择生成IP的协议类型,此处选择lite协议,然后选择主机,数据位宽只能固定为32位。之后点击下一步,如下图所示。 通过修改上图设置,可以生成axi_lite、axi_full、axi_stream协议的主机和从机模块,后文会使用其余模块,就不再详细讲解。 最后需要选择Edit IP,才会生成IP的源文件,如下图所示。 之后会生成一个工程,生成的工程会包含axi_lite_master_v1_0_M00_AXI的一个模块,这个模块就是生成的axi_lite_master模块。 本文只是告诉读者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 |