Hardware Interfaces


Note that parameters prefixed with RndCnst are random netlist constants that need to be regenerated via topgen before the tapeout (typically by the silicon creator).

ParameterDefault (Max)Top EarlgreyDescription
IdcodeValue32'h0000000132'h00000001Idcode for the LC JTAG TAP.
RndCnstLcKeymgrDivInvalid(see RTL)(see RTL)Diversification value used for all invalid life cycle states.
RndCnstLcKeymgrDivTestUnlocked(see RTL)(see RTL)Diversification value used for the TEST_UNLOCKED* life cycle states.
RndCnstLcKeymgrDivDev(see RTL)(see RTL)Diversification value used for the DEV life cycle state.
RndCnstLcKeymgrDivProduction(see RTL)(see RTL)Diversification value used for the PROD/PROD_END life cycle states.
RndCnstLcKeymgrDivRma(see RTL)(see RTL)Diversification value used for the RMA life cycle state.


Referring to the Comportable guideline for peripheral device functionality, the module lc_ctrl has the following hardware interfaces defined

  • Primary Clock: clk_i
  • Other Clocks: clk_kmac_i
  • Bus Device Interfaces (TL-UL): tl
  • Bus Host Interfaces (TL-UL): none
  • Peripheral Pins for Chip IO: none
  • Interrupts: none

Inter-Module Signals

Port NamePackage::StructTypeActWidthDescription
strap_en_overridelogicunireq1This signal transitions from 0 -> 1 by the lc_ctrl manager after volatile RAW_UNLOCK in order to re-sample the HW straps. The signal stays at 1 until reset. Note that this is only used in test chips when SecVolatileRawUnlockEn = 1. Otherwise this signal is tied off to 0.

Security Alerts

Alert NameDescription
fatal_prog_errorThis alert triggers if an error occurred during an OTP programming operation.
fatal_state_errorThis alert triggers if an error in the life cycle state or life cycle controller FSM is detected.
fatal_bus_integ_errorThis fatal alert is triggered when a fatal TL-UL bus integrity fault is detected.

Security Countermeasures

