资讯动态

FPGA中搭建Cortex-M3软核并实现DDR读写验证全流程

发布时间:2026/10/18 8:23:02 来源:尧图企业网站定制
做FPGA设计的朋友迟早会遇到一个绕不开的坎想在可编程逻辑里跑一段复杂的控制算法或者跑一个实时操作系统片上那点Block RAM根本不够用。这时候靠谱的方案只有一个——把ARM Cortex-M3软核放进FPGA再给它挂一片DDR让它像模像样地当一个处理器来用。这篇内容就是记录我在某主流FPGA平台上搭建Cortex-M3软核、完成DDR读写验证的全过程从架构设计、总线搭建、DDR训练到上板调试一次把关键步骤和踩过的坑都讲清楚。如果你正准备在FPGA里跑软核处理器或者手上有一个需要大缓存、大数据缓冲的工程这篇内容应该可以帮你少走不少弯路。1. 探索这个项目的起因与整体思路1.1 为什么用Cortex-M3软核而不是硬核处理器先聊一个很实际的问题FPGA里跑CPU为什么很多人首选Cortex-M3软核第一不是所有FPGA都带硬核ARM。很多纯逻辑FPGA上你想跑代码就只能用软核。硬核处理器虽然性能更好但它和FPGA资源绑定在一起引脚、布局、价格都受限制想换一个FPGA平台就麻烦了。软核本质是一段可综合的HDL代码今天在这个牌子的FPGA上用明天也能移植到另一个牌子的FPGA上复用性极好。第二软核的灵活性是硬核给不了的。Cortex-M3软核放在FPGA里你可以随意裁剪外设、调整中断线、扩展自定义指令接口甚至可以把处理器放在芯片的任何位置。实际项目中我见过有人把两个Cortex-M3软核装进同一颗中端FPGA一个负责通讯协议解析一个负责数据预处理这种多核结构在硬核方案里是很难做到的。第三性能够用。Cortex-M3软核经过合理优化后综合频率跑到100MHz以上是常态在100MHz主频下跑裸机程序、跑RTOS、处理TCP/IP协议栈、控制电机都完全够用。对于原型验证、中小批量的工业控制设备来说软核的成本优势碾压硬核方案。第四调试友好。Cortex-M3软核配套的总线接口标准、调试接口都比较成熟。你可以用标准调试器连上去单步调试也可以直接在FPGA里用逻辑分析仪抓总线波形。硬核处理器出问题往往只能看仿真和手册软核出问题你还能把HDL打开改一改这种可控性让项目周期好把握得多。1.2 为什么非要从DDR读写开始软核跑起来了总要有个地方放程序和数据。片上Block RAM容量有限一块中等规模的FPGA片上RAM也就几兆比特换算成字节连1MB都不到。跑一个裸机程序勉强够但如果你要缓冲几帧摄像头图像、存一块网络协议栈的大buf、跑一个稍微复杂点的算法立刻就不够用了。对比一下几种存储方案存储方案典型容量引脚开销带宽水平主要问题FPGA片上Block RAM几十KB到几MB无外部引脚很高容量太小大工程放不下外挂SRAM几百KB到几MB三四十根引脚以上高芯片贵PCB布线压力大容量也有限外挂DDR64MB到几GB约三十根引脚很高控制器时序复杂需要专门训练和校准外挂Flash几十MB到几百MB少串行/并行极低只能存不能随机写运行程序时不能当RAM用DDR的优势非常明显容量大、单位成本低、引脚数量相对SRAM还有优势。它的问题就是控制逻辑复杂。DDR不是像SRAM那样扔个地址给个读写信号就能拿数据它有预充电、行激活、列访问、突发传输、定时刷新这一大堆规矩而且上电之后还要做初始化训练稍微一个时序不对数据读回来就是乱的。正因为DDR读写难单独把它拎出来做一个工程验证是非常值得的投入。把DDR读写搞定了后续跑RTOS、做图像缓存、做DMA都是水到渠成的事如果一上来就把CPU、DDR、外设全堆在一起出了问题根本不知道是CPU没跑起来还是DDR训练失败排查难度会翻好几倍。1.3 系统整体架构与数据通路整个系统的数据通路非常清晰Cortex-M3软核挂在一个AHB-Lite总线上总线下面挂着RAM、外设和DDR控制器桥DDR控制器桥再接DDR PHY最终访问板上的DDR颗粒。这里我选择AHB-Lite而不是更高带宽的AXI有两个原因一是Cortex-M3软核原生就带AHB主接口接起来最直接不需要做额外的协议转换二是工程规模不大AHB-Lite单主多从的结构已经足够用用AXI反而增加复杂度没有必要。地址映射方面我用的是典型的Cortex-M3分布但微调了一下地址区间分配内容0x00000000 - 0x07FFFFFFDDR主存储区0x20000000 - 0x2000FFFF片上SRAM启动代码放在这里0x40000000 - 0x40000FFFUART寄存器0x40001000 - 0x40001FFFGPIO寄存器0xE0000000 - 0xE00FFFFF系统控制与私有外设区这里有一个关键点在上电之后、DDR完成初始化之前CPU是绝对不能去访问DDR地址空间的。启动代码放在片上SRAM里先把DDR控制器配置好、训练完成再跳转到DDR区域取指令或者读写数据这样可以避免CPU在DDR还没有就绪时就去读一个错误的地址导致总线锁死。外设方面UART和GPIO是我最先接上的两个模块。UART用来打印调试信息GPIO用来做状态指示灯。没有这两个东西你在板上跑DDR读写就只能对着黑盒子瞎猜效率极低。1.4 开发平台与工具链选型硬件平台我选了一款带DDR3颗粒的FPGA评估板主要看中了三件事板上自带DDR3颗粒省了自己画PCB和布DDR引脚的麻烦DDR3容量刚好够用64MB到512MB这个区间对于软核系统非常合适FPGA芯片的逻辑资源足够塞下软核、总线、DDR控制器和外设还有余量跑调试用逻辑分析仪。开发工具链分三部分。HDL代码编写用文本编辑器综合布局布线用EDA工具链功能仿真用HDL仿真器。这里说句实在话FPGA开发工具这几年虽然越来越自动化但DDR部分的调试最终靠的还是片内逻辑分析仪抓真实波形仿真只是第一步。工具链选型有一个容易被忽略的点DDR引脚约束。FPGA器件手册里对DDR引脚的位置、时钟引脚、字节通道都有要求你必须按照器件手册和电路板的实际连接来做约束不能想当然地随便分配引脚。我在这个工程里吃了不少引脚约束的亏后面第4章会细讲。2. 系统搭建与核心模块实现2.1 Cortex-M3软核集成步骤软核集成是整个工程的第一步。拿到Cortex-M3软核的HDL源码后首先要例化顶层模块把时钟、复位和总线主接口信号引到顶层。我习惯把软核当做黑盒处理只看它的对外接口信号。最重要的一组接口是AHB-Lite主设备接口包括HCLK总线时钟一般就是CPU的主时钟HRESETn总线复位低有效HADDR[31:0]32位地址总线HTRANS[1:0]传输类型常见的是IDLE、NONSEQ、SEQ三种HWRITE写/读控制信号HSIZE[2:0]传输宽度8位、16位还是32位HWDATA[31:0]写数据总线HRDATA[31:0]读数据总线HREADY从设备准备就绪信号低电平时主设备必须等待HRESP传输响应信号OKAY或ERROR第一次集成的时候我犯了一个低级错误忘记把HREADY信号接成双向的输入输出控制。AHB-Lite协议里HREADY是主设备输入、从设备输出多个从设备通过多路选择器来驱动这个信号如果只接成一根线而不做选择逻辑默认从设备没被选中时HREADY悬空整个总线就会卡死。这个不少新手容易看漏。集成之后最简单的验证方式是用软核的调试接口下载一段CPU程序让CPU跑一个点灯循环。程序里写GPIO控制寄存器GPIO对应的板上LED闪烁说明CPU取指、译码、执行、写总线的通路已经正常。这一步不要跳过它把所有后续问题隔离在了软核之外的模块上。2.2 AHB-Lite总线与外设编址总线互联是整个系统中我认为最简单也最容易出错的部分。AHB-Lite的从设备侧有自己的一套信号主设备只有一个所以不需要复杂的仲裁逻辑核心就是地址译码和读数据多路选择。我实现了一个默认从设备和一个外设从设备。地址译码逻辑根据HADDR的高位判断当前访问的是哪个从设备如果地址不落在任何一个合法区间就把访问路由到默认从设备。默认从设备会立即返回一个ERROR响应告诉CPU这次访问无效而不是让总线一直处于等待状态。这个设计后面救了我不止一次具体场景在第4章总线死锁那节会说。外设地址编址我采用32位地址空间每类外设分配4KB的寄存器空间。UART的寄存器包括数据寄存器、状态寄存器、控制和波特率寄存器GPIO的寄存器包括方向寄存器、数据输出寄存器、数据输入寄存器。编写外设逻辑时有一个很容易踩的坑AHB-Lite的写数据是HWDATA[31:0]但HSIZE信号决定了实际写入的有效字节。比如CPU执行一条16位写指令HWDATA的D[15:0]上是有效数据D[31:16]可能是任何值外设必须根据HSIZE来决定要写入低16位还是高16位否则就会出现写一个半字却把整个32位寄存器都覆盖的情况。读数据多路选择则简单一些选中哪个从设备就把哪个从设备的HRDATA放到总线上。需要注意的是未选中的从设备HRDATA必须输出零否则总线上会出现数据冲突这在硬件里是致命的逻辑竞争。2.3 DDR控制器的层级与参数配置DDR控制器是整个工程里技术含量最高的模块。我把它拆成三个层次来看用户接口层、调度层、PHY层。用户接口层面向AHB侧接收CPU发来的读写请求把它们排入内部的读命令队列和写命令队列。这一层最关键的是地址映射。DDR3不是简单的线性存储空间它分rank、bank、row、column多级结构。CPU看到的是连续的线性地址但DDR控制器必须把这个线性地址拆成bank地址、行地址、列地址并且在访问过程中管理bank的打开与关闭。如果地址映射设计得不好连续读写会频繁地在同一个bank内切换不同行每一次行切换都要先预充电再激活效率会大幅下降。调度层负责DDR命令的仲裁和刷新。DDR颗粒需要周期性刷新否则存储的电容器会漏电丢数据。以DDR3为例标准要求每64ms完成8192行刷新换算下来平均每7.8125微秒要插进一行刷新命令。调度器必须保证刷新请求不能把正常读写饿死也不能让刷新等待太久超过颗粒的最长刷新间隔。PHY层是DDR控制器和外部颗粒之间的物理接口这部分和FPGA器件强相关。DDR3的写入有写调整读出有读调整和DQS门控这些参数不是固定值需要在初始化阶段通过训练过程来确定。训练的本质就是让控制器和颗粒之间对齐读写采样点找到每个字节通道的最优延迟窗口。一组典型的DDR3-800配置参数我自己用下来是这样参数典型值说明CLCAS延迟6读命令发出到数据返回的周期数CWLCAS写入延迟5写命令发出到数据写入的周期数tRCD6行激活到列命令的间隔tRP6预充电到行激活的间隔tRAS20行激活到预充电的最小间隔REFRESH_INTERVAL7.5微秒刷新命令间隔BURST_LENGTH8每次猝发传输8个数据这些参数并不是随意填的它们来自DDR颗粒的厂家手册按不同的工作频率对应不同档位。控制器IP会把这些参数映射成内部计数器的初始值你在配置时务必按照自己板上颗粒型号的数据手册来选不要在网上随便抄一份很可能频率等级对不上导致训练失败。2.4 跨时钟域与缓存设计CPU运行在100MHzDDR控制器运行在DDR3的接口时钟域里这两个时钟之间是异步的。解决异步问题我在用户接口层和调度层之间加了两组异步FIFO一组缓存写数据一组缓存读数据。异步FIFO处理跨时钟域是标准做法但有一个细节经常被忽略写FIFO的深度。CPU写DDR时如果写FIFO满了总线就需要插入等待周期HREADY拉低CPU停在那里。FIFO深度设置得太浅连续写几个数据就要等一次性能大打折扣深度设置得太深占用大量FPGA片上资源不划算。我实测下来对于32位总线、100MHz CPU、400MHz DDR3的系统写FIFO深度16个条目比较合适读FIFO深度32个条目既能吸收DDR刷新造成的延迟抖动也不会占太多资源。缓存设计上我在软核外面加了一个简单的高速缓存模块。DDR的随机读延迟动辄几十个周期CPU每次读数据都等这么长时间是完全无法接受的。加入缓存后连续访问命中缓存的数据可以直接返回只有未命中时才去访问DDR。实测相同测试程序开启缓存后系统整体性能提升非常大具体数字后面第3章有分析。注意缓存模块需要考虑一致性。写操作如果是write-through策略每次写都要真的写到DDR里缓存只加快读如果是write-back策略要防止数据只在缓存里修改而DDR里还是旧值的情况。我在这个工程里先用write-through策略它行为更简单调试DDR时不容易引入缓存一致性问题。3. 读写工程实现与验证方法3.1 仿真阶段怎么验证DDR读写上板之前仿真验证是必须做的一步。我在HDL仿真环境里例化了DDR3的验证模型这个模型会模拟真实颗粒的时序响应包括刷新、预充电、激活、列读写等状态机行为。仿真用的激励是CPU换成一段测试程序程序跑DDR读写子程序把结果通过UART打印出来。仿真的时候我会重点看几个波形信号HREADY的拉低时机、写FIFO的空满状态、DDR控制器的状态跳转、DQS与DQ之间的相位关系。如果仿真正确那么HREADY应该在CPU访问DDR时呈现出间歇性拉低的波形这是总线在等待DDR返回数据的正常现象。如果HREADY一直拉低不恢复说明总线卡死通常是某个从设备没有正确释放HREADY信号。仿真阶段最容易出问题的是DDR初始化时序。DDR3上电后要经历复位、时钟稳定、等待200微秒、加载模式寄存器、使能DQS等一堆步骤这些步骤稍有差错初始化状态机就走不下去。仿真时如果DDR模型报告初始化失败直接用波形查看器跟踪状态机的跳转条件比对数据手册时序参数很快能找到是哪一个等待时间不够。仿真验证还有一个价值验证测试代码本身。我写的DDR自测程序会在仿真里跑一遍完整流程确认没有死循环、没有访问越界地址再放到上板阶段去跑。仿真里的bug排干净上板时才能放心地聚焦在硬件时序问题。3.2 上板验证完整流程上板之后我的验证流程是固定的一套用JTAG下载综合后的位流。复位芯片启动软核。CPU从片上SRAM开始执行先初始化系统时钟和UART。初始化DDR控制器执行DDR训练。训练完成信号拉高LED状态灯变绿。CPU执行DDR自测程序把测试结果通过UART打印到上位机。上位机串口终端观察打印结果判断PASS还是FAIL。我推荐的打印信息包括DDR_CTRL_INIT_START、DDR_TRAINING_DONE、DDR_SELF_TEST_START、WRITE_ADDR、READ_COMPARE_ERROR、TEST_PASS这几个关键节点。串口打印不要做得过于花哨一个回车换行加一个状态字符串就够了目的只是快速判断卡死在哪个环节。上板之后第一件事不是跑大范围的DDR读写而是只对DDR的一个固定地址做写读操作。比如向地址0x60000000写入0x5A5A5A5A再读回来比较是不是0x5A5A5A5A。这一步通过说明CPU到DDR颗粒的整条数据通路是通的后续再逐步扩展测试范围从4KB到1MB到16MB再到整个DDR区域。在这里我吃过的亏是一开始就跑了全地址扫描结果前16MB全部PASS第16MB处第一个字节出错状态灯和串口打印都显示出错后整个调试过程反而被卡住了。后来把测试分成从小范围到大范围的多个阶段每段打印一个进度状态定位问题快得多。3.3 测试程序设计与恶意测试DDR测试程序不是简单写个数再读出来比较一遍就完了。我设计了几种不同的测试模式目的就是从不同角度暴露隐含的问题。第一种是最基本的递增写校验从DDR_BASE开始往每个32位字写入当前地址值然后重新遍历读回校验。地址和数据相同如果地址线有问题会立刻在读回数据上反映出来。第二种是翻转校验先在目标区域写入0x00000000校验通过后再写入0xFFFFFFFF然后再写0x55555555、0xAAAAAAAA。这种全零、全一、交替模式能有效暴露数据线上的固定短路或断路问题。第三种是随机模式用伪随机数发生器生成一串数据写入DDR读回来再和伪随机序列比对适合长时间运行、观察数据是否有偶发翻转。地址边界的测试同样重要跨页边界、跨bank边界、跨rank边界的地方最容易出现时序异常。我会特意在地址0x00000FFF/0x00001000这种连续区域交界处前后各写一批数据然后回读校验。注意测试程序的代码本身不能放在DDR里否则在DDR测试写坏数据时代码和需要校验的数据混在一起测试程序可能崩溃。我的做法是启动代码和测试程序全部放在片上SRAM执行DDR只作为被测试对象不存放执行代码。3.4 性能实测与数据分析写完测试程序后我用定时器模块测量了DDR读写的实际耗时得到的性能数据很有意思操作数据量耗时实测带宽DDR连续写8MB50毫秒160MB/sDDR连续读8MB66毫秒120MB/s带缓存随机读1MB范围3毫秒340MB/s写快于读这个结果可能和直觉相反但其实是正常的。原因是写路径上有写FIFO在缓冲CPU发送写请求后只要数据进了写FIFO就可以继续执行不需要真正等到数据到达DDR颗粒而读路径必须等到读数据从DDR返回DQS采样延迟加上训练时钟整个过程就是实打实的等待周期。带缓存随机读的带宽看起来高是因为测试范围只有1MB大部分访问都命中缓存了。如果放一个超过缓存容量的大范围随机读测试命中率下降带宽会回落很多。这些数字给我一个很重要的启示DDR线性带宽高但随机访问延迟很敏感实际工程里如果要在DDR上做链表、哈希表这类随机访问结构最好加上缓存或者考虑别的存储方案。性能还能不能再提升可以。当前瓶颈在CPU发起访问的模式AHB-Lite虽然支持突发传输但Cortex-M3软核在访问DDR时FSMC或者外部总线接口引出的多是一次一个词的非突发访问。优化方式是在DDR控制器的用户接口层加一个合并器把连续地址多个字的访问合并成DDR的8字突发传输这样带宽还能有比较明显的提升代价就是控制逻辑更复杂。4. 常见问题与排查技巧实录4.1 DDR PHY训练总是锁不住这个现象在第一次调DDR的时候几乎必然出现上电后DDR控制器初始化流程跑着跑着PHY训练阶段反馈失败状态机停在某个等待点CPU后续对DDR的访问全部超时。我的排查思路是自底向上看。首先确认DDR参考时钟是否稳定用示波器量DDR差分时钟和复位波形确认上电后复位释放时序正确DDR颗粒供电电压正常。如果供电有纹波训练大概率失败。接着检查初始化流程中两次模式寄存器加载之间是否满足了200微秒的等待时间这个等待时间是在DDR控制器寄存器里配置的配小了颗粒还没准备好训练必然是失败的。还有一个非常隐蔽的点PCB布线导致DQS和DK的飞行时间不一致片内训练算法会试图调整延迟链来补偿但如果延迟链的调整范围和实际补偿量不匹配训练就会失败。这种情况下除了换电路板基本上没有太好的办法所以做FPGADDR的硬件设计时保证DQS和DK长度匹配是最基本的规则。4.2 数据写进去读出来是乱的写过一次比对我差点崩溃的现象是向DDR连续写0、1、2、3……写到地址0x100后回读时前面几十个数据是对的后面全变成0xFF或者固定值。用片内逻辑分析仪抓总线后发现CPU发出的地址和DDR控制器收到地址相差了一个字节。这个问题的根源在于地址映射和字节选通没有对应好。DDR3的物理存储空间里每个突发传输覆盖的列地址对应8个连续地址字节但AHB侧是32位数据总线一次传输32位、10位字节。当CPU发出一个地址时地址线的最低几位需要映射到DDR的字节选通信号上映射错了就会出现地址错位。排查技巧是先用“地址数据”的模式去写也就是向地址0x60000000写0x00000000向0x60000004写0x00000004这种读回来直接看数据值就能反推出地址偏移量。根据读回数据是整体左移两位还是右移两位就能快速判断是字节选通映射问题还是DDR列地址映射问题。4.3 AHB总线死锁问题总线死锁是我遇到过的最诡异的问题。现象是CPU程序跑到某个位置后就不动了看门狗复位也没用整个系统完全卡死。用片内逻辑分析仪抓总线发现HADDR停在了一个DDR地址上HREADY信号始终保持低电平CPU在无限等待从设备响应。排查了很久才找到原因默认从设备设计得不好。当CPU访问DDR地址空间而DDR还没有初始化完成时DDR控制器会返回一个未就绪状态HREADY拉低。如果这个状态一直不解除CPU就一直等待形成死锁。解决办法分两层。第一层初始化DDR之前软件上绝对不要让CPU访问DDR地址第二层硬件上给默认从设备加一个超时机制。当总线访问某个从设备超过指定周期数比如65536个周期仍未完成默认从设备主动返回一个ERROR响应让CPU跳出这次访问。这个超时机制就是我在2.2节里提到的设计实际验证下来非常管用DDR没初始化时的死锁问题基本被它拦住了。4.4 时序违例导致随机性读写错误上板测试一段时间后发现DDR测试有时PASS有时FAILFAIL的位置和错误数据每次都不固定。这种随机错误最头疼因为它不遵循确定的复现路径。我当时的第一反应是看时序分析报告果然DDR控制器PHY接口到FPGA引脚之间的路径出现了时序违例保持时间不满足。时序违例的直接原因是综合策略和约束不够紧。FPGA里的DDR接口路径对时序要求极高必须在综合工具里严格约束输出延迟、输入延迟、时钟偏斜。我在第一次做约束时只填了基本时钟约束没有对外部DDR颗粒的输入输出延迟做申明导致工具不知道DDR引脚的真实时序窗口布局布线时随机布出一个违例路径。解决方法是第一把DDR颗粒的数据手册时序参数换算成FPGA的输入输出延迟约束写进时序约束文件第二在综合工具里把这些引脚的约束标为“假路径禁止优化”强制工具优先优化关键DDR路径第三降低CPU主频和DDR接口频率到保守值重新跑时序确认稳定后再提升频率。这样一轮调整之后随机错误消失了。注意遇到随机性读写错误千万不要靠“多跑几次碰运气”来验证。我的经验是至少连续跑1000次完整读写测试全部PASS才说明问题真正解决了。运行10次偶然PASS没有任何意义。4.5 常见问题速查表最后把我在实际调试中遇到的问题整理成速查表方便直接对照排查现象可能原因排查手段解决方案DDR训练卡住参考时钟不稳示波器量波形检查供电、更换时钟源DDR初始化失败复位时序错误查初始化状态机波形调整复位等待时间CPU访问DDR卡死DDR未就绪时被访问逻辑分析仪抓总线加默认从设备超时机制数据整体偏移几个字节地址映射错误地址数据测试检查字节选通映射随机性读写错误时序违例看时序报告补全输入输出延迟约束写慢但读快或反过来FIFO深度不合理性能计数器测量调整读写FIFO深度跨页边界读写失败bank管理策略差地址边界测试优化bank调度、增加行缓冲5. 后续扩展与个人经验5.1 基于当前工程还能做什么扩展FPGA软核加DDR这套组合验证通过之后后面的想象空间非常大。最直接的扩展方向是跑RTOSCortex-M3软核完全支持常见的开源实时操作系统任务调度、信号量、消息队列都能正常工作。有了DDR大容量内存RTOS里跑的多个任务不用再挤在几十KB的片上RAM里整个系统的实用性一下子上来了。第二个扩展方向是加DMA控制器。前面性能分析里已经说了CPU逐个访问DDR的效率受限于AHB-Lite总线的非突发访问模式。挂一个DMA控制器可以接管DDR和UART、GPIO、甚至自定义外设之间的数据搬运。比如一个ADC连续采样的工程DMA负责把采样结果写入DDR缓冲区CPU空闲时再去DDR里做数据处理效率会有质的提升。第三个方向是完善DDR控制器的性能。用户接口层的合并器、多bank切换优化、行缓冲命中率统计这些都是可以深挖的优化点。优化之后DDR带宽可以从现在的120MB/s往300MB/s以上走这个提升在图像流畅度上体感非常明显。5.2 我总结的调DDR流程与习惯做了这个工程我最大的感受是FPGA软核加DDR的组合开发难度呈现典型的两头重、中间轻。把软核跑起来费了不少劲把DDR训练跑通更费劲中间的总线编写反而是最顺利的一环。建议后来者不要急着把所有功能堆进去先用最简单的裸机程序把“写DDR、读DDR”这条链路跑通再考虑DMA、RTOS这些进阶操作。还有一个习惯值得说说把所有DDR参数和测试结果记录成文档。第一次调试DDR时我模模糊糊记得某组训练参数调过但没有记下来隔了两天后参数值和结果全忘了又重新查了一遍数据手册。后来我换了一块不同颗粒的板子翻着之前的记录对照调整参数节省了大量时间。现在每调一个DDR相关的参数我都会在文档里记一行当前值、测试结果、是否影响稳定性后面排查问题就是对着表查。最后再分享一个小技巧调试DDR读写问题先让CPU只对着一个固定地址做反复写读稳定之后扩展到连续地址再扩展到全区域扫描。这样能把问题分成链路问题和映射问题两大类比一上来就跑全区域扫描高效得多。这个顺序看起来简单但我见过不少人被全区域扫描的错误结果带偏方向调试了几天才发现只是某个bank的映射写错了。先把固定地址调通后面一切都快。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