FPGA - ZYNQ 基于Axi_Lite的PS和PL交互

前言

在FPGA - ZYNQ 基于EMIO的PS和PL交互中介绍了ZYNQ 中PS端和PL端交互的开发流程,接下来构建基于基于Axi_Lite的PS和PL交互。

开发流程

Axi_Lite从机

在FPGA - AXI4_Lite(实现用户端与axi4_lite之间的交互逻辑)中,详解介绍了AXI4总线,以及AXI_LITE端口信号及其功能,其中axi4_lite 读写过程框架图中介绍了axi4_lite主机搭建过程。

接下来构建axi4_lite从机

Axi4_lite端口信号及其功能

根据axi_lite读写信号分析:

在这里我们需要构建axi4lite_slaveuser_ram

axi4lite_slave:

`timescale 1ns / 1psmodule axilite_slave #(parameter USER_WR_DATA_WIDTH    = 32 , //用户写数据位宽和AXI4―Lite数据位宽保持一致parameter USER_RD_DATA_WIDTH    = 32 , //用户读数据位宽和AXI4―Lite数据位宽保持一致parameter AXI_DATA_WIDTH 		= 32,  //AXI4_LITE总线规定,数据位宽只支持32Bit或者64bitparameter AXI_ADDR_WIDTH        = 32	
)(input       								    axi_clk,    input       								    reset,output  reg								        s_wr_vld,output  reg    [USER_WR_DATA_WIDTH-1:0]	        s_wr_data,output  reg    [AXI_ADDR_WIDTH-1 :0]		    s_wr_addr,output  reg								        s_rd_addr_vld,output  reg    [AXI_ADDR_WIDTH-1 :0]		    s_rd_addr,input          [USER_RD_DATA_WIDTH-1:0]	        s_rd_data,input                                           s_rd_data_vld,input          [AXI_ADDR_WIDTH -1:0]  	        s_axi_awaddr, //axi write address channelinput          [2:0] 				 	        s_axi_awprot, input      		 				 	            s_axi_awvalid, output reg    		 			 	            s_axi_awready,input          [AXI_DATA_WIDTH-1:0]	 	        s_axi_wdata,   //axi write data channelinput          [AXI_DATA_WIDTH/8-1:0] 	        s_axi_wstrb,input           					 	        s_axi_wvalid,output  reg          					 	    s_axi_wready,output         [1:0]	         	            s_axi_bresp,  //axi wirte response channeloutput  reg	   			         	            s_axi_bvalid,input        			         	            s_axi_bready,input      		 							    s_axi_arvalid, // axi read address channeloutput  reg       		 					    s_axi_arready, input          [AXI_ADDR_WIDTH-1:0] 			s_axi_araddr,input          [2:0] 							s_axi_arprot, output  reg    [AXI_DATA_WIDTH-1:0]	    		s_axi_rdata,   // axi read data channeloutput         [1:0] 				    		s_axi_rresp,output  reg     					    		s_axi_rvalid,input        						   	 		s_axi_rready);(* dont_touch="true" *) reg a_reset_sync_d0;
(* dont_touch="true" *) reg a_reset_sync_d1;
(* dont_touch="true" *) reg a_reset_sync;
/*------------------------------------------*\状态机信号定义
\*------------------------------------------*/
reg [1:0] wr_cur_status;
reg [1:0] wr_nxt_status;
reg [1:0] rd_cur_status;
reg [1:0] rd_nxt_status;localparam WR_IDLE    = 3'b000;
localparam WE_DATA    = 3'b001;
localparam WR_BRESP   = 3'b010;localparam RD_IDLE    = 3'b000;
localparam RD_PRE     = 3'b001;
localparam RD_DATA    = 3'b010;/*------------------------------------------*\assign
\*------------------------------------------*/
assign s_axi_bresp = 0;
assign s_axi_rresp  = 0;/*------------------------------------------*\CDC
\*------------------------------------------*/
always @(posedge axi_clk) begina_reset_sync_d0 <= reset;a_reset_sync_d1 <= a_reset_sync_d0;a_reset_sync    <= a_reset_sync_d1;
end/*------------------------------------------*\AXILITE从机写过程
\*------------------------------------------*/
always @(posedge axi_clk) beginif (a_reset_sync) wr_cur_status <= WR_IDLE;else wr_cur_status <= wr_nxt_status;
endalways @(*) beginif (a_reset_sync) wr_nxt_status <= WR_IDLE;else case(wr_cur_status)WR_IDLE : beginif (s_axi_awvalid && s_axi_wvalid) wr_nxt_status <= WE_DATA;else wr_nxt_status <= wr_cur_status;endWE_DATA : beginwr_nxt_status <= WR_BRESP;endWR_BRESP : beginif (s_axi_bvalid && s_axi_bready) wr_nxt_status <= WR_IDLE;else wr_nxt_status <= wr_cur_status;enddefault : wr_nxt_status <= WR_IDLE;endcase    
endalways @(*) beginif (a_reset_sync) begins_axi_awready <= 0;s_axi_wready  <= 0;end  else begins_axi_awready <= wr_cur_status == WE_DATA;s_axi_wready  <= wr_cur_status == WE_DATA;    	end  
endalways @(posedge axi_clk) beginif (a_reset_sync) s_axi_bvalid <= 0;else if (s_axi_bvalid && s_axi_bready) s_axi_bvalid <= 0;else if (wr_cur_status == WR_BRESP)s_axi_bvalid <= 1'b1;else s_axi_bvalid <= s_axi_bvalid;
endalways @(posedge axi_clk) beginif (wr_cur_status == WE_DATA) begins_wr_vld  <= 1'b1;s_wr_data <= s_axi_wdata;s_wr_addr <= s_axi_awaddr;endelse begins_wr_vld  <= 0;s_wr_data <= s_wr_data;s_wr_addr <= s_wr_addr;    	end    
end/*------------------------------------------*\AXILITE从机读过程
\*------------------------------------------*/
always @(posedge axi_clk) beginif (a_reset_sync) rd_cur_status <= RD_IDLE;else rd_cur_status <= rd_nxt_status;
endalways @(*) beginif (a_reset_sync) rd_nxt_status <= RD_IDLE;else case(rd_cur_status)RD_IDLE : beginif (s_axi_arvalid)rd_nxt_status <= RD_PRE;else rd_nxt_status <= rd_cur_status;endRD_PRE : beginrd_nxt_status <= RD_DATA;endRD_DATA : beginif (s_axi_rvalid && s_axi_rready) rd_nxt_status <= RD_IDLE;else rd_nxt_status <= rd_cur_status;	enddefault : rd_nxt_status <= RD_IDLE;endcase    
endalways @(*) beginif (a_reset_sync) s_axi_arready <= 0; else s_axi_arready <= rd_cur_status == RD_PRE;
endalways @(posedge axi_clk) beginif (rd_cur_status == RD_PRE) begins_rd_addr_vld <= 1'b1;s_rd_addr     <= s_axi_araddr;endelse begins_rd_addr_vld <= 0;   s_rd_addr     <= s_rd_addr; 	end     
endalways @(posedge axi_clk) beginif (a_reset_sync) begins_axi_rdata  <= 0;s_axi_rvalid <= 0;endelse if (s_axi_rvalid && s_axi_rready) begins_axi_rvalid <= 0;endelse if (s_rd_data_vld) begins_axi_rvalid <= 1'b1;s_axi_rdata  <= s_rd_data;endelse begins_axi_rvalid <= s_axi_rvalid;s_axi_rdata  <= s_axi_rdata;end    
endendmodule

user_ram

`timescale 1ns / 1psmodule user_ram #(parameter USER_WR_DATA_WIDTH 	=   32 ,parameter USER_RD_DATA_WIDTH 	=   32 ,parameter AXI_DATA_WIDTH        =   32 , //注意AXI4的数据位宽只有32Bit或者64bitparameter AXI_ADDR_WIDTH        =   32	
)(input                                           clk          ,input                                           reset        ,input  								            s_wr_vld     ,input      [USER_WR_DATA_WIDTH-1:0]	            s_wr_data    ,input      [AXI_ADDR_WIDTH-1 :0]		        s_wr_addr    ,input  								            s_rd_addr_vld,input      [AXI_ADDR_WIDTH-1 :0]		        s_rd_addr    ,output reg [USER_RD_DATA_WIDTH-1:0]	            s_rd_data    ,output reg                                      s_rd_data_vld);
localparam SIZE = 1024;
reg [AXI_DATA_WIDTH-1:0] ram [SIZE - 1 : 0] ;always @(posedge clk) beginif (s_wr_vld) ram[s_wr_addr] <= s_wr_data;
endalways @(posedge clk) beginif (reset) begins_rd_data_vld <= 0;s_rd_data     <= 0;endelse if (s_rd_addr_vld) begins_rd_data_vld <= 1'b1;s_rd_data     <= ram[s_rd_addr];end   else begins_rd_data_vld <= 0;s_rd_data     <= 0;endend
endmodule

