ZYNQ开发系列——使用AXI4LITE接口进行PS和PL交互

news/2024/12/22 23:54:19/

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

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总线接口进行了设计,但为了验证其是否正确,在后面的博文中将会讲到对齐进行读写验证操作


http://www.ppmy.cn/news/314960.html

相关文章

ZYNQ 应用笔记(2)PS/PL接口

相比传统的SOC 芯片&#xff0c;Xilinx 公司ZYNQ 的最大优势在于&#xff0c;除了内嵌的硬核ARM 处理器自带的IO接口之外&#xff0c;能够利用FPGA 自由地构建符合应用需求的IO外设和基于verilog/HDL的算法。这给嵌入式系统设计带来的巨大的灵活性。 ZYNQ 分成所谓的Processing…

面向对象——接口

接口&#xff1a;接口是一种用来定义程序的协议&#xff0c;它描述可属于任何类或结构的一组相关行为&#xff0c;可以把它看成是实现一组类的模板。接口可有方法、属性、事件和索引器或这4种成员类型的任何组合构成&#xff0c;但不能包含字段。 类和结构可以像类继承基类一样…

PS4 eye camera v2 ROS测试

For the I-RC ps4 eye camera 是一款性价比很高的双目摄像头&#xff0c;之前已经有人设计完成了一代产品的ROS驱动程序&#xff0c;代码见GitHub[1],今天要测试的是去年发布的新款摄像头. 一代摄像头二代摄像头 ps4 camera 接口是USB3.0 的一个衍生版本&#xff0c;需要进…

PS2接口协议及代码分析

一.电气特性 1 DATA Key Data 2 n/c Not connected 3 GND Gnd 4 VCC Power , 5 VDC 5 CLK Clock 6 n/c Not connected 二.数据格式 1个起始位 总是逻辑0 8个数据位 &#xff08;LSB&#xff09;低位在前 1个奇偶校验位 奇校验 1个停止位 总…

jmeter接口测试

jmeter进行http接口测试的主要步骤&#xff08;1.添加线程组 2.添加http请求 3.在http请求中写入接口的URL&#xff0c;路径&#xff0c;请求方式&#xff0c;参数 4.添加查看结果树 5.调用接口&#xff0c;查看返回值&#xff09; 针对接口添加header在如下途径添加&#xff…

计算机ps2定义,PS2通信协议说明及接口定义(键盘及鼠标).doc

PS2键盘与鼠标的接口定义 针脚定义: 原理 PS/2鼠标接口采用一种双向同步串行协议?即每在时钟线上发一个脉冲,就在数据线上发送一位数据?在相互传输中,主机拥有总线控制权,即它可以在任何时候抑制鼠标的发送?方法是把时钟线一直拉低,鼠标就不能产生时钟信号和发送数据?在两…

交通物流模型 | Python实现基于张量分解的交通流量时空模式挖掘(出租车车载GPS数据、公交卡刷卡数据、POI的分布数据)

文章目录 效果一览文章概述研究内容源码设计参考资料效果一览 文章概述 一般出行行程通常都由某种明确目的驱使,例如上班、购物或娱乐,出行的起始区域因其承担功能的不同,通常能够反映出用户的出行目的,于此同时,从宏观来看,区域之间的交通流量在一天内的变化规律也能够反…

每日一点硬件小知识—PS/2接口

每日一点硬件小知识—PS/2接口 1、 PS/2接口概述 PS/2是在较早电脑上常见的接口之一&#xff0c;用于鼠标、键盘等设备。 PS/2的命名来自于1987年时IBM所推出的个人电脑&#xff1a;PS/2系列。 PS/2接口是输入装置接口&#xff0c;而不是传输接口。所以PS2口没有传输速率的…