AXI4总线协议 ------ AXI_LITE协议

一、AXI 相关知识介绍

https://download.csdn.net/download/mvpkuku/90841873 AXI_LITE

 选出部分重点,详细文档见上面链接。

1.AXI4 协议类型

2.握手机制 

 二、AXI_LITE 协议的实现 

 1. AXI_LITE 通道及各通道端口功能介绍

2.实现思路及框架 

2.1 总体框架 

2.2 写通道 

1.复位信号进行跨时钟域同步(用户时钟/AXI4时钟)

2.仅当user_wr_ready为高时,用户的写通道是有效的

3.例化两个fifo分别存储用户端传来的地址以及数据用户时钟写入,并通过AXI时钟读出

4.控制AXI_LITE(状态机)接口信号是在AXI时钟下进行 (控制cmd_rden/data_rden并输出对应的相关接口数据)

`timescale 1ns / 1ps
//
// Description: AXI_lite写通道
//
module axlite_wr_channel#(parameter USER_WR_DATA_WIDTH    = 32 ,//用户写数据位宽和AXI4—Lite数据位宽保持一致parameter AXI_DATA_WIDTH 		= 32, //AXI4_LITE总线规定,数据位宽只支持32Bit或者64bitparameter AXI_ADDR_WIDTH        = 32	
)(input   wire							        clk,     //用户写时钟		input   wire									axi_clk, //从机读时钟   input   wire									reset,//与 用户端 交互信号input   wire								    user_wr_en,input   wire  [USER_WR_DATA_WIDTH-1:0]	        user_wr_data,input   wire  [AXI_ADDR_WIDTH-1 :0]		        user_wr_addr,output  wire                                    user_wr_ready,	//与 axi_lite从机 交互信号output  reg   [AXI_ADDR_WIDTH -1:0]  	        m_axi_awaddr, //write addr channeloutput  wire  [2:0] 				 	        m_axi_awprot, output  reg   		 				 	        m_axi_awvalid, input   wire    		 			 	        m_axi_awready,output  reg   [AXI_DATA_WIDTH-1:0]	 	        m_axi_wdata,   //write data channeloutput  wire  [AXI_DATA_WIDTH/8-1:0] 	        m_axi_wstrb,output  reg      					 	        m_axi_wvalid,input   wire    					 	        m_axi_wready,input   wire  [1:0]	         	                m_axi_bresp,  //wirte response channelinput   wire	   			         	        m_axi_bvalid,output  wire    			         	        m_axi_bready
);(* dont_touch = "true"*) reg reset_sync_d0;  //user clk
(* dont_touch = "true"*) reg reset_sync_d1;
(* dont_touch = "true"*) reg reset_sync;
(* dont_touch = "true"*) reg a_reset_sync_d0; //axi clk
(* dont_touch = "true"*) reg a_reset_sync_d1;
(* dont_touch = "true"*) reg a_reset_sync;reg	 [31:0]  cmd_din;
reg          cmd_wren;
wire [31:0]  cmd_dout;
reg 		 cmd_rden;
wire		 cmd_wrfull ;
wire		 cmd_rdempty;
wire [4:0]   cmd_wrcount;
wire [4:0]   cmd_rdcount;reg	 [31:0]  data_din;
reg          data_wren;
wire [31:0]  data_dout;
reg 		 data_rden;
wire		 data_wrfull;
wire		 data_rdempty;
wire [4:0]   data_wrcount;
wire [4:0]   data_rdcount;reg [2 : 0]	 cur_status;
reg [2 : 0]	 nxt_status;localparam WR_IDLE     = 3'b000;
localparam WR_PRE      = 3'b001;
localparam WR_DATA_EN  = 3'b010;
localparam WR_END      = 3'b100;
/*--------------------------------------------------*\assign
\*--------------------------------------------------*/
assign m_axi_bready  = 1'b1;
assign m_axi_awprot  = 0;
assign m_axi_wstrb   = {AXI_DATA_WIDTH/8{1'b1}};assign user_wr_ready = reset_sync ? 1'b0 : cmd_wrcount <= 'd12 ; //留一点余量 //当user_wr_ready为低的时候,用户发送写是无效的
/*--------------------------------------------------*\CDC process
\*--------------------------------------------------*/
always @(posedge clk) beginreset_sync_d0   <= reset;reset_sync_d1   <= reset_sync_d0;reset_sync      <= reset_sync_d1;
endalways @(posedge axi_clk) begina_reset_sync_d0 <= reset;a_reset_sync_d1 <= a_reset_sync_d0;a_reset_sync    <= a_reset_sync_d1;
end/*--------------------------------------------------*\wirte addr to cmd fifo、write data to data fifo 
\*--------------------------------------------------*/
always @(posedge clk) beginif (user_wr_ready) begincmd_wren  <= user_wr_en;cmd_din   <= user_wr_addr;data_wren <= user_wr_en;data_din  <= user_wr_data; 		endelse begincmd_wren  <= 0;cmd_din   <= 0;data_wren <= 0;data_din  <= 0; 		end
end/*--------------------------------------------------*\WR state machine  (三段式)
\*--------------------------------------------------*/
always@(posedge axi_clk)beginif(a_reset_sync)cur_status <= WR_IDLE;elsecur_status <= nxt_status;       
endalways@(*)beginif(a_reset_sync)beginnxt_status <= WR_IDLE;endelse begincase(cur_status)WR_IDLE : beginif(!cmd_rdempty)nxt_status <= WR_PRE;elsenxt_status <= cur_status;endWR_PRE : beginnxt_status <= WR_DATA_EN;endWR_DATA_EN : beginif (m_axi_bvalid && m_axi_bready)nxt_status <= WR_END;else nxt_status <= cur_status;end			WR_END : beginnxt_status <= WR_IDLE;enddefault : nxt_status <= WR_IDLE;endcaseend  
end
/*-----------------------------------------------------------*\read addr from cmd_fifo 、 read data from data_fifo  
\*-----------------------------------------------------------*/
always @(*) beginif (a_reset_sync) begincmd_rden   <= 0;data_rden  <= 0;endelse begincmd_rden   <= cur_status == WR_PRE;data_rden  <= cur_status == WR_PRE;end
endalways @(posedge axi_clk) beginif (cmd_rden) m_axi_awaddr <= cmd_dout;else m_axi_awaddr <= m_axi_awaddr;
endalways @(posedge axi_clk) beginif (a_reset_sync) m_axi_awvalid <= 0;else if (cur_status == WR_PRE)m_axi_awvalid <= 1'b1;else if (m_axi_awvalid && m_axi_awready)m_axi_awvalid <= 0;
endalways @(posedge axi_clk) beginif (data_rden) m_axi_wdata <= data_dout;else m_axi_wdata <= m_axi_wdata;
endalways @(posedge axi_clk) beginif (a_reset_sync) m_axi_wvalid <= 0;else if (cur_status == WR_PRE)m_axi_wvalid <= 1'b1;else if (m_axi_wvalid && m_axi_wready)m_axi_wvalid <= 0;
end//写地址fifo
fifo_w32xd16 wr_cmd_fifo (.rst          ( reset_sync  ), // input wire rst.wr_clk       ( clk         ), // input wire wr_clk         用户写时钟.din          ( cmd_din     ), // input wire [31 : 0] din.wr_en        ( cmd_wren    ), // input wire wr_en.rd_clk       ( axi_clk     ), // input wire rd_clk         从机读时钟 .rd_en        ( cmd_rden    ), // input wire rd_en.dout         ( cmd_dout    ), // output wire [31 : 0] dout.full         ( cmd_wrfull  ), // output wire full.empty        ( cmd_rdempty ), // output wire empty.rd_data_count( cmd_wrcount ), // output wire [4 : 0] rd_data_count.wr_data_count( cmd_rdcount )  // output wire [4 : 0] wr_data_count
);//写数据fifo
fifo_w32xd16 wr_data_fifo (.rst          ( reset_sync   ), // input wire rst.wr_clk       ( clk          ), // input wire wr_clk        用户写时钟.din          ( data_din     ), // input wire [31 : 0] din.wr_en        ( data_wren    ), // input wire wr_en.rd_clk       ( axi_clk      ), // input wire rd_clk        从机读时钟 .rd_en        ( data_rden    ), // input wire rd_en.dout         ( data_dout    ), // output wire [31 : 0] dout.full         ( data_wrfull  ), // output wire full.empty        ( data_rdempty ), // output wire empty.rd_data_count( data_rdcount ), // output wire [4 : 0] rd_data_count.wr_data_count( data_wrcount )  // output wire [4 : 0] wr_data_count
);
endmodule

2.3 读通道 

读通道的实现分两步,用户端发出读请求并给读的地址,然后从机根据地址发出数据,用户读出。

因此读地址fifo的逻辑部分与写通道一致,只有状态机跳转的RD_DATA_EN的条件根据模块端口有所改变,但是读数据fifo,是在AXI_CLK的时钟域下,端口输入有效及端口输入数据,根据非空开始用户读,然后赋给模块用户端口

`timescale 1ns / 1ps
//
// Description: AXI_LITE读通道
//
module axilite_rd_channel#(parameter USER_RD_DATA_WIDTH    = 32 , //用户读数据位宽和AXI4—Lite数据位宽保持一致parameter AXI_DATA_WIDTH 		= 32, parameter AXI_ADDR_WIDTH        = 32		
)(input   wire								    clk,  	  input   wire								    axi_clk,    input   wire								    reset,//用户端读请求,读地址信号input   wire								    user_rd_en,input   wire  [AXI_ADDR_WIDTH-1 :0]		        user_rd_addr,output  wire                                    user_rd_ready,output  reg   [USER_RD_DATA_WIDTH-1:0]	        user_rd_data,output  reg                                     user_rd_valid,//与AXI_LITE从机 交互信号output  reg   		 							m_axi_arvalid, // axi read address channelinput   wire   		 							m_axi_arready, output  reg   [AXI_ADDR_WIDTH-1:0] 				m_axi_araddr,output  wire  [2:0] 							m_axi_arprot, input   wire  [AXI_DATA_WIDTH-1:0]	    		m_axi_rdata,   // axi read data channelinput   wire  [1:0] 				    		m_axi_resp,input   wire     					    		m_axi_rvalid,output  wire   						   	 		m_axi_rready
);(* dont_touch = "true"*) reg reset_sync_d0;  //user clk
(* dont_touch = "true"*) reg reset_sync_d1;
(* dont_touch = "true"*) reg reset_sync;
(* dont_touch = "true"*) reg a_reset_sync_d0; //axi clk
(* dont_touch = "true"*) reg a_reset_sync_d1;
(* dont_touch = "true"*) reg a_reset_sync;reg	 [31:0]  cmd_din;
reg          cmd_wren;
wire [31:0]  cmd_dout;
reg 		 cmd_rden;
wire		 cmd_wrfull;
wire		 cmd_rdempty;
wire [4:0]   cmd_wrcount;
wire [4:0]   cmd_rdcount;reg	 [31:0]  data_din;
reg          data_wren;
wire [31:0]  data_dout;
wire 		 data_rden;
wire		 data_wrfull;
wire		 data_rdempty;
wire [4:0]   data_wrcount;
wire [4:0]   data_rdcount;reg [2 : 0]	 cur_status;
reg [2 : 0]	 nxt_status;localparam RD_IDLE     = 3'b000;
localparam RD_PRE      = 3'b001;
localparam RD_DATA_EN  = 3'b010;
localparam RD_END      = 3'b100;
/*--------------------------------------------------*\assign
\*--------------------------------------------------*/
assign user_rd_ready = reset_sync ? 1'b0 : cmd_wrcount <= 'd12 ; 
assign m_axi_rready  = 1'b1;
assign m_axi_arprot  = 0;
/*--------------------------------------------------*\CDC process
\*--------------------------------------------------*/
always @(posedge clk) beginreset_sync_d0   <= reset;reset_sync_d1   <= reset_sync_d0;reset_sync      <= reset_sync_d1;
endalways @(posedge axi_clk) begina_reset_sync_d0 <= reset;a_reset_sync_d1 <= a_reset_sync_d0;a_reset_sync    <= a_reset_sync_d1;
end/*--------------------------------------------------*\wirte addr to cmd fifo
\*--------------------------------------------------*/
always @(posedge clk) beginif (user_rd_ready) begincmd_wren  <= user_rd_en;cmd_din   <= user_rd_addr;	endelse begincmd_wren  <= 0;cmd_din   <= 0;			end
end/*--------------------------------------------------*\RD state machine  
\*--------------------------------------------------*/
always @(posedge axi_clk) beginif (a_reset_sync) begincur_status <= RD_IDLE;endelse begincur_status <= nxt_status;end
endalways @(*) beginif (a_reset_sync) beginnxt_status <= RD_IDLE;		endelse begincase(cur_status)RD_IDLE : beginif (~cmd_rdempty)nxt_status <= RD_PRE;else nxt_status <= cur_status;endRD_PRE : beginnxt_status <= RD_DATA_EN;endRD_DATA_EN : beginif (m_axi_rvalid && m_axi_rready)nxt_status <= RD_END;else nxt_status <= cur_status;endRD_END : beginnxt_status <= RD_IDLE;enddefault : nxt_status <= RD_IDLE;endcase	end
end/*-----------------------------------------------------------*\read addr from cmd_fifo 
\*-----------------------------------------------------------*/
always @(*) beginif (a_reset_sync) cmd_rden  <= 0;else cmd_rden  <= cur_status == RD_PRE;
endalways @(posedge axi_clk) beginif (cmd_rden) m_axi_araddr <= cmd_dout;else m_axi_araddr <= m_axi_araddr;
endalways @(posedge axi_clk) beginif (a_reset_sync) m_axi_arvalid <= 0;else if (cur_status == RD_PRE)m_axi_arvalid <= 1'b1;else if (m_axi_arvalid && m_axi_arready)m_axi_arvalid <= 0;
end/*-----------------------------------------------------------*\read user data from data fifo
\*-----------------------------------------------------------*/
always @(posedge axi_clk) begindata_din  <= m_axi_rdata;data_wren <= m_axi_rvalid;
end assign data_rden = reset_sync ? 1'b0 : ~data_rdempty;always @(posedge clk) beginuser_rd_valid  <= data_rden;user_rd_data   <= data_dout;
end//读地址fifo
fifo_w32xd16 rd_cmd_fifo (.rst          ( reset_sync  ), // input wire rst.wr_clk       ( clk         ), // input wire wr_clk         用户写时钟.din          ( cmd_din     ), // input wire [31 : 0] din.wr_en        ( cmd_wren    ), // input wire wr_en.rd_clk       ( axi_clk     ), // input wire rd_clk         从机读时钟 .rd_en        ( cmd_rden    ), // input wire rd_en.dout         ( cmd_dout    ), // output wire [31 : 0] dout.full         ( cmd_wrfull  ), // output wire full.empty        ( cmd_rdempty ), // output wire empty.rd_data_count( cmd_wrcount ), // output wire [4 : 0] rd_data_count.wr_data_count( cmd_rdcount )  // output wire [4 : 0] wr_data_count
);//读数据fifo
fifo_w32xd16 rd_data_fifo (.rst          ( a_reset_sync ), // input wire rst.wr_clk       ( axi_clk      ), // input wire wr_clk        从机写时钟.din          ( data_din     ), // input wire [31 : 0] din.wr_en        ( data_wren    ), // input wire wr_en.rd_clk       ( clk          ), // input wire rd_clk            用户读时钟 .rd_en        ( data_rden    ), // input wire rd_en.dout         ( data_dout    ), // output wire [31 : 0] dout.full         ( data_wrfull  ), // output wire full.empty        ( data_rdempty ), // output wire empty.rd_data_count( data_rdcount ), // output wire [4 : 0] rd_data_count.wr_data_count( data_wrcount )  // output wire [4 : 0] wr_data_count
);
endmodule

