ARM技术论坛
直播中

HCPcry

8年用户 1103经验值
擅长:处理器/DSP
私信 关注
[经验]

在SpinalHDL中的代码组织结构如何实现Component参数化设计呢

习惯了Verilog的小伙伴,初次看到SpinalHDL的代码时,总会不自觉的和Verilog代码对照,本篇就SpinalHDL中的代码组织结构进行一个简要的梳理。

Component<—>module

我们在编写Verilog代码时,代码的的组织往往是按照module来组织的,而在SpianlHDL里,与之相对的是Component,SpianlHDL里我们编写的每个class继承Component则与之对应的在生成RTL时会相对生成一个module,因而往往我们在编写SpinalHDL时更多的是继承Component:


这里定义了两个class:AdderCell及Adder,这两个类均继承了Component,因此在生成RTL时与之对应的将会生成AdderCell及Adder两个module。而我们在使用时需要做的即使模块例化,端口链接,而当端口将多时,我们可以定义伴生对象来解决,避免成为连线工程师。

端口声明

和我们编写Verilog代码相同,当在SpinalHDL里的class继承了Component之后,那么我们需要在class里声明输入输出端口,而SpinalHDL里提供的输入输出端口声明的关键词有:


对于普通的输入输出引脚,我们可以用in/out去进行端口声明,而这里值得注意的是,在SpinalHDL里,我们甚至可以用一个类来做端口:

这里我们在VgaCtrl里,timeings端口将VgaTimings类作为一个端口声明,如此能够将结构性的端口“一劳永逸”,避免像我们手写Verilog时千行代码,百行端口声明的尴尬。

当我们用class来做端口声明时,master/slave是另一种选择,它需要我们在定义类时继承扩展BundleImaster Slave:

这里我们继承了ImasterSlave,则需要我们在class中实现asMaster方法,asMaster方法中需要声明当我们这个类用做端口声明的master时,里面的哪些变量为输入端口,哪些变量为输出端口。这里Vga中,表明当Vga做master端口时,vSync、hSync、colorEn、color均作为输出端口,而做slave端口时,这些端口将会被推断为输入端口

还有一点值得注意的是,在SpianlHDL里,较为推荐将端口的声明放在Bundle中:

将端口声明放在Bundle中,SpinalHDL在生成RTL时,会检测在Bundle中的所有元素是否都声明了端口方向。

有一点是像上面的MyAdder将端口声明放在Bundle中,生成的RTL代码的端口都会有一个"io_"前缀,若想在代码中避免可在SpinalHDL里添加"noIoPrefix()"。

在SpinalHDL里,Component对于端口的访问与Verilog类似:

可读本Component的输入输出端口及

可读本Component例化的子Component输入输出端口

有趣的一点是当我们想访问更深一级子Compontent变量或端口名时也有方式:
some.where.else.theSignal.pull()
在生成RTL代码时,会讲该信号声明一个端口链接偷穿到我们这一级的Component。

Component参数化设计

与我们编写Verilog时相同,在SpinalHDL里同样支持参数化设计,而且更加的强大:

这里MyAdder的端口位宽采用参数化设计,我们可以在例化时实时的配置修改端口位宽声明。而当我们有多个参数时,我们可以将参数封装为参数类:

这里MySoc的所有参数声明均在MySocConfig中,不同模块都要使用这里面的参数时就不用每个都反复的声明一遍了~。

原作者:玉骐

更多回帖

发帖
×
20
完善资料,
赚取积分