【芯片设计】配置寄存器为啥要提供总线读写标记信号

乐活   2025-01-20 11:59   北京  
继续最近的项目交付总结归纳,读写标记信号的总结让我发现很多个人之前觉得没有什么意义或者多此一举的设置和要求,或许只是应用和踩坑的场景还没有遇到。哪天遇到了,没准还会赞叹一句“这个操作还真是运筹帷幄啊”。这也驱动着在完成最近的交付总结系列之后,开始回过头去看一看之前遇到的很多不太理解的编码“规范与交付“要求”,尝试去探究下这些的由来在哪。为了追求更多的共鸣,“规范要求”系列同时在知乎和小红薯更新,于是评论区就非常的两级分化(当然也有爹味评论和争吵),很有意思来年更的时候再说。
那先回到今天的话题,这次是在提升模块gating比例的代码优化过程中发现的一个经验。这个题目有点拗口(虽然已经删了挺多字),但是也没有更准确的描述方式,所以先解释一下这个题目的意思

配置寄存器其实就是大家经常提到的包括配置、状态、中断等寄存器单元的寄存器模块,对应验证里的就是ral_model,因为怕写标准寄存器有歧义所以写成了配置寄存器。那么标准配置寄存器是啥呢,我这里想要指的是由VCS工具提供的寄存器生成流程(会生成RAL+RTL)生成的寄存器模块。这个东西展开就比较大了,之前在专栏里讨论和实践过,加之和今天的内容不是强相关所以就一笔带过,当然也欢迎查看和订阅专栏《uvm ral_model与寄存器集成》。

那么直入主题,VCS在基础框架的层面提供了若干种寄存器域类型供使用,具体可以在$VCS_HOME/etc/vmm/sv/RAL/RTL路径下查看:

$cd /tools/synopsys/vcs/vcs-mx_vL-2016.06/etc/vmm/sv/RAL/RTL/total 40-rw-r--r--. 1 xiaotu xiaotu 1608 May 25  2016 vmm_ral_a0_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1606 May 25  2016 vmm_ral_a1_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1610 May 25  2016 vmm_ral_host_itf.sv-rw-r--r--. 1 xiaotu xiaotu 1201 May 25  2016 vmm_ral_notifier_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1554 May 25  2016 vmm_ral_rc_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1095 May 25  2016 vmm_ral_ro_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1445 May 25  2016 vmm_ral_ru_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1549 May 25  2016 vmm_ral_rw_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1611 May 25  2016 vmm_ral_w1c_field_rtl.sv-rw-r--r--. 1 xiaotu xiaotu 1362 May 25  2016 vmm_ral_wo_field_rtl.sv
这里面大部分模块看名字就知道是什么读写属性,不过vmm_ral_notifier_rtl.sv这个模块很有意思,显然我们不会去定义一个“通知”寄存器。那这个寄存器是干嘛的呢,看下代码大概就明确了:
module vmm_ral_notifier_rtl(clk, rstn, sel, wen, rd, wr);   input sel, wen;   input clk, rstn;   output rd, wr;
reg rd, wr;
always @(posedge clk or negedge rstn) begin if (!rstn) begin rd <= 0; wr <= 0; end else begin rd <= sel & ~wen; wr <= sel & wen; end end
endmodule
sel会外接总线选通信号(就是对该寄存器或域的读写使能),wen会外接总线写有效。那么结合RTL行为就是:rd和wr会将总线对该寄存器的读写操作以脉冲的方式驱动出去。而对于通过EDA生成的寄存器单元而言,其内部的组织形式是这样的:
vmm_ral_rw_field_rtl #(4, 'h8)   intp_cfg(clk, rstn, intp_cfg_out,   hst_wdat[3:0], hst_sel[0], hst_wen,   intp_cfg_in, intp_cfg_wen);vmm_ral_rw_field_rtl #(4, ('h1234567>>0))   rsvd_3_0(clk, rstn, rsvd_out[3:0],   hst_wdat[7:4], hst_sel[0], hst_wen,   rsvd_in[3:0], rsvd_wen); vmm_ral_rw_field_rtl #(8, ('h1234567>>4))   rsvd_11_4(clk, rstn, rsvd_out[11:4],   hst_wdat[15:8], hst_sel[1], hst_wen,   rsvd_in[11:4], rsvd_wen);vmm_ral_rw_field_rtl #(8, ('h1234567>>12))   rsvd_19_12(clk, rstn, rsvd_out[19:12],   hst_wdat[23:16], hst_sel[2], hst_wen,   rsvd_in[19:12], rsvd_wen); vmm_ral_rw_field_rtl #(8, ('h1234567>>20))   rsvd_27_20(clk, rstn, rsvd_out[27:20],   hst_wdat[31:24], hst_sel[3], hst_wen,   rsvd_in[27:20], rsvd_wen);
vmm_ral_notifier_rtl _n_intp_cfg(clk, rstn, hst_sel[0], hst_wen, intp_cfg_rd, intp_cfg_wr);vmm_ral_notifier_rtl _n_rsvd(clk, rstn, |hst_sel[3:0], hst_wen, rsvd_rd, rsvd_wr);
也就是说每个寄存器内部构成都是这样的,每个field会对应输出xxx_out和xxx_rd+xxx_wr来告诉RTL侧这个寄存器发生了一次读取或更新:
比如看这个寄存器的接口:
module ral_reg_MVU_REG_global_cfg_AXI_W_CFG_rtl(input  clk,                             input  rstn,                             input  [31:0] hst_wdat,                             output [31:0] hst_rdat,                             input  [3:0] hst_sel,                             input  hst_wen,                             output [1:0] awburst_out,                             output awburst_rd, awburst_wr,                             input  awburst_wen,                             input  [1:0] awburst_in,                             output [3:0] awcache_out,...
好的背景部分完成,因为这些代码是VCS的寄存器生成工具ralgen生成的标准寄存器代码,因此在题目里称之为:“标准配置寄存器”输出的读写标记信号。

之后再说说为啥是突然理解,主要之前我一般不用这个信号,写的寄存器生成工具里也直接把这个信号没有外接,事实上VCS提供的代码是以SystemVerilog interface打包的,我在做工具时加了一个interface转port的操作。而在我所经历的项目交付以及使用其他工具生成的寄存器单元里,也几乎没有用到和见到使用这组信号的场景,所以我一直心安理得的认为这组信号没有什么大用,不接出来也很合理。

然后最近不是提升gating比例么,所以我就通过工具排查了一下哪些模块gating比例比较低,准备进行优化。随机发现了一个模块不大但是比例超级低,这里面主要的逻辑是什么呢:

就是这样的结构,需要根据几个寄存器的配置计算出一个值,这个值再去参与后续的逻辑运算。因为每个寄存器都是可以带流改配的,因此这个的打拍我选择了不带使能的寄存器dffr。而后就可想而知了,这个48bit的dffr完全插不进去gating,当然这里也没有开-gate_clock因此不会自动根据D端和Q端综合出带EN端的dffre。但是即使通过D!=Q来产生EN了这里的逻辑深度也太深了,直接干到en端-240ps/d端-160ps的violation,不能接受。

在思考怎么解决这个问题的时候突然就悟了,这里如果有三个配置寄存器的总线写有效信号就好了,如果任一配置发生了更新,才需要更新后面的dffre,也就是en = reg_a_wr || reg_b_wr || reg_c_wr。这样即使寄存器是随时可带流配置的,也不会有什么问题,直接一手cover住。于是就理解了为什么工具提供的标准模块会有这组信号,一定是有许许多多类似的小经验小巧思最后才凝结为一个通用的交付模块的。

当然,这个思考发现也不一定准确,单纯是一次总结输出吧。

系列文章入口——

【芯片设计】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?
芯片搬砖日常·逼死强迫症的关键词不对齐事件
熟人社会里,一群没有社会价值的局外人


芯时代青年
专心数字前端全流程,芯时代有为青年的自我修养
 最新文章