3.仿真 

通过调用AXI_LITE接口的BRAM IP核,实/复位结束等一会儿进入写数据状态,读写数据(写10个数据,读10个数据),数据一致累加,地址也不断累加,地址最大为1024。

 仿真结果如下,可以看出读写地址和数据完全一样,说明AXI_LITE接口代码实现无误。

 

需要工程请私信

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

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

相关文章

idea运行

各种小kips Linuxidea上传 Linux 部署流程 1、先在idea打好jar包&#xff0c;clean之后install 2、在Linux目录下&#xff0c;找到对应项目目录&#xff0c;把原来的jar包放在bak文件夹里面 3、杀死上一次jar包的pid ps -ef|grep cliaidata.jar kill pid 4、再进行上传新的jar…

FPGA: XILINX Kintex 7系列器件的架构

本文将详细介绍Kintex-7系列FPGA器件的架构。以下内容将涵盖Kintex-7的核心架构特性、主要组成部分以及关键技术&#xff0c;尽量全面且结构化&#xff0c;同时用简洁的语言确保清晰易懂。 Kintex-7系列FPGA架构概述 Kintex-7是Xilinx 7系列FPGA中的中高端产品线&#xff0c;基…

【LLM】大模型落地应用的技术 ——— 推理训练 MOE,AI搜索 RAG,AI Agent MCP

