在迭代运算函数的最后一步 ι 变换中,需要将不同的轮常数与三维数据矩阵 S [0,0]这一“道”(Lane)的数据进行异或计算。根据迭代运算的迭代轮数,需要有不同的轮常数参与运算。迭代运算一共有24轮,所以完整的运算步骤共有24个64位数据参与运算。因此,需要有单独的硬件结构负责提供正确的轮常数参与ι 变换。通常而言,轮常数有两种实现方法:一种是使用线性反馈移位寄存器实时生成需要的轮常数;第二种是事先将所有的轮常数计算好,存储在寄存器或其他存储单元中,在需要时将其取出来即可。第一种方法的特点是资源开销较小,但是需要正确的运算电路和相对复杂的控制信号,使得每个迭代轮中生成正确的轮常数。第二种方法实现相对简单,只需要在每个迭代轮中将对应的轮常数从存储电路中取出即可,但是缺点是24个64位轮常数所需存储电路的资源开销相较于第一种更大。
经过比较和权衡,本节的设计采取了第二种方法,即预先将轮常数计算好并存储在寄存器中,但是存储的64位数据被缩减为7位,这样既避免了过多的控制信号,减少出错的可能性,又缩小了所需的存储空间。经过对表4-3的分析可以发现,这24个64位轮常数,仅第0、1、3、7、15、31、63位发生了变化,其他位固定为0,因此只需要存储这7位数据即可,这样就将24个64位的存储空间缩小为24个7位。简化的轮常数(Simplified Round Contant,SRC)见表4-5。
表4-5 简化的轮常数(二进制)
简化的轮常数带来两方面的益处:一是缩小了存储这些轮常数所需的硬件空间,二是降低了ι 变换的运算复杂度。因为0和其他二进制数的异或值是其本身,使用简化的轮常数后,不再需要对 S [0,0]中的全部64位数据和轮常数进行异或操作,仅需要对其中的第0、1、3、7、15、31、63位与简化的轮常数异或即可,这样就将单次运算所需的异或门数由64个减少为7个。无论是缩小存储空间还是降低运算复杂度,简化的轮常数都将有效降低电路的资源开销。
迭代运算模块具有处理数据量大,所需逻辑门数量多的特点。在电路实现过程中发现,这个模块的组合逻辑延迟非常大,是影响SHA-3模块最高频率的关键部分。提高系统的时钟频率可以采用流水线(Pipeline)技术,即在较长的组合逻辑路径中插入适当数量的寄存器,将其分割为若干小段,以缩短最大延迟,从而提高系统频率。采用流水线技术有两个需要注意的原则:一是在满足频率要求的前提下插入的寄存器数量尽可能少,因为过多的流水线级数会带来系统的延迟和资源开销的增加;二是流水线对关键路径的切割需要尽可能均匀,分割不均匀的流水线对频率的提高作用十分有限。
对于SHA-3的迭代运算模块,由于处理数据量较大且迭代轮数较多,任意一级流水都会增加至少1600位寄存器的资源开销和24个周期的系统延迟,所以使用的流水线级数不宜过多。通常的做法是在θ 变换和ρ 变换之间插入一级流水线 [29-30] ,如图4-22所示;或者在π变换和χ变换之间插入一级流水线 [31-33] ,如图4-23所示。从本质上来说,如果不考虑线延迟的影响,这两种方法对于关键路径的分割效果几乎是一样的,因为ρ 变换和π 变换是移位和旋转变换,并不消耗门电路。通过这两种方法,关键路径几乎被分为两半,系统的最高频率得到了有效提升。
图4-22 θ变换和ρ变换之间插入一级流水线
图4-23 π变换和χ变换之间插入一级流水线
本节设计一种新型的流水线结构,如图4-24所示。这种流水线结构将关键路径分割得更加精确合理。该新型流水线同样是在迭代运算模块内部插入一级流水线,不同的是 θ 变换被分解为三步 θ1、θ2和 θ3,流水线插入在θ2和θ3之间。分解的三步θ1、θ2和θ3分别对应式(4-5)、式(4-6)和式(4-7),消耗的门电路数量分别为4个异或门、1个异或门和1个异或门。根据对迭代函数各个部分表达式和映射成的电路的分析,如果将流水线插入在θ变换和ρ变换之间,或者插入在π变换和χ变换之间,则在寄存器之前路径包含6个异或门,在寄存器之后包含2个异或门、1个与门和1个非门。也就是说,关键路径被分割为两个部分,第一个部分包含6个门电路,第二个部分包含4个门电路。对于新型流水线结构,流水线插入在θ2和θ3之间,在寄存器之前包含5个异或门,寄存器之后包含3个异或门、1个与门和1个非门。也就是说,关键路径分割为的两个部分,均包含5个门电路。相比于图4-22和图4-23所示的前两种结构,最长的关键路径包含的门电路从6个减为5个。
图4-24 本节设计的新型流水线结构
本节设计的新型流水线结构内部详细电路如图4-25所示,除特别标注部分,所有的数据线宽均为64位。进入迭代运算模块的1600位数据被均分为25路,每路的数据线宽为64位,之后数据会依次经过θ1变换、θ2变换、θ3变换、ρ变换、π变换、χ变换和ι变换。除了ι变换之后本身已有的寄存器,新型流水线寄存器被插入在θ2变换和θ3变换之间。需要注意的是,相比于θ变换和ρ变换之间或是π变换和χ变换之间的流水线,为了数据流的正确传输和同步,新型的流水线结构需要额外的5个64位寄存器。但是从实现结果来看,相比于最高频率的大幅提升,这些额外的硬件资源开销是值得的。
对于提高SHA-3实现的吞吐量,除了流水线技术,还可以用循环展开(Loop Unrolling)的优化方法。循环展开指的是在一个时钟周期内计算多轮迭代函数。例如,对于基本的迭代运算模块而言,通常是一个周期计算一轮迭代函数,24轮迭代运算则需要24个周期。但是如果能一个周期计算两轮迭代函数,则需要的总时钟周期数则缩短为12个周期。一个时钟周期计算的迭代函数的次数称为展开因数(Unrolling Factor),展开因数越高,所需要的总时钟周期越少,但所需要的资源开销也越大,同时关键路径的延迟会增加,系统的最高频率会显著下降。所以使用循环展开的优化方法,难点在于选择合适的展开因数,平衡吞吐量和资源开销之间的关系,使得增益效果最大化。
图4-25 本节设计的新型流水线结构内部详细电路
在使用循环展开的优化方法后,再搭配流水线可以解决最高频率下降的问题。一般来说,如果在展开结构中,插入流水线寄存器的位置与展开之前是相同的,系统的最高频率几乎不会受到影响。在展开结构的基础上,流水线除了插入在迭代运算模块内部,还可以在两轮迭代模块之间。这样,不同的展开因数和不同的流水线级数相互组合,可以得到不同的设计结构,在最高频率、吞吐量和电路面积方面都有不同的表现。迭代运算模块不同展开因数和流水线级数的组合电路如图4-26所示。
图4-26 迭代运算模块不同展开因数和流水线级数的组合电路
本节设计的SHA-3模块实现的目标是在获得更高吞吐量的同时,尽可能缩小电路的面积,即实现硬件效率(吞吐量/面积)的最大化,所以没有选择更高的流水线级数和展开级数。在综合比较图4-26(a)~(e)的实现效果后,迭代运算模块采用了图4-26(e)所示的2级展开、2级流水线、2级子流水线的优化方式。
图4-27是在采用简化的轮常数、新型的流水线,以及2级展开、2级流水线、2级子流水线的优化方式后SHA-3模块的结构图。优化后的SHA-3模块同样由填充模块(Padding)、迭代运算模块(Transformation Round)、控制模块(Control Unit)和截取模块(Truncating)四个部分组成,迭代运算模块具有迭代运算模块1(Transformation Round 1)和迭代运算模块2(Transformation Round 2)两个部分。
图4-27 采用简化的轮常数、新型的流水线,以及2级展开、2级流水线、2级子流水线的优化方式后SHA-3模块的结构图(优化后)
模块启动后,输入种子会经过寄存器(reg)到填充模块(Padding),数据填充完成后通过数据选择器(mux)进入迭代运算模块1(Transformation Round 1),迭代运算模块1执行迭代运算操作,模块的内部有一级子流水线寄存器(sub_reg1),位于θ2变换和θ3变换之间。在最后一步ι变换中,十二选一数据选择器(12 to 1 mux)会选择简化的偶数轮轮常数(SRC0、SRC2、…、SRC22)参与运算。运算完成后,数据会经过一级流水线寄存器(reg1)再次进入迭代运算模块2(Transformation Round 2)执行迭代运算操作。迭代运算模块2的结构和迭代运算模块1相似,唯一的不同是十二选一数据选择器会选择简化的奇数轮轮常数(SRC1、SRC3、…、SRC23)参与运算。运算完成的数据经过第二级流水线寄存器(reg2),之后通过数据分配器(dmux)和数据选择器(mux)再次进入迭代运算模块1,如此循环,直至24轮迭代运算完成,通过数据分配器(dmux)从截取模块(Truncating)得到相应输出值。