Why Learn Multi-Voltage Design? Operating different blocks at optimized voltage levels enables significant power savings—high-voltage for performance-critical paths, low-voltage for non-critical logic. Multi-voltage design can reduce power by 30-50% compared to single-voltage implementations, making it essential for battery-powered and thermally-constrained systems. In this tutorial, you'll master level shifter requirements and multi-voltage UPF specifications.

15 min read | Intermediate Level

What You'll Learn

  • Understand multi-voltage design concepts and power benefits
  • Identify when level shifters are required at voltage boundaries
  • Define level shifter strategies using set_level_shifter
  • Implement voltage area planning in UPF

Understanding Multi-Voltage Design

Multi-voltage design partitions a chip into voltage domains, where different functional blocks operate at different supply voltages. This exploits the quadratic relationship between power and voltage (P ∝ V²) to optimize power consumption.

Power Savings from Voltage Scaling

Dynamic power has a quadratic dependence on supply voltage:

P_dynamic = α × C × V_dd² × f

Reducing voltage from 1.2V to 1.0V (17% reduction) yields:

Power_ratio = (1.0/1.2)² = 0.69

Power savings = 31%

This dramatic power reduction motivates multi-voltage design, despite the added complexity.

While voltage scaling reduces dynamic power quadratically, it also increases delay (slower switching). Multi-voltage design assigns high voltage to speed-critical blocks and low voltage to non-critical blocks, optimizing power without sacrificing performance on critical paths.

Multi-Voltage in Practice

A typical mobile SoC might use: 1.2V for high-speed CPU cores and memory interfaces (performance-critical), 1.0V for GPU and DSP (moderate speed), 0.9V for peripheral controllers (low-speed), and 1.8V for I/O pads (compatibility with external devices). This voltage partitioning can reduce overall chip power by 30-40% compared to running everything at the highest required voltage (1.8V).

Voltage Domain Boundaries

When signals cross between voltage domains, special handling is required.

The Level Shifting Problem

Consider a signal crossing from 1.0V domain to 1.2V domain:

Low-Voltage Domain (1.0V)        High-Voltage Domain (1.2V)
┌────────────────┐               ┌────────────────┐
│  Logic         │               │  Logic         │
│  VDD = 1.0V    │──────────────>│  VDD = 1.2V    │
│  VOH = ~1.0V   │  Signal=1.0V  │  Expects 1.2V  │
└────────────────┘               └────────────────┘

The receiving logic expects VOH (logic high output voltage) ≈ 1.2V, but gets only 1.0V. This can cause:

  • Logic errors: 1.0V may not register as valid logic '1' in 1.2V domain
  • Increased delay: Weak drive strength slows transitions
  • Shoot-through current: Both PMOS and NMOS partially on simultaneously

Directly connecting domains at different voltages without level shifters can cause functional failures, timing violations, and excessive power consumption due to shoot-through current. Level shifters are mandatory at voltage boundaries.

Quick Check

Q: Why don't signals from high-voltage to low-voltage domains have the same problem?

Show Answer

High-to-low transitions (e.g., 1.2V → 1.0V) are safer but still problematic. A 1.2V signal entering a 1.0V domain exceeds the gate oxide voltage rating, potentially causing oxide stress and reliability issues. Level shifters are required in both directions for safe operation, though the failure mechanisms differ (logic errors for low-to-high, reliability for high-to-low).

Level Shifter Fundamentals

A level shifter is a special circuit that translates signals between voltage domains while maintaining correct logic levels.

Level Shifter Types

TypeDirectionCharacteristics
Low-to-High (LH)0.9V → 1.2VConverts low-voltage signals to high-voltage
High-to-Low (HL)1.2V → 0.9VConverts high-voltage signals to low-voltage
BidirectionalBoth directionsUsed for bidirectional buses (less common)

When Level Shifters Are Required

  • Different VDD levels: Any signal crossing between domains with different supply voltages
  • Both directions: Low-to-high AND high-to-low crossings need shifters
  • All signal types: Data, control, clock signals all require level shifting