IP核生成

在ZYNQ开发中,要将构建的axi4lite_slave和user_ram打包为 IP核

首先,创建新工程,将axi4lite_slave和user_ram代码导入:

点击OK

点击Finish

可以看到在Sources界面中已经有axi4lite_slave和user_ram文件

可以看到axi4lite_slave 是顶层。

---------------------------------------------------------------------------------------------------------------------------------

然后开始打包创建IP核

点击NEXT

选择IP保存位置 点击Next

点击OK

点击Finish

然后会弹出一个新工程:

这里是IP配置信息:

保持默认 然后点击Review and Package , 点击Package IP:

点击Yes

然后打开IP保存位置文件夹,可以看到如下:

点击src文件夹里面是axilite_slave.v文件

点击xgui文件夹是axilite_slave_v1_0.tcl文件
这样axilite_slave IP核打包完成。

然后切换user_ram文件为顶层:

右击user_ram文件 点击Set as Top

然后重复axilite_slave打包过程,

打开IP核存放地址

至此,axi4lite_slave和user_ram文件打包ip核完成。

---------------------------------------------------------------------------------------------------------------------------------

硬件系统搭建

搭建硬件系统

具体构建过程可见:

FPGA - ZYNQ 基于EMIO的PS和PL交互icon-default.png?t=N7T8https://blog.csdn.net/weixin_46897065/article/details/137865852?spm=1001.2014.3001.5501如下:

---------------------------------------------------------------------------------------------------------------------------------

然后需要将上面打包的IP核,加载到IP库中:

点击Seting ,再点击IP,然后点Repository

找到上面axi4lite_slave和user_ram IP 核存放位置,点击Select:

点击ok

然后搜索axilite_slave和user_ram:

双击添加,点击Run Block Automation

然后点击RUN connection Automation

连线完成如下:

---------------------------------------------------------------------------------------------------------------------------------

由于axi4lite_slave和user_ram 是高复位,所以删除原来的低复位,重新连接高复位引脚:

删除重新连接:

复位连接完成如下:

然后将axilite_slave 引脚 和user_ram 引脚相连:

连接完成如下:

然后点击重新布局:

然后点击验证设计:

点击OK 

然后按照FPGA - ZYNQ 基于EMIO的PS和PL交互中的开发流程:

生成封装,生成底层和顶层文件,

然后生成比特流,导出硬件,启动SDK。

---------------------------------------------------------------------------------------------------------------------------------

SDK 程序设计

创建SDK工程

点击空工程  点击finish

添加source file 

---------------------------------------------------------------------------------------------------------------------------------

在硬件系统搭建中,我们看到,自动连线后,会出现一个AXI Interconnect。如下图:

这个模块在PS设计中,通过API接口实现axilite读写。

基于自定义AXI_lite 与 PS  API接口 之间的映射关系

PS端API函数  和 AXI4_lite  总线的映射关系 对应关系
写入数据  Xil_Out32()函数
读出数据  Xil_In32()   函数 

1,利用API接口函数实现读写axilite读写:


#include "xparameters.h"
#include "sleep.h"
#include "xil_io.h"#define AXI_LITE_BASEADDR 0x40000000通过函数编写int main()
{u32 rddata;Xil_Out32(AXI_LITE_BASEADDR,1000);Xil_Out32(AXI_LITE_BASEADDR + 4,500);Xil_Out32(AXI_LITE_BASEADDR + 8,800);rddata = Xil_In32(AXI_LITE_BASEADDR);rddata = Xil_In32(AXI_LITE_BASEADDR + 4);return 0;
}

2,利用指针实现读写axilite读写:


#include "xparameters.h"
#include "sleep.h"
#include "xil_io.h"#define AXI_LITE_BASEADDR 0x40000000int main()
{u32* LitePtr  = (u32*)AXI_LITE_BASEADDR;  //强制转换 转为地址u32 wrdata = 0;u32 rddata = 0;int i = 0;//向PL写数据for (i = 0; i < 128; i++ ){*LitePtr++ = wrdata++;}LitePtr  = (u32*)AXI_LITE_BASEADDR;for (i = 0; i < 128; i++ ){rddata = *LitePtr++;printf("rddata= %d \n",rddata);}return 0;
}

最后,下载验证。

总结

        在这里,实现了基于Axi_Lite的PS和PL交互,和axilite_slave(axilite从机)的实现,以及自定义IP核的创建,并且在SDK程序中实现了2种axilite的读写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/640044.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序:基于MySQL+Nodejs的汽车品牌管理系统

各位好&#xff0c;接上期&#xff0c;今天分享一个通过本地MySQLNodejs服务器实现CRUD功能的微信小程序&#xff0c;一起来看看吧~ 干货&#xff01;微信小程序通过NodeJs连接MySQL数据库https://jslhyh32.blog.csdn.net/article/details/137890154?spm1001.2014.3001.5502 …

针对窗口数量多导致窗口大小显示受限制的问题,使用滚动条控制窗口

