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

从零开始讲DDR(8)——AXI 接口MIG 使用(1)

一、前言

        在之前的系列文章中,我们已经讨论过了MIG ip的接口内容,配置方式和modelsim独立仿真相关的内容,因此,本文对于之前已经讨论过的相关内容只做简单描述,着重介绍AXI 接口MIG使用上与普通ui接口的不同之处。感兴趣的读者可以自行阅读之前的相关系列文章。

二、MIG配置

        在配置上,我们选择AXI4 Interface。

        在AXI接口的选择上选择64bit,写优先模式。然后就是通过打开xilinx提供的example project,并导出modelsim独立仿真所需要的相关文件,构建自己的独立仿真工程。

三、AXI 接口MIG仿真文件解析

        从example project导出的仿真文件中,我们可以看到如下的一系列测试平台列表

3.1 sim_tb_top.sv

3.1.1 注释说明

        根据官方给出的注释说明,我们可以看到这部分的内容主要的功能是:(1)整个测试平台的顶层模块(2)例化了内存模型(3)生成了时钟和复位逻辑。

3.1.2 代码解析

        sim_tb_top.sv中首先完成了一些必要信号的定义,然后就是进行了复位信号和时钟信号的产生,接下来就是例化了example_top模块,再之后就是例化的内存模型。这里我们并不需要关心内存模型是怎么实现的,我们只需要理解在sim_tb_top中核心功能就是例化了example_top模块。

        而如果我们希望仿真我们自己独立的代码逻辑,有2种可行的方式:(1)把自己的逻辑替换example_top模块(2)注释掉example_top模块,把相关的数据线从内部逻辑转换成input/output/inout的形式,形成对外的接口,这样我们就可以把整个sim_tb_top模块当做一个例化了内存模型,能自主进行复位和时钟产生的DDR测试模型,这样把我们自己的代码逻辑接到此文件,就可以进行独立的DDR模型仿真了。

3.2 example_top

        在编写我们自己独立的DDR读写逻辑之前,学习一下官方给出的示例工程还是非常必要的,我们知道在sim_tb_top中主要的功能是例化了example_top模块,因此,我们接下来来学习example_top模块。

3.2.1 注释说明

        从注释中我们可以发现, example_top模块的主要功能是作为一个测试的顶层文件,允许用户自定义他们的设计。主要例化了DDR MIG(就是我们生成的IP)和一个可综合测试平台,用于建模用户的后端逻辑和传输不同的流量模式。

3.2.2 代码解析

        从代码角度看,首先还是一些必要参数和信号定义,然后就是实例化了一个DDR MIG的ip模型,接下来例化了一个ddr4_v2_2_8_axi_tg_top模块。tg就是Traffic Generator的缩写。

        首先可以看到的是对于 c0_init_calib_complete 信号的一个寄存,这里的主要目的是为了在c0_init_calib_complete信号拉高后,生成一个boot_mode_start的pulse信号。简单推测就是在c0_init_calib_complete拉高后,开始进行boot mode的流量测试。

        接下来就是对于ddr4_v2_2_8_axi_tg_top的例化,ddr4_v2_2_8_axi_tg_top从接口上来看,主要包含3个部分:(1)AXI tg Input control signals (2)AXI MIG接口(3)Axi tg Error status signals。AXI MIG接口相对简单,就是用来和MIG进行连接的interface。Axi tg Error status signals看起来是和debug相关的,我们后面有需要的时候再详细展开,AXI tg Input control signal这里我们稍微关注一下:

        从信号的名称来看,大概指的是这个 Traffic Generator 支持的3种模式,分别是boot,custom和prbs。这里的执行逻辑是 custom 模式暂时没有使用,首先在c0_init_calib_complete 拉高后进行boot模式,然后,在boot_mode_done之后,boot_mode_done被接到了prbs_mode_start接口上,意味着在完成boot模式后,执行prbs模式。

3.3 ddr4_v2_2_8_axi_tg_top

        接下来我们来重点关注ddr4_v2_2_8_axi_tg_top模块

3.3.1 注释说明

        这个模块实例化了boot/prbs/custom-mode_gen模块。 根据用户输入,这些模式中的任何一个都可以处于运行状态,运行模式将驱动axi_opcode_gen模块的输入,该模块为AXI 从接口测试生成符合AXI4协议的流量。

  • *_mode_start->模式启动
  • *_mode_stop->模式停止
  • *_mode_done->为高表示用户停止模式或模式完成其表中的所有指令,可以通过断言任*_mode_start来清除

        简单判断就是提供了3种不同的模式,每种模式有各自的一组控制信号start,stop和done