Exception: Signals within the same voltage domain never need level shifters, even if they cross power domain boundaries (e.g., two domains both at 1.0V).

Level shifter delay is typically 2-5× that of a regular buffer. Place shifters carefully to minimize impact on critical timing paths, and account for shifter delay in timing analysis.

Multi-Voltage UPF Example

Let's create a complete multi-voltage design with three voltage levels.


# ===================================================================
# Three-Voltage SoC: 1.2V / 1.0V / 1.8V
# ===================================================================

# TOP DOMAIN: 1.2V (control logic)
create_power_domain PD_TOP -include_scope
create_supply_net VDD_1V2 -domain PD_TOP
create_supply_net VSS -domain PD_TOP

create_supply_set SS_1V2 \
  -function {power VDD_1V2} \
  -function {ground VSS}
associate_supply_set SS_1V2 -handle PD_TOP

add_power_state VDD_1V2 -state {ON 1.2}
add_power_state VSS -state {ON 0.0}

# CPU DOMAIN: 1.0V (power-optimized)
create_power_domain PD_CPU -elements {cpu_subsystem}
create_supply_net VDD_1V0 -domain PD_CPU
create_supply_net VSS -domain PD_CPU

create_supply_set SS_1V0 \
  -function {power VDD_1V0} \
  -function {ground VSS}
associate_supply_set SS_1V0 -handle PD_CPU

add_power_state VDD_1V0 -state {ACTIVE 1.0}

# I/O DOMAIN: 1.8V (external interface)
create_power_domain PD_IO -elements {io_subsystem}
create_supply_net VDD_1V8 -domain PD_IO
create_supply_net VSS -domain PD_IO

create_supply_set SS_1V8 \
  -function {power VDD_1V8} \
  -function {ground VSS}
associate_supply_set SS_1V8 -handle PD_IO

add_power_state VDD_1V8 -state {ON 1.8}

# ===================================================================
# Voltage Boundaries:
# - TOP (1.2V) ↔ CPU (1.0V): Level shifters required
# - TOP (1.2V) ↔ I/O (1.8V): Level shifters required
# - CPU (1.0V) ↔ I/O (1.8V): Level shifters required (if signals cross)
# ===================================================================

This structure creates three voltage islands. Any signal crossing between these domains requires a level shifter.

Voltage Planning Strategy

When planning voltage domains, group blocks by speed requirement: High-speed blocks (CPU cores, memory interfaces) get high voltage for performance. Medium-speed blocks (GPU, peripherals) use moderate voltage. Low-speed blocks (timers, power management) use low voltage for maximum power savings. I/O domains match external interface standards (1.8V, 3.3V). This strategic voltage assignment optimizes the performance-power tradeoff.

Syntax: set_level_shifter

The set_level_shifter command defines level shifter requirements at voltage domain boundaries.

Basic Form


set_level_shifter strategy_name -domain domain_name \
  -applies_to {inputs|outputs|both} \
  [options]

Key Parameters

  • strategy_name - Unique identifier for the level shifter strategy (required)
  • -domain domain_name - Domain where shifters are applied (required)
  • -applies_to {inputs|outputs|both} - Which signals get shifters (required)
  • -location {self|parent|fanout|automatic} - Where shifters are placed
  • -threshold voltage - Voltage difference threshold for shifter insertion
  • -rule {low_to_high|high_to_low|both} - Which voltage transitions need shifters

Usage Variations

1. Basic Level Shifter (All Outputs):


set_level_shifter LS_CPU -domain PD_CPU \
  -applies_to outputs \
  -location self

2. Bidirectional Level Shifters:


set_level_shifter LS_IO -domain PD_IO \
  -applies_to both \
  -location automatic

3. Threshold-Based (Only Insert if ΔV > threshold):


set_level_shifter LS_CONDITIONAL -domain PD_GPU \
  -applies_to outputs \
  -threshold 0.2 \    # Only if voltage difference > 0.2V
  -location self