【LLM】大模型落地应用的技术 ——— 推理训练MOE&#xff0c;AI搜索RAG&#xff0c;AI Agent MCP 文章目录 1、推理训练 MOE2、AI搜索 RAG3、AI Agent MCP 1、推理训练 MOE MoE 是模型架构革新&#xff0c;解决了算力瓶颈。原理是多个专家模型联合计算。 推理训练MoE&#xff…

10 web 自动化之 yaml 数据/日志/截图

文章目录 一、yaml 数据获取二、日志获取三、截图 一、yaml 数据获取 需要安装 PyYAML 库 import yaml import os from TestPOM.common import dir_config as Dir import jsonpathclass Data:def __init__(self,keyNone,file_name"test_datas.yaml"):file_path os…

中exec()函数因$imagePath参数导致的命令注入漏洞

exec(zbarimg -q . $imagePath, $barcodeList, $returnVar); 针对PHP中exec()函数因$imagePath参数导致的命令注入漏洞&#xff0c;以下是安全解决方案和最佳实践&#xff1a; 一、漏洞原理分析 直接拼接用户输入$imagePath到系统命令中&#xff0c;攻击者可通过注入特殊字…

this.$set的用法-响应式数据更新

目录 一、核心作用 三、使用场景与示例 1. 给对象添加新属性 四、与 Vue.set 的关系 五、底层原理 六、Vue 3 的替代方案 七、最佳实践 八、常见问题 Q&#xff1a;为什么修改嵌套对象属性不需要 $set&#xff1f; Q&#xff1a;$set 和 $forceUpdate 的区别&#xf…

