二、RTL级低功耗设计
前面介绍了系统级的低功耗设计,换句话说就是在系统级降低功耗可以考虑的方面。系统级的低功耗设计,主要是由系统级设计、具有丰富经验的人员实现,虽然还轮不到我们设计,我们了解一下还是比较好的。我们前端设计人员的重点不在系统级设计上面,而是在RTL级(及综合)上面。下面我们就来介绍RTL编码与逻辑综合的低功耗设计,重点是门控时钟和操作数隔离技术。今天主要是讲解操作数和一些常见的方法;门控时钟由于内容比较多,所以写在后面。
(1)并行与流水的选择
对于某一个功能模块,我们可以通过并行的方式进行实现,也可以通过流水线的方式进行实现,这两种方法都是面积换速度,不过在一定的场合下可以降低功耗,需要灵活应用,下面就简要地介绍一下这两种方法(的使用)。
·并行处理常用于数字信号处理部分。采用并行处理,可以降低系统工作频率,从而可能降低功耗。例如下图中:
用两个乘法器来取代原设计中的一个乘法器。这样,时钟频率可以降低,系统的整体功耗会降低。采用这种方法,要在增加的面积与节省的功耗之间进行权衡。
·流水线技术可以将一个较长的组合路径分成M级流水线。路径长度缩短为原始路径长度的1 /M。这样,一个时钟周期内充/放电电容变为C/M。如果在加入流水线之后,时钟速度不变,则在一个周期内,只需要对C/M进行充/放电,而不是原来对C进行充/放电。因此,在相同的速度要求下,可以采用较低的电源电压来驱动系统。这样,系统的整体功耗可能会降低。例如对于下面的流水线设计:
假设在一个设计中,关键路径是一个32bit X 32bit的乘法器。假设该乘法器的整体电容为C,工作频率为f。
->不加流水线时,要达到此工作频率,工作电压应该为V。
->当采用流水线方式时,该路径被分成两部分。对于每一部分,整体电容变为C/2。这样,如果要达到原来的工作频率f,工作电压可以降为βV,这里β<1. 因此,整个系统可以工作在βV电压下,整体功耗变为原来的β^2倍,即:
(2)资源共享与状态编码
对于设计比较多算术运算的设计,如果有同样的操作在多处使用,那我们就可以避免相应的运算逻辑在多个位置重复出现。例如下面是没有进行共享资源的代码:
进行资源共享后的代码如下所示:
上述代码中,在各分支中只使用一个比较器和一个算术比较器就可以实现相同的功能,因此极大地减少了功耗。
此外,对于一些变化非常频繁的信号,我们利用数据编码来降低开关活动(例如,用格雷码比用二进制码翻转更少,功耗更低)。
(3)操作数隔离
下面我们重点介绍另外一种常用的方法——操作数隔离(operand isolation,简称OI)的方法。
①操作数隔离的原理
我们先来看一个电路,如下所示:
上面的电路图中,当SEL_0≠1,SEL_1≠0时,加法器Add_0的运算结果并不能通过mux_0和mux_1到达寄存器reg_0的输入端口,也就是说寄存器reg_0将不会保存加法器Add_0的运算结果,这就意味着加法器Add_0的运算是不必要的。为了节省功耗,我们可以用操作数分离的方法,在某些条件下,使加法器不工作,保持静态,进行操作隔离之后的电路如下所示:
因此,操作数隔离的原理就是:如果在某一段时间内,数据通路的输出是无用的,则将它的输入置成个固定值,这样,数据通路部分没有翻转,功耗就会降低。
下面我们再举一个例子,对于下面的电路:
上图所示的乘法器中,如果知道乘法操作延迟超过半个时钟周期,则将乘法器的输出与反相时钟进行与操作,可以保证在时钟前半周期乘法器的输出不会导致加法器的翻转。这就是操作数隔离技术的基本思想。不过需要注意的是,采用这种方法,会增加面积,并影响到DFT,所以在使用前应该对它的利弊进行权衡。
②OI的物体选择
OI并不是什么时候都可以进行使用的(也就是说不是所有的对象(物体)都符合操作数隔离的要求)。此外操作数隔离主要是:满足一定条件下,通过指定操作数隔离的物体来实现的;指定操作数隔离的物体可以通过EDA工具自动执行(我们一般使用这种方法),也可以通过我们手动进行。下面我们就分别介绍一下这两种方式。
·EDA工具自动指定操作数隔离的物体
默认情况下,如果操作数隔离的物体满足下列条件,Power Compiler自动选择它(们):
1.OI物体是算术运算器或层次组合单元。
2.OI物体的输出是选择性地使用。
3.运算器必须有非零的翻转率。
4.仅当工具进行功耗估算后,用操作数隔离具有潜在的功耗可节省,才把它(们)作为OI物体。
自动进行操作数隔离的脚本如下:
set do_operand_isolation true
set_operand_isolation_style
read_saif
……
compile
·手动指定操作数隔离的物体
除了使用EDA工具自动选择IO物体,我们也可以手动进行指定,然后进行操作数隔离。手动完成操作数隔离大致可以分为两步:
A:设定操作数隔离的风格为手动(用户自定义模式):
在约束脚本中加入下面的命令,说明是使用手动的方式指定IO物体:
set_operand_isolation_style -user_directives
B:手动指定IO物体:
手动指定IO物体有下面两种方式:
1.用命令指定OI物体:set_opreand_isolation_cell,例如:
set_operand_isolation_cell [get_cells U1]
2.在RTL代码中加综合指引(pragma)
例如:下面的RTL中加入了综合指令“//synopsys_isolate_operands":
if(c2 == 1’b1)
o = a + b ;
else
o = c + d ; //synopsys_isolate_operands
完成前面A、B两步的设置之后,在使用compile命令进行综合时,如果手动指定的IO物体满足前面的三点:
1.OI物体是算术运算器或层次组合单元。
2.OI物体的输出是选择性地使用。
3.运算器必须有非零的翻转率。
那么综合器就会进行操作数隔离。
③操作数隔离的范围
有些时候,我们需要在整个设计中指定某些模块要做操作数隔离,某些模块不要做操作数隔离。这时候我就可以使用set_operand_isolation_scope命令来实现了。例如下面的分层模块中:
我们只对SUB2模块中的操作数做隔离,其他的模块不做操作数隔离,那么就可以使用下面的示例脚本:
set_operand_isolation_scope [get_designs tops] false
set_operand_isolation_scope [get_designs sub1] false
set_operand_isolation_style
······
④隔离逻辑的设置
实现操作数隔离需要插入相应的隔离逻辑,比如与门或者或门之类的。这些逻辑可以由EDA自动选择,也可以由我们自己手动指定。下面就来介绍这两种方式。
·默认的EDA工具选择
默认情况下,隔离逻辑由工具自动选择。工具根据输入数据连线的静态概率(SP)来选择适合的隔离逻辑为“AND'’门或“OR”门。使用的命令如下所示:
set_operand_isolation_style -logic adaptive
如果SP > 0.5,选择“OR”门作为隔离逻辑
如果SP < 0.5,选择“AND”门作为隔离逻辑
·手动
我们可以手工地选择隔离逻辑,例如下面命令指定用“AND”门作为隔离逻辑:
set_operand_isolation_style -logic AND
通过前面的描述,我们知道操作隔离的实现可以通过EDA全自动化实现,也可以通过我们指定OI物体的半自动化实现。完成操作数隔离后,我们可以用命令报告设计中的操作数隔离,例如:
report -operand_isolation -isolated -verb命令显示如下的信息:
⑤操作数隔离的复原
加入隔离逻辑之后,如果时序变差达到不能满足要求的情况,我们就要复原原来的逻辑。复原的方法也是有自动和手动的方法。
·自动
一般情况下,如果加了隔离逻辑后,设计的时序变差了,即当WNS(worst negative slack)大于指定的slack时,EDA工具会使设计自动复原到原来没有操作数隔离的状态。例如下面的脚本适用于如果WNS大于0. 5时,设计自动复原到原来的状态:
set_operand_isolation_slack 0.5
compile
compile -inc
·手动
我们也可以用手工的方法复原操作数隔离。用手工的方法进行操作数隔离的复原是在指定的时序路径上删除OI逻辑。这时候不考虑slack。需要执行增量编辑去删除OI逻辑。脚本如下:
remove_operand_isolation -from <starting_point> to <end_point>
compile -inc
······
最后,提供一个完整的加入操作数隔离的示例脚本,如下所示,使用了默认的隔离逻辑类型和操作数隔离的自动恢复:
set do_operand_isolation true
read_verilog mydesign.v
current_design top
link
create_clock -p 10 [get_ports clk]
set_operand_isolation_style
set_operand_isolation -slack 0.1
compile
report_operand_isolation -verb -isolated
······