OpenCores

ASIC implementation

Table of content

1. Introduction

This section covers specific points of the openMSP430 ASIC implementation, in particular:
      • The ASIC specific RTL configuration options.
      • Some DFT considerations.
      • A description of each ASIC sensitive module.
Keep in mind that as no exotic design technique were used in the openMSP430, following a standard implementation flow from Synthesis to P&R is the best way to go.
 

2. RTL Configuration

Whenever the "`define ASIC" statement of the Expert System Configuration section is uncommented, all ASIC specific configuration options are enabled.

2.1 Basic Clock Module

In its ASIC configuration, the Basic clock module of the openMSP430 can support  up to all features described in the MSP430x1xx Family User's Guide (Chapter 4).

In particular, the ASIC_CLOCKING option activates all advancd clocking options (note that formal equivalence with the FPGA version is achieved by commenting this option out):




//===============================================================
// ASIC CLOCKING
//===============================================================

//-------------------------------------------------------
// When uncommented, this define will enable the ASIC
// architectural clock gating as well as the advanced low
// power modes support (most common).
// Comment this out in order to get FPGA-like clocking.
//-------------------------------------------------------
`define ASIC_CLOCKING


All these advanced clocking options are highlighted in the following diagram and discussed below:

Clock Module ASIC configuration

2.1.1 Low-Frequency Clock Domain

The LFXT clock domain can be enabled thanks to the following configuration option:




//============================================================================
// LFXT CLOCK DOMAIN
//============================================================================

//-------------------------------------------------------
// When uncommented, this define will enable the lfxt_clk
// clock domain.
// When commented out, the whole chip is clocked with dco_clk.
//-------------------------------------------------------
`define LFXT_DOMAIN


Note 1: When commented-out:
      • ACLK is running on DCO_CLK
      • MCLK_MUX and SMCLK_MUX options are not supported
      • OSCOFF_EN low power mode is not supported
Note 2: Unlike its name suggest, there is no frequency limitation on LFXT_CLK. The name was simply kept in order to be consistent with the original MSP430 documentation, where LFXT_CLK is typically connected to a 32 kHz crystal oscillator.


2.1.2 Clock Muxes

The MCLK and SMCLK clock muxes can be enabled or disabled with the following options:




//============================================================================
// CLOCK MUXES
//============================================================================

//-------------------------------------------------------
// MCLK: Clock Mux
//-------------------------------------------------------
// When uncommented, this define will enable the
// MCLK clock MUX allowing the selection between
// DCO_CLK and LFXT_CLK with the BCSCTL2.SELMx register.
// When commented, DCO_CLK is selected.
//-------------------------------------------------------
`define MCLK_MUX

//-------------------------------------------------------
// SMCLK: Clock Mux
//-------------------------------------------------------
// When uncommented, this define will enable the
// SMCLK clock MUX allowing the selection between
// DCO_CLK and LFXT_CLK with the BCSCTL2.SELS register.
// When commented, DCO_CLK is selected.
//-------------------------------------------------------
`define SMCLK_MUX


Note 1: When a MUX is excluded, the concerned clock (MCLK and/or SMCLK) is running with DCO_CLK.

Note 2: If a MUX is included, the implementation and sign-off tools (in particular CTS and STA) must be aware that a new clock needs to be defined on the MUX output.


2.1.3 Clock Dividers

The MCLK, SMCLK and ACLK clock dividers can be enabled or disabled with the following options:




//============================================================================
// CLOCK DIVIDERS
//============================================================================

//-------------------------------------------------------
// MCLK: Clock divider
//-------------------------------------------------------
// When uncommented, this define will enable the
// MCLK clock divider (/1/2/4/8)
//-------------------------------------------------------
`define MCLK_DIVIDER

//-------------------------------------------------------
// SMCLK: Clock divider (/1/2/4/8)
//-------------------------------------------------------
// When uncommented, this define will enable the
// SMCLK clock divider
//-------------------------------------------------------
`define SMCLK_DIVIDER