【生成式AI文本生成实战】DeepSeek系列应用深度解析

目录 &#x1f31f; 前言&#x1f3d7;️ 技术背景与价值&#x1fa79; 当前技术痛点&#x1f6e0;️ 解决方案概述&#x1f465; 目标读者说明 &#x1f9e0; 一、技术原理剖析&#x1f4ca; 核心概念图解&#x1f4a1; 核心作用讲解&#x1f527; 关键技术模块说明⚖️ 技术选…

c/c++的opencv的图像预处理讲解

OpenCV 图像预处理核心技术详解 (C/C) 图像预处理是计算机视觉任务中至关重要的一步。原始图像往往受到噪声、光照不均、尺寸不一等多种因素的影响&#xff0c;直接用于后续分析&#xff08;如特征提取、目标检测、机器学习模型训练等&#xff09;可能会导致性能下降或结果不准…

使用 Docker 部署 React + Nginx 应用教程

目录 1. 创建react项目结构2. 创建 .dockerignore3. 创建 Dockerfile4. 创建 nginx.conf5. 构建和运行6. 常用命令 1. 创建react项目结构 2. 创建 .dockerignore # 依赖目录 node_modules npm-debug.log# 构建输出 dist build# 开发环境文件 .git .gitignore .env .env.local …

Java 流(Stream)API

