前几章从系统架构师和芯片设计者的角度讨论了低功耗设计。本章从复杂IP设计工程师的角度来描述低功耗设计,如处理器、DSP、USB、PCI Express和总线基础架构。到目前为止,我们已经假设IP是相对固定的,我们必须增加低功耗能力。现在,我们将讨论如何设计复杂的IP,以满足我们的低功耗目标。
今天,绝大多数复杂芯片都是使用IP设计的——第三方或内部开发。设计好的IP的关键是以一种允许它在多个应用程序中使用的方式来设计它。
为了确保一个IP可以在多个需要低功率的应用程序中有效地使用,我们必须设计使其能够与不同的功率策略一起使用。在一个应用程序中,时钟门控和多电压阈值库可能提供足够低的功率。对于其他应用,可能需要针对性的片上功率门控。在其他应用中,动态电压缩放可能是实现芯片功率目标的关键。
为了满足这些各种需求,我们需要做以下工作:
在我们经历IP的架构、设计和包装过程时,我们需要记住,在芯片中的IP的实际实现中,可以使用以下任何一种或所有技术:
对于某些类型的IP,可能需要对这些功能提供不同类型的支持。
内存和其他硬IP块对低功耗有特殊的要求。低功率存储器通常有各种模式:正常工作模式、保留模式和关机模式。在保留模式下,电压会降低到保留数据所需的最小值,但低于读写所需的电压。
USB或PCI Express等IO标准的物理层接口通常有较多的电源模式。除了正常工作模式之外,还可以是驱动功率接近于零的完全关闭模式。可能有一个额外的操作模式,其中足够的电路通电,以便它可以唤醒以响应其接口上的活动。
可配置的软IP,因为它可以由用户配置,所以提供了一个复杂的设计挑战,在某种意义上是硬IP的超级挑战集。对于softIP,必须以用户可配置的方式支持多种强大、易使用模式和多种节能技术。如何设计这样的IP是本章其余部分的重点。
我们以SALT芯片上包含的USB On-the-Go(OTG)IP为例。OTG核心是synopsys数字软IP核心,设计之初规划具有功率门控,但实际上从来没有添加到电源门控能力。我们修改了RTL,增加了一个电源门控控制器、保留寄存器和隔离单元。当然,今天,我们将使用UPF来描述大多数这些修改,如本章后面所述。
体系结构的一个良好的工作定义(至少在IP设计的上下游中)是IP的分区和接口设计。在支持各种低功耗策略时,功率门控提出了IP架构中最大的新架构挑战。
为支持功率门控,我们需要:
在SALT芯片上,我们包括了一个电源门控版本的CPU和USB OTG数字核心。CPU的策略是由软件控制断电顺序。当软件确定要关闭CPU时,它会向CPU电源控制器发出信号。然后控制器产生断电顺序。1个处理器被激活来响应一个中断足矣。当适当的中断发生时,例如中断源自定时器外围设备或从外部源,CPU的电源控制器然后执行所有的通电序列。
USB OTG的策略是在空闲时间内关机,但只有在CPU允许的情况下才能关机。CPU在USB OTG的寄存器中写入一个使能位来关闭电源——本质上是说它已经完成了事务。然后,USB OTG等待USB总线空闲3ms(表明USB OTG可以进入暂停( SUSPEND )模式)。当进入SUSPEND时,USB信号指示USB电源控制器开始断电顺序。足够的USB OTG,它可以响应CPU的读写或USB总线上的活动。如果CPU清除了断电使能位,或者如果在USB总线上有活动,那么控制器将执行通电顺序。
图8-1显示了USB OTG数字核的简化图。在断电期间,总线接口单元保持通电,以便它可以响应一个CPU请求来通电。类似地,PHY接口块保持通电,以便如果检测到USB活动,它可以向电源控制器发出信号并唤醒该核心。时钟和复位块也保持通电,为总线接口单元和PHY接口提供时钟。
USB OTG核心的所有其余逻辑都是电源门控的。状态和控制寄存器在电源门控序列使用由单个引脚NRETAIN控制的保留寄存器进行保存和恢复。协议引擎,因为它从头开始每个交易,只是在通电时复位。
只是为了方便起见,电源控制器包含在总线接口单元的AHB从模块中——它在AHB时钟下运行,需要在电源门控期间保持通电,并且电源门控使能寄存器也位于此处。但控制器也可以很容易地成为一个单独的块。
在USB OTG数字核心的电源门控区域中,有两个时钟域——AHB时钟域和PHY时钟域。控制信号在跨越两个时钟域时使用了同步器,包括功率门控制信号。因此,从断言一个功率门控控制信号(在ahb域中)到它可以有效作用于PHY域的时间延迟并不是确定性的。在事实中可以有很大的不同,因为这两个领域之间的时序关系在不同的应用中可以非常不同。
因此,大量的电源门控控制信号采用请求-确认握手机制。
USB OTG内的功率控制器使用`ifdef进行条件编译;如果用户不想使用功率门控,设计中的控制器将不会编译。
功率控制器是一个简单的状态机用于控制如下信号:
接收如下输入:
功率控制器检测到suspend_detected信号断言(功率门控使能位在状态寄存器中置位),则开启断电序列。该顺序如图8-2所示,描述如下:
当电源控制器看到enable_power_gating已被清除(指示CPU想要启动USB OTG)或在USB总线上检测到活动时,则电源控制器状态机启动唤醒顺序:
一旦接收到确认信号,功率控制器进入空闲状态,USB OTG恢复正常的操作。
除了实现上述功能,IP的功率控制器必须设计为可移植式,也就是说可以在多个应用以及不同的库中使用。此处主要的两个挑战为:
基本的控制功能是打开和关闭电源,打开和关闭时钟和复位,打开和关闭隔离单元,并对保留触发器发出保存/恢复命令。这些是几乎所有的电源门控设计。但特定的库可能需要不同的细节:
建议:
随着电源门控变得越来越普遍,芯片很可能会使用一个中心功率控制器来协调设计中各种电源门控块的活动。特别是,如果多个块想要同时通电,它可能需要通过块排序,一次通电一个,以限制过高电压峰值的噪声。可能需要一个中央代理来仲裁所有想要通电或断电的区块。
在前一节中描述的那种功率控制器应该能够适应这样的系统架构。用户可以将断电请求路由到中央控制器,中央控制器可以在其决定服务该请求时发出确认。对IP设计的唯一要求是,断电请求和确认信号必须在IP的顶级端口可用。
由于各种原因,需要控制IP的时钟和复位:
由于这些原因,在IP中有一个专用的时钟和重置模块越来越重要,它只处理时钟和复位,并提供了满足上述需求的灵活性。
为了为扫描测试提供最佳的可控性,我们建议功率控制器本身可以从IP外部进行控制。也就是说,一个中央的、芯片级的扫描控制器需要能够强制打开或关闭IP电源,以及强制时钟,复位、强制断电区域的保存和恢复。
在SALT芯片,我们也决定做所有扫描时钟混合到USB OTG IP外部。PHY时钟由USB PHY生成,并在向数字核心提供PHY时钟之前通过一个选择器。此mux在PHY时钟(在正常模式下使用)和扫描时钟(在扫描测试时使用)之间切换。
任何可配置IP的验证都是一个很大的挑战。这个挑战由增加电源门控带来的。
在开发USB OTG的电源门控版本时,我们最初在没有电源选通电路的情况下进行了完整的RTL功能测试。当USB OTG通过所有诊断后,我们添加了电源选通功能并重新运行诊断程序。当这些都通过后,我们运行了一组诊断程序来测试掉电功能本身。
由于电源门控功能完全独立于其他USB功能,这种方法似乎是最小化验证工作并仍然提供强验证的合适方法。
在RTL级别上,我们通过在断电期间强制寄存器输出到“X”来仿真电源开关结构。这种方法允许我们在RTL级别上完全验证核心。但是由于电源门控与开关结构的物理实现紧密相连,我们也对断电功能进行了广泛的门级仿真。这允许我们为开关结构使用详细的模型,包括完全通电或断电所需的时间。
SALT芯片是在UPF可用之前开发的,UPF可以提供指定IP块功率策略的方便方法。随着UPF的引入,在IP的最终打包中包含电源策略变得更加简单。
任何IP都需要以允许用户配置其应用程序的方式打包IP。这通常是使用配置工具来完成的。对于软IP,最终的包装包括:
对于支持电源门控的核心,我们需要添加:
图8-3显示了USB数字核心OTG更详细的框图。在最初的SALT芯片中,我们必须在RTL中直接添加保留、隔离和电源开关。通过引入UPF,我们可以使用UPF tel命令来描述这种功能兼容性。
请注意,电源控制块仍然必须在RTL中设计,并在设计中实例化。
添加电源门控、保留和隔离的UPF代码如下所示。块名称otg(核心的顶层)、biu、mac等是RTL中这些模块实例的名称。
为了使UPF代码可移植,我们使用一个变量($otg)来指示从设计的顶部到RTL中核心的顶层的实际路径。我们还使用变量描述了VDD和VSS电源网的起源。这些很可能是在芯片的顶层。
set_scope $otg
create_power_domain otg_power_domain
-elements {aiu pfc mac sync csr}
create_supply_net switched_VDD
-domain otg_power_domain
set_domain_supply_net otg_power_domain
-primary_power_net switched_VDD
-primary_ground_net /$top_VSS
create_power_switch power_switch
-domain otg_power_domain
-input_supply_port {sw_input_port /$top_VDD}
-output_supply_port {sw_output_port switched_VDD}
-control_port {sw_control_port biu/pwr_dwn_req_n}
-ack_port {pwr_ack_port biu/pwr_dwn_ack_n}
-on_state {pwr_on_state sw_input_port
{sw_control_port ==1}}
-off_state {pwr_off_state {sw_control_port ==0}}
set_isolation otg_isolation -domain otg_power_domain
-isolation_power_net $top_VDD
-clamp_value 0
set_isolation_control otg_isolation
-domain otg_power_domain
-isolation_signal biu/bius_pwr_clamp
set_retention otg_retention
-domain otg_power_domain
-retention_power_net $top_VDD
set_retention_control otg_retention
-domain otg_power_domain
-save_signal {biu/retain_n negedge}
-restore_signal {biu/retain_n posedge}
下面的代码作为一个简单的电源控制器状态机的示例。它被编码为分层状态机——我们发现这种格式非常有用,尤其是在更复杂的状态机中。
//====================================================
//
//
// (C) Copyright 2004-2005, Synopsys, Inc.
// ALL RIGHTS RESERVED
//
//
// Filename : optc_sm.v
// Author : Mike Keating
// Date : November 28, 2005
// Version : 1.0
// Description : This Module implements state machine
// part of power down control logic for
// OTG
//
//====================================================
//====================================================
reg [2:0] main_state;
parameter TOP_IDLE= 3'd0;
parameter SLEEP= 3'd1;
parameter WAKEUP= 3'd2;
parameter FLUSH_FIFO=3'd3;
reg [2:0] SLEEP_state;
parameter SLEEP_IDLE=3'd0;
parameter CLAMP= 3'd1;
parameter SAVE = 3'd2;
parameter PWR_DOWN= 3'd3;
parameter CLOCKS_OFF=3'd4;
parameter SLEEP_DONE=3'd5;
parameter RESET_PDN =3'd6;
reg [2:0] WAKEUP_state;
parameter WAKEUP_IDLE=3'd0;
parameter WAKEUP_DONE=3'd1;
parameter PWR_UP= 3'd2;
parameter CLAMPS_OFF=3'd3;
parameter RESTORE= 3'd4;
parameter CLOCKS_ON=3'd5;
parameter RESET_OFF=3'd6;
always @ ( posedge hclk or negedge hreset_n ) begin
if (!hreset_n) begin
bius_pwr_reset_n <= 1'b1;
pwr_clamp_n_tmp <= 1'b1;
bius_pwr_clamp_n_tmp <= 1'b1;
h2pl_pwr_clamp_n_tmp <= 1'b1;
bius_pwr_clamp_tmp <= 1'b0;
bius_gate_hclk_tmp <= 1'b0;
h2pd_stop_pclk <= 1'b0;
retain_n <= 1'b1;
pwr_dwn_req_n <= 1'b1;
main_state <= TOP_IDLE;
SLEEP_state <= SLEEP_IDLE;
WAKEUP_state <= WAKEUP_IDLE;
end else begin
case (main_state)
TOP_IDLE: begin
if (suspend_detected_interrupt &&
enable_power_gating)
begin
main_state <= FLUSH_FIFO;
end
end
SLEEP: begin
sleep;
if (SLEEP_state == SLEEP_DONE &&
(sp2ht_wkup_res_det_biu ||
!enable_power_gating ))
begin
main_state <= WAKEUP;
SLEEP_state <= SLEEP_IDLE;
end
end
WAKEUP: begin
wakeup;
if (WAKEUP_state == WAKEUP_DONE)
begin
main_state <= TOP_IDLE;
WAKEUP_state <= WAKEUP_IDLE;
end
end
FLUSH_FIFO: begin
if (fifo_flushed)
begin
main_state <= SLEEP;
end
end
endcase
end
end
//-------------------------------------------------
// sleep_task
//-------------------------------------------------
task sleep;
case (SLEEP_state)
SLEEP_IDLE: SLEEP_state <= CLAMP;
CLAMP: begin
pwr_clamp_n_tmp <= 1'b0;
bius_pwr_clamp_n_tmp <= 1'b0;
h2pl_pwr_clamp_n_tmp <= 1'b0;
bius_pwr_clamp_tmp <= 1'b1;
if (pwr_clamp_ack_sync==1)
SLEEP_state <= CLOCKS_OFF;
end
CLOCKS_OFF: begin
bius_gate_hclk_tmp <= 1'b1;
h2pd_stop_pclk <= 1'b1;
if (stop_pclk_ack_sync==1)
begin
SLEEP_state <= SAVE;
retain_n <= 1'b0;
end
end
SAVE: SLEEP_state <= RESET_PDN;
RESET_PDN: begin
bius_pwr_reset_n <= 1'b0;
SLEEP_state <= PWR_DOWN;
end
PWR_DOWN: begin
pwr_dwn_req_n <= 1'b0;
if (!pwr_dwn_ack_sync_n)
SLEEP_state <= SLEEP_DONE;
end
SLEEP_DONE:
endcase
endtask
//-------------------------------------------
// wakeup_task
//-------------------------------------------
task wakeup;
case (WAKEUP_state)
WAKEUP_IDLE: WAKEUP_state <= PWR_UP;
PWR_UP: begin
pwr_dwn_req_n <= 1'b1;
if (pwr_dwn_ack_sync_n==1'b1)
WAKEUP_state <= RESET_OFF;
end
RESET_OFF: begin
bius_pwr_reset_n <= 1'b1;
WAKEUP_state <= RESTORE;
end
RESTORE: begin
retain_n <= 1'b1;
WAKEUP_state <= CLOCKS_ON;
end
CLOCKS_ON: begin
bius_gate_hclk_tmp <= 1'b0;
h2pd_stop_pclk <= 1'b0;
if (stop_pclk_ack_sync==0)
WAKEUP_state <= CLAMPS_OFF;
end
CLAMPS_OFF: begin
pwr_clamp_n_tmp <= 1'b1;
bius_pwr_clamp_n_tmp <= 1'b1;
h2pl_pwr_clamp_n_tmp <= 1'b1;
bius_pwr_clamp_tmp <= 1'b0;
if (pwr_clamp_ack_sync==0)
WAKEUP_state <= WAKEUP_DONE;
end
WAKEUP_DONE:
endcase
endtask
图8-4显示了顶层状态机。符号是UML2.0中使用的状态图符号。我们发现这种格式比传统的气泡图更有用。
下图所示为SLEEP和WAKEUP状态的细节:
第八章结束~