//-------------------------------------------------------
// ACLK: Clock divider (/1/2/4/8)
//-------------------------------------------------------
// When uncommented, this define will enable the
// ACLK clock divider
//-------------------------------------------------------
`define ACLK_DIVIDER


The clock dividers instantiate a clock gate on the clock tree and are implemented as following:

Clock Divider

2.1.4 Low-Power Modes


2.1.4.1 Internal clocks ( MCLK / SMCLK )

Two bit fields in the status register (R2) allow to control the system clocks:
      • CPUOFF allows to switch-off MCLK
      • SCG1 allows to switch-off SMCLK
These control bits are supported by the openMSP430 and can be included in the design with the following defines:




//============================================================================
// LOW POWER MODES
//============================================================================

//-------------------------------------------------------
// LOW POWER MODE: CPUOFF
//-------------------------------------------------------
// When uncommented, this define will include the
// clock gate allowing to switch off MCLK in
// all low power modes: LPM0, LPM1, LPM2, LPM3, LPM4
//-------------------------------------------------------
`define CPUOFF_EN

//-------------------------------------------------------
// LOW POWER MODE: SCG1
//-------------------------------------------------------
// When uncommented, this define will include the
// clock gate allowing to switch off SMCLK in
// the following low power modes: LPM2, LPM3, LPM4
//-------------------------------------------------------
`define SCG1_EN


In order to keep the clock tree as flat as possible, the CPUOFF and SCG1 low power options share the same clock gate with the clock divider:

Clock Divider and low power

2.1.4.2 Clock oscillators ( DCO_CLK / LFXT_CLK )

There are two bit fields in the status register (R2) allowing to control the clock oscillators:
      • SCG0 allows to switch-off the DCO oscillator
      • OSCOFF allows to switch-off the LFXT oscillator
These control bits are supported by the openMSP430 and can be included in the design with the following defines:




//============================================================================
// LOW POWER MODES
//============================================================================

//-------------------------------------------------------
// LOW POWER MODE: SCG0
//-------------------------------------------------------
// When uncommented, this define will enable the
// DCO_ENABLE/WKUP port control (always 1 when commented).
// This allows to switch off the DCO oscillator in the
// following low power modes: LPM1, LPM3, LPM4
//-------------------------------------------------------
`define SCG0_EN

//-------------------------------------------------------
// LOW POWER MODE: OSCOFF
//-------------------------------------------------------
// When uncommented, this define will include the
// LFXT_CLK clock gate and enable the LFXT_ENABLE/WKUP
// port control (always 1 when commented).
// This allows to switch off the low frequency oscillator
// in the following low power modes: LPM4
//-------------------------------------------------------
`define OSCOFF_EN


The control logic of both DCO and LFXT oscillators is identical.

When disabled, the *_WKUP signal is used to asynchronously wake up the oscillator. Once the oscillator is awake (and therefore a clock is available), the *_ENABLE signal will take over and synchronously keep the oscillator enabled until the CPU clears the SCG0 or OSCOFF bit again.

The following two waveforms illustrate the CPU entering the LPM1 mode, and in particular the DCO oscillator being switched-off:
  • Entering LPM1 through a BIS #N, R2 instruction:
Entering LPM1 with BIS
  • Entering LPM1 through a RETI instruction:
Entering LPM1 with RETI

Note: the DCO oscillator is enabled until the BIS and RETI instruction are fully executed (i.e. until the CPU state machines reach their IDLE state).


At last, this waveform shows the CPU going out of LPM1 mode and in particular the DCO oscillator wake-up sequence:

Wakeup from LPM1

In order to wake-up the CPU from ANY low power mode, the system MUST ALWAYS go through the following chain of events (as illustrated in the previous waveform):
      1.  The peripheral (for example a timer) asserts the WKUP input of the openMSP430 in order to asynchronously restore the clocks. At this stage, DCO_WKUP is activated and DCO_ENABLE is still cleared.
      2.  Once MCLK is available, the peripheral generates a synchronous IRQ signal in order to re-activate the CPU state machines.
      3.  The CPU state machines activated, DCO_ENABLE is synchronously set.
      4.  When the global interrupt enable flag (GIE) is cleared, DCO_WKUP is released two clock cycles later (i.e. same behavior as a reset synchronizer).
        Important note: the peripheral should release the
        WKUP input when its interrupt pending flag is cleared. Otherwise the DCO_WKUP signal will be set again as soon as the GIE flag is restored by the RETI instruction... which is probably not the intended behavior :-P
      5. The DCO oscillator is now enabled until SCG0 is set again.

2.2 Other configuration options

2.2.1 Fine Grained Clock Gating

Nowadays, all synthesis tools support automatic (fine grained) clock gating insertion.
However, as some design houses still prefer to have the clock gates directly instantiated in the RTL, there is the possibility to include the 'manual' fine grained clock gates in the design with the following define:




//============================================================================
// FINE GRAINED CLOCK GATING
//============================================================================

//-------------------------------------------------------
// When uncommented, this define will enable the fine
// grained clock gating of all registers in the core.
//-------------------------------------------------------
`define CLOCK_GATING