Countermeasure IDDescription
LC_CTRL.BUS.INTEGRITYEnd-to-end bus integrity scheme.
LC_CTRL.TRANSITION.CONFIG.REGWENThe transition interface registers are REGWEN protected. The REGWEN is governed by hardware, and is only set to 1 if the interface mutex has been successfully claimed. Also, the REGWEN is set to 0 while a state transition is in progress in order to prevent any accidental changes to the transition interface CSRs during that phase.
LC_CTRL.MANUF.STATE.SPARSEThe manufacturing state vector is sparsely encoded. Although the encoding is randomly chosen, it satisfies specific Hamming weight and Hamming distance thresholds (see lc_ctrl_state_pkg.sv for the statistics). All manufacturing state encodings (except for the RAW state) have been constructed so that all OTP words belonging to the manufacturing state vector have a non-zero value. The individual OTP words are unique and have been engineered so that each word can be incrementally overwritten with another engineered value without causing the ECC bits added by the OTP macro to become inconsistent.
LC_CTRL.TRANSITION.CTR.SPARSEThe life cycle transition counter state is sparsely encoded. Although the encoding is randomly chosen, it satisfies specific Hamming weight and Hamming distance thresholds (see lc_ctrl_state_pkg.sv for the statistics). All counter state encodings (except for the 0 state) have been constructed so that all OTP words belonging to the counter state vector have a non-zero value. The individual OTP words are unique and have been engineered so that each word can be incrementally overwritten with another engineered value without causing the ECC bits added by the OTP macro to become inconsistent.
LC_CTRL.MANUF.STATE.BKGN_CHKThe manufacturing state vector is continuously decoded and checked, once the life cycle controller has initialized. If any mismatch is detected, local escalation is triggered (MAIN.FSM.LOCAL_ESC).
LC_CTRL.TRANSITION.CTR.BKGN_CHKThe life cycle transition counter is continuously decoded and checked, once the life cycle controller has initialized. If any mismatch is detected, local escalation is triggered (MAIN.FSM.LOCAL_ESC). Note that any non-RAW manufacturing state requires the transition counter to be nonzero. Also, the transition counter is used to enforce a limit of maximum 24 state transitions in order to guard against bruteforcing.
LC_CTRL.STATE.CONFIG.SPARSEThe decoded manufacturing state uses a replicated enum encoding to fill the 32bit value exposed in the CSRs (both the LC_STATE and TRANSITION_TARGET registers). This is done to 1) ease hardening of firmware code, and 2) to ensure that even the decoded life cycle state vector inside the life cycle controller still has a redundant encoding.
LC_CTRL.MAIN.FSM.SPARSEThe main state FSM is sparsely encoded.
LC_CTRL.KMAC.FSM.SPARSEThe KMAC interface FSM is sparsely encoded.
LC_CTRL.MAIN.FSM.LOCAL_ESCUpon local escalation due to an invalid state encoding of the life cycle state vector or an invalid KMAC interface FSM state, the main state FSM moves to the InvalidSt state which behaves like a virtual scrap state.
LC_CTRL.MAIN.FSM.GLOBAL_ESCUpon global escalation (triggered by the alert escalation receivers), the main state FSM moves to the EscalateSt state which behaves like a virtual scrap state.
LC_CTRL.MAIN.CTRL_FLOW.CONSISTENCYThe control flow of the main FSM is constructed so that the FSM only progresses linearly in one direction. There are no transition arcs that loop back to previous FSM states.
LC_CTRL.INTERSIG.MUBILife cycle control signals are multibit encoded.
LC_CTRL.TOKEN_VALID.CTRL.MUBIThe token valid signals coming from OTP are MUBI encoded.
LC_CTRL.TOKEN.DIGESTLife cycle transition tokens are hashed with cSHAKE128, using a custom ‘LC_CTRL’ prefix.
LC_CTRL.TOKEN_MUX.CTRL.REDUNThe life cycle transition token mux is broken into two halves that are steered with separately decoded and buffered MUBI valid signals (see also TOKEN_VALID.CTRL.MUBI).
LC_CTRL.TOKEN_VALID.MUX.REDUNThe life cycle transition token valid mux is replicated twice. If a transition is initiated and the two mux index signals are inconsistent or if any of the two valid mux outputs is not set to valid, the transition will fail with a TRANSITION_ERROR.
jtag_iinputjtag_pkg::jtag_req_tJTAG input signals for life cycle TAP.
jtag_ooutputjtag_pkg::jtag_rsp_tJTAG output signals for life cycle TAP.
esc_scrap_state0_tx_iinputprim_esc_pkg::esc_tx_tEscalation input from alert handler. Moves the life cycle state into an invalid state upon assertion.
esc_scrap_state0_rx_ooutputprim_esc_pkg::esc_rx_tEscalation feedback to alert handler
esc_scrap_state1_tx_iinputprim_esc_pkg::esc_tx_tEscalation input from alert handler. Moves the life cycle state into an invalid state upon assertion.
esc_scrap_state1_rx_ooutputprim_esc_pkg::esc_rx_tEscalation feedback to alert handler
pwr_lc_iinputpwrmgr::pwr_lc_req_tInitialization request coming from power manager.
pwr_lc_ooutputpwrmgr::pwr_lc_rsp_tInitialization response and programming idle state going to power manager.
lc_otp_program_ooutputotp_ctrl_pkg::lc_otp_program_req_tLife cycle state transition request.
lc_otp_program_iinputotp_ctrl_pkg::lc_otp_program_rsp_tLife cycle state transition response.
kmac_data_ooutputkmac_pkg::app_req_tLife cycle RAW token hashing request.
kmac_data_iinputkmac_pkg::app_rsp_tLife cycle RAW token hashing response.
otp_lc_data_iinputotp_ctrl_pkg::otp_lc_data_tLife cycle state output holding the current life cycle state, the value of the transition counter and the tokens needed for life cycle transitions.
lc_keymgr_div_ooutputlc_keymgr_div_tLife cycle state group diversification value.
lc_flash_rma_seed_ooutputlc_flash_rma_seed_tSeed for flash RMA.
otp_device_id_iinputotp_device_id_tHW_CFG0 bits from OTP (DEVICE_ID_0).
otp_manuf_state_iinputotp_manuf_state_tHW_CFG0 bits from OTP (MANUF_STATE_0).
lc_otp_vendor_test_ooutputotp_ctrl_pkg::lc_otp_vendor_test_req_tVendor-specific test bits to OTP (OTP_VENDOR_TEST_CTRL).
lc_otp_vendor_test_iinputotp_ctrl_pkg::lc_otp_vendor_test_rsp_tVendor-specific test bits to OTP (OTP_VENDOR_TEST_STATUS).
lc_dft_en_ooutputlc_tx_tMultibit control signal.
lc_nvm_debug_en_ooutputlc_tx_tMultibit control signal.
lc_hw_debug_en_ooutputlc_tx_tMultibit control signal.
lc_cpu_en_ooutputlc_tx_tMultibit control signal.
lc_creator_seed_sw_rw_en_ooutputlc_tx_tMultibit control signal.
lc_owner_seed_sw_rw_en_ooutputlc_tx_tMultibit control signal.
lc_iso_part_sw_rd_en_ooutputlc_tx_tMultibit control signal.
lc_iso_part_sw_wr_en_ooutputlc_tx_tMultibit control signal.
lc_seed_hw_rd_en_ooutputlc_tx_tMultibit control signal.
lc_keymgr_en_ooutputlc_tx_tMultibit control signal.
lc_escalate_en_ooutputlc_tx_tMultibit control signal.
lc_check_byp_en_ooutputlc_tx_tMultibit control signal.
lc_clk_byp_req_ooutputlc_tx_tMultibit control signal.
lc_clk_byp_ack_ioutputlc_tx_tMultibit control signal.
lc_flash_rma_req_ooutputlc_tx_tMultibit control signal.
lc_flash_rma_ack_ioutputlc_tx_tMultibit control signal.

