电子产业一站式赋能平台

PCB联盟网

搜索
查看: 62|回复: 0
收起左侧

【芯片设计】偶遇编码建议(二)在设计中优先使用无复位寄存器

[复制链接]

407

主题

407

帖子

5214

积分

四级会员

Rank: 4

积分
5214
发表于 2025-3-5 15:10:00 | 显示全部楼层 |阅读模式
编写RTL一晃十来年了,遇到了很多形形色色工程编码规范、约束和建议,故而在此阶段性汇总。本系列中所提及和讨论的verilog/sv编码建议以及一些工程的要求只是工作过程所接触和了解内容,非普适性的编码规范,也并不代表个人赞同这些规范,一家之言仅和大家探讨这些建议原因和得失。
本系列的前三篇请参见:
  • 为什么要求不在RTL中使用always
  • 为什么避免在RTL中滥用宏定义
  • 为什么避免在RTL中使用task[/ol]本篇为系列的第四篇也是争议比较大的一篇,在知乎专栏中的原题目为《为什么无复位寄存器的比例要高于95%》。那么让我们抛开争议,一起探究下无复位寄存器在芯片设计中的使用。如果抛不开的话,欢迎到“阅读原文”评论区讨论。在正文开始之前,先看下小红薯上对各位同行朋友进行问卷调查的结果:

    ktraoy551to6404510617.jpg

    ktraoy551to6404510617.jpg

    通过322人参与投票的结果来看,有近6成的朋友都有在设计中使用无复位寄存器的经验,显然这并不是一个小众设计方式。而在前司对于无复位寄存器比例的要求则更加严苛,就如原文题目中所说的要求子系统的无复位寄存器比例高于95%。这一条既是设计checklist检查项,又可以视为一项设计编码规范,即在客观条件允许的前提下尽可能使用无复位寄存器作为时序单元而非带复位的寄存器。关于这点我是倾向于赞同,理由大概有几点。1. 无复位寄存器的面积优势。带复位端口的寄存器需要额外的逻辑电路来实现复位功能,包括复位信号的输入、复位值的选择以及复位信号的驱动电路。根据查到的一些文章,考虑工艺节点和设计的具体实现带复位端口的寄存器通常比不带复位的寄存器面积增加5%到20%(之前在请教时得到的答复是,无复位寄存器约有不到10%的面积减小,不是很关键)。“例如,在一个典型的28nm工艺中,一个不带复位的D触发器可能占用约10μm2的面积,而带复位端口的D触发器可能占用11μm2到12μm2的面积。”
    2. 无复位寄存器的功耗优势。这个是前司leader提到的最多的,这么高的无复位寄存器比例要求,主要也是出于功耗考虑。无复位寄存器的静态功耗(带复位端口的寄存器需要额外的晶体管来实现复位功能,这些晶体管在非复位状态下也会产生漏电流,从而增加静态功耗)和动态功耗(当复位信号切换时会驱动大量的寄存器,导致较大的电容充放电电流)均低于带复位寄存器,这个数值能查到的大约也在5%到15%之间,典型值记忆里是15%。
    3. 无复位寄存器的布线优势。显而易见,复位信号通常是一个全局信号,需要连接到大量的寄存器。这种全局信号的布线会占用大量的布线资源,并增加布线的复杂度。无复位寄存器不需要复位信号,布线资源自然就释放出来很多。对于一个曾经调congestion调到脑袋疼的人而言,这项真实喜闻乐见。
    4. 其他方面。这个是别人跟我提的,复位信号通常是一个高扇出信号,切换可能会引入噪声和干扰影响其他信号的完整性,这方面我没有什么经验所以就简单放在这里吧。
    而关于时序方面我也比较感兴趣,于是以带复位和不带复位两种代码结构,用130工艺简单综合了一个1024bit打拍的模块:
  • always @(posedge clk or negedge rst_n) begin  if(!rst_n) begin    o_sig 1024'b0;  end else begin    o_sig   endend带复位的CK-Q时序为0.11:
      Point                                    Incr       Path
      -----------------------------------------------------------
      clock clk (rise edge)                    0.00       0.00
      clock network delay (ideal)              0.00       0.00
      o_sig_reg[0]/CK (DFFRHQX1)               0.00 #     0.00 r
      o_sig_reg[0]/Q (DFFRHQX1)                0.11       0.11 r
      U3/Y (INVXL)                             0.05       0.16 f
      U4/Y (INVX6)                             0.30       0.46 r
      o_sig[0] (out)                           0.00       0.46 r
      data arrival time                                   0.46不带复位的CK-Q时序为0.14:
    Point                                    Incr       Path
      -----------------------------------------------------------
      clock clk (rise edge)                    0.00       0.00
      clock network delay (ideal)              0.00       0.00
      o_sig_reg[0]/CK (DFFQX1)                 0.00 #     0.00 r
      o_sig_reg[0]/Q (DFFQX1)                  0.14       0.14 r
      U3/Y (INVXL)                             0.05       0.19 f
      U4/Y (INVX6)                             0.30       0.48 r
      o_sig[0] (out)                           0.00       0.48 r
      data arrival time                                   0.48带复位的D触发器反而本身时序偏好一些,或者至少可以看出无复位寄存器在时序上没有什么明显优势。此外,无复位寄存器还有哪些缺点呢?
    1. 验证风险和复杂度增加。无复位寄存器的初始状态是不确定的(在仿真时通常通过initreg配置为随机值包括X态),这可能会增加验证的复杂度。验证工程师需要确保设计在初始状态下能够正确运行,或者通过其他方式(如软件初始化)来确保系统的稳定性。这也就是xprop发挥作用的领地了:
    【芯片验证】RTL仿真中X态行为的传播 —— 从xprop说起
    【芯片验证】RTL仿真中X态行为的传播 —— xprop平替策略
    2. 功能安全性风险。无复位寄存器的初始状态不确定性可能会导致系统在启动时出现不可预测的行为,尤其是在安全性要求较高的应用中(如汽车电子、医疗设备)。在系统出现错误时,带复位端口的寄存器可以通过复位操作快速恢复到已知状态,而无复位寄存器则缺乏这种能力,可能会增加错误恢复的难度。所以现在做车载芯片方向之后,似乎关于复位比例要求就没有了。
    所以显然无复位寄存器的使用会同时带来巨大的收益和风险,那么还是要协调平衡一下无复位寄存器的使用,通常的准则是”数据寄存器不复位,控制寄存器要复位“。
    鉴于这个话题引起了比较大的争议,在此我几项佐证(后面如果看到再继续补充)。当然这里要佐证的并不是“无复位寄存器比例要高于95%”,而是“在RTL中使用无复位寄存器是一种客观存在的行为”。
    第一项是英伟达(NVIDIA)在guihub上开源的深度学习加速器NVDLA RTL代码,stars为1.8K:
  • https://github.com/nvdla/hw

    z4yaqt1fa1i6404510717.jpg

    z4yaqt1fa1i6404510717.jpg

    然后随便点开的一个模块(还真的是随便点的,本来想找找看因为不知道具体的结构,结果点开的第一个就看到了):
    hw/vmod/nvdla/cacc
    /NV_NVDLA_CACC_assembly_buffer.v可以看到使能和地址信息打拍时用的带复位寄存器,数据打拍用的无复位寄存器:

    afp0qp5qlby6404510817.jpg

    afp0qp5qlby6404510817.jpg

    可能看不清,复制一部分代码吧:
  • ////////////////////////////////////////////////////////////////////////// Input write stage1 registers                                       //////////////////////////////////////////////////////////////////////////always @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin  if (!nvdla_core_rstn) begin    abuf_wr_en_d1 8{1'b0}};  end else begin  abuf_wr_en_d1   endendalways @(posedge nvdla_core_clk or negedge nvdla_core_rstn) begin  if (!nvdla_core_rstn) begin    abuf_wr_addr_d1 0}};  end else begin  abuf_wr_addr_d1   endendalways @(posedge nvdla_core_clk) begin  if ((abuf_wr_en_d1_w[0]) == 1'b1) begin    abuf_wr_data_0_d1   // VCS coverage off  end else if ((abuf_wr_en_d1_w[0]) == 1'b0) begin  end else begin    abuf_wr_data_0_d1 'bx;  // spyglass disable STARC-2.10.1.6 W443 NoWidthInBasedNum-ML -- (Constant containing x or z used, Based number `bx contains an X, Width specification missing for based number)  // VCS coverage on  endendalways @(posedge nvdla_core_clk) begin  if ((abuf_wr_en_d1_w[1]) == 1'b1) begin    abuf_wr_data_1_d1 {abuf_wr_data_1_d1_w};  // VCS coverage off  end else if ((abuf_wr_en_d1_w[1]) == 1'b0) begin  end else begin    abuf_wr_data_1_d1 // spyglass disable STARC-2.10.1.6 W443 NoWidthInBasedNum-ML -- (Constant containing x or z used, Based number `bx contains an X, Width specification missing for based number)  // VCS coverage on  endendalways @(posedge nvdla_core_clk) begin  if ((abuf_wr_en_d1_w[2]) == 1'b1) begin    abuf_wr_data_2_d1   // VCS coverage off  end else if ((abuf_wr_en_d1_w[2]) == 1'b0) begin  end else begin    abuf_wr_data_2_d1 for based number)  // VCS coverage on  endendNV还是厉害,我们之前的编码规范里是绝对不允许赋X态的,所以对这段代码我有另外一个疑问,有机会聊。第二项佐证是开源的RISC-V处理器蜂鸟E200系列,我自己的代码风格其实和蜂鸟很接近,他家的文档上也提到无复位寄存器的事了:

    e1ttd1abxjc6404510917.jpg

    e1ttd1abxjc6404510917.jpg

  • https://github.com/SI-RISCV/e200_opensource其stars为2.6K是Github verilog类里排第二星数的开源库。在代码库的寄存器单元里:
    e200_opensource/rtl/e203/general
    /sirv_gnrl_dffs.v直接封装了不带复位的寄存器供使用:
  • // ===========================================================================//// Description://  Verilog module sirv_gnrl DFF with Load-enable, no reset //// ===========================================================================module sirv_gnrl_dffl # (  parameter DW = 32) (  input               lden,   input      [DW-1:0] dnxt,  output     [DW-1:0] qout,  input               clk );reg [DW-1:0] qout_r;always @(posedge clk)begin : DFFL_PROC  if (lden == 1'b1)    qout_r #1 dnxt;endassign qout = qout_r;`ifndef FPGA_SOURCE//{`ifndef DISABLE_SV_ASSERTION//{//synopsys translate_offsirv_gnrl_xchecker # (  .DW(1)) sirv_gnrl_xchecker(  .i_dat(lden),  .clk  (clk));//synopsys translate_on`endif//}`endif//}    endmodule然后是在代码中具体例化使用的例子(dfflr是带复位的,dffl是不带复位的):

    0bnis4ct1mr6404511017.jpg

    0bnis4ct1mr6404511017.jpg

    第三项是和一些朋友聊天问到的,总结一下:某司某芯片部门不要求使用无复位寄存器,另一处理器核部门(具体是某项目组,不确定是否为整部门)要求无复位寄存器比例,某终端部门可以使用无复位寄存器但在面积功耗达标的情况下优先使用带复位寄存器。某司芯片的内核部分要求无复位寄存器比例,soc部分不要求。某车载智驾芯片要求是所有寄存器必须带复位,对此双手赞同毕竟车载芯片的功能安全可不是闹着玩的(〒▽〒)。

    02rpab01e3w6404511117.jpg

    02rpab01e3w6404511117.jpg

    t1fcnu40dwt6404511218.png

    t1fcnu40dwt6404511218.png

    系列文章入口
    【芯片设计】SoC 101(一):绪论【芯片设计】FIFO漫谈(零)从无处不在的FIFO开始说起【芯片设计】计算机体系结构(一)虚拟内存【芯片设计】深入理解AMBA总线(零)绪论
    【芯片设计】握手协议的介绍与时序说明【芯片设计】复位那些小事 —— 复位消抖【芯片设计】快速入门数字芯片设计(一)Introduction【芯片验证】UVM源码计划(零)下定决心读源码前的自测环节
    【芯片设计】异步电路碎碎念(一) 到底什么是异步电路
    【芯片设计】从RTL到GDS(一):Introduction
    【芯片设计】系统中的可维可测状态记录寄存器设计
    其他文章链接
    【芯片验证】sva_assertion: 15道助力飞升的断言练习【芯片验证】可能是RTL定向验证的巅峰之作【芯片验证】RTL仿真中X态行为的传播 —— 从xprop说起【芯片验证】年轻人的第一个systemVerilog验证环境全工程与解析
    【芯片设计】verilog中有符号数和无符号数的本质探究
    【芯片设计】论RTL中always语法的消失术
    【芯片设计】代码即注释,注释即代码
    【芯片设计】700行代码的risc处理器你确实不能要求太多了
    入职芯片开发部门后,每天摸鱼之外的时间我们要做些什么呢
    如何计算系统的outstanding 和 burst length?
    芯片搬砖日常·逼死强迫症的关键词不对齐事件
    熟人社会里,一群没有社会价值的局外人
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表