3.3.2 代码解析

        首先还是进行一系列的参数和信号定义,然后我们关注下图中的代码逻辑,这里设置了running信号,用来表示当时正在执行的时什么模式。

        接下来,以running信号为依据,将正在运行的模式的相关控制信号,接到axi_opcode_gen的信号组上。

         然后就是一组模块的实例化,分别例化了boot_mode_gen,prbs_mode_gen,custom_mode_gen和axi_opcode_gen。功能分析起来也并不复杂,首先用户通过start,stop和done控制运行的模式(同一时间只能运行一种模式),然后boot_mode_gen,prbs_mode_gen,custom_mode_gen是各自模式的激励生成器,会生成对应模式的测试激励,然后根据running信号,选择对应的激励驱动到axi_opcode_gen的输入端接口,axi_opcode_gen会将激励转换成符合axi4协议规范的信号,驱动到MIG的AXI4从接口上。

        梳理清楚了核心逻辑,我们还需要关注一下最后的一部分自动化测试逻辑。

        首先是watch_dog ,它的功能是检测AXI总线是否卡死——如果超过C_TG_WATCH_DOG_MAX_CNT个时钟周期没有读写活动,触发watch_dog_hang信号,终止仿真并报错($finish)。

localparam C_TG_WATCH_DOG_MAX_CNT = 16'hFFFF;
reg [15:0] watch_dog_cnt;
wire watch_dog_enable;
reg watch_dog_rst;
wire watch_dog_hang;assign watch_dog_enable = 1'b1; // 看门狗常启// 任何AXI读写活动都会复位计数器
always@(posedge clk) beginwatch_dog_rst <= #TCQ ((axi_awready && axi_awvalid) || // 写地址通道活动(axi_wready && axi_wvalid) ||    // 写数据通道活动(axi_bready && axi_bvalid) ||    // 写响应通道活动(axi_arready && axi_arvalid) ||  // 读地址通道活动(axi_rready && axi_rvalid));     // 读数据通道活动
end// 看门狗计数逻辑
always@(posedge clk) beginif (tg_rst | watch_dog_rst) begin           // 全局复位或AXI活动时清零watch_dog_cnt <= #TCQ 'h0;endelse if (watch_dog_enable && ~watch_dog_hang && (vio_axi_tg_boot_mode_running ||     // 在TG运行模式下递增计数vio_axi_tg_custom_mode_running || vio_axi_tg_prbs_mode_running)) beginwatch_dog_cnt <= #TCQ watch_dog_cnt + 'h1;end
end
assign watch_dog_hang = (watch_dog_cnt == C_TG_WATCH_DOG_MAX_CNT); // 超时标志

        然后是错误状态记录与VIO调试接口,它的作用是记录首次发生的数据不匹配错误,并通过VIO接口输出详细的错误上下文(地址、ID、数据差异等),方便硬件调试。类似地处理写响应错误(vio_axi_tg_write_resp_error)和读响应错误(vio_axi_tg_read_resp_error)。

// 同步错误状态到VIO(Virtual Input/Output)可观察信号
always @(posedge clk) beginif (tg_rst) begin  // 全局复位时清零vio_axi_tg_mismatch_error      <= #TCQ 0;   // 数据不匹配错误vio_axi_tg_expected_bits       <= #TCQ 0;   // 预期数据值vio_axi_tg_actual_bits         <= #TCQ 0;   // 实际收到的数据值vio_axi_tg_error_bits          <= #TCQ 0;   // 出错的数据位掩码vio_axi_tg_error_status_id     <= #TCQ 0;   // 错误交易IDvio_axi_tg_error_status_addr   <= #TCQ 0;   // 错误地址vio_axi_tg_error_status_len    <= #TCQ 0;   // 错误交易长度vio_axi_tg_error_status_size   <= #TCQ 0;   // 错误数据大小(字节)vio_axi_tg_error_status_burst  <= #TCQ 0;   // 错误突发类型endelse if(axi_tg_mismatch_error && ~vio_axi_tg_mismatch_error) begin// 捕获第一次出现的错误(Sticky Error)vio_axi_tg_mismatch_error      <= #TCQ 1;vio_axi_tg_expected_bits       <= #TCQ axi_tg_expected_bits;vio_axi_tg_actual_bits         <= #TCQ axi_tg_actual_bits;// ...其他信号赋值省略...end  
end

        接下来是仿真调试输出,用来在仿真中实时报告错误,并在测试完成后统计成功率。

