ZYNQ开发系列——使用AXI4LITE接口进行PS和PL交互
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
ZYNQ开发系列——使用AXI4LITE接口进行PS和PL交互
- 前言
- PS端AXI接口
- AXI4LITE slave模块的设计
- 后记
前言
前面我们讲到使用AXI4LITE来作为总线接口来实现PS和PL的交互。同时我们为了支持《从零开始研发GPS接收机连载系列》博文的内容,将PS端的内容与我的ZYNQ7030+AD9363硬件平台进行同步。
PS端AXI接口
在ZYNQ7030+AD9363平台中,PS端也是规划为使用AXI4LITE总线与PL进行交互,其设计如下
这个设计上很简单。
ZYNQ7内核的协议交互接口主要配置如下:
配置一个M AXI接口,这个作为PS和PL的AXI交互接口,端口直接出来是AXI3协议接口,后面通过AXI_interconnect模块进行协议转换为AXI4LITE
为其分配地址以及区间为:
注意,BUS_AXI这个端口的PROTOCOL协议需改成AXI4LITE。
AXI4LITE slave模块的设计
在我的博文《ZYNQ开发系列——AXI4LITE协议的理解》中说明了可以直接利用vivado的 创建新AXI4外设的功能来替我们把AXI4LITE接口的代码给写出来,在这里我们稍加进行修改,变成如下模样,注意我们是需要对总线进行分段设计,做成如下框图所示:
这个AXI4LITE总线转换模块代码如下:
`timescale 1 ns / 1 psmodule axi_bus
(output BUS_CLK,output BUS_RST_N,input [15 : 0] BUS_AXI_awaddr,input [2 : 0] BUS_AXI_awprot,input BUS_AXI_awvalid,output reg BUS_AXI_awready,input [31 : 0] BUS_AXI_wdata, input [3 : 0] BUS_AXI_wstrb,input BUS_AXI_wvalid,output reg BUS_AXI_wready,output [1 : 0] BUS_AXI_bresp,output reg BUS_AXI_bvalid,input BUS_AXI_bready,input [15 : 0] BUS_AXI_araddr,input [2 : 0] BUS_AXI_arprot,input BUS_AXI_arvalid,output reg BUS_AXI_arready,output reg [31 : 0] BUS_AXI_rdata,output [1 : 0] BUS_AXI_rresp,output reg BUS_AXI_rvalid,input BUS_AXI_rready,input clk_sys,input rst_n,output hreg_wren,output time_wren,output acq_wren,output trkflg_wren,output [11:0]track_wren,output hreg_rden,output time_rden,output acq_rden,output trkflg_rden,output [11:0]track_rden, output [5:0]fpga_waddress,output [5:0]fpga_raddress,output [31:0]fpga_wdata,input [31:0]fpga_rdata );reg [15 : 0] axi_awaddr ;
reg [15 : 0] axi_araddr ;
reg [31 : 0] axi_rdata ;
reg [31 : 0] axi_rdata_pre ;
reg axi_rvalid ;wire all_reg_rden;
wire all_reg_wren;
reg [31:0] all_reg;reg [15:0] all_waddr;
reg [31:0] reg_data_out;
reg aw_en;assign BUS_CLK = clk_sys;
assign BUS_RST_N = rst_n;assign BUS_AXI_bresp = 2'b00;
assign BUS_AXI_rresp = 2'b00;always @( posedge BUS_CLK)
beginif ( BUS_RST_N == 1'b0 )beginBUS_AXI_awready <= 1'b0;aw_en <= 1'b1;end elsebegin if (~BUS_AXI_awready && BUS_AXI_awvalid && BUS_AXI_wvalid && aw_en)beginBUS_AXI_awready <= 1'b1;aw_en <= 1'b0;endelse if (BUS_AXI_bready && BUS_AXI_bvalid)beginaw_en <= 1'b1;BUS_AXI_awready <= 1'b0;endelse beginBUS_AXI_awready <= 1'b0;endend
end always @( posedge BUS_CLK)
beginif ( BUS_RST_N == 1'b0 )beginaxi_awaddr <= 0;end elsebegin if (~BUS_AXI_awready && BUS_AXI_awvalid && BUS_AXI_wvalid && aw_en)beginaxi_awaddr <= BUS_AXI_awaddr;endend
end always @( posedge BUS_CLK)
beginif ( BUS_RST_N == 1'b0 )beginBUS_AXI_wready <= 1'b0;end elsebegin if (~BUS_AXI_wready && BUS_AXI_wvalid && BUS_AXI_awvalid && aw_en )beginBUS_AXI_wready <= 1'b1;endelsebeginBUS_AXI_wready <= 1'b0;endend
end assign all_reg_wren = BUS_AXI_wready && BUS_AXI_wvalid && BUS_AXI_awready && BUS_AXI_awvalid;assign fpga_waddress = axi_awaddr[7:2];
assign fpga_wdata = BUS_AXI_wdata;assign hreg_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0000_0000;
assign time_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0000_0001;
assign acq_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0011_1110;
assign trkflg_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0011_1111;genvar i;
generate
for (i = 0; i < 12; i = i + 1) begin: TRACK_CS_Nassign track_wren[i] = all_reg_wren && ( axi_awaddr[15:8] == 8'b0100_0000 + i);
end
endgenerate///always @( posedge BUS_CLK)
beginif ( BUS_RST_N == 1'b0 )beginBUS_AXI_bvalid <= 0;end elsebegin if (BUS_AXI_awready && BUS_AXI_awvalid && ~BUS_AXI_bvalid && BUS_AXI_wready && BUS_AXI_wvalid)beginBUS_AXI_bvalid <= 1'b1;end elsebeginif (BUS_AXI_bready && BUS_AXI_bvalid) beginBUS_AXI_bvalid <= 1'b0; end endend
end always @( posedge BUS_CLK)
beginif ( BUS_RST_N == 1'b0 )beginBUS_AXI_arready <= 1'b0;end elsebegin if (~BUS_AXI_arready && BUS_AXI_arvalid)beginBUS_AXI_arready <= 1'b1;endelsebeginBUS_AXI_arready <= 1'b0;endend
end always @( posedge BUS_CLK )beginif ( BUS_RST_N == 1'b0 )beginBUS_AXI_rvalid <= 0;end elsebegin if (BUS_AXI_arready && BUS_AXI_arvalid && ~BUS_AXI_rvalid)beginBUS_AXI_rvalid <= 1'b1;end else if (BUS_AXI_rvalid && BUS_AXI_rready)beginBUS_AXI_rvalid <= 1'b0;end endend assign fpga_raddress = BUS_AXI_araddr[7:2];assign hreg_rden = BUS_AXI_araddr[15:8] == 8'b0000_0000;
assign time_rden = BUS_AXI_araddr[15:8] == 8'b0000_0001;
assign acq_rden = BUS_AXI_araddr[15:8] == 8'b0011_1110;
assign trkflg_rden = BUS_AXI_araddr[15:8] == 8'b0011_1111;generate
for (i = 0; i < 12; i = i + 1) begin: TRACK_CS_N1assign track_rden[i] = (BUS_AXI_araddr[15:8] == 8'b0100_0000 + i) ;
end
endgenerate assign all_reg_rden = BUS_AXI_arready && BUS_AXI_arvalid && BUS_AXI_rvalid == 0;always @( posedge BUS_CLK)
beginif ( BUS_RST_N == 1'b0 )beginBUS_AXI_rdata <= 0;end elsebegin if (all_reg_rden)beginBUS_AXI_rdata <= fpga_rdata;end end
end endmodule
注意:
1、 AXI地址是以字节为单位进行递增的,因此每一个地址实际上代表的是一个字节,而我们一般交互一次是32bit数据,因此AXI地址我们要舍去低2bit。
2、 采用地址分区块的方式,各个模块的地址范围已经在这里进行了划分,这样每个模块只需要关注对偏移地址的分配,各个模块的地址不会互相干扰和重合
例如:
assign hreg_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0000_0000;
assign time_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0000_0001;
assign acq_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0011_1110;
assign trkflg_wren = all_reg_wren && axi_awaddr[15:8] == 8'b0011_1111;
assign hreg_rden = BUS_AXI_araddr[15:8] == 8'b0000_0000;
assign time_rden = BUS_AXI_araddr[15:8] == 8'b0000_0001;
assign acq_rden = BUS_AXI_araddr[15:8] == 8'b0011_1110;
assign trkflg_rden = BUS_AXI_araddr[15:8] == 8'b0011_1111;
特别要注意,参考vivado的 创建新AXI4外设的例程,对于读总线操作,需要进行数据汇聚操作
每一个模块需要将读数据写成三态总线的形式:
assign hreg_rdata = (hreg_rden == 1) ? data_out : 32'hzzzzzzzz;
后记
这里对PL端的AXI4-LITE slave总线接口进行了设计,但为了验证其是否正确,在后面的博文中将会讲到对齐进行读写验证操作
ZYNQ开发系列——使用AXI4LITE接口进行PS和PL交互相关推荐
- ZYNQ开发系列——PS和PL交互之PS端开发
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--PS和PL交互之PS端开发 前言 函数封装 后记 前言 前面<ZYNQ开发系列--使用AXI4LITE接口进 ...
- ZYNQ开发系列——为PS和PL的交互做准备
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--为PS和PL的交互做准备 我们使用ZYNQ的片子,肯定存在PS和PL交互的情况.一般来说大部分应用都是以PS为主机 ...
- ZYNQ开发系列——PS开发之HelloWorld
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--PS开发之HelloWorld 前言 外设接口 SDK建立工程相关操作记录 前言 俗话说一日不见,如隔三秋.两年没 ...
- ZYNQ开发系列——把PS和PL程序烧写到FLASH中
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--把PS和PL程序烧写到FLASH中 生成 fsbl.elf 生成 BOOT.bin 下载 BOOT.bin 文件到 ...
- zynq开发系列5:通过AXI GPIO的中断实现PL端按键控制PS端LED(SDK开发详解)
axi_gpio是PL端gpio(FPGA资源搭建的软核),ps7_gpio是ps端gpio(硬核).打开Documentation的示例Examples,可知第二个是关于中断的示例.导入示例impo ...
- ZYNQ开发系列——PS响应PL中断请求
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 ZYNQ开发系列--PS响应PL中断请求 前言 中断的设置 PS部分代码 前言 PS和PL的交互中,还有一个中断没有讲到,在<从 ...
- zynq开发系列4:MIO按键中断控制LED
与实验三类似 zynq开发系列3:GPIO连接MIO通过按键控制LED灯亮起 ,PS部分设置为与实验一helloword相同的最小系统,但按键控制LED的方式设置为中断,即通过按下按键为中断这一方式从 ...
- zynq开发系列4:EMIO连接按键控制MIO连接的灯
EMIO是负责PL端和PS端通信,PL侧按键可以通过连接EMIO来控制连接到MIO的PS侧的LED.原理和实验3 zynq开发系列3:GPIO连接MIO通过按键控制LED灯亮起 类似,只是由MIO侧的 ...
- zynq开发系列3:GPIO连接MIO通过按键控制LED灯亮起
按键和LED由MIO连接,在PS端用按键控制LED,按键按下时发出信号,LED接收到信号后亮起 可以参考上一节实验 zynq开发系列2:GPIO连接MIO控制LED闪烁 的流程和代码,在vivado操 ...
最新文章
- Jetty服务器jmx监控
- 我在系统设计上犯过的14个错
- 下载chrome驱动 for selenium库
- Fedora安装Mariadb数据库
- hdu 4856 Tunnels
- 特斯拉柏林超级工厂最终环保审批结果有望周五揭晓
- RAR 5.50 控制台使用记录
- kindeditor java上传_富文本编辑器kindeditor上传图片的配置方法
- 常用应用层传输协议和端口
- C语言:对包含10个整数的数组进行如下的操作,从下标为0的元素开始到最后一个元素,依次向前移动一个位置。
- Cost function of Logistic Regression and Neural Network
- mongodb 查多个不等于_MongoDB增删查
- elk logstach收集交换机日志
- 在windows平台上打造Linux开发环境-洋葱先生-杨少通
- c语言让数码管显示时间,请问51单片机肿么编写程序让8个数码管显示时间(时分秒)...
- Wampserver图标是橙色的【问题与解决方案】
- tomcat配置https(jks)证书,启动后提示Keystore was tampered with, or password was incorrect
- st58服务器装系统,微pe硬盘安装系统教程
- 数据分析之matplotlib画图工具的使用(一)
- Mendix与JEECG对比
热门文章
- JAX-FLUIDS:可压缩两相流的完全可微高阶计算流体动力学求解器
- win7电脑桌面图标和下方任务栏都消失了怎么办
- 单目标跟踪 (一)相关滤波器 方法综述
- 准备注册网易企业邮箱,安全功能怎么样?
- 水泥caement英语
- SpringBoot中banner个性启动(内附自定义设计网站)
- i.MX 6ULL 驱动开发 一:搭建开发环境
- oracle 2019 ocp,2019 OCP简介
- 哥德尔不完全性定理探索数学边界
- 什么软件可以测试自己的穿衣,心理测试:4个女孩,哪个穿衣风格跟你最像?秒测你的真实性格...