编写RTL一晃十来年了,遇到了很多形形色色工程编码规范、约束和建议,故而在此阶段性汇总。本系列中所提及和讨论的verilog/sv编码建议以及一些工程的要求只是工作过程所接触和了解内容,非普适性的编码规范,也并不代表个人赞同这些规范,一家之言仅和大家探讨这些建议原因和得失。
严格来说这不是编码建议的第一篇文章,因为之前就提过一些:【芯片设计】论RTL中always语法的消失术【芯片设计】宏定义和parameter在设计领域的使用讨论如果类似用这篇标题的格式,那么可以重命名为:为什么要求不在RTL中使用always为什么避免在RTL中滥用宏定义[/ol]当然了,题目里还要加上(某司/某某司)这类限定词来强调下这并非行业普适。鉴于前两篇已经写过了,那就从第三篇开始吧!关于RTL中避免使用task的这个编码建议本没打算在这个系列写,因为系列本意是想汇总一下个人遇到的那些形形色色的编码约束并探求背后的考虑,分析其是否有道理和必要。而RTL中避免使用task我一直以为是比较普遍普适的编码习惯,属于那种大家都这样做因此根本没有必要单独一篇来讨论的内容。但是最近发现不是这样,这里我的视野还是窄了。在评论区一位朋友推荐一本贯穿Synopsys RTL编码思路的书里发现,作者是比较推荐使用task(当然,也很推荐function)进行RTL搭建,于是发现原来不用task并不是普适性的编码约束。那么为啥之前待的团队都不让用task,这一点主要是task可综合性的问题。在我之前的培训笔记里,task被归类在“不完全可综合语法”一栏中,还备注了一些EDA工具不支持综合task。因为从来没有在RTL里写过task,所以具体是什么情况我其实不是太清楚。这里直接参考下ds的回答。在Verilog RTL设计中,避免使用task的原因主要有以下几点:1. 可综合性问题 不可综合:task通常用于仿真,许多综合工具无法将其转换为硬件电路,导致设计无法综合。 行为不可预测:即使某些工具支持task综合,其行为可能与仿真不一致,增加设计风险。
2. 代码可读性和维护性 复杂性:task可能包含复杂逻辑,增加代码理解难度,尤其在大型团队中。 调试困难:task的调试比普通代码更复杂,尤其在涉及时序和并发时。
3. 时序和并发问题 时序不确定性:task中的延迟和控制结构可能导致时序问题,影响设计功能。 并发执行问题:task在并发执行时可能引发竞争条件,导致仿真与硬件行为不一致。
4. 仿真性能 仿真速度慢:task可能降低仿真速度,尤其当频繁调用或包含复杂逻辑时。
5. 标准化和一致性 团队规范:许多团队为保持代码一致性,避免使用task,转而使用function或always块等更可控的结构。
6. 替代方案 使用function:function通常可综合,适合纯计算任务。 使用always块:复杂逻辑可通过always块实现,便于综合和仿真。
总结:避免使用task主要是为了确保代码的可综合性、可读性和可维护性,同时减少时序和并发问题。大多数设计团队倾向于使用更可控的结构来实现相同功能。估计正是基于以上这些认识和经验,所以之前的团队都不允许在rtl里写task。根据在小红薯的调查,也可以发现投票的大部分朋友(应该都是同行吧)都没有在rtl里写过:
但是思路改变发生在读了《The Simple Art of Soc Design》之后,还是让ds先介绍一下这本书的作者Micheal Keating:《The Simple Art of SoC Design》的作者Michael Keating是一位在集成电路设计领域具有深厚影响力的专家,尤其在系统级芯片(SoC)设计和低功耗设计方法论方面贡献显著。以下是关于他的主要信息总结:1. 专业背景与贡献Michael Keating的著作《The Simple Art of SoC Design》聚焦于如何简化复杂SoC设计流程,弥合寄存器传输级(RTL)与电子系统级(ESL)之间的鸿沟。书中提出的方法论包括:
高级综合工具的应用,减少低层级RTL设计工作量。
模块化设计和IP核复用,提升开发效率并降低复杂度。
软硬件协同设计的理念,强调硬件实现与软件开发的并行性
此外,他还参与编写了另一本经典教材《Low Power Methodology Manual for System-on-Chip Design》,系统探讨低功耗设计技术。
2. 学术与行业影响力书籍定位:他的著作被广泛视为SoC设计领域的指南,既适合初学者入门,也为资深工程师提供深入的技术洞见。
技术趋势前瞻:书中还展望了SoC设计的未来趋势,例如人工智能集成、异构计算与安全性增强等方向。
工具链支持:通过结合Systemc和SystemVerilog等工具,他的方法论推动了ESL设计流程的普及,显著缩短了芯片开发周期。
3. 职业经历根据书籍版权信息,Michael Keating与Synopsys公司(全球领先的EDA工具提供商)有密切联系,其著作《The Simple Art of SoC Design》由Synopsys Inc.参与出版。这反映了他可能在Synopsys担任技术专家或顾问,专注于设计方法学与工具链的研发。
4. 写作风格与目标读者他的著作以实践为导向,通过案例分析和技术对比(如RTL与ESL的权衡)帮助读者理解复杂概念。目标读者包括硬件工程师、SoC架构师以及对设计自动化和验证技术感兴趣的研究人员。
总结Michael Keating作为SoC设计领域的权威,通过理论与实际结合的方法,推动了设计方法学的进步。他的作品不仅提供了技术细节,还强调设计哲学与流程优化,对现代芯片设计行业具有重要参考价值。如需进一步了解其著作,可参考Springer出版的版本或相关技术文库资源。
在这本书的第四章状态机设计部分,有如下的代码(也就是序章里贴的):
这段代码的思路就是状态机和子状态机,因为他遵循7±2的原则,建议主状态机不要过于庞大(这个在后面的编码建议中再聊),因此拆分了两个子状态机并通过task实现。截止到这个时间点,我觉得能够理解使用task进行rtl编码的一些思路和好处了。而后在第七章“降低数据主导设计的复杂性”这就懵了,task已经进化到在这一步了:
这块dct的一部分,思路就是用一个task main把所有的操作封装进去,里面再调用其他的function和task,function里放组合逻辑,task里放非阻塞赋值相关的逻辑。一直认为封main函数是C或者嵌入式这类代码的常规操作,没成想在这也见到了。怪不得副标题是closing the gap between RTL and ESL,如果是ESL这样写那确实合理很多了。
截止到这个时间点,我的倾向变成了在RTL里写task也不是什么大不了的事,一家一个风格嘛。但是事情还没有结束,我带这个新奇的发现去和大家分享时,又看到了最新的观点。最早最典型的说明是EDA厂商的朋友带来的解释:
带着这个疑问又和一些朋友讨论了一下,最终看到了一些观点一致的官方和半官方的使用建议,摘录在这里:HDL Compiler UG,Using Void Functions Instead of Tasks Inside always_comb:The IEEE Std 1800-2012 states that always_comb is sensitive to changes within the contents of a function, whereas always @* is only sensitive to changes to the arguments of a function. It does not define the behavior of a task inside an always_comb block or the sensitivity list. This can cause a mismatch between simulation and synthesis. To prevent such mismatches, use void functions instead of tasks inside an always_comb block.
IEEE Std 1800-2012标准规定always_comb对函数内部的变化敏感,而always @*仅对函数参数的变化敏感。它没有定义任务在always_comb块或敏感列表中的行为,这可能导致仿真和综合之间的不匹配。为了避免这种不匹配,建议在always_comb块中使用void函数而不是任务。
某综合指导文档,综合指导原则:
在可综合的模块中,使用空函数来代替任务。
空函数的优势在于它像任务一样被调用,但须遵循函数编码规则,例如函数不能包含事件控制。这样的限制有助于确保能综合出正确的结果。
其它参考文档:SystemVerilog adds the ability to declare a function as void, indicating the function does not have a return value (but can assign to output arguments). A void function is used in the same way as a task, but with the requirement that it must execute in zero time (the function cannot contain any construct that might block until simulation time advances).SystemVerilog Advantage 11: Using void functions in RTL code can help ensure that subroutines will synthesize. This is because functions cannot have delays, which is also a general synthesis restriction.Recommendation: Use void functions instead of tasks in RTL models that will be synthesized. This prevents a common problem when using tasks, where the model works in simulation, but the task won't synthesize. This problem is much less likely to occur with void functions.
建议: 在将要被综合的RTL模型中使用空函数代替任务。这防止了一个常见的问题,即在使用任务时,模型可以在仿真中工作,但任务无法被综合。而使用空函数出现这种问题的可能性要小得多。
情况到这里基本就明确了,确实可以在RTL中使用task(这里偏向于sv for design),但是目前较为普遍的做法是,推荐以function void替代task。
题外话,我还问了问sv里的function能不能写非阻塞赋值
最后,欢迎加入我们的讨论群!
系列文章入口
【芯片设计】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? | 芯片搬砖日常·逼死强迫症的关键词不对齐事件 | 熟人社会里,一群没有社会价值的局外人 |
|