2.2.2 Watchdog Clock Mux

The watchdog clock mux allows to select between ACLK and SMCLK. It can be enabled or disabled with the WATCHDOG_MUX define.
When excluded, the additional WATCHDOG_NOMUX_ACLK  option allows the user to decide if the watchdog clock should be hard-wired to ACLK (if uncommented) or SMCLK (if commented-out)




//============================================================================
// CLOCK MUXES
//============================================================================

//-------------------------------------------------------
// WATCHDOG: Clock Mux
//-------------------------------------------------------
// When uncommented, this define will enable the
// Watchdog clock MUX allowing the selection between
// ACLK and SMCLK with the WDTCTL.WDTSSEL register.
// When commented out, ACLK is selected if the
// WATCHDOG_NOMUX_ACLK define is uncommented, SMCLK is
// selected otherwise.
//-------------------------------------------------------
`define WATCHDOG_MUX
//`define WATCHDOG_NOMUX_ACLK



3. DFT Considerations

The openMSP430 is designed to be fully scan friendly. During production, the ATE controls the core through the scan_mode and scan_enable signals. The scan_mode port is always asserted during scan testing and is used to switch between functional and scan mode.

3.1 Resets

When in scan mode (i.e. scan_mode input port is set), ALL internal resets of the openMSP430 are connected the reset_n input port.
Taking the POR generation as an example, it is implemented using the omsp_scan_mux module as following:

DFT Reset

3.2 Clock Gates

When in scan mode (i.e. scan_mode input port is set), ALL clock gates instantiated in the design must be enabled during scan shifting. This is can be achieved by setting the scan_enable input port during the shift phase.
On the other hand, during the capture phase, the scan_enable port must be cleared in order to restore the functional behavior of the clock gate.

This feature is implemented in the omsp_clock_gate module as following:

DFT Clock Gate

3.3 Clock Muxes

When in scan mode (i.e. scan_mode input port is set), the MCLK and SMCLK clock muxes are both running on DCO_CLK. The watchdog mux is running SMCLK (i.e. DCO_CLK).

This feature is implemented in the omsp_clock_mux module as following:

DFT Clock MUX

Note: if the LFXT clock domain is enabled, the LFXT_CLK input port should also be connected to the scan clock when in scan mode.

3.4 Coverage

After synthesizing the openMSP430 in its maximum configuration (in particular with ALL clock domains available and ALL clock muxes included), the core reaches 99.7% stuck-at fault coverage:

Tetramax



4. Sensitive Modules

ALL modules discussed in this section have a simple and well defined functionality but nonetheless lay on sensitive parts of the design (clock tree, wake-up path, ...).

In the industry, it is common place for companies to have policies recommending designers to use textbook structures or specific standard cells when implementing circuits considered as 'sensitive'.
This section will hopefully help to quickly identify these 'sensitive' circuits and adapt them to your requirements if necessary.

4.1 AND Gate ( omsp_and_gate.v )

