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

news2024/9/28 15:30:14

前言

在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 / 1ps

module 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或者64bit
	parameter 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 channel
	input          [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 channel
	input          [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 channel
	output  reg	   			         	            s_axi_bvalid,
	input        			         	            s_axi_bready,

	input      		 							    s_axi_arvalid, // axi read address channel
	output  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 channel
	output         [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) begin
	a_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) begin
    if (a_reset_sync) 
        wr_cur_status <= WR_IDLE;
    else 
        wr_cur_status <= wr_nxt_status;
end

always @(*) begin
    if (a_reset_sync) 
        wr_nxt_status <= WR_IDLE;
    else 
    	case(wr_cur_status)
    		WR_IDLE : begin
    			if (s_axi_awvalid && s_axi_wvalid) 
    				wr_nxt_status <= WE_DATA;
    			else 
    				wr_nxt_status <= wr_cur_status;
    		end
    		WE_DATA : begin
    			wr_nxt_status <= WR_BRESP;
    		end
    		WR_BRESP : begin
    			if (s_axi_bvalid && s_axi_bready) 
    				wr_nxt_status <= WR_IDLE;
    			else 
    				wr_nxt_status <= wr_cur_status;
    		end
    	    default : wr_nxt_status <= WR_IDLE;
    	endcase    
end

always @(*) begin
    if (a_reset_sync) begin
    	s_axi_awready <= 0;
    	s_axi_wready  <= 0;
    end  
    else begin
    	s_axi_awready <= wr_cur_status == WE_DATA;
    	s_axi_wready  <= wr_cur_status == WE_DATA;    	
    end  
end

always @(posedge axi_clk) begin
    if (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;
end

always @(posedge axi_clk) begin
    if (wr_cur_status == WE_DATA) begin
    	s_wr_vld  <= 1'b1;
    	s_wr_data <= s_axi_wdata;
    	s_wr_addr <= s_axi_awaddr;
    end
    else begin
    	s_wr_vld  <= 0;
    	s_wr_data <= s_wr_data;
    	s_wr_addr <= s_wr_addr;    	
    end    
end

/*------------------------------------------*\
             AXILITE从机读过程
\*------------------------------------------*/
always @(posedge axi_clk) begin
    if (a_reset_sync) 
        rd_cur_status <= RD_IDLE;
    else 
        rd_cur_status <= rd_nxt_status;
end

always @(*) begin
    if (a_reset_sync) 
        rd_nxt_status <= RD_IDLE;
    else 
    	case(rd_cur_status)
    		RD_IDLE : begin
    			if (s_axi_arvalid)
    				rd_nxt_status <= RD_PRE;
    			else 
    				rd_nxt_status <= rd_cur_status;
    		end
    		RD_PRE : begin
    			rd_nxt_status <= RD_DATA;
    		end
    		RD_DATA : begin
    			if (s_axi_rvalid && s_axi_rready) 
    				rd_nxt_status <= RD_IDLE;
    			else 
    				rd_nxt_status <= rd_cur_status;	
    		end

    	    default : rd_nxt_status <= RD_IDLE;
    	endcase    
end

always @(*) begin
    if (a_reset_sync) 
        s_axi_arready <= 0; 
    else 
        s_axi_arready <= rd_cur_status == RD_PRE;
end

always @(posedge axi_clk) begin
    if (rd_cur_status == RD_PRE) begin
    	s_rd_addr_vld <= 1'b1;
    	s_rd_addr     <= s_axi_araddr;
    end
    else begin
    	s_rd_addr_vld <= 0;   
    	s_rd_addr     <= s_rd_addr; 	
    end     
end

always @(posedge axi_clk) begin
    if (a_reset_sync) begin
 		s_axi_rdata  <= 0;
 		s_axi_rvalid <= 0;
    end
    else if (s_axi_rvalid && s_axi_rready) begin
		s_axi_rvalid <= 0;
    end
    else if (s_rd_data_vld) begin
    	s_axi_rvalid <= 1'b1;
    	s_axi_rdata  <= s_rd_data;
    end
    else begin
    	s_axi_rvalid <= s_axi_rvalid;
    	s_axi_rdata  <= s_axi_rdata;
    end    
end

endmodule

user_ram

`timescale 1ns / 1ps



module user_ram #(
	parameter USER_WR_DATA_WIDTH 	=   32 ,
	parameter USER_RD_DATA_WIDTH 	=   32 ,
	parameter AXI_DATA_WIDTH        =   32 , //注意AXI4的数据位宽只有32Bit或者64bit
	parameter 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) begin
    if (s_wr_vld) 
    	ram[s_wr_addr] <= s_wr_data;
end

always @(posedge clk) begin
    if (reset) begin
        s_rd_data_vld <= 0;
        s_rd_data     <= 0;
    end
    else if (s_rd_addr_vld) begin
    	s_rd_data_vld <= 1'b1;
    	s_rd_data     <= ram[s_rd_addr];
    end   
    else begin
    	s_rd_data_vld <= 0;
    	s_rd_data     <= 0;
    end
        
end
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 0x40000000

int 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.coloradmin.cn/o/1614986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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

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

4.10 SpringBoot整合Servlet、Filter过滤器和Listener

4.10 整合Servlet、Filter和Listener 1. 启动类1. 整合Servlet2. Filter过滤器3. Listener监听器4. 总结5. JavaWeb三大组件**************************************************** 一般情况下&#xff0c;使用Spring、Spring MVC这些框架之后&#xff0c;基本上就告别Servlet、…

# 从浅入深 学习 SpringCloud 微服务架构(三)注册中心 Eureka(1)

从浅入深 学习 SpringCloud 微服务架构&#xff08;三&#xff09;注册中心 Eureka&#xff08;1&#xff09; 段子手168 1、微服务的注册中心 注册中心可以说是微服务架构中的”通讯录”&#xff0c;它记录了服务和服务地址的映射关系。 在分布式架构中服务会注册到这里&am…

【HCIP学习】重发布和路由策略

一、重发布&#xff08;路由引入&#xff09; 1、背景&#xff1a; 一个网络拓扑中存在多种不同的路由协议&#xff0c;为了使多种不同的路由协议间能相互通信&#xff0c;出现了路由引入 为啥会存在多种不同的网络&#xff1f; 例如&#xff1a;OSPF由于区域架构的限制&am…

web前端 html5+css3相关知识点(跟着黑马学)8

先总结一下网页常见的布局方式&#xff1a; 1. 标准流 块级元素独占一行 -> 垂直布局 行内元素/行内块元素一行显示多个 -> 水平布局 2. 浮动 可以让原本垂直布局的块级元素变成水平布局。 3. 定位 可以让元素自由的摆放在网页的任意位置 一般用于盒子之间的层叠…

【RAG 论文】WikiChat:从 WikiPedia 检索数据来提高 LLM 的事实性的聊天机器人

论文&#xff1a;WikiChat: Stopping the Hallucination of Large Language Model Chatbots by Few-Shot Grounding on Wikipedia ⭐⭐⭐⭐ Stanford University, EMNLP 2023 相关地址&#xff1a; demo 体验地址CodeHuggingface 模型 文章目录 论文速读模型 demo一些其他的细节…

让流程图动起来

我们平时画流程&#xff0c;然后贴到文档&#xff0c;就完事了。但是过程演示的时候&#xff0c;如果只是一张静态图&#xff0c;很难吸引到听众的注意力&#xff0c;表达效果并不太好。常用的方法是可以用PPT进行动态演示&#xff0c;做PPT也是需要花一些时间&#xff0c;同时…

[StartingPoint][Tier2]Base

Task 1 Which two TCP ports are open on the remote host? (远程服务器开放了哪两个TCP端口?) $ nmap -sC -sV 10.129.234.232 22,80 Task 2 What is the relative path on the webserver for the login page? (相关的登录页面路径是什么?) /login/login.php Task 3 …

1 transformers:词典,(文本如何处理)

0 介绍 NLP任务最初&#xff0c;就是在于如何处理文本。无论从TFIDF到word2Vec的过程&#xff0c;还是BERT都是想找到文本的向量表达&#xff0c;如何表示更好处理我们的下游任务。那么&#xff0c;这个过程是如何做的呢&#xff0c;本文主要就是介绍这一个过程&#xff0c;还是…

【C++ 多态】(一)虚函数重写✍

文章目录 1.虚函数重写的三个例外1.1协变(基类与派生类虚函数返回值类型不同)1.2析构函数的重写(基类与派生类析构函数的名字不同)1.3派生类可以不写 virtual 2.面试题✍ 1.虚函数重写的三个例外 1.1协变(基类与派生类虚函数返回值类型不同) ①&#x1f34e;协变的概念&#…

Linux学习之路 -- 进程篇 -- 进程地址空间

目录 一、背景介绍 二、进程地址空间 1.看现象 2.先简单描述一下地址空间&#xff08;地址空间全在操作系统的内部&#xff09; 3.地址空间详细一点的描述 4.进程地址空间里面的内容&#xff08;部分&#xff09; 三、进程地址空间的转换机制 1.页表 2.进程地址空间和页…

牛客NC162 二叉树中和为某一值的路径(三)【中等 dfs C++、Java、Go、PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/965fef32cae14a17a8e86c76ffe3131f 思路 既然要找所有路径上节点和等于目标值的路径个数&#xff0c;那我们肯定先找这样的路径起点啊&#xff0c; 但是我们不知道起点究竟在哪里&#xff0c; 而且任意节点都有…

Navicat 干货 | 掌握 PostgreSQL 规则语法

PostgreSQL 规则提供了一种强大的机制&#xff0c;控制查询执行并在数据库内部实施数据操作。理解规则的语法和用法对于有效利用其功能至关重要。在上周的文章中&#xff0c;我们探讨了 PostgreSQL 规则的工作原理及其与触发器的区别。今天的文章将使用免费的 “dvdrental”示例…

笔记本电脑坏了硬盘数据会丢失吗 笔记本电脑坏了如何取出硬盘的资料 数据恢复软件

笔记本电脑对我们真的非常重要了&#xff0c;是实现无纸化办公和学习的重要工具&#xff0c;但是如果笔记本电脑坏了我们存储在电脑里的资料该怎么办&#xff1f;笔记本电脑坏了硬盘数据会丢失吗&#xff1f;相信有许多朋友都会有这样的担忧。本文今天就为大家解决笔记本电脑坏…

3月衣物清洁行业数据概况和趋势分析:总销额环比上涨超60%!

人们日常生活离不开衣物清洁产品&#xff0c;同时随着生活品质得提高和消费者健康意识得增强&#xff0c;对于衣物清洁行业的需求量与日俱增。作为日常必备的消耗品&#xff0c;衣物清洁产品备受消费者关注。借此&#xff0c;衣物清洁行业在3月份表现出稳定的发展态势。 根据鲸…

【软件测试】关于Web自动化测试

文章目录 &#x1f343;前言&#x1f332;如何实现Web自动化&#x1f6a9;安装驱动管理&#x1f6a9;Selenium库的安装 &#x1f333;自动化常用函数&#x1f6a9;元素的定位&#x1f388;cssSelector&#x1f388;xpath &#x1f6a9;操作测试对象&#x1f388;点击/提交对象—…

洗地机选哪个牌子好?过来人建议买这四款:性价比高质量好

随着生活节奏的加快&#xff0c;洗地机逐渐成为了人们生活中的清洁小能手&#xff0c;但市面上品牌众多&#xff0c;性能参差不齐&#xff0c;消费者往往难以抉择。在选择洗地机时&#xff0c;我们不仅要考虑其清洁效果&#xff0c;还应着重考察性价比。那么&#xff0c;面对如…

3.AlexNet--CNN经典网络模型详解(pytorch实现)

看博客AlexNet--CNN经典网络模型详解&#xff08;pytorch实现&#xff09;_alex的cnn-CSDN博客&#xff0c;该博客的作者写的很详细&#xff0c;是一个简单的目标分类的代码&#xff0c;可以通过该代码深入了解目标检测的简单框架。在这里不作详细的赘述&#xff0c;如果想更深…

[Meachines][Easy]Devvortex

Main $ nmap -p- 10.10.11.242 --min-rate 1000 # echo 10.10.11.242 devvortex.htb>>/etc/hosts 子域名爆破 $ apt install seclists $ wfuzz -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt -u "http://devvortex.htb/" -H &…

【Transformer】detr梳理

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 detr detr 1. 引言 论文&#xff1a; https://arxiv.org/pdf/2005.12872v3.pdf 时间&#xff1a; 2020.5.26 作者&#xff1a; Nicolas Carion?, Fra…