Power Manager Interface

The power manager interface is comprised of three signals overall: an initialization request (pwr_lc_i.lc_init), an initialization done response (pwr_lc_o.lc_done) and an idle indicator (pwr_lc_o.lc_idle).

The power manager asserts pwr_lc_i.lc_init in order to signal to the life cycle controller that it can start initialization, and the life cycle controller signals completion of the initialization sequence by asserting pwr_lc_o.lc_done (the signal will remain high until reset).

The idle indication signal pwr_lc_o.lc_idle indicates that the life cycle controller is idle. If this bit is 0, the life cycle controller is either not initialized or in the middle of carrying out a life cycle state transition. The power manager uses that indication to determine whether a power down request needs to be aborted.

Since the power manager may run in a different clock domain, the pwr_lc_i.lc_init signal is synchronized within the life cycle controller. The power manager is responsible for synchronizing the pwr_lc_o.lc_done and pwr_lc_o.lc_idle signals.

See also power manager documentation.

OTP Interfaces

All interfaces to and from OTP are explained in detail in the OTP Specification Document.

KMAC Interface

The life cycle controller interfaces with KMAC through a side load interface in the same way as the key manager. Since the KMAC and life cycle controller are in different clock domains, the KMAC interface signals are synchronized to the life cycle clock inside the life cycle controller.

Control Signal Propagation

For better security, all the life cycle control signals are broadcast in multi-bit form. The active ON state for every signal is broadcast as 4'b1010, while the inactive OFF state is encoded as 4'b0101. For all life cycle signals except the escalation signal ESCALATE_EN, all values different from ON must be interpreted as OFF in RTL. In case of ESCALATE_EN, all values different from OFF must be interpreted as ON in RTL. To that end the functions lc_tx_test_true_strict(), lc_tx_test_true_loose(), lc_tx_test_false_strict() and lc_tx_test_false_loose() in the lc_ctrl_pkg must be employed unless there is a strong reason not to. The reason must be documented and agreed at block sign-off.

Since many signals cross clock boundaries, their synchronization needs to be taken into account. However, since the ON / OFF encoding above has been chosen such that all bits toggle exactly once for a transition from OFF to ON (and vice-versa), all that needs to be done is guard against metastability using a two-stage synchronizer, as illustrated below.

Multibit Sync

In other words, since each bit in the encoding flips exactly once upon an OFF -> ON or ON -> OFF transition, we can guarantee that there are no transient patterns toggling back and forth between enabling and disabling a function. It is crucial however that the design follows the guidance above and interprets all undefined values as either ON or OFF in order to avoid issues due to staggered bits after synchronization.

Note that even though synchronization can be achieved with a simple two-stage synchronizer, designs must use the prim_lc_sync primitive. This primitive has additional LC-specific assertions and provides a parametric amount of separately buffered copies of the life cycle signal to prevent logic optimization by the synthesis tool (buffers have a ‘size_only’ constraint in synthesis). For all signals except ESCALATE_EN, it is recommended to structure the design such that at least two separately buffered copies of the life cycle signals have to be consumed in order to unlock a certain function.

Key Manager Interface

The lc_keymgr_div_o signal is a 128bit diversification constant that is output to the key manager once the life cycle controller has initialized, and is asserted at the same time as lc_keymgr_en_o. Depending on which group the life cycle state is in, this signal is assigned a different random netlist constant as defined in the table below.

Life Cycle State GroupAssigned Diversification Constant
PROD, PROD_ENDRndCnstLcKeymgrDivProduction
All Other StatesRndCnstLcKeymgrDivInvalid

Note that this signal is quasistatic. It is hence recommended to place a max-delay constraint on it and leverage the synchronized version of lc_keymgr_en_o to enable any downstream register in different clock domains than the life cycle controller.