一入此门深似海,似猿非猿半硅农。FPGA探索,你我同行。
最近在项目中以SpinalHDL为主体做系统集成,其中遇到了不少模块命名与管理的坑,借此机会,再来聊一聊混合编程中的模块件命名与管理的事情。
问题是什么
不可否认,在当前的整体大环境下,Verilog/SystemVerilog仍然是主流,而SpinalHDL其本质上更像是一个生成Verilog的脚本工具。在团队合作中,最终拿去生成跑综合及布局布线生网表的仍然是Verilog代码。团队合作时当同时存在SpianlHDL代码和Verilog代码时不可避免的存在命名冲突的问题:
尽管SpinalHDL支持参数化设计,但其参数化是基于Scala层面上的,当我们调用SpinalHDL同一个IP以不同的参数例化时往往会为每次例化均生成一个Verilog模块代码。而当合作中存在多人调用组件生成RTL代码时最后往往会有模块命名撞车的问题。
在《被忽略的两个Tips》及《换个名字混江湖》中对于模块的命名均有提到一些方法,这里就真实的使用场景来看看这个问题。
setDefinitionName
在《换个名字混江湖》中对setDefinitionName的使用有较为详细的介绍,setDefinitionName可以手动的修改最终生成的Verilog代码对应的模块名,像下面的这段代码:
这里在例化Apb3Decoder这个SpinalHDL中的IP组件时,通过setDefinitionName来设置生成RTL代码时该模块名重新命名为Deocer。最终生成的代码便是下面这样:
倘若不添加setDefinitionName指定那么生成的RTL代码则保持原来的名字:
通过setDefinitionName可以手动的为我们的模块指定特定的名称,但如此做带来的问题是我们需要要求每个人在例化每个模块时均指定名称。稍有不慎漏掉一个那么在最后合并整体工程时便会有重复命名的问题。更值得把握的是当我们调用的其他lib有多层嵌套例化时那么这种方式便显得更为复杂了。
globalPrefix
通过globalPrefix的方式可以使得在生成RTL代码时为每个模块添加一个特定的前缀。像下面的代码:
指定每个模块的命名前面均添加“test\_”,可以看到最终生成的RTL代码的每个模块前均添加有"test\_"前缀:
多人合作时根据每个人负责的功能模块分别添加响应的模块命名前缀似乎是一个很的方式,然而是否通用?
看下面的例子:
这里我们在SpinalHDL中调用了封装好的RTL代码addTop,如果我们在例化时指定globalPrefix为“test_”,那么看看会是什么样子:
问题来了,我例化的BlackBox代码模块名称为addTop,而这里例化的时候却例化了test_addTop——一个压根没有的模块。
也就意味着当代码里存在Verilog和SpinalHDL代码混合使用时那么这种globalPrefix方式便显得太“一刀切”了。
怎么做
解决不了上面的问题那么无论SpinalHDL再怎么优秀那终究是鸡肋~
怎么做?合二为一呗!
看下面的代码:
而最终生成的RTL代码为:
是不是看起来解决了我们的问题?
setDefinitionName的优先级是高于globalPrefix的,我们在例化BlackBox时通过setDefinitionName指定模块的名字来避免在添加globalPrefix时带来的问题便可。
小小建议
在当前的环境下,团队合作时若你采用SpinalHDL作为编程语言不妨采用下面的方式来进行混合编程下的模块命名与管理:
- 若只负责单个模块的开发,那么在生成rtl代码时根据模块的功能通过globalPrefix添加适当的前缀。
- 若在SpinalHDL中例化封装Verilog代码时,在例化时通过setDefinitionName指定例化时的模块名称确保生成RTL代码时不会被修改掉。
END
作者:玉骐
原文链接:https://mp.weixin.qq.com/s/DH6N0PNzj00BC9oKIQMxPw
微信公众号:
推荐阅读
- 被忽略的两个Tips
更多SpinalHDL技术干货请关注Spinal FPGA专栏。