一、理论说明 1. 流的定义 Java 流&#xff08;Stream&#xff09;是 Java 8 引入的新特性&#xff0c;用于对集合&#xff08;如 List、Set&#xff09;或数组进行高效的聚合操作&#xff08;如过滤、映射、排序&#xff09;和并行处理。流不存储数据&#xff0c;而是按需计…

网络协议分析 实验七 FTP、HTTP、DHCP

文章目录 实验7.1 FTP协议练习二 使用浏览器登入FTP练习三 在窗口模式下&#xff0c;上传/下传数据文件实验7.2 HTTP(Hyper Text Transfer Protocol)练习二 页面提交练习三 访问比较复杂的主页实验7.3 DHCP(Dynamic Host Configuration Protocol) 实验7.1 FTP协议 dir LIST&…

go语言学习进阶

目录 第一章 go语言中包的使用 一.main包 二.package 三.import 四.goPath环境变量 五.init包初始化 六.管理外部包 第二章 time包 第三章 File文件操作 一.FileInfo接口 二.权限 三.打开模式 四.File操作 五.读文件 参考1&#xff1a;Golang 中的 bufio 包详解…

Hue面试内容整理-后端框架

Cloudera 的 Hue 项目在后端采用了成熟的 Python Web 框架 Django,结合其他组件构建了一个可扩展、模块化的系统,便于与 Hadoop 生态系统中的各个组件集成。以下是 Hue 后端架构的详细介绍: 后端架构概览 1. Django Web 框架 Hue 的核心是基于 Django 构建的 Web 应用,负责…

