ARTICLE DETAIL

资讯详情

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

SRAM Compiler中Number of Banks参数详解:面积、功耗与时序的权衡

SRAM Compiler中Number of Banks参数详解:面积、功耗与时序的权衡 1. Number of banks 到底在配置什么做芯片设计的人只要用过 SRAM compiler基本都对着“Number of banks”这个选项犹豫过。它不像 word width、depth 那样直白——那俩一眼就能看出是存储容量但 banks 这个参数初看似乎只是把一块大 SRAM 切成几块小的可你在 compile 之后翻 report面积、功耗、时序全都跟着变甚至变好还是变坏都不一定。我在几个项目里调过这个参数也踩过不少坑这篇就把 banks 的设置逻辑、物理本质和实操方法一次说清楚。先给个最直白的定义Number of banks 是 SRAM compiler 把一块大的存储阵列从中间切分成多少个独立的 bank每个 bank 有自己独立的行译码器、列译码器、灵敏放大器和写驱动电路它们共享地址总线、数据总线和控制信号但内部物理阵列是隔开的。你设 banks1就是一整块方方正正的大阵列设 banks2就相当于把这块阵列从中间劈开变成左右两块或上下两块取决于 compiler 的切分策略设 banks4就是横竖各切一刀变成四块。为什么要切 bank三个字位线太长。SRAM 阵列里每一列存储单元共享一条位线位线越长寄生电容越大读写时需要对位线充放电的能量就越多速度也越慢。你想想看一条位线上挂了 1024 个 cell和挂 256 个 cell读操作时那个 sense amplifier 需要感知的电压差、需要克服的寄生电容完全不是一个量级。切 bank 的本质就是让每个 bank 内部行数变少从而缩短位线、字线长度把单次访问涉及的物理范围缩小最终换取功耗和速度上的收益。不过这里面有个很容易被忽略的关键点切 bank 不是白给的。每个 bank 都要额外配一套行译码、列译码、灵敏放大器、写驱动器还有 bank 间的隔离电路。也就是说area 上你在省存储单元间互联开销的同时也在增加外围电路开销。到底值不值完全取决于你的存储容量、位宽、工艺节点和目标指标。这也是为什么我会建议所有做 SoC、MCU 或存储子系统设计的人在定 SRAM compiler 配置之前先花半小时把 banks 对面积、功耗、时序的实际影响吃透。2. 一个参数怎么同时牵动面积、功耗和速度2.1 面积加 bank 未必更小还有可能更大很多人第一次调 banks 都会有个直觉把大 SRAM 切小了面积不是应该更小吗实际上完全不一定。我举个例子在一个 28nm 工艺项目里我需要一块 1Mb按 1024Kb 算的单口 SRAMword width32num words32768默认 banks1 时 compile 出来面积大约是 0.35mm²。我把它改成 banks4面积测下来 0.31mm²确实小了 12% 左右。但同样的容量我在另一个项目里把 word width 提到 128num words8192这时候明明是“同一块 SRAM”从 banks1 改成 banks4面积不但没降反而从 0.28mm² 涨到了 0.31mm²。为什么会出现这种反差关键在于位宽。当 word width 很宽时存储阵列已经呈明显的扁长形每行的 cell 数量很多而行数相对少位线本身就不算长这时候切 bank 带来的位线电容收益非常有限。相反你每切一个 bank 都要复制一整套外围电路word width 越宽外围电路被复制的面积开销就越大结果面积不降反升。还有一个容易忽略的点aspect ratio长宽比。Compiler 在生成 layout 时会尽量把 SRAM 做成接近正方形的形状因为这种形状在 floorplan 中最好摆放。如果你只有一个 bank大容量 SRAM 的长宽比可能非常极端比如 4:1 甚至 6:1在 floorplan 里根本塞不进去。切成多个 bank 后每个 bank 的长宽比都更接近正方形整体 floorplan 反而更好用了。所以在某些场景里你多花的那点外围电路面积换来的是 floorplan 顺利通过整体 chip 面积其实是省的。我自己的经验是判断某个容量该不该加 bank不要凭感觉要把不同 banks 配置跑出来分别看 area、aspect ratio再结合你实际 floorplan 的需求来定。跑一个 compile 一般也就几分钟比拍脑袋可靠得多。2.2 功耗位线电容才是大头功耗这块是 banks 参数最明显的收益区原理可以用一个非常朴素的公式解释动态功耗 P α·C·V²·f。这里的 C 是平均每次翻转的等效电容V 是电源电压f 是工作频率α 是翻转率。在电压、频率不变的前提下你能控制的只有 C。而 SRAM 访问时最大的 C恰恰就来自位线和字线上的寄生电容。每次读操作预充电电路都要把位线充到 VDD然后选中的 cell 把一条位线往下拉产生一个小的电压差sense amplifier 来感知。整个过程里位线越长、挂的 cell 越多需要充放电的电容就越大功耗自然就上去了。切了 bank 之后每个 bank 的列数不变因为数据位宽不变但行数变成原来的 1/N每条位线上挂的 cell 数量变成原来的 1/N位线电容近似线性下降单次访问的功耗随之明显降低。不过要注意这个收益只针对“你正在访问的那个 bank”。SRAM 工作的时候只有一个 bank 被真正激活进行读写其他 bank 处于 idle 状态。idle 的 bank 不吃动态功耗但它吃漏电。也就是说切 bank 对动态功耗的优化非常直接对静态功耗漏电反而是负面效果——你多了外围电路漏电面积变大了。这个取舍在做低功耗 IoT 芯片时尤其关键如果 SRAM 常驻供电、长期待机漏电占比高banks 数不宜开得过大工作频率高、访问频繁动态功耗占比高banks 数加大是划算的。再说一个实测数据供参考同样的 256Kb SRAM在 40nm 工艺、1.1V、100MHz 条件下banks1 时动态功耗约 1.8mW/MHzbanks2 时约 1.35mW/MHzbanks4 时约 1.1mW/MHz。但漏电从 banks1 的 12µW 涨到了 banks4 的 16µW。很明显动态功耗在降漏电在涨具体怎么选就看你的系统是“一直在干活”还是“大多数时候在睡觉”。2.3 速度位线变短变快但外围延迟也进来了时序上banks 的影响有点像“分蛋糕”你从位线电容这块蛋糕上省下了延迟但必须切出一块还给外围电路。位线短了读操作时 sense amplifier 输入端建立的电压差更快、更明显cell 访问时间cell access time确实会变短。同时字线也变短了字线驱动延迟下降行译码到 wordline 的路径也更快。但每个 bank 的译码器是全新的一套bank 选择信号bank select需要经过额外的译码和驱动逻辑这个路径会加在地址到数据输出的总延迟里。如果你的编译器在 banks1 时走的是单级译码而 banks4 时变成了“bank 预译码 bank 内译码”两级结构那多出来的这级译码延迟可能直接把位线缩短的收益吃掉。我做一个 512Kb SRAM 时对比过读时序banks1 时时钟到数据输出CLK-to-Q是 1.42nsbanks2 时是 1.31nsbanks4 时是 1.35ns。看出来了吗2 banks 是最优4 banks 反而比 2 banks 慢了。这就是因为 bank 选择逻辑的延迟随着 bank 数量增加而增加在 4 banks 时开始压过位线收益。所以如果你是做高性能方向建议把几种 banks 配置的 .lib 里的 setup time、CLK-to-Q 都拉出来对比一下别默认“banks 越多越快”。这个结论在工艺越先进的节点越明显因为先进工艺下逻辑门延迟本身很小位线电容的改善空间也在缩小。3. 实操篇在 compiler 里怎么设 banks 并做验证3.1 典型 compiler 面板的完整设置流程我以一款最常见的 SRAM compiler 界面为例它通常会这样排列选项Word Width数据位宽。例如 32表示每个地址对应 32 bit 数据。Num Words地址深度。例如 1024、4096、16384。Mux Ratio列复用比默认 1、2、4、8 可选。它控制同一 bank 内每列的复用程度。Number of Banks我们这篇文章的主角可选 1、2、4、8有的 compiler 还支持到 16。Aspect Ratio有的 compiler 不直接给要通过 banks 和 mux 组合间接控制。Compiler 选项单口/双口/伪双口ECC 或 BIST 插入等。实操时我一般这样操作第一步先把 Word Width 和 Num Words 按实际需求填好明确我要的存储容量。比如我要 512Kb可以做 word32、num words16384也可以做 word64、num words8192。第二步Mux Ratio 先不动保持默认 1等观察完 area 和 timing 再做决定。第三步把 Number of Banks 从 1 开始按 1、2、4、8 分别跑一遍 compile。注意不是让你四个配置同时跑完就完了而是每跑完一个就存一份 .lib、.lef、.gds 和 summary report尤其是 summary report 里的 area、aspect ratio、leakage、dynamic power、setup time、CLK-to-Q 这些关键指标后面全要用到。第四步把这几个配置的指标汇总到一个表格里对比再结合你的 floorplan 区域形状和功耗预算来定最终值。有一个小技巧一旦你选定了一个配置后续做 DFT 或者 BIST 的时候一定要保持 banks 设置和 compile 时一致。我见过不止一次RTL 里写死了一个 memory 型号结果后端工具重新 compile 时默认 banks1 重新生成两边实体对不上后面 ECO 改起来极其痛苦。3.2 算一算从需求倒推合理 banks 数光看怎么选还不过瘾我直接给一个从需求出发推导 banks 数的完整流程。假设项目需要一块 1Mb SRAMword width64num words16384。目标是在 floorplan 里放成一块宽度不超过 1.5mm、高度不超过 0.8mm 的区域在一个 28nm 工艺下。先看 banks1 的默认结果。一般编译器会生成一个接近正方形的矩形但因为行数有 16384位线很长时钟频率目标 500MHz 可能过不了时序。这种情况下我在实践中会直接尝试 banks2 和 banks4。banks2 意味着每个 bank 内 num words 变成 8192位线长度减半时序理论上更有优势。banks4 则每个 bank 内 num words 变成 4096位线更短但多了两个 bank 的外围电路。你把两个配置都 compile 出来评估假设结果如下示意数据banks2面积 0.53mm²宽高比约 1.4:1读 CLK-to-Q0.82ns动态功耗 18mW/MHzbanks4面积 0.57mm²宽高比约 1.8:1读 CLK-to-Q0.79ns动态功耗 14mW/MHz。看到没有banks4 时序和功耗都更好但面积反而更大长宽比也拉大了。这时候你就要拿目标区域对比如果 1.8:1 的长宽比在 floorplan 里可以接受banks4 就是更好的选择如果 floorplan 里更希望接近正方形可能还得靠调整 mux ratio 来配合。这里也给个通用公式每 bank 行数 Num Words / (Number of Banks × Mux Ratio)。你在心里估算时序和功耗时会很有用。单看计算公式你可能没感觉我再补一句很多 compiler 生成的最大 capacity 是有限制的比如单个 bank 最多支持 8192 rows如果你要 16384 rowsbanks1 直接就不让 compile。这种情况不是“要不要切”而是“必须切”只能接受 banks≥2。选的时候多留一档余量对后续换工艺节点复用也有好处。3.3 banks 和 mux ratio 容易混淆一次讲清楚新手最容易把 Number of Banks 和 Mux Ratio 搞混甚至以为这两个是同一个东西的两种叫法。实际上这是两个不同维度的事。Mux Ratio 是在同一个 bank 内部把多个 bit 通过一个 IO 在时间上复用也就是说你一个读周期里先从一列里选出 1/N 的数据然后分 N 拍送出去。它影响的是 IO 数量、外围电荷分享的复杂度和最高频率物理上并没有改变存储阵列的行数位线长度也不怎么受影响。Banks 则是在阵列级别做物理切分每个 bank 都是完整独立的存储块有自己的一套译码和 IO它们之间互不影响只有一个被选通。banks 改变的是行数、位线长度、每块面积mux 改变的是数据和 IO 的复用关系。我打个比方。Mux Ratio 像是一个仓库里货架还是那些货架但每次只开一个门几个门轮流放行Banks 则是把一个仓库隔成好几个独立的小房间每个房间有自己的门取货的时候只打开其中一个房间的门。前者不改变货架布局后者连房间隔墙都要造。在编译器 GUI 配置里通常这两个是分开的选项你也可以同时设置。我遇到过不少工程师用 mux 去解决本该用 banks 解决的问题——比如觉得时序差不去加 banks却把 mux 从 1 改为 2结果 IO 数减半速度也没变快常常收益有限。反过来也有人只想改 mux不小心动到了 banks导致后端 ECO 时整个 memory 的节点名全部变化牵一发动全身。所以我的建议是先把 banks 定下来再通过 mux 微调两者不要在同一轮里同时改。这样你的变量唯一出了问题也容易定位。4. 常见问题与排查实录4.1 加了 banks 面积不降反增哪里出了问题这是我被问得最多的一个问题很多人在 compiler 里把 banks 从 1 改成 2面积居然涨了 20%。这种情况通常是下面的原因之一第一你的 word width 太宽。前面 2.1 节已经说过当单行 cell 数很多时外围电路复制成本的增速远大于位线电容省下的面积。这时候建议把容量和位宽代入前面的公式估算一下取舍之后可能 banks1 反而更优。第二你选的 compiler 是 high-density高密度类型的。这种类型的 memory cell 本身面积占比极高外围电路的面积占比很小加 banks 只会增加周边开销面积几乎一定变大。反之如果你是 high-speed 类型的 memory外围电路占比大加 banks 有可能减小面积因为省下的布线资源比新增的外围还多。第三你的容量本来就小。比如你只有 16Kb切成两个 bank每个 bank 只有 8Kb面积很可能直接翻倍。小容量 SRAM 根本不需要切 bank切了纯属给自己找麻烦。最直接的排查方法就是把不同配置的 report 打开看总的 cell area 和 macro area 各自怎么变。我遇到过好几次面积涨了但实际上存储单元面积没怎么变变的是外围电路也遇到过面积涨但 floorplan 里因为长宽比更合理整体 chip 面积反而小了。所以不能只看 memory 本身,要在芯片整体层面评判。4.2 时序优化不达预期甚至变差怎么办前面 2.3 节讲过banks4 可能比 banks2 更慢这里再给一个排查思路。当你加了 banks 后 CLK-to-Q 或 setup time 变差优先检查三样东西第一check compiler 的 report 里 bank select 路径的 cell delay。如果这个 delay 占了总延迟的 20% 以上说明 bank 选择逻辑成本偏高可以考虑减少 banks或者选一个 bank select timing 优化更好的 compiler。第二检查你的地址总线上有没有额外插入逻辑。有些设计为了省功耗会在地址上做 clock gating 或地址译码先行处理这些逻辑若在 memory 外部但会跟 bank select 路径叠加导致时序不降反升。可以在 compiler report 里把外设逻辑的影响拆开看。第三看看 supply voltage 和 PVT 条件下的 lib。同一个配置在 SS corner 下 banks4 的收益可能明显而在 FF corner 下可能刚好被外围延迟反超。有时候不是你的配置不对而是你固定住了某些条件导致对比结果有欺骗性。最好的办法是把所有 banks 配置在同一个 corner 下重新 compile用同一份约束跑时序。如果你比较着急还有一个退而求其次的做法先满足 setup然后用后端工具在 memory 周围加 pipeline register。memory 本身切片收益有限但如果你把数据寄存器放在 bank 之间读延迟可以被流水化吸收。我做过一个设计1GHz 目标频率下 memory 内部 CLK-to-Q0.85ns加两级流水之后整体吞吐率硬是拉上去了代价只是增加了大约 100 个 flip-flop 的面积。4.3 编译报错与 legal 限制SRAM compiler 本身有很多隐含的 limit比如每 bank 最大 rows、最大 capacity、最小 word width 等。这些限制一般不会在 GUI 上直接写出来但在 compile 时可能直接报错。最常见的报错就是 “No solution for the given configuration”这种时候基本就是单 bank rows 超出上限总容量超过 compiler 最大支持word width 和 mux ratio 组合不符合该 compiler 的资源需求某些 compiler 要求 mux ratio ≥ 某个值才能支持某个 bank 数。遇到报错先把 banks 降到 1然后看能不能编译。如果 banks1 都能过再加到 2、4 逐个试探。如果 banks1 都过不了那问题必然出在容量或位宽上要重新审视需求。还有一类隐藏问题是 compiler 输出的 .lib 和你 floorplan 里 memory hard macro 的位置不匹配。比如你选了 banks2但 lib 里的 pin 位置和时序 arc 是假设两个 bank 并排排列的你后端 floorplan 却把它们上下堆叠这会导致你 extraction 出来的功耗和 pin capacitance 和 compiler 预期差很多。所以千万记得memory 在 floorplan 里的摆放方向最好参考 compiler 生成的示意图别强行扭。下面把这几个常见问题整理成速查表方便对照排查现象可能原因排查/对策加 banks 面积变大word width 过宽、容量过小、high-density cell对比 cell area 与 macro area改用 banks1 或调整容量时序改善不达预期bank select 逻辑延迟占主导、外部地址逻辑叠加、corner 差异查看 bank select path delay优化外部逻辑多 corner 对比编译报错 “No solution”超出单 bank rows / compiler 容量上限降低 bank 数确认 word width 与 mux 组合是否合法功耗不降反升多 bank 漏电升高、ecc/bist 逻辑被复制确认 idle 功耗占比必要时在低功耗模式下断电或降 banksfloorplan 无法对齐摆放方向与 compiler 假设不一致参照 compiler 示意图放置 hard macro4.4 ECC、BIST 等额外电路对 banks 的影响很多编译器在生成 SRAM 时可以顺便插入 ECC 或 BIST 逻辑。这个功能本身没问题但如果你选了 4 banksECC 的 Hamming 编码解码逻辑也是每 bank 一套还是全局一套不同 compiler 的处理完全不一样。用编译器默认选项的人可能根本注意不到我吃过一次亏某次选了 banks4 ECC结果 compile 后的面积比 banks4 不加 ECC 多了将近 25%后来查 report 发现它把 ECC 逻辑在每个 bank 里都复制了一份最后不得不拆到 banks2。所以在预估成本和功耗时ECC 和 BIST 带来的开销会随 banks 放大。如果你的 SRAM 需要 ECC尽量选择支持全局 ECC 的 compiler 配置——少数几家有“ECC on aggregation”之类的选项能有效降低外围开销。但全局 ECC 的缺点是可修复粒度变粗对单点多位错误更敏感所以是否全局化最终还是看你的可靠性目标。5. 几个不同容量的真实配置参考为了让你更有体感我把这几组我在不同项目里最终定下来并量产的配置列出来供参考应用场景容量位宽深度Banks最终结论MCU 缓存64Kb3220481容量太小banks1 最省面积AI 加速器 buffer512Kb6481922banks2 折中功耗和长宽比基带数据存储1Mb32327684banks4 缓解位线并降低动态功耗高吞吐网络芯片2Mb128163844banks4 配合 mux4 达到 1.2GHz低功耗 IoT SRAM256Kb16163842权衡漏电没用 banks4第一行那个 64Kb 的我最初也尝试过 banks2但面积涨了接近 30%动态功耗只省了 10%后来果断退回 banks1。第三行那个 1Mb 的banks4 在动态功耗上比 banks2 省了差不多 15%因为操作频繁最终选了它。第五行特别说一下低功耗场景。IoT 芯片对漏电极度敏感本来 banks4 动态功耗最少但漏电比 banks2 高了约 30%考虑到待机时长远大于工作时长最终选了 banks2。这其实就是系统级 trade-off 的典型例子。很多时候“哪个 banks 指标最好”都不是唯一的答案关键看你的产品优先级。另外前两行的配置也提醒大家一个重要原则不要用同一个 banks 数套所有容量。同一颗 SoC 里往往有多块 SRAM容量各不相同如果图省事全部设 banks4小容量那块可能平白多出一截面积和功耗大容量那块又不够快。宁可多花一点时间逐块配置也要避免一刀切。根据我自己的经验最稳妥的做法是在项目前期的 memory 选型阶段把不同容量、不同 banks 配置做成一张 Excel 表列上面积、漏电、动态功耗、CLK-to-Q、长宽比后端和功耗工程师直接在这张表里做选择。这个表一旦定下来后面所有 memory 例化都按这个口径走RTL 和 DFT 回归都不容易出偏差。我后面几个项目都是这么过来的省了很多沟通成本。最后分享一个我个人的心得banks 参数不是一个“越大越好”或者“越小越好”的单调问题它的最优值跟你在优化什么目标强相关。做低功耗优先看动态功耗和漏电的交叉点做性能优先对比 CLK-to-Q 和 setup 曲线的拐点做面积优先老老实实把几种配置都跑出来看数据。真正吃了亏之后你会明白SRAM compiler 给的自由度越多越考验你对物理设计的理解深度。
返回列表