两种电路描述的差异
考虑下下面两种电路的差异:
sum=data_0+data_1+data_2+data_3
其综合电路为:

sum=(data_0+data_1)+(data_2+data_3)
其综合电路为:

第一种直接相加的方式会生成一个较长的加法链,而第二种加法方式相当于实现了一个加法树,其在时序收敛上相较于第一种方式更加友好,也往往采用较多。
第一种电路的实现方式在《软为硬用,如是而已》中提到过,采用reduce即可:

而类似第二种欲实现一个树形电路的描述则需要调用reduceBalancedTree方法:

reduceBalancedTree
SpinalHDL对于reduceBalancedTree提供了两个方法调用:

Vec类型和Seq类型均可以调用该方法,该方法实现为:

从源代码里可以看出,该方法最终的实现依赖两个参数:
op: (T, T) => T 树的每一层级的操作,上面的加法树里我们定义的是将两个电路对象相加,当然你也可以用来实现其他的方法,只要符合op方法定义即可。
levelBridge: (T, Int) => T 树层级间的调用方法,该方法依赖两个参数,第一个参数为带操作的电路对象,第二个参数为树的level层级(level从零开始)。
分析源代码不难看出,其通过递归实现一个树形结构,而stage将在生成RTL代码前会完成电路树形结构的生成(可参照《SpinalHDL—if向左、when向右》)。
当调用reduceBalancedTree(op: (T, T) => T)时,其实现里将levelBridge实现为(s,l)=>s,即对树层级间不做任何的操作。上面的加法树中我们在加法树的每个层级添加寄存器:


仅在奇数级插入寄存器(level是从零开始):


写在最后
用Verilog/SystemVerilog实现一个类似reduceBalancedTree功能的模版你可还能接受么~
原作者:玉琪
|