Skycore includes assertion templates for common RF interfaces: SPI register access, power-up sequencing, PLL lock and loss-of-lock clock-domain checks, and more. They cover much of a typical RF verification plan. For many early-access teams, the defaults were enough to pass a first simulation without hand-written assertions.
As reusable RF IP accumulates across tape-out projects, gaps appear. A mixer may impose a gain-step ordering rule that no generic template represents. A VCO tuning register may require a write-before-enable sequence that is clear to block experts but absent from generic rules. Such constraints remain in engineers' memories and old simulation logs instead of a shared assertion library.
This post shows how Skycore encodes team-specific constraints as reusable verification rules, using an internal example based on our RF building blocks.
Where Generic Assertions Miss Shared IP Bugs
Generic assertions catch clear protocol errors: writing a read-only field, popping an empty FIFO, or toggling a clock before reset deassertion. These are structural defects. One template can define the pattern and apply it wherever that pattern occurs.
Shared RF IP libraries also collect semantic constraints tied to analog behavior. An LNA may require gain mode before bias-current programming because its bias table depends on gain mode. Programming bias first still lets the simulator run and the register map retain the values, but silicon receives the wrong bias. A generic assertion misses this because the transaction sequence is valid at the protocol level.
The pattern also applies to PLL charge-pump settings, PA power-class initialization, and ADC reference-voltage ordering. Each may appear in a datasheet or design-review note, but that scattered documentation is the issue: the requirement is absent from the verification environment that must enforce it.
Skycore Custom Rule Format
A Skycore custom verification rule is a named constraint with four fields: scope, identifying the block or register map; trigger, defining the transaction or signal event; predicate, stating what must be true; and severity. Rules reside in YAML read during block configuration, and the verification agent converts each one into an SVA property within the generated testbench.
Here is a shortened gain-before-bias rule:
# skycore-rules.yaml for lna_ctrl block
rules:
- name: gain_mode_before_bias_write
scope: lna_ctrl
trigger:
register: BIAS_CTRL
access: write
predicate:
register_written_before: GAIN_MODE
field: GAIN_MODE.enable
expected_state: 1
severity: error
message: "BIAS_CTRL written before GAIN_MODE.enable is set; bias table selection will be incorrect"
The verification agent parses this rule and creates an SVA property that triggers when a write to BIAS_CTRL occurs before GAIN_MODE.enable is set. The resulting SystemVerilog is approximately:
property gain_mode_before_bias_write;
@(posedge clk)
(spi_write && spi_addr == BIAS_CTRL_ADDR)
|-> ##[0:$] (gain_mode_enable_latched == 1'b1)
throughout (spi_write && spi_addr == BIAS_CTRL_ADDR)[*1];
endproperty
assert property (gain_mode_before_bias_write)
else $error("BIAS_CTRL written before GAIN_MODE.enable is set");
Generated output differs with the block clock setup and register map, but its logic comes straight from the rule. The YAML author need not know SVA syntax, while an engineer reviewing the SVA can trace it to the source YAML rule.
Structuring Rules for a Block Library
After the first few custom rules, organize them for discovery, tape-out reuse, and straightforward updates when block behavior changes.
Use one rule file per block, matching its module name. Keep these files in a shared, source-controlled verification-rules directory apart from RTL. During testbench generation, Skycore searches a configurable path for the matching file. Found rules merge with the default assertions; otherwise, only defaults are used.
For blocks reused across chip projects with different register-map revisions, Skycore supports versioning through schema_version. Increment that field when the map changes and create rules for the new version. At generation, the verification agent chooses the version matching the supplied block configuration. This avoids stale assertions pointing to addresses from an earlier block revision.
Capturing Initialization Order
Initialization constraints are often the hardest rules in an RF block library. They describe register writes that must occur in order before normal operation begins. A single-trigger predicate is insufficient because the requirement spans transactions over time.
Skycore uses a sequence rule type for this case. It lists the required steps in order, while the verification agent builds a state machine and reports failure when a step is skipped or arrives out of order:
rules:
- name: pll_init_sequence
type: sequence
scope: pll_ctrl
steps:
- register: PLL_RST
field: reset_n
value: 0
- register: PLL_CFG
field: ref_div
any_value: true
- register: PLL_CFG
field: fb_div
any_value: true
- register: PLL_RST
field: reset_n
value: 1
severity: warning
message: "PLL initialization sequence violated; lock behavior undefined"
With any_value: true, the rule checks only that a write occurs at that sequence position, not its value. This suits project-specific divider settings when the ordering remains fixed.
Limits of This Approach
This custom format fits register-map constraints and transaction ordering. It does not replace analog coverage, transistor-level simulation, or block characterization. Because the rules observe the digital control interface, they cannot detect analog drift caused by process corners or temperature. Those checks belong elsewhere in the verification plan.
Rule generation also depends on rule quality. If a team has not recorded a constraint in a rule file, Skycore cannot infer it. The tool translates documented requirements into executable assertions; it does not uncover unspecified constraints.
Early-access teams have gained the most by converting one engineer's mental model of block quirks into a shared, executable, version-controlled artifact. The block expert records the rules once, and each later tape-out using that block receives them automatically, without relying on someone to recall the sequencing requirements.
Building Your First Rule Set
Start with one RF block in the current project. Identify the top three constraints behind simulation bugs or bring-up problems in the previous tape-out, then encode those three as Skycore rules. Run the verification agent and check that its assertions match your intent. Add the file to the verification repository, then configure Skycore to load it during the next RTL generation pass.
The payoff grows with each block and tape-out. By the third project, a carefully written rule set clearly repays its cost: the engineer on that project may not have designed the block and would otherwise lack its constraints.
Good rule-file documentation also matters. The message field supplies the simulation-log error text. Explaining both the constraint and its purpose reduces triage time when an assertion fires and an engineer unfamiliar with the block must determine the fix.
Teams setting up Skycore around an existing IP library can use its documentation to convert verification notes or block datasheets into rule files. It defines the YAML schema and available rule types. Once the format is understood, turning written requirements into executable rules is largely mechanical.