Part 8 · Checking & Coverage · Intermediate

Algorithmic (Untimed) Reference Models

Pure computation models — CRC example, package functions, and TLM wrapper components.

Untimed transforms

Algorithmic reference models compute a pure function of input data: CRC over a byte stream, AES encryption of a payload, checksum accumulation, parity generation. They consume no simulation time, hold no protocol state beyond the computation, and run entirely inside a write() call or a standalone predict() function.

The preferred pattern is a package function for the spec algorithm (unit-testable in isolation) wrapped by a thin uvm_component that implements the analysis imp and analysis port for TLM connectivity.

diagram
[CHECK] algorithmic model data flow

  byte_pkt (observed payload) ──► crc32_spec(data[]) ──► crc_result
                                         │
                                         ▼
                                   compare with DUT CRC field
                                   (via scoreboard exp vs act)
diagram
[UVM] package + component split

  ref_model_pkg::crc32_spec()     ← unit tests, spec from datasheet
         ▲
         │ called from
         │
  crc_ref_model::write(pkt)       ← TLM only: req_imp + ap

CRC reference model component

Ethernet and storage controllers often expose a hardware CRC engine. The verification plan checks that the DUT-computed CRC matches the IEEE 802.3 polynomial. The model implements the spec algorithm — bit-reversed polynomial 0xEDB88320 for CRC-32 — independent of whether the RTL uses a linear-feedback shift register, lookup table, or parallel tree.

systemverilog
class crc_ref_model extends uvm_component;
  `uvm_component_utils(crc_ref_model)
  uvm_analysis_imp #(byte_pkt, crc_ref_model) pkt_in;
  uvm_analysis_port #(crc_result) ap;

  function new(string name, uvm_component parent);
    super.new(name, parent);
    pkt_in = new("pkt_in", this);
    ap     = new("ap", this);
  endfunction

  function void write(byte_pkt pkt);
    crc_result res = crc_result::type_id::create("res");
    res.id  = pkt.id;
    res.crc = crc32_spec(pkt.data);
    `uvm_info("CRC_REF", $sformatf("id=%0d crc=%08h", res.id, res.crc), UVM_HIGH)
    ap.write(res);
  endfunction

  // Spec algorithm — lives here or in ref_model_pkg for unit tests
  function bit [31:0] crc32_spec(byte data[]);
    bit [31:0] crc = 32'hFFFFFFFF;
    foreach (data[i]) crc = update_crc_byte(crc, data[i]);
    return ~crc;
  endfunction

  function bit [31:0] update_crc_byte(bit [31:0] crc, byte d);
    crc ^= d;
    for (int b = 0; b < 8; b++)
      crc = (crc[0]) ? ((crc >> 1) ^ 32'hEDB88320) : (crc >> 1);
    return crc;
  endfunction
endclass
  • No virtual interface — zero simulation time consumed in the model.

  • Spec algorithm from datasheet — independent of RTL implementation (LFSR vs table).

  • Package function variant allows directed unit tests without UVM overhead.

  • Component wrapper connects pkt_in to monitor, ap to scoreboard exp_imp.

  • Include transaction ID in output so scoreboard can pair out-of-order CRC results.


Package-level unit test pattern

Test before env integration

Run directed tests on crc32_spec() with known vectors from the spec appendix before wiring into the environment. Catches polynomial, bit-order, and init-value bugs without simulation overhead.

systemverilog
// ref_model_pkg — no UVM required
package ref_model_pkg;
  function automatic bit [31:0] crc32_spec(byte data[]);
    // ... same implementation ...
  endfunction
endpackage

// Directed test (module or class)
initial begin
  byte vec[] = '{8'h00, 8'h01, 8'h02};
  bit [31:0] exp_crc = 32'hXXXX_XXXX;  // from spec appendix
  assert (ref_model_pkg::crc32_spec(vec) == exp_crc);
end

Other algorithmic examples

  • AES encrypt/decrypt — NIST test vectors in package, component wraps for block-aligned bus transactions.

  • IP checksum — RFC 1071 one's complement sum over payload bytes.

  • ECC encode — matrix multiply over GF(2); verify syndrome on injected bit errors.

Key takeaways

  • Algorithmic models: lowest cost, highest independence from RTL.

  • Package function + thin component = testable spec + TLM connectivity.

Common pitfalls

  • Reimplementing RTL CRC micro-architecture instead of spec polynomial — couples to implementation.

  • Missing transaction ID in output — scoreboard cannot pair on out-of-order buses.

  • Scheduling delays in algorithmic model — unnecessary; latency is not the check target.