This module implements a simple AND2 gate and is instantiated several times on the wake-up paths in order to ensure a glitch free generation of the wake-up signals. The idea behind this block is to prevent the synthesis tool from optimizing the combinatorial wake-up path and potentially generate a glitchy logic.

There are three different ways to handle this block:
  1. Do nothing
  2. Modify the RTL by directly instantiating an AND2 cell from the target library and applying a don't touch or size only attribute on it before proceeding to the synthesis compile step
  3. Keep the RTL unchanged and when running synthesis, first compile this module separately before going to the top down compile (don't forget the don't touch or size only attribute)
Note that the first option is actually acceptable because in low power mode, there are no clocks available, which means no glitch... However, in active mode, the wake-up line could see a lot of glitches, which is functionally not a problem (since the core is awake anyway) but could be considered as not really elegant...

4.2 Clock Gate ( omsp_clock_gate.v )

Almost every company has a different policy for handling clock gates. Therefore, this module is probably the most likely to be modified.

So here are the facts:
  • There are only rising edge flip-flop in the design1
      as a consequence clock gates can indifferently park the clock high or low without affecting functionality.

  • The enable signal of ALL clock gates in the openMSP430 are generated with the rising edge of the clock
      this leaves the door open for both LATCH and NAND2 based clock gates.
1: beside for the DCO_ENABLE and LFXT_ENABLE signals and the clock MUXes. However, these can be safely ignored

As a consequence, you can feel free to use:
  • A LATCH based clock gate. For example:
    Clock Gate Latch
  • Or a NAND2 based clock gate:
Clock Gate NAND2

4.3 Clock Mux ( omsp_clock_mux.v )

The clock muxes of the openMSP430 are implemented as following:
Clock Mux
In order to make this  implementation 100% bullet proof, the RTL could be modified by manually instantiating the NAND2 and AND2 cells directly from the target library (with the associated don't touch or size only attributes of course).
However, if you decide to compile this module as it is, the synthesis tool should normally be smart enough and not mess it up (but PLEASE PLEASE PLEASE double check manually the resulting gate netlist).

4.4 Scan Mux ( omsp_scan_mux.v )

As illustrated in the section 3.1 , the scan mux cell allows ALL internal resets to be controllable with the reset_n input port in scan mode.
In addition, the scan mux is also used by the omsp_wakeup_cell (see section 4.7 below).

4.5 Sync Cell ( omsp_sync_cell.v )

The following synchronization cell is instantiated on all clock domain crossing data paths:

Sync Cell

4.6 Sync Reset ( omsp_sync_reset.v )

Internal resets are generated using the following standard reset synchronizer:
Sync Reset

4.7 Wakeup Cell ( omsp_wakeup_cell.v )

The wakeup cell is the most unconventional module of the openMSP430 design as it contains a flip-flop whose clock and reset are both coming from a data path.
In the openMSP430 core, it is instantiated a single time in the watchdog timer but can also be reused in external custom peripherals.

The implementation of the block looks as following:
Wakeup cell

The basic idea here is simply to set the WKUP_OUT signal with a rising edge on the WKUP_EVENT port, and clear it when WKUP_CLEAR is active (i.e. level sensitive clear).

In order to give a better perspective from a system point of view, the following diagram shows how the wakeup cell has been used in the particular case of the watchdog timer (note that WDTIFG_CLR_REG and WDTQN_EDGE_REG are both output of a flip-flop and therefore glitch-free):

Watchdog wakeup

Note: Wake-up signals can of course be generated in a different way as long as they directly come from a flip-flop (or are certified to be non-glitchy).
For example a simple handshake between the WDT_CLK and MCLK clock domains could have been used to clear the WDT_WKUP signal in a fully synchronous manner.
However, it is to be noted that this handshake would introduce some synchronization delay, which might not be negligible if MCLK and WDT_CLK frequencies are orders of magnitude apart (i.e. several MHz for MCLK and 32kHz for WDT_CLK).
As getting the oscillators back to sleep as fast as possible might prove to be extremely important for low-power designs, this asynchronous solution was selected for the omsp_watchdog implementation.