// 仿真时打印错误信息
always @(posedge clk) beginif(axi_tg_mismatch_error) begin$display("ERROR::数据不匹配");$display("地址='h%h, 长度='d%0d, 数据大小='d%0d, 突发类型='b%2b",...);endelse if(axi_tg_write_resp_error) begin$display("ERROR:: 时间 %t 写响应错误", $time);end// ...读响应错误处理类似...
end// 看门狗超时终止仿真
always @(posedge clk) beginif(watch_dog_hang) begin$display("ERROR:: 看门狗超时,AXI总线无响应");$finish; // 强制结束仿真end
end// 测试结束总结
initial beginwait(prbs_mode_done == 1); // 等待测试模式完成if(mismatch_err_cnt == 0) $display("测试通过");else $display("测试失败,错误次数 = %0d", mismatch_err_cnt);$finish;
end

        最后是窄突发(Narrow Burst)断言检查,作用是当DDR控制器不支持窄突发(Narrow Burst)时,强制检查所有AXI传输的awsize/arsize是否等于全数据宽度(避免配置错误导致数据错位)。

generate 
if((C_AXI_NBURST_SUPPORT == 0) && (APP_DATA_WIDTH == C_AXI_DATA_WIDTH)) begin// 检查写请求的突发大小是否符合限制property narrow_burst_disabled_check_size_for_writes;@(posedge clk) disable iff (tg_rst) (axi_awready && axi_awvalid) |-> (axi_awsize == C_WSTRB_WIDTH_LOG2);endpropertyassert property(narrow_burst_disabled) else $error("错误:控制器不支持窄突发时发送了不匹配的AXI写请求大小(h%0h)",axi_awsize);// 读请求也有类似检查
end
endgenerate

四、小结

        至此,我们已经简单拆解了MIG AXI接口中测试文件的整体框架,首先在sim_tb_top.sv文件中例化了DDR模型和example_top。在example_top中,又例化了MIG IP和一个流量产生器ddr4_v2_2_8_axi_tg_top。在ddr4_v2_2_8_axi_tg_top中的主要功能是分别例化了boot_mode_gen,prbs_mode_gen,custom_mode_gen和axi_opcode_gen。用户通过start,stop和done控制运行的模式(同一时间只能运行一种模式),boot_mode_gen,prbs_mode_gen,custom_mode_gen是各自模式的激励生成器,会生成对应模式的测试激励,然后根据running信号,选择对应的激励驱动到axi_opcode_gen的输入端接口,axi_opcode_gen会将激励转换成符合axi4协议规范的信号,驱动到MIG的AXI4从接口上。在后面的文章中,我们将继续展开介绍boot_mode_gen,prbs_mode_gen,custom_mode_gen和axi_opcode_gen的原理。

相关文章:

  • 滥用绑定变量导致Oracle实例宕机
  • nt!NtReplyWaitReceivePortEx函数分析之nt!LpcpMoveMessage拷贝csr_api_msg
  • NV162NV172美光固态颗粒NV175NV188
  • 010302-oss_反向代理_负载均衡-web扩展2-基础入门-网络安全
  • AI日报 · 2025年05月02日 | 再见GPT-4!OpenAI CEO 确认 GPT-4 已从 ChatGPT 界面正式移除
  • Linux——进程终止/等待/替换
  • # 前后端分离象棋对战项目开发记录
  • AE/PR插件 转场创建大师专业版 Transition Master Pro v2.0.2 Win+使用教程
  • 2025年- H21-Lc129-160. 相交链表(链表)---java版
  • Spring Boot 集成 Elasticsearch 的详细步骤
  • new的几种形式
  • Python 数据智能实战 (7):智能流失预警 - 融合文本反馈
  • 创意效率双提升,AIGC让增长更轻盈
  • Spring Boot中集成Guava Cache或者Caffeine
  • 第 1 篇:起点的选择:为何需要超越数组与链表?
  • 菲索旋转齿轮法:首次地面光速测量的科学魔术
  • 信息收集新利器:SSearch Chrome 插件来了
  • ROPE(旋转位置编码)简述
  • 当神经网络突破摩尔定律:探索大模型时代的算力新纪元
  • AimRT从入门到精通 - 03Channel发布者和订阅者
  • “名额5分钟抢完”,一场花费上万元:越野赛凭什么这么火?
  • 人民日报评论员:把造福人民作为根本价值取向
  • 魔都眼|西岸国际咖啡生活节:连接艺术、音乐与宠物
  • 女冰队长于柏巍,拒绝被年龄定义
  • 中央宣传部、全国总工会联合发布2025年“最美职工”先进事迹
  • 量子传感新技术“攻克”退相干难题