Level Shifter Placement Strategies

The -location option controls where level shifters are physically placed.

Location Options

LocationPlacementUse Case
selfInside source domainPlace shifters at output of source domain
parentIn parent domainPlace shifters outside source domain boundary
fanoutAt each sinkOne shifter per receiving instance (high fanout)
automaticTool decidesLet synthesis tool choose optimal location

Self Location (Most Common)


# Place level shifters at PD_CPU outputs (inside CPU domain)
set_level_shifter LS_CPU_OUT -domain PD_CPU \
  -applies_to outputs \
  -location self
PD_CPU (1.0V)                     PD_TOP (1.2V)
┌─────────────────────┐           ┌────────────┐
│  Logic              │           │            │
│  ↓                  │           │            │
│  [Level Shifter] ───┼──────────>│  Logic     │
│  (placed at edge)   │  1.2V     │            │
└─────────────────────┘           └────────────┘

Parent Location


# Place level shifters in parent domain (outside CPU)
set_level_shifter LS_CPU_OUT -domain PD_CPU \
  -applies_to outputs \
  -location parent
PD_CPU (1.0V)            PD_TOP (1.2V)
┌──────────────┐         ┌───────────────────────┐
│  Logic    ───┼────────>│  [Level Shifter]      │
│              │  1.0V   │  ↓                    │
└──────────────┘         │  Logic (receives 1.2V)│
                         └───────────────────────┘

Use -location self by default—it's clearer for physical design and keeps voltage translation within the domain boundary. Use -location automatic if synthesis tools have better placement heuristics for your design.

Defining Level Shifters for Multiple Domains

Each domain with voltage differences requires level shifter strategies.


# ===================================================================
# Level Shifter Strategies for Multi-Voltage SoC
# ===================================================================

# CPU outputs (1.0V → 1.2V) going to top domain
set_level_shifter LS_CPU_OUT -domain PD_CPU \
  -applies_to outputs \
  -location self

# CPU inputs (1.2V → 1.0V) coming from top domain
set_level_shifter LS_CPU_IN -domain PD_CPU \
  -applies_to inputs \
  -location parent

# I/O outputs (1.8V → 1.2V) going to top domain
set_level_shifter LS_IO_OUT -domain PD_IO \
  -applies_to outputs \
  -location self

# I/O inputs (1.2V → 1.8V) coming from top domain
set_level_shifter LS_IO_IN -domain PD_IO \
  -applies_to inputs \
  -location parent

# ===================================================================
# Result:
# - All voltage crossings have level shifters
# - Outputs shift at source domain (self)
# - Inputs shift at parent domain
# ===================================================================

Quick Check

Q: If two domains both operate at 1.0V (same voltage), do signals crossing between them need level shifters?

Show Answer

No. Level shifters are only required when signals cross between different voltage levels. Two domains at the same voltage (both 1.0V) can communicate directly without level shifters, even if they are separate power domains (e.g., one is power-gated and the other is always-on). However, isolation may still be needed if one domain can be powered off.

Mapping Level Shifters to Library Cells

UPF level shifter strategies must be mapped to physical library cells during synthesis.

Syntax: map_level_shifter_cell


map_level_shifter_cell strategy_name -domain domain_name \
  -lib_cells {cell_list}

Example


# Map CPU output level shifters to library cell
map_level_shifter_cell LS_CPU_OUT -domain PD_CPU \
  -lib_cells {LS_LH_1V0_1V2}    # Low-to-High: 1.0V → 1.2V

# Map CPU input level shifters to library cell
map_level_shifter_cell LS_CPU_IN -domain PD_CPU \
  -lib_cells {LS_HL_1V2_1V0}    # High-to-Low: 1.2V → 1.0V

The -lib_cells specifies which level shifter cells from your technology library to use. Different cells are needed for:

  • Low-to-high vs high-to-low conversion
  • Different voltage combinations (1.0V→1.2V vs 0.9V→1.8V)
  • Different drive strengths (X1, X2, X4)

