ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DRAM刷新三种方式:集中式、分散式与异步式原理及计算

DRAM刷新三种方式:集中式、分散式与异步式原理及计算 计组里 DRAM 刷新的三种方式——集中式刷新、分散式刷新、异步式刷新属于那种“第一遍看觉得很直白、真做题时总在细节上翻车”的典型知识点。我当年准备 408 计组的时候这三个词背得滚瓜烂熟可真到算死时间、算刷新间隔、比较访存效率的时候就开始卡壳问题就出在书上只给结论、不讲推导让人只能死记。后来帮同学一起折腾西电计组课设基本模型机重新把这一段翻出来啃才意识到这三种刷新方式本质是一道非常典型的工程取舍题刷新开销、访存连续性、控制逻辑复杂度三者互相拉扯选哪种完全取决于你更在乎哪一头。下面我按自己的理解顺序把这块内容捋一遍先把 DRAM 为什么非要刷新的根刨清楚再逐个拆解三种方式的工作机理和量化算法最后给几处我踩过的坑和计算题的固定套路。不管你是刚开始学计组、在刷 408 计组真题还是正在做存储器相关的课设应该都能捞到能直接抄作业的东西。1. 先把“为什么要刷新”想透三种方式才不是死记硬背我见过太多人一上来就背“集中式有死区、分散式没死区、异步式是折中”背完做题还是不会算。原因很朴素不知道刷新是为了解决什么物理问题自然就推不出各种时间参数该怎么用。1.1 电容存电荷这件事天生就是个“漏勺”DRAM 的存储单元本质上就是一个晶体管加一个小电容1 和 0 靠电容上有没有电荷来表示。这个结构的好处是每个单元只要一个管子集成度能做到极高单位容量便宜坏处是电容容量小得可怜而且绝缘层也不是绝对绝缘电荷会随着时间慢慢漏掉。温度每升高一点漏电速度还会明显加快所以夏天机房空调坏了往往就是内存开始出错的时候。漏电带来的直接后果是你写进去的那个 1过一段时间就自己变成 0 了。业界给的标准是绝大多数 DRAM 单元能保证电荷在2ms内不丢这个 2ms 是教材里最常用的经典值不同器件规格会有差异有的是 8ms、16ms、64ms但考法和思路完全一样。也就是说必须在电荷掉到读不出来的地步之前把数据读出来再原样写回去给电容重新充满。这个“读出来再写回去”的动作就是刷新。这里有个容易被忽略的点刷新不是简单的“写 1”或者“写 0”它必须先把原数据读出来经过读出放大器整形后再写回同一行。所以刷新本质上是一次“内部读 内部写”它占用的是存储器的内部操作时间只是数据不会送到 CPU 那边去。理解了这一点你就能明白为什么刷新是以行为单位、为什么要用行地址计数器、为什么刷新期间不能接受正常的访存请求。1.2 刷新周期、存取周期、最大刷新间隔这三个时间必须先分清这三个词混在一起是初学者翻车的头号原因。我用一句话把它们钉死存取周期 tCPU 给一次地址、存储器完成一次读或写所需要的完整时间这个值包含了地址建立、读出放大、写回等所有环节通常比“存取时间”大。经典数值取 0.5μs。最大刷新间隔 T同一行两次刷新之间允许拉开的极限时间超过它数据就可能丢。经典值取 2ms。刷新周期一轮刷新时间把所有行都刷一遍所花的累计时间等于“行数 × 每次刷新占用时间”。注意很多书上也会把 2ms 直接叫“刷新周期”那就是在说“最大刷新间隔”遇到时结合上下文判断。真正做题时你需要反复用到的一个换算关系是在 T 时间内存储器最多能完成 T / t 个存取周期。拿 2ms 和 0.5μs 举例2ms / 0.5μs 4000 个。这个 4000 是后面的算账基准——刷新要从中挖走多少、剩下多少给正常读写全靠它。1.3 三种刷新的分类依据刷新到底“插在哪”搞清楚了上面两个量三种刷新方式的差异其实就一句话能概括刷新操作在时间轴上被安排到哪个位置。集中式刷新把 T 时间的前面绝大部分让给正常读写最后集中拿出一整段时间把所有行刷完这段时间内不响应访存。分散式刷新把每个存取周期一分为二前半段正常读写后半段顺手刷一行等于每一拍都刷。异步式刷新把 T 平均切成“行数”份每份里挑一个存取周期用来刷一行刷新点均匀撒开。这三种安排没有绝对优劣它们是三种不同的取舍。集中式把连续性留给访存代价是有一段谁都别想访存的空白分散式保证任何时候最长等待都不超过一个周期代价是存储器整体速度被砍掉一半异步式想在两者之间找平衡用“均匀撒点”把最长等待压到中间水平同时保住大部分有效带宽。想明白这一层后面所有公式都是从这三个画面里推出来的。2. 集中式刷新把刷新攒到最后一把梭代价是那段死区集中式刷新是三种里最容易理解的也是最容易算错的。它的画面感很强整整一个刷新间隔内存储器几乎都在勤勤恳恳地服务 CPU直到最后关头才把大门一关一口气把所有行刷完。2.1 工作机理前段全给读写末段开足马力刷行假设存储矩阵有 128 行最大刷新间隔 2ms存取周期 0.5μs。集中式刷新的做法是在 2ms 这个窗口的前面部分允许 CPU 随便访问一个周期接一个周期地用等时间快用完了再连续拿出 128 个存取周期一行一行地刷128 行刷完为止。这 128 个周期内存储器不接收任何来自 CPU 的读写请求这段时间就是所谓的死时间或者死区。为什么非得一次性刷完、不能拆开因为每一行都有“2ms 内必须被刷一次”的硬性约束。如果你把 128 行分散到 2ms 的两端去刷那么第 1 行被刷完跑到第 128 行刷完再绕回来刷第 1 行中间隔的时间可能就超过 2ms 了。集中式刷新的做法把所有行挤在一起刷对每一行来说两次刷新的间隔恰好攒到了接近 2ms 的极限值——高效但也几乎不留余量。注意集中式刷新对时序余量极其敏感。一旦刷新期间被打断或者器件本身的最大刷新间隔比标称值短一点就有数据丢失风险。这也是为什么真实控制器里很少纯粹使用集中式而是偏向异步式。2.2 死时间怎么算行数乘存取周期死时间的公式非常直接死时间 需要刷新的行数 × 每次刷新占用的时间在集中式里每次刷新占用的是一个完整的存取周期所以死时间 行数 × 存取周期 t带入数字128 × 0.5μs 64μs。再算死时间占比64μs / 2000μs 3.2%。有效时间 2ms − 64μs 1936μs折算成有效读写周期数 1936μs / 0.5μs 3872 个。这三行数字就是集中式刷新的全部家底。你会发现它其实很“划算”只损失了 3.2% 的时间剩下的 96.8% 都能正常服务 CPU。跟分散式一比效率优势立刻出来。但它的软肋同样明显——那 64μs 是不可被打断的连续空白CPU 在这段时间里发过来的请求只能干等最长等待时间就是 64μs 这个量级。如果 CPU 主频很高、对访存延迟敏感64μs 的等待足以让它数十条指令拿不到数据性能抖动会非常难看。所以集中式通常出现在对平均吞吐量敏感、对瞬时延迟不敏感的场景里比如一些早期的批量数据处理系统。2.3 换个数再算一遍把公式焊死在脑子里为了不让公式变成背出来的东西我们换一组参数验证一下。假设某个 DRAM 芯片内部是 512 行最大刷新间隔 8ms存取周期 0.5μs。先算基准8ms / 0.5μs 16000 个存取周期。死时间 512 × 0.5μs 256μs。死时间率 256μs / 8000μs 3.2%。诶又是 3.2%这不是巧合完全是巧合——严格来说它取决于“最大刷新间隔 / 存取周期”和“行数”这两个数的相对关系。如果行数变多而刷新间隔不变占比就会上升。你可以自己试试把行数改成 1024、刷新间隔仍是 8ms死时间率立刻变成 6.4%。这说明一个规律在刷新间隔固定的前提下行数越多单位时间要刷的行越多开销越大。这也是为什么大容量 DRAM 更倾向于采用异步式刷新之外的机制比如片内自动刷新把控制逻辑做进芯片里减少对系统总线的干扰。2.4 集中式的适用场合与隐藏风险集中式刷新适合那种“可以容忍一段固定时间完全不访存”的场合。比如某些图形缓冲区、批处理数据流数据在固定节奏里成批搬运中间本来就存在等待窗口把刷新塞进去正好填补空隙。反过来如果访存请求是随机、实时、不可预测的集中式的死区就是一颗定时炸弹。还有一个不太被提到的风险集中式刷新的每一行刷新间隔都贴近 2ms 上限意味着只要系统时钟有一点点漂移或者刷新控制逻辑里插入了一个额外的等待周期就可能让某些行超期。工程上通常会在计算出来的时间上再打一个安全系数比如按 1.5ms 而不是 2ms 来安排宁可多刷一点也不冒丢数据的风险。这一点考试里不会考但真做存储器控制器的时候是常识。3. 分散式刷新每一拍都顺手刷一行图的是不被打断分散式刷新走的是另一个极端。它不让刷新独占一段时间而是把刷新碾碎均匀撒到每一个存取周期里。这样做的好处是明显的坏处同样明显而且坏处是实打实地体现在速度上。3.1 系统周期被劈成两半分散式的操作画面是这样的本来一个存取周期 0.5μs现在把它一分为二前 0.25μs 干正事——响应 CPU 的读写后 0.25μs 干私活——刷一行。于是存储器对外表现的系统存取周期变成了 1μs读写 0.5μs 刷新 0.5μs不同教材会把刷新占用时间写成半个周期或一个完整周期最常见的写法是系统周期等于两倍存取周期。为什么最长等待只有大约一个周期因为不管 CPU 什么时候发请求最多等一个系统周期就能轮到它刷新永远不会形成大块的阻塞。这就是分散式最核心的卖点无死区实时响应好。但是它付出的代价非常扎眼。同样在 2ms 内系统周期变成 1μs 之后总共只能完成 2ms / 1μs 2000 个系统周期其中真正用来读写的是 2000 个每个系统周期里都包含一次读写。对比集中式的 3872 个有效读写周期分散式的有效带宽直接腰斩。用一句话总结分散式用一半的速度换来了永远不被长时间打断的确定性。3.2 刷新次数严重过剩这是它的原罪再看一个更“扎心”的账。2ms 内分散式总共刷了 2000 次可实际上只有 128 行需要刷理论上刷 128 次就够了。也就是说刷新次数是实际需求的 15.6 倍。为什么会这样因为分散式不管你需不需要每个周期都雷打不动地刷一行在 128 行的矩阵上转圈刷2ms 里把整个矩阵刷了十几遍。这不叫浪费叫什么。教材里给这种做法的评价通常是“刷新过于频繁降低了整机速度”。换个角度想如果行数更多比如 1024 行那 2ms 内 2000 个系统周期每个周期刷一行也才刷 2000 行勉强覆盖 1024 行的矩阵两遍不到。这说明分散式的“过剩程度”跟行数直接相关行数越多过剩越少相对浪费就越小。所以在很小的存储矩阵上分散式非常不划算行数一多它的效率损失反而被稀释。提示别看分散式“浪费”它在某些特定场合反而是唯一选择。比如需要严格保证最坏情况访存延迟的实时系统宁可整体慢一点也不能出现一段谁都别想访存的空窗。工程上从来没有免费的午餐只有选择哪种代价。3.3 什么时候能接受这种浪费我个人的判断标准是两条一是系统能不能容忍一块连续的访存空白二是速度损失是不是可以承受。如果 CPU 的访存请求是突发式的比如一批数据搬完之后要算很久才回来取下一批那集中式显然更划算如果访存请求是持续不断的流式访问任何一点空白都会造成流水线停顿那就得考虑分散式或异步式。还有一个折中的变体值得一提有些教材会提到在分散式的基础上用行地址计数器让刷新按行循环推进同时给系统周期留出弹性——也就是后面要讲的异步式的思路。所以这三种刷新方式并不是孤立的三个知识点它们是一条连续谱上的三个位置从“极致追求吞吐”到“极致追求确定性”中间还有无数过渡形态。4. 异步式刷新把刷新点均匀撒开兼顾死区与效率异步式刷新是我个人认为最值得认真理解的一种因为它代表了真实工程里最常用的思路不追求任何一个指标的极致而是把参数调到整体最优。它在教材里出现的频率很高也是 408 计组里计算题最喜欢考的形式。4.1 刷新间隔的分配算法异步式的核心操作只有一步把最大刷新间隔按行数等分每一份里安排一次刷新。还是用 128 行、2ms、0.5μs 这组参数每份的时长 2ms / 128 15.625μs。在每一份 15.625μs 里拿出一个存取周期0.5μs来刷新一行剩下的时间正常读写。这样 128 份刚好把 128 行刷完循环往复。算一下开销死时间总量 128 × 0.5μs 64μs和集中式完全一样占比也是 3.2%有效读写周期数同样是 3872 个。看到这里你可能觉得异步式和集中式没区别——区别在于死时间的分布方式。集中式的 64μs 是连成一整块的最长等待 64μs异步式的 64μs 被切成 128 个 0.5μs 的小片分散在整个 2ms 里最长等待只有大约 15.625μs。也就是说异步式用集中式同等的开销换来了四倍多的延迟改善。这就是它被称为折中最优的原因。实际设计时有一个细节15.625μs 2ms / 128 是理论极限值每一行的刷新间隔刚好卡到 2ms不留余量。所以工程上会取一个略小于它的值比如按 2ms / 128 的 0.9 倍来安排刷新间隔或者干脆预留几个周期的缓冲。考试里如果题目直接问“异步式刷新的刷新间隔”一般直接用 T / 行数不用考虑余量。4.2 三种方式的量化对比把前面的账汇总成一张表对比会非常直观。参数统一为128 行2ms0.5μs。对比项集中式刷新分散式刷新异步式刷新刷新时机周期末集中刷完每个系统周期刷一行每 15.625μs 刷一行系统周期0.5μs刷新时暂停1μs读写加刷新正常 0.5μs插入刷新周期死时间总量64μs无连续死区64μs死时间率3.2%约 50% 速度损失3.2%有效读写周期数387220003872最长访存等待约 64μs约 1μs约 15.6μs控制逻辑复杂度低低中典型取向追吞吐追确定性综合最优这张表我建议不要死记而是每次自己从“行数、T、t”三个数推一遍。推两三次之后你会发现所有数字都能在十秒内报出来。4.3 一道典型计算题的完整推演题目大概是这个形状某动态存储器有 256 行存取周期 0.5μs最大刷新间隔 4ms分别按集中式、分散式、异步式计算刷新开销和最长等待时间。第一步算基准4ms / 0.5μs 8000 个存取周期。集中式死时间 256 × 0.5μs 128μs死时间率 128 / 4000 3.2%最长等待 128μs。分散式系统周期按 1μs 算4ms 内系统周期数 4000有效读写周期 4000刷新次数 4000 次而需求只有 256 次过剩约 15.6 倍无连续死区最长等待约 1μs。异步式刷新间隔 4ms / 256 15.625μs每次占用 0.5μs死时间总量 256 × 0.5μs 128μs占比 3.2%最长等待 15.625μs。你看换了参数异步式的刷新间隔居然还是 15.625μs这不是巧合——4ms / 256 2ms / 128比例相同。这类题目出题人经常有意把行数和刷新间隔成比例地放大或缩小就是为了让你在“总量开销”和“间隔分布”这两个维度上都算对。我自己做题时会先用铅笔在草稿纸上写下三个数T、t、行数 n。然后固定写两行——T/t 是多少T/n 是多少。这两行一写三种刷新的所有结果都能顺手推出来基本不会错。5. 常见问题与排查技巧实录这一节讲的是我在做题和做课设过程中真实踩过的坑。有些是概念混淆有些是计算习惯问题还有些是理解偏差每一条都值得提前避开。5.1 高频踩坑清单第一个坑把“刷新周期”和“存取周期”搞混。看到题目里出现“刷新周期 2ms”一定要先判断它指的是最大刷新间隔还是刷完所有行的时间。绝大多数情况下指的是前者。判断方法很简单如果这个数用来和“行数 × 存取周期”做比较那它就是最大刷新间隔。第二个坑以为分散式刷新有死时间。严格说分散式没有连续死区它的代价是把系统周期拉长了属于“均匀的慢”不是“突然的停”。所以在回答“哪种刷新方式没有死区”时答案只能是分散式异步式虽然最长等待短但那 0.5μs 仍然是不可用时间段。第三个坑算异步式时忘记减去刷新占用的周期。有效读写周期数 T/t − 行数而不是直接把 T/t 当成有效数。集中式和异步式的有效周期数是一样的都是 T/t − n这个结论值得单独记一下。第四个坑把刷新和读操作当成一回事。刷新是内部读后再写回数据不送到外部不占用数据总线。所以在统计“刷新对总线的影响”时只能算时间占用不能算带宽占用。第五个坑忽略温度对最大刷新间隔的影响。芯片手册标称的 2ms 通常是在常温条件下温度上升后漏电加快实际允许的刷新间隔会缩短。做系统设计时必须在标称值上留余量考试里一般按标称值算就行。5.2 课设里真要用到刷新控制该怎么下手西电计组课设的基本模型机据我了解和看到的常见做法数据存储器多用片内 RAM 或静态 RAM 实现静态 RAM 靠触发器保存数据只要不断电就不用刷新所以课设里大多数同学其实碰不到 DRAM 刷新这个问题这也导致这块知识只能靠做题去建立实感。如果课设里真的要求扩展动态存储器那刷新控制器的实现思路大致是这样用一个行地址计数器循环给出刷新行地址用一个定时计数器控制刷新间隔两者在读写请求的空隙里交替占用存储器的行地址总线。关键时刻是刷新请求和 CPU 读写请求冲突的时候谁优先——通常刷新优先因为它有硬性时限CPU 请求可以稍等。// 刷新请求生成的简化逻辑示意计数到刷新间隔就拉高刷新请求 reg [31:0] refresh_cnt; wire refresh_req (refresh_cnt REFRESH_INTERVAL); always (posedge clk or negedge rst_n) begin if (!rst_n) refresh_cnt 32d0; else if (refresh_cnt REFRESH_INTERVAL) refresh_cnt 32d0; // 触发刷新的同时清零计数 else refresh_cnt refresh_cnt 32d1; end这段逻辑的意思是刷新计数器一直在跑跑到预先算好的刷新间隔就触发一次刷新请求同时清零重新计数。刷新行地址则由另一个计数器每次加一提供刷完整圈就绕回来。真正实现时还要处理一个细节——刷新请求触发的那一拍正好 CPU 也在发访存请求怎么办。我通常的做法是让刷新插入一个周期把 CPU 请求延后用状态机保证不会丢失请求。5.3 一套自测题和记忆锚点如果你想验证自己是不是真懂了可以试着不看书回答下面这几个问题128 行、2ms、0.5μs 下三种刷新的死时间总量各是多少哪一种刷新的有效读写周期数最少少多少异步式刷新的刷新间隔是怎么推出来的如果一个系统对访存延迟极其敏感你会选哪一种为什么我自己的记忆锚点是三句话集中式是“攒着刷省但会卡”分散式是“每拍都刷稳但慢”异步式是“均匀撒点两头兼顾”。这三句话不是背下来的结论而是你从三个数字推出来的画面。真到了考场上你只要在草稿纸上写下 T、t、n两行除法所有答案都会自己浮出来。最后再分享一个小习惯做题时把所有时间量统一换成微秒再算不要一会儿毫秒一会儿微秒地跳单位换来换去是这类题目最常见的低级失分点。我自己吃过至少两次亏都是 2ms 和 0.5μs 乘除的时候忘了换算答案直接差三个数量级。把单位统一这件事养成肌肉记忆比多背十个公式都管用。
返回列表