建议&#xff1a;首先观察结果展示&#xff0c;判断是否可以满足你的需求。 目录 1. 问题分析 2. 解决方案 2.1 界面设计 2.2 生成代码 2.3 源码实现 3. 结果展示 1. 问题分析 项目需要显示的窗口数量颇多&#xff0c;主界面中&#xff0c;如果一次性显示全部窗口&#x…

飞书小技巧:markdown导出

文章目录 下载Feishu2Md飞书应用配置配置feishu2md工具绑定应用导出markdown 下载Feishu2Md Feishu2Md 飞书应用配置 进入飞书开发者后台 https://open.feishu.cn/app。 点击“创建企业自建应用”&#xff0c;并填写应用名称等信息。而后点击创建。 PS: 此处作者创建应用名…

面向对象设计与分析40讲(25)中介模式、代理模式、门面模式、桥接模式、适配器模式

文章目录 门面模式代理模式中介模式 之所以把这几个模式放到一起写&#xff0c;是因为它们的界限比较模糊&#xff0c;结构上没有明显的差别&#xff0c;差别只是语义上。 这几种模式在结构上都类似&#xff1a; 代理将原本A–>C的直接调用变成&#xff1a; A–>B–>…

网渲应用领域有哪些?渲染100邀请码1a12

网渲是一种利用云计算技术把本地渲染上传到云端进行的过程&#xff0c;它极大提高了渲染效率&#xff0c;摆脱了本地限制&#xff0c;使用网渲的领域有很多&#xff0c;这里我们列举下。 1、影视制作 在影视制作当中&#xff0c;对于需要大量特效和动画效果的电影来说&#x…

【STM32】嵌入式实验二 GPIO 实验:数码管

实验内容&#xff1a; 编写程序&#xff0c;在数码管上显示自己的学号。 数码管相关电路&#xff1a; PA7对应的应该是段码&#xff0c;上面的图写错了。 注意&#xff1a;选中数码管是低电平选中&#xff1b;并且用74HC595模块驱动输出的段码&#xff0c; 这个模块的学习可以…

太奇怪了!99%的人没见过的Oracle故障:网络恢复后,集群的监听和vip无法启动

故障描述 15:46操作系统日志出现net4、net5网卡down&#xff0c;15:53分钟的网络恢复。网络中断是由于db汇聚交换机出现了问题。 网络恢复后&#xff0c;节点1的监听和vip无法启动。 故障分析 查看grid alert日志可以看到监听资源确实没有正常启动。 由于监听资源是crs的Ora…

有了可视化工具,你定制设计得瑟瑟发抖了吧,其实你想多了。

目前市面上有N多可视化的工具&#xff0c;可以做成可视化大屏&#xff0c;甚至有很多B端系统也附带可视化页面&#xff0c;据此就有很多人开始怀疑我们这些做定制开发的&#xff0c;还有啥生存空间。 其实你真的多虑了&#xff0c;存在即合理&#xff0c;我们承认可视化工具的标…

weblogic反序列化漏洞(CVE-2017-10271)复现

直接用vuluhub搭建现成的靶场做 访问靶场 打开是这样表示成功 想反弹shell 就先开启kali1的nc监听&#xff0c;这就监听2233端口吧 linux&#xff1a;nc -l -p 2233 抓包修改为攻击数据包 ip和端口可以任意修改 反弹的shell 还可以写入文件shell 只需要把提供的poc POS…

URL解析

目录 URIURLURL语法相对URLURL中的转义 现在与未来PURL 在 URL出现之前&#xff0c;人们如果想访问网络中的资源&#xff0c;就需要使用不同的 应用程序&#xff0c;如共享文件需要使用 FTP程序&#xff0c;想要发送邮件必须使用 邮件程序&#xff0c;想要看新闻那只能使用…

Agent 智能体食用指南

Agent 智能体食用指南 三年前都在 ALL in AI&#xff0c;一年前都在 ALL in LLM&#xff0c;现在都在 ALL in AgentAutoGEN分析MetaGPT 分析RAG 分析MOE 多专家分析 三年前都在 ALL in AI&#xff0c;一年前都在 ALL in LLM&#xff0c;现在都在 ALL in Agent 科技圈焦点&…

【Java】常见锁策略 CAS机制 锁优化策略

前言 在本文会详细介绍各种锁策略、CAS机制以及锁优化策略 不仅仅局限于Java&#xff0c;任何和锁相关的话题&#xff0c;都可能会涉及到下面的内容。 这些特性主要是给锁的实现者来参考的. 普通的程序猿也需要了解一些, 对于合理的使用锁也是有很大帮助的 文章目录 前言✍一、…