Level shifter cell names are technology-specific and come from your standard cell library. Consult your library documentation for available level shifter cells and their voltage ranges. Common naming: LS_LH (low-to-high), LS_HL (high-to-low), followed by voltage levels.

Voltage Threshold for Conditional Level Shifting

The -threshold option controls when level shifters are inserted based on voltage difference.


# Only insert level shifters if voltage difference > 0.2V
set_level_shifter LS_CONDITIONAL -domain PD_GPU \
  -applies_to outputs \
  -threshold 0.2 \
  -location self

Example: Three Voltage Levels with Threshold

From DomainTo DomainΔVThreshold 0.2VShifter Needed?
1.0V1.1V0.1VBelow thresholdNo (direct connection)
1.0V1.2V0.2VAt thresholdYes
1.0V1.8V0.8VAbove thresholdYes

Using threshold-based level shifting is risky. Small voltage differences (0.1-0.2V) may seem safe but can still cause timing issues, shoot-through current, and reliability concerns. Recommended practice: Use level shifters for any voltage difference, or set a very conservative threshold (e.g., 0.05V).

Complete Multi-Voltage Example with Level Shifters


# ===================================================================
# Complete Multi-Voltage Design with Level Shifters
# ===================================================================

# TOP DOMAIN: 1.2V (always-on control)
create_power_domain PD_TOP -include_scope
create_supply_net VDD_1V2 -domain PD_TOP
create_supply_net VSS -domain PD_TOP

create_supply_set SS_1V2 \
  -function {power VDD_1V2} \
  -function {ground VSS}
associate_supply_set SS_1V2 -handle PD_TOP

add_power_state VDD_1V2 -state {ON 1.2}

# CPU DOMAIN: 1.0V (power-optimized)
create_power_domain PD_CPU -elements {cpu_inst}
create_supply_net VDD_1V0 -domain PD_CPU
create_supply_net VSS -domain PD_CPU

create_supply_set SS_1V0 \
  -function {power VDD_1V0} \
  -function {ground VSS}
associate_supply_set SS_1V0 -handle PD_CPU

add_power_state VDD_1V0 -state {ACTIVE 1.0}

# GPU DOMAIN: 0.9V (maximum power savings)
create_power_domain PD_GPU -elements {gpu_inst}
create_supply_net VDD_0V9 -domain PD_GPU
create_supply_net VSS -domain PD_GPU

create_supply_set SS_0V9 \
  -function {power VDD_0V9} \
  -function {ground VSS}
associate_supply_set SS_0V9 -handle PD_GPU

add_power_state VDD_0V9 -state {ACTIVE 0.9}

# I/O DOMAIN: 1.8V (external interface)
create_power_domain PD_IO -elements {io_pads}
create_supply_net VDD_1V8 -domain PD_IO
create_supply_net VSS -domain PD_IO

create_supply_set SS_1V8 \
  -function {power VDD_1V8} \
  -function {ground VSS}
associate_supply_set SS_1V8 -handle PD_IO

add_power_state VDD_1V8 -state {ON 1.8}

# ===================================================================
# LEVEL SHIFTER STRATEGIES
# ===================================================================

# CPU ↔ TOP (1.0V ↔ 1.2V)
set_level_shifter LS_CPU_OUT -domain PD_CPU \
  -applies_to outputs \
  -location self

set_level_shifter LS_CPU_IN -domain PD_CPU \
  -applies_to inputs \
  -location parent

# GPU ↔ TOP (0.9V ↔ 1.2V)
set_level_shifter LS_GPU_OUT -domain PD_GPU \
  -applies_to outputs \
  -location self

set_level_shifter LS_GPU_IN -domain PD_GPU \
  -applies_to inputs \
  -location parent

# I/O ↔ TOP (1.8V ↔ 1.2V)
set_level_shifter LS_IO_OUT -domain PD_IO \
  -applies_to outputs \
  -location self

