当前位置: 首页 > news >正文

自研PE单元AXI接口记录(2)

紧接着上一篇,这期记录我实现PE单元C矩阵的AXI接口的过程。
一、设计前
PE的C矩阵信号端为(outputc_ptr_addr ,c_ptr_addr_v ,c_data_v,c_data),并且也是地址递增,结合AXI4特性,我们应该怎么做呢
二、设计思路
这里就简要带过了,发出写使能时存入fifo,然后在almost_full时发出写请求,这里写请求必须独立发出了,幸好datav频率没那么高,不然超出ping-pong buffer的fifo发出写请求是一个很危险的事。
还要注意的是,如果我们这里使用的base_addr都是以0x000结尾的,因此只要按照固定2的指数个突发长度读或者写,就不会触发4kb边界报错。但是我们要注意pe计算结束时必须清空fifo,所以写请求条件除了almost_full还必须加上pe_done。
三、工程代码实现(让ai缩短了)

点击查看代码
`timescale 1 ns / 1 psmodule pe_system_v1_0_m02_axi #
(parameter integer C_M_AXI_BURST_LEN	    = 256,parameter integer C_M_AXI_ID_WIDTH	    = 2,parameter integer C_M_AXI_ADDR_WIDTH	= 32,parameter integer C_M_AXI_DATA_WIDTH	= 32
)
(// --- Matrix C PE Interface ---input wire [C_M_AXI_ADDR_WIDTH-1:0]  c_ptr_addr,input wire                           c_ptr_addr_v, input wire [C_M_AXI_ADDR_WIDTH-1:0]  c_col_addr,input wire                           c_col_addr_v, input wire [C_M_AXI_ADDR_WIDTH-1:0]  c_val_addr,input wire                           c_val_addr_v, input wire [C_M_AXI_DATA_WIDTH-1:0]  c_ptr_data,input wire           				 c_ptr_data_v,input wire [C_M_AXI_DATA_WIDTH-1:0]  c_col_data,input wire           				 c_col_data_v,input wire [C_M_AXI_DATA_WIDTH-1:0]  c_val_data,input wire           				 c_val_data_v,input wire [C_M_AXI_ADDR_WIDTH-1:0]  c_ptr_base_addr,input wire [C_M_AXI_ADDR_WIDTH-1:0]  c_col_base_addr,input wire [C_M_AXI_ADDR_WIDTH-1:0]  c_val_base_addr,input wire                           pe_done,// --- AXI4 写物理接口 ---input wire  M_AXI_ACLK,input wire  M_AXI_ARESETN,output wire [C_M_AXI_ID_WIDTH-1 : 0]    M_AXI_AWID,output wire [C_M_AXI_ADDR_WIDTH-1 : 0]  M_AXI_AWADDR,output wire [7 : 0]                     M_AXI_AWLEN,output wire [2 : 0]                     M_AXI_AWSIZE,output wire [1 : 0]                     M_AXI_AWBURST,output wire                             M_AXI_AWLOCK,output wire [3 : 0]                     M_AXI_AWCACHE,output wire [2 : 0]                     M_AXI_AWPROT,output wire [3 : 0]                     M_AXI_AWQOS,output wire                             M_AXI_AWVALID,input  wire                             M_AXI_AWREADY,output wire [C_M_AXI_DATA_WIDTH-1 : 0]  M_AXI_WDATA,output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB,output wire                             M_AXI_WLAST,output wire                             M_AXI_WVALID,input  wire                             M_AXI_WREADY,input  wire [C_M_AXI_ID_WIDTH-1 : 0]    M_AXI_BID,input  wire [1 : 0]                     M_AXI_BRESP,input  wire                             M_AXI_BVALID,output wire                             M_AXI_BREADY,output wire                             TXN_DONE,output reg                              ERROR
);// --- 内部寄存器定义 ---parameter [1:0] IDLE = 2'b00, BUSY = 2'b01;reg [1:0] mst_exec_state;reg [C_M_AXI_ADDR_WIDTH-1 : 0]  axi_awaddr_reg;reg                             axi_awvalid;reg [7:0]                       axi_awlen_reg;reg [C_M_AXI_ID_WIDTH-1 : 0]    current_awid;reg [7:0]                       write_index;reg                             burst_write_active;reg                             w_active; // 新增:控制 W 通道数据流的开启// 三路独立偏移量 (复刻 M00 逻辑)reg [C_M_AXI_ADDR_WIDTH-1:0] ptr_offset, col_offset, val_offset;// FIFO 信号声明wire [10:0] c_ptr_data_cnt, c_col_data_cnt, c_val_data_cnt;wire c_ptr_fifo_rd_en, c_col_fifo_rd_en, c_val_fifo_rd_en;wire [31:0] c_ptr_fifo_dout, c_col_fifo_dout, c_val_fifo_dout;wire c_ptr_empty, c_col_empty, c_val_empty;wire c_ptr_almost_full, c_col_almost_full, c_val_almost_full;// --- AXI 物理接口赋值 ---assign M_AXI_AWID    = current_awid;assign M_AXI_AWADDR  = axi_awaddr_reg;assign M_AXI_AWLEN   = axi_awlen_reg;assign M_AXI_AWSIZE  = 3'b010; // 4 bytesassign M_AXI_AWBURST = 2'b01;assign M_AXI_AWLOCK  = 1'b0;assign M_AXI_AWCACHE = 4'b0011;assign M_AXI_AWPROT  = 3'h0;assign M_AXI_AWQOS   = 4'h0;assign M_AXI_AWVALID = axi_awvalid;assign M_AXI_WSTRB   = 4'b1111;assign M_AXI_BREADY  = 1'b1;assign TXN_DONE      = pe_done && c_ptr_empty && c_col_empty && c_val_empty && !burst_write_active;// --- W 通道核心控制 (解决 STABLE 错误) ---// 只有在 w_active 期间且对应 FIFO 不为空时,才允许拉高 WVALIDassign M_AXI_WVALID = w_active && ((current_awid == 2'b00 && !c_ptr_empty) || (current_awid == 2'b01 && !c_col_empty) || (current_awid == 2'b10 && !c_val_empty));assign M_AXI_WDATA  = (current_awid == 2'b00) ? c_ptr_fifo_dout :(current_awid == 2'b01) ? c_col_fifo_dout : c_val_fifo_dout;assign M_AXI_WLAST  = (write_index == axi_awlen_reg);// FIFO 读使能:只有总线真正握手成功(收走数据)时,才从 FIFO 弹出下一个// 这保证了 empty 信号只在时钟沿更新,且 WVALID 不会在 WREADY 为低时掉下来assign c_ptr_fifo_rd_en = (M_AXI_WVALID && M_AXI_WREADY && (current_awid == 2'b00));assign c_col_fifo_rd_en = (M_AXI_WVALID && M_AXI_WREADY && (current_awid == 2'b01));assign c_val_fifo_rd_en = (M_AXI_WVALID && M_AXI_WREADY && (current_awid == 2'b10));// --- 地址偏移量自增 (由 AW 握手驱动) ---always @(posedge M_AXI_ACLK) beginif (!M_AXI_ARESETN) beginptr_offset <= 0; col_offset <= 0; val_offset <= 0;end else if (M_AXI_AWVALID && M_AXI_AWREADY) begincase(current_awid)2'b00: ptr_offset <= ptr_offset + ((axi_awlen_reg + 1) << 2);2'b01: col_offset <= col_offset + ((axi_awlen_reg + 1) << 2);2'b10: val_offset <= val_offset + ((axi_awlen_reg + 1) << 2);endcaseendend// --- 状态机控制 ---always @(posedge M_AXI_ACLK) beginif (!M_AXI_ARESETN) beginmst_exec_state <= IDLE;axi_awvalid    <= 1'b0;axi_awaddr_reg <= 0;axi_awlen_reg  <= 0;current_awid   <= 0;end else begincase (mst_exec_state)IDLE: beginif (!burst_write_active && !axi_awvalid) beginif (c_ptr_almost_full || (pe_done && !c_ptr_empty)) begincurrent_awid   <= 2'b00;axi_awaddr_reg <= c_ptr_base_addr + ptr_offset;axi_awlen_reg <= (c_ptr_data_cnt >= 256) ? 8'd255 : (c_ptr_data_cnt > 0 ? c_ptr_data_cnt - 1 : 8'd0);axi_awvalid    <= 1'b1;mst_exec_state <= BUSY;end else if (c_col_almost_full || (pe_done && !c_col_empty)) begincurrent_awid   <= 2'b01;axi_awaddr_reg <= c_col_base_addr + col_offset;axi_awlen_reg  <= (c_col_data_cnt >= 256) ? 8'd255 : (c_col_data_cnt > 0 ? c_col_data_cnt - 1 : 8'd0);axi_awvalid    <= 1'b1;mst_exec_state <= BUSY;end else if (c_val_almost_full || (pe_done && !c_val_empty)) begincurrent_awid   <= 2'b10;axi_awaddr_reg <= c_val_base_addr + val_offset;axi_awlen_reg  <= (c_val_data_cnt >= 256) ? 8'd255 : (c_val_data_cnt > 0 ? c_val_data_cnt - 1 : 8'd0);axi_awvalid    <= 1'b1;mst_exec_state <= BUSY;endendendBUSY: beginif (M_AXI_AWREADY && axi_awvalid) axi_awvalid <= 1'b0;// 当收到最后一个数据的写响应 BVALID 后,才返回 IDLEif (!burst_write_active && !axi_awvalid) mst_exec_state <= IDLE;endendcaseendend// 写数据活跃状态:AW握手开始,WLAST握手结束always @(posedge M_AXI_ACLK) beginif (!M_AXI_ARESETN) w_active <= 0;else if (axi_awvalid && M_AXI_AWREADY) w_active <= 1;else if (M_AXI_WVALID && M_AXI_WREADY && M_AXI_WLAST) w_active <= 0;end// 整个写突发活跃状态:从 AWVALID 到 BVALIDalways @(posedge M_AXI_ACLK) beginif (!M_AXI_ARESETN) burst_write_active <= 0;else if (axi_awvalid && M_AXI_AWREADY) burst_write_active <= 1;else if (M_AXI_BVALID && M_AXI_BREADY) burst_write_active <= 0;end// 写索引计数器always @(posedge M_AXI_ACLK) beginif (!M_AXI_ARESETN || (axi_awvalid && M_AXI_AWREADY)) beginwrite_index <= 0;end else if (M_AXI_WVALID && M_AXI_WREADY) beginwrite_index <= write_index + 1;endend// --- FIFO 实例化集群 ---
// ==========================================================// --- Matrix C FIFO 实例化集群 (替换 sync_fifo) ---// ==========================================================// C_PTR FIFOnew_fifo c_ptr_fifo (.clk           (M_AXI_ACLK),.srst          (!M_AXI_ARESETN),   // 高电平复位.din           (c_ptr_data),.wr_en         (c_ptr_data_v),.rd_en         (c_ptr_fifo_rd_en),.dout          (c_ptr_fifo_dout),.empty         (c_ptr_empty),.full          (),                 // 留空.almost_full   (),                 // 留空(改用 prog_full).almost_empty  (),.valid         (),.data_count    (c_ptr_data_cnt),.prog_full     (c_ptr_almost_full), // 对接逻辑用的 almost_full.prog_empty    (),.wr_rst_busy   (),.rd_rst_busy   ());// C_COL FIFOnew_fifo c_col_fifo (.clk           (M_AXI_ACLK),.srst          (!M_AXI_ARESETN),.din           (c_col_data),.wr_en         (c_col_data_v),.rd_en         (c_col_fifo_rd_en),.dout          (c_col_fifo_dout),.empty         (c_col_empty),.full          (),.almost_full   (),.almost_empty  (),.valid         (),.data_count    (c_col_data_cnt),.prog_full     (c_col_almost_full),.prog_empty    (),.wr_rst_busy   (),.rd_rst_busy   ());// C_VAL FIFOnew_fifo c_val_fifo (.clk           (M_AXI_ACLK),.srst          (!M_AXI_ARESETN),.din           (c_val_data),.wr_en         (c_val_data_v),.rd_en         (c_val_fifo_rd_en),.dout          (c_val_fifo_dout),.empty         (c_val_empty),.full          (),.almost_full   (),.almost_empty  (),.valid         (),.data_count    (c_val_data_cnt),.prog_full     (c_val_almost_full),.prog_empty    (),.wr_rst_busy   (),.rd_rst_busy   ());
endmodule
http://www.jsqmd.com/news/524910/

相关文章:

  • S12SD紫外线传感器模块嵌入式集成与GD32F470驱动实践
  • K8s集群频繁重启?可能是etcd磁盘性能拖了后腿(附调优参数详解)
  • NodeJS 内存泄漏实战:从日志分析到优化策略
  • Xshell7免费版获取与安装全攻略(附最新网盘资源)
  • 芸豆花客服咨询AI流量赋能,重塑智能体验新标杆 - 王老吉弄
  • Unity实战:利用粒子系统打造炫酷道具收集动画效果
  • 【芯片设计】深入解析DC综合中的retiming优化技巧与实战案例
  • 手眼标定结果不准?教你用标准差分析标定质量(附Python脚本)
  • 从BRDF到MIS:一篇讲透游戏引擎中的现代光线采样技术
  • MPU6050六轴传感器驱动与DMP姿态解算实战
  • 2026化纤色纺纱订纺优质供应商推荐榜:紧密纺色纺纱订制/纱线工厂色纺纱ODM/OEM/绢丝/棉色纺纱线订制/绢丝混色纱线定制/选择指南 - 优质品牌商家
  • ERA5风场数据可视化:Python实现U/V风合成与气象要素分析
  • 从Fireworks到Figma:老牌网页设计工具在现代工作流中的替代方案
  • MATLAB GUI界面设计与图像处理的奇妙融合
  • UOS家庭版(21.2)运行SecureCRT(deb包)的依赖库缺失与权限修复实战
  • 数电课设实战:基于Verilog状态机的饮料自动贩卖机设计
  • 一键解决PyTorch生态依赖难题:自动化安装脚本设计与实现
  • 汇川伺服Modbus-RTU通讯实战:从帧结构解析到西门子PLC程序实现
  • 你的Emby媒体库还缺个‘新闻官’?手把手教你用TMDB API和Telegram Bot丰富推送卡片信息
  • ROS Melodic在树莓派4B上的避坑指南:解决rosdep init失败的终极方案
  • YOLOv13全网首发:CVPR2026 MixerCSeg | DEGConv方向引导边缘门控,破解细长裂缝检测难题
  • 2026年合金铝板优质厂家推荐榜:3mm铝单板/冲孔铝板/北京氟碳铝单板/北京铝单板/北京铝板/压花铝板/合金铝板/选择指南 - 优质品牌商家
  • Transformer目标跟踪实战:从ViT到DiffusionTrack的保姆级代码解析
  • SUPER COLORIZER创意工坊:利用Agent概念构建智能上色提示词生成器
  • Vue项目实战:使用relation-graph构建可交互的鱼骨图式关系图谱
  • 制造业实战:如何用PDCA循环+六西格玛降低产品缺陷率(附汽车行业案例)
  • 推荐系统实战:如何用余弦相似度找到相似用户(含Spark优化技巧)
  • 从‘素模’到‘高仿’:我是如何用Blender和PS给Tianbot Mini小车激光雷达‘化妆’并跑进Gazebo的
  • Qwen-Image入门指南:RTX4090D镜像中Qwen-VL模型路径、依赖库版本与兼容性说明
  • STM32F103C8T6实战:手把手教你用串口IAP升级固件(附完整代码)