Web-CSS入门

WEB前端&#xff0c;三部分&#xff1a;HTML部分、CSS部分、Javascript部分。 1.HTML部分&#xff1a;主要负责网页的结构层 2.CSS部分&#xff1a;主要负责网页的样式层 3.JS部分&#xff1a;主要负责网页的行为层 **基本概念** 层叠样式表&#xff0c;Cascading Style Sh…

2025年PMP 学习十六 第11章 项目风险管理 (总章)

2025年PMP 学习十六 第11章 项目风险管理 &#xff08;总章&#xff09; 第11章 项目风险管理 序号过程过程组1规划风险管理规划2识别风险规划3实施定性风险分析规划4实施定量风险分析规划5规划风险应对执行6实施风险应对执行7监控风险监控 目标: 提高项目中积极事件的概率和…

基于SpringBoot的小区停车位管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

HTML常用标签用法全解析:构建语义化网页的核心指南

HTML作为网页开发的基石&#xff0c;其标签的合理使用直接影响页面的可读性、SEO效果及维护性。本文系统梳理HTML核心标签的用法&#xff0c;结合语义化设计原则与实战示例&#xff0c;助你构建规范、高效的网页结构。 一、基础结构与排版标签 1.1 文档结构 <!DOCTYPE htm…

国产linux系统(银河麒麟,统信uos)使用 PageOffice自定义Word模版中的数据区域

​ PageOffice 国产版 &#xff1a;支持信创系统&#xff0c;支持银河麒麟V10和统信UOS&#xff0c;支持X86&#xff08;intel、兆芯、海光等&#xff09;、ARM&#xff08;飞腾、鲲鹏、麒麟等&#xff09;、龙芯&#xff08;Mips、LoogArch&#xff09;芯片架构。 在实际的Wor…

.NET Core liunx二进制文件安装

最近遇见个尴尬的事情&#xff0c;都2025年了。我需要部署一个自己多年前写的项目。由于时间紧、任务重&#xff0c;我懒得去升级到8.0了。于是计划在Ubuntu20.04上安装.NET Core3.1项目。可以使用包管理器却安装不上了。于是&#xff0c;我就尝试二进制文件安装。 实际上二进…

【python基础知识】Day 27 函数专题2:装饰器

知识点&#xff1a; 装饰器的思想&#xff1a;进一步复用函数的装饰器写法注意内部函数的返回值 装饰器教程 作业&#xff1a; 编写一个装饰器 logger&#xff0c;在函数执行前后打印日志信息&#xff08;如函数名、参数、返回值&#xff09; def logger(func):def wrapper(*ar…