set_level_shifter LS_IO_IN -domain PD_IO \
  -applies_to inputs \
  -location parent

# ===================================================================
# MAP TO LIBRARY CELLS (technology-specific)
# ===================================================================

# CPU level shifters
map_level_shifter_cell LS_CPU_OUT -domain PD_CPU \
  -lib_cells {LS_LH_1V0_1V2_X1 LS_LH_1V0_1V2_X2}

map_level_shifter_cell LS_CPU_IN -domain PD_CPU \
  -lib_cells {LS_HL_1V2_1V0_X1 LS_HL_1V2_1V0_X2}

# GPU level shifters
map_level_shifter_cell LS_GPU_OUT -domain PD_GPU \
  -lib_cells {LS_LH_0V9_1V2_X1 LS_LH_0V9_1V2_X2}

map_level_shifter_cell LS_GPU_IN -domain PD_GPU \
  -lib_cells {LS_HL_1V2_0V9_X1 LS_HL_1V2_0V9_X2}

# I/O level shifters
map_level_shifter_cell LS_IO_OUT -domain PD_IO \
  -lib_cells {LS_HL_1V8_1V2_X1 LS_HL_1V8_1V2_X2}

map_level_shifter_cell LS_IO_IN -domain PD_IO \
  -lib_cells {LS_LH_1V2_1V8_X1 LS_LH_1V2_1V8_X2}

# ===================================================================
# Power Savings Analysis:
# - CPU at 1.0V vs 1.2V: 31% power reduction (dynamic)
# - GPU at 0.9V vs 1.2V: 44% power reduction (dynamic)
# - Overall chip power reduction: ~30-40% (depends on mix)
# ===================================================================

Common Beginner Mistakes

Mistake #1: Defining level shifters only for outputs, forgetting inputs


# INCOMPLETE: Only outputs have shifters
set_level_shifter LS_CPU -domain PD_CPU \
  -applies_to outputs \
  -location self

# COMPLETE: Both directions need shifters
set_level_shifter LS_CPU_OUT -domain PD_CPU \
  -applies_to outputs \
  -location self

set_level_shifter LS_CPU_IN -domain PD_CPU \
  -applies_to inputs \
  -location parent

Why? Voltage boundaries require level shifting in both directions. Signals going out (outputs) and coming in (inputs) both cross voltage thresholds.

Mistake #2: Assuming same-voltage domains don't need any special handling

Clarification: While same-voltage domains don't need level shifters, they may still need isolation if one can be power-gated. Level shifters handle voltage differences; isolation handles power-off conditions.

Mistake #3: Not mapping level shifter strategies to library cells


# INCOMPLETE: Strategy defined but not mapped
set_level_shifter LS_CPU_OUT -domain PD_CPU \
  -applies_to outputs \
  -location self

# COMPLETE: Add library cell mapping
map_level_shifter_cell LS_CPU_OUT -domain PD_CPU \
  -lib_cells {LS_LH_1V0_1V2_X1}

Why? UPF strategies are abstract. Synthesis needs map_level_shifter_cell to know which physical library cells to use for implementation.

Practice Exercise

Challenge: Multi-Voltage SoC with Level Shifters

Create a multi-voltage design with the following specifications:

  • PD_CORE: High-speed CPU at 1.2V
  • PD_CACHE: L2 cache at 1.0V (power-optimized)
  • PD_PERIPH: Peripherals at 0.9V (low-power)

All domains communicate, requiring level shifters between each pair. Write complete UPF including domains, supplies, states, and level shifter strategies with library cell mappings.

Hint

You need 3 domains, 3 supply nets (VDD_1V2, VDD_1V0, VDD_0V9), and 6 level shifter strategies (inputs + outputs for each domain). Map shifters to appropriate library cells for each voltage transition.

Solution

# ===================================================================
# Multi-Voltage SoC Exercise Solution
# ===================================================================

# CORE DOMAIN: 1.2V (high-speed)
create_power_domain PD_CORE -include_scope
create_supply_net VDD_1V2 -domain PD_CORE
create_supply_net VSS -domain PD_CORE

create_supply_set SS_1V2 \
  -function {power VDD_1V2} \
  -function {ground VSS}
associate_supply_set SS_1V2 -handle PD_CORE

add_power_state VDD_1V2 -state {ON 1.2}
add_power_state VSS -state {ON 0.0}

# CACHE DOMAIN: 1.0V (power-optimized)
create_power_domain PD_CACHE -elements {l2_cache}
create_supply_net VDD_1V0 -domain PD_CACHE
create_supply_net VSS -domain PD_CACHE

create_supply_set SS_1V0 \
  -function {power VDD_1V0} \
  -function {ground VSS}
associate_supply_set SS_1V0 -handle PD_CACHE

add_power_state VDD_1V0 -state {ACTIVE 1.0}

# PERIPHERAL DOMAIN: 0.9V (low-power)
create_power_domain PD_PERIPH -elements {periph_subsystem}
create_supply_net VDD_0V9 -domain PD_PERIPH
create_supply_net VSS -domain PD_PERIPH

create_supply_set SS_0V9 \
  -function {power VDD_0V9} \
  -function {ground VSS}
associate_supply_set SS_0V9 -handle PD_PERIPH

add_power_state VDD_0V9 -state {ACTIVE 0.9}

# LEVEL SHIFTER STRATEGIES

# CACHE level shifters (1.0V ↔ 1.2V with CORE)
set_level_shifter LS_CACHE_OUT -domain PD_CACHE \
  -applies_to outputs \
  -location self

set_level_shifter LS_CACHE_IN -domain PD_CACHE \
  -applies_to inputs \
  -location parent

# PERIPHERAL level shifters (0.9V ↔ 1.2V with CORE)
set_level_shifter LS_PERIPH_OUT -domain PD_PERIPH \
  -applies_to outputs \
  -location self

set_level_shifter LS_PERIPH_IN -domain PD_PERIPH \
  -applies_to inputs \
  -location parent

# LIBRARY CELL MAPPING

# Cache shifters (1.0V ↔ 1.2V)
map_level_shifter_cell LS_CACHE_OUT -domain PD_CACHE \
  -lib_cells {LS_LH_1V0_1V2_X1 LS_LH_1V0_1V2_X2}

map_level_shifter_cell LS_CACHE_IN -domain PD_CACHE \
  -lib_cells {LS_HL_1V2_1V0_X1 LS_HL_1V2_1V0_X2}

# Peripheral shifters (0.9V ↔ 1.2V)
map_level_shifter_cell LS_PERIPH_OUT -domain PD_PERIPH \
  -lib_cells {LS_LH_0V9_1V2_X1 LS_LH_0V9_1V2_X2}

map_level_shifter_cell LS_PERIPH_IN -domain PD_PERIPH \
  -lib_cells {LS_HL_1V2_0V9_X1 LS_HL_1V2_0V9_X2}

# ===================================================================
# Note: If CACHE and PERIPH communicate directly (not through CORE),
# additional level shifters needed for 1.0V ↔ 0.9V boundary
# ===================================================================

Summary

In this tutorial, you learned:

  • Multi-voltage design reduces power by 30-50% through quadratic voltage-power relationship (P ∝ V²), assigning optimal voltages to blocks
  • Level shifters are required at all voltage boundaries to prevent logic errors, timing violations, and reliability issues
  • set_level_shifter defines shifter strategies with -applies_to (inputs/outputs) and -location (placement)
  • Both directions need shifters: low-to-high prevents logic errors, high-to-low prevents oxide stress
  • map_level_shifter_cell connects UPF strategies to physical library cells for synthesis implementation
  • Level shifter delay (2-5× buffer delay) impacts timing and must be considered in critical path analysis
Did you find what you were looking for?

Quiz

No quiz questions available for this article.