A daily series of self-contained design-verification projects in SystemVerilog/UVM. One documented, simulate-able verification exercise per day.
Each day lives in its own folder (dayN-name/) containing a self-contained project with source, a self-checking testbench, a Makefile, a waveform image, and a README write-up.
| Day | Project | Key concepts | Folder |
|---|---|---|---|
| 1 | Constrained-Random FIFO Scoreboard | Reference-model scoreboard, $-queue golden model, directed + constrained-random stimulus, functional coverage, SVA assertions |
day01-fifo_scoreboard/ |
| 2 | UVM APB4 Register-File Verification | Full UVM agent (driver/monitor/sequencer), golden reference-model scoreboard, layered sequences, virtual sequencer + virtual sequences, functional coverage, APB protocol SVA | day02-apb4_register_file/ |
| 3 | UVM AXI4-Lite Register-Block Verification | Five-channel AXI4-Lite agent (driver/monitor/sequencer), golden reference-model scoreboard, layered + virtual sequences, functional coverage, AXI4-Lite protocol SVA (VALID/READY stability, response codes) | day03-axi4_lite_regblock/ |
| 4 | UVM UART Verification Environment | TX + RX agents, serial-line monitors that reconstruct bytes, dual sent-vs-serialized / on-wire-vs-received scoreboard, directed + random sequences across baud settings, data×baud coverage, start/stop framing SVA | day04-uart_verification/ |
| 5 | UVM RAL (Register Abstraction Layer) Demo | uvm_reg model with RW/RO/W1C fields, uvm_reg_adapter + explicit uvm_reg_predictor, front-door and back-door access, built-in uvm_reg_hw_reset_seq / uvm_reg_bit_bash_seq, register field-value coverage |
day05-ral_demo/ |
| 6 | UVM Packet-Router Verification | Store-and-forward 1→N packet router, input-stream agent + output-backpressure agent, golden per-port FIFO reference-model scoreboard, virtual sequencer + smoke/regress virtual sequences, FIFO-full & backpressure corners, dest×last coverage, SVA (no valid-while-empty, stable-under-backpressure) | day06-packet_router/ |
| 7 | UVM Round-Robin Arbiter Verification | Parameterized round-robin arbiter, independent golden pointer-tracking reference model, fairness / anti-starvation checking, backpressure stall + circular skip + idle corners, virtual sequencer + smoke/regress virtual sequences, winner×density coverage, SVA (one-hot grant, grant-is-request, progress, no-grant-when-disabled) | day07-round_robin_arbiter/ |
| 8 | UVM Async FIFO (CDC) Verification | Dual-clock Gray-pointer asynchronous FIFO, 2-flop synchronizer clock-domain crossing, per-domain write/read agents on non-commensurate clocks, golden-queue reference-model scoreboard (order + data integrity across the CDC), fill-to-full & drain-to-empty corners, virtual sequencer + fill/drain & concurrent virtual sequences, data-range coverage, SVA (no overflow, no underflow, single-bit Gray transitions) | day08-async_fifo_cdc/ |
| 9 | UVM ALU Functional-Coverage Verification | Registered 8-op ALU (ADD/SUB/logic/shift/SLT) with {zero,carry,overflow,negative} flags, shared golden reference model driving both scoreboard and coverage, expected-response FIFO scoreboard (result + all four flags), directed/corner/random layered sequences, virtual sequencer + smoke/regress virtual sequences, opcode×flag cross coverage, SVA (zero⇔0, negative=MSB, no-X on response) | day09-alu_coverage/ |
| 10 | UVM AXI4-Stream Skid-Buffer Verification | Full-throughput register slice with one-entry skid register (registered TVALID/TREADY + payload), two active agents (stream source + back-pressure sink) each with driver/monitor/sequencer, golden order-preserving queue scoreboard (lossless, in-order, {TDATA,TKEEP,TLAST} exact, null-byte TKEEP=0), directed showcase + random-packet layered sequences, virtual sequencer + concurrent smoke/regress virtual sequences, tlast×tkeep coverage, AXI-Stream SVA (VALID held until READY, payload stable while stalled, no-X) | day10-axi4_stream_skid_buffer/ |
| 11 | UVM SPI Master Verification | Parameterized SPI master (all four CPOL/CPHA modes, programmable clock divider, MSB-first full-duplex), master agent (parallel request driver/monitor) + independent SPI-slave agent (MISO responder driver/monitor), golden full-duplex reference-model scoreboard (master.rx == slave.tx on MISO, slave.rx == master.tx on MOSI), directed all-modes + constrained-random layered sequences, virtual sequencer + concurrent smoke/regress virtual sequences, mode×divider×data coverage, pin-level SVA (cs_n idle, done one-cycle pulse, gated sclk, no-X) | day11-spi_master/ |
| 12 | UVM Sequential (Restoring) Divider Verification | Multi-cycle unsigned restoring divider with start/busy/done handshake and divide-by-zero handling, divider agent (handshake driver + independent pin-reconstructing monitor), golden reference-model scoreboard (/ and % plus a structural q*d+r==dividend, r<divisor identity re-check), directed showcase + corner sequences (0/x, x/1, a<b, max/max, x/0), divide-by-zero stress + constrained-random regression, virtual sequencer + smoke/regress virtual sequences, dividend×divisor / dbz / quotient-zero coverage, handshake SVA (one-cycle done, busy-until-done, bounded completion, no-X) |
day12-sequential_divider/ |
| 13 | UVM GPU Tensor-Core Dot-Product (MAC) Engine Verification | Streaming signed multiply-accumulate reduction lane (the GEMM/tensor-core primitive) emitting one dot product per in_last with zero-bubble back-to-back vectors, input monitor that reconstructs each vector from the operand stream + output monitor, golden signed dot-product reference-model scoreboard (in-order, ACC_W 2's-complement wraparound, extra/missing-result accounting), directed showcase + corners (length-1, all-zero, all-negative, −128·−128 magnitude stress) + constrained-random variable-length regression, virtual sequencer + smoke/regress virtual sequences, length×sign-cross×zero coverage, result-contract SVA (one-cycle out_valid pulse, causality vs in_valid&in_last, no-X) |
day13-tensor_core_dotproduct/ |
| 14 | UVM GPU Memory-Coalescing Unit Verification | Warp load/store address coalescer (per-lane byte addresses + active mask → minimum set of cache-line transactions, the coalesced-access / memory-efficiency block), source agent (warp-request driver/monitor) + sink agent (line-stream back-pressure driver + transaction monitor), golden coalescing reference model reused by scoreboard and coverage (unique lines in first-seen lane order, per-line lane mask, txn_last, lossless/disjoint lane accounting), directed showcase (8 lanes→2 lines) + corners (fully coalesced, fully scattered, partial mask, all-disabled→0 txns, single lane) + constrained-random regression under random back-pressure, virtual sequencer + smoke/regress virtual sequences, active-lanes×#lines×efficiency coverage, streaming SVA (mask≠0, VALID-held-stable, disjoint lanes, txn_last drains last pending, no-X) |
day14-memory_coalescing_unit/ |
| 15 | UVM GPU SIMT Reconvergence-Stack Verification | Hardware SIMT divergence/reconvergence stack of {active-mask, PC} entries (the warp control-flow block: INIT launch, DIVERGE split into taken/fall-through with true-divergence push, uniform-taken and uniform-fall-through retarget, POP reconverge, full/cmd_ready overflow guard), single command agent (driver + monitor pairing each accepted command with its resulting TOS status one cycle later), golden shadow-stack predictor reference model reused by scoreboard and coverage (checks tos_mask/tos_pc/sp/empty/full every command), directed launch→diverge→reconverge→retire showcase + corners (uniform branches, nested divergence, single-lane warp, empty-warp launch, pop-past-empty) + constrained-random legal-program regression, virtual sequencer + smoke/regress virtual sequences, op×divergence-outcome×depth coverage, SVA (depth bound, grow-by-2, shrink-by-1, empty⇔sp==0, nonzero TOS mask, no-X) |
day15-simt_reconvergence_stack/ |
| 16 | UVM GPU Shared-Memory Bank-Conflict Serializer Verification | Warp shared-memory access serializer (per-lane word addresses → bank = addr%NBANKS, one distinct address per bank per phase), broadcast (same-bank/same-address lanes coalesced) + bank-conflict serialization (same-bank/different-address lanes drained one per phase) + parallel independent banks, request driver/monitor that reassembles {request, its phase-beat list}, golden bank-conflict reference model reused by scoreboard (beat-for-beat ph_served/ph_bank_use + phase-count check) and coverage, directed showcase (3-way bank-0 conflict + broadcast + 4 parallel banks) + corners (conflict-free 8-way, full broadcast, worst-case 8-way serialized, partial mask, single lane, all-inactive empty phase) + constrained-random regression, virtual sequencer + smoke/regress virtual sequences, conflict-degree×active-lanes×broadcast coverage, streaming SVA (ready⇔idle, contiguous stream, monotonic ph_index, progress, no-X) |
day16-bank_conflict_serializer/ |
| 17 | UVM GPU Warp-Level Bitonic Sorting-Network Verification | Fully-pipelined Batcher bitonic sort of an N-record warp (the GPU sort / top-K / order-book-priority primitive: data-independent compare-exchange schedule, NSTAGE = log2(N)·(log2(N)+1)/2 registered layers, fixed LAT = NSTAGE+1, zero-bubble streaming), records are {key, tag} compared as one unsigned word → total order → deterministic duplicate-key handling (tag = order-id tie-break), runtime ascending/descending (in_dir), driver streams one vector per cycle + monitor FIFO-pairs each input vector with its sorted output (latency-independent), independent insertion-sort golden reference reused by scoreboard (lane-by-lane exact match ⇒ sorted permutation) and coverage, directed showcase (reverse-ramp ascending sort) + corners (descending sort, already-sorted identity, equal-keys tie-break, all-identical, min/max extremes, single large element, zero-bubble back-to-back stream) + constrained-random regression with forced-duplicate-key vectors, virtual sequencer + smoke/regress virtual sequences, direction×orderedness×distinct-keys×extremes coverage, SVA (fixed-latency contract, per-lane monotonicity split by direction, no-X) |
day17-bitonic_sorting_network/ |
| 18 | UVM GPU Warp-Level Parallel Prefix-Sum (Scan) Verification | Fully-pipelined Kogge-Stone parallel prefix-sum over an N-lane warp (the GPU scan primitive behind stream-compaction / radix-sort digit counts / histogram-CDF / warp-aggregation, and the HFT running-cumulative-volume / order-book-depth ladder & running-P&L block: data-independent add schedule, L = log2(N) registered layers lane[i]+=lane[i-2^(s-1)], fixed LAT = L+2, zero-bubble streaming), runtime inclusive/exclusive scan (in_excl; exclusive lane 0 = additive identity), signed modular DW-bit accumulation with deterministic wraparound, driver streams one vector per cycle + monitor FIFO-pairs each input vector with its scanned output (latency-independent), independent sequential modular-prefix golden reference reused by scoreboard (lane-by-lane exact ⇒ correct running sums + mode) and coverage, directed showcase (inclusive ramp 1..8 → triangular 1,3,6,10,15,21,28,36) + corners (exclusive ramp, all-zero, single one, alternating +1/−1, 16-bit wraparound, large-negative, zero-bubble back-to-back stream) + constrained-random regression with small-signed-magnitude vectors, virtual sequencer + smoke/regress virtual sequences, mode×total-sign×zero-content×wrap coverage, SVA (fixed-latency contract, exclusive-lane-0-is-zero, no-X) |
day18-prefix_sum_scan/ |
| 19 | UVM Best-Bid/Best-Offer (BBO) Top-of-Book Reduction-Tree Verification | Fully-pipelined argmax + argmin reduction tree over an N-level price ladder — the single most latency-critical block in an FPGA matching engine / market-data handler (top-of-book: every cycle emit best bid = highest price + its level and best offer = lowest price + its level; the generic hardware winner-take-all / priority-select / top-1 primitive): balanced tree collapses N candidates to 1 in L = log2(N) registered compare layers, fixed LAT = L+2, zero-bubble one-snapshot-per-cycle streaming, deterministic lowest-index-wins tie-break (left child always lower index ⇒ keep-left-on-tie is globally lowest-index), per-level populated-mask so empty levels never win + empty-book identity outputs (any=0, max=0, min=all-ones), driver streams one ladder per cycle + monitor FIFO-pairs each ladder with its BBO result (latency-independent), independent lowest-index argmax/argmin golden reference reused by scoreboard (value+index+any exact match) and coverage, directed showcase (full book 110@lvl3 tie→lvl3, offer 100@lvl0) + corners (single level, empty book, simultaneous max+min ties, all-equal, price extremes 0x0000/0xFFFF, sparse mask, zero-bubble back-to-back stream) + constrained-random regression with tie-forcing small-range prices, virtual sequencer + smoke/regress virtual sequences, occupancy×max-tie×min-tie×edge coverage, SVA (fixed-latency contract, best-bid≥best-offer, index-in-range, no-X) |
day19-bbo_reduction_tree/ |
| 20 | UVM Pre-Trade Risk-Check Gate ("Fat-Finger" Order-Validation Gateway) Verification | Fully-pipelined, fixed-latency (LAT=PIPE+1) pre-trade risk gate — the first, most latency-critical block in an FPGA trading gateway: validates one order {side,price,qty} per cycle (zero-bubble) against runtime-programmed limits and emits accept/reject + a strict-priority reason code (1 qty-zero, 2 qty-max, 3 price-band/collar, 4 max-notional price*qty, 5 net-position limit), maintaining a stateful signed net-position accumulator that advances only on accepts and enforces a symmetric ±pos_limit; UVM driver programs the limits then streams orders, latency-independent FIFO-pairing monitor, independent stateful golden reference model reused by the scoreboard (checks accept+reason+echoed side+running position in arrival order), directed showcase (one order per reject reason + accepts + a position-reducing sell) + boundary corners (values exactly at every limit accepted, strict +1 breaches rejected on both position limits, a full swing +pos_limit→0→-pos_limit) + constrained-random regression squeezed toward the limits, virtual sequencer + smoke/regress virtual sequences, reason×side coverage, SVA (fixed-latency contract, accept⇔reason==0, reason-in-range, no-X) |
day20-risk_check_gate/ |
| 21 | UVM Market-Data Sequence Gap Detector & Duplicate Suppressor Verification | Cut-through, fixed-latency (LAT=PIPE+1) feed-handler front end — the first, most latency-critical block in an FPGA market-data / ticker-plant ingest path: sanitizes a monotonically-numbered message stream (exchanges publish it on redundant A/B lines) so downstream sees each sequence exactly once, in order. Against a running next-expected counter it classifies every message PASS (in-order → forward, advance), DUP (seq < expected → duplicate B-line copy or stale retransmit → drop, freeze), or GAP (seq > expected → report gap = seq−expected missing-message count for the retransmit request, forward, and resync expected := seq+1); a detector/sanitizer, not a reorder buffer, so it never stalls the line-rate stream. UVM driver programs the session start (cfg_init_seq) then streams one message/cycle zero-bubble, latency-independent FIFO-pairing monitor, independent stateful golden reference model reused by the scoreboard (checks action + forward flag + gap size + echoed seq + running next-expected in arrival order), directed showcase (PASS / duplicate-copy / gap=2 / stale-retransmit in one zero-bubble stream) + corners (resume, immediate duplicate, minimal gap-of-1, large gap, far-behind stale, resync-and-continue) + constrained-random regression that random-walks around the expected sequence, virtual sequencer + smoke/regress virtual sequences, action×gap-size coverage, SVA (fixed-latency contract, action-in-range, fwd ⇔ action≠DUP, gap≠0 ⇔ GAP, no-X) |
day21-gap_detector/ |
| 22 | UVM Token-Bucket Order-Rate Limiter ("Exchange Gateway Throttle") Verification | Cut-through, fixed-latency (LAT=PIPE+1) token-bucket rate limiter — the outbound self-policing throttle in an FPGA trading gateway that keeps a firm under the exchange's orders-per-second ceiling before a message leaves the wire: a lazy-refill bucket where each request carries a monotonically non-decreasing timestamp ts so refill = (ts−last_ts)·REFILL_PER_TICK saturated at BUCKET_MAX is realized on access (no per-cycle adder) — making admission a pure function of the {ts,cost} stream, latency-independent and transaction-checkable; against the refilled level it emits a strict-priority reason code (0 GRANT spend cost, 1 THROTTLE rate-exceeded, 2 ZEROCOST malformed, 3 OVERSIZED cost>BUCKET_MAX unsatisfiable) + grant flag while advancing the running {tokens,last_ts} on every accepted request; UVM driver programs the session (cfg_init_ts, bucket→full) then streams one request/cycle zero-bubble, latency-independent FIFO-pairing monitor, independent stateful golden token-bucket reference model reused by scoreboard (grant+reason+echoed ts/cost+available+remaining tokens in arrival order) and coverage, directed showcase (burst-drain→throttle→refill-recover→zerocost→oversized in one zero-bubble stream) + corners (long-idle saturation, exact-boundary grant, one-over throttle, single-shot full drain, oversized, zerocost) + constrained-random regression with same-tick bursts and limit-squeezed costs, virtual sequencer + smoke/regress virtual sequences, reason×cost-class + avail-level coverage, SVA (fixed-latency contract, reason-in-range, grant⇔reason==GRANT, tokens≤BUCKET_MAX, grant-implies-could-pay, monotonic timestamps, no-X) |
day22-token_bucket_limiter/ |
| 23 | UVM Streaming CRC-32 (Ethernet FCS) Generator/Checker Verification | Byte-serial one-byte-per-cycle reflected CRC-32 / ISO-HDLC engine (the zlib / PNG / IEEE-802.3 Ethernet Frame-Check-Sequence block, poly 0xEDB88320, init/xorout 0xFFFFFFFF) — bit-identical to zlib/binascii.crc32 so an independent golden model checks it byte-for-byte (canonical CRC32("123456789")==0xCBF43926), sop/eop-framed zero-bubble stream with a per-frame mode latched at sop: GENERATE (emit the FCS a transmitter appends) + CHECK (receiver residue verdict — a good frame's message‖FCS folds to the constant residue 0x2144DF1C ⇒ out_ok=1, a corrupted frame ⇒ out_ok=0), fixed latency LAT=PIPE from in_eop, full UVM env (byte-stream driver + frame-reconstructing monitor, FIFO golden-CRC scoreboard checking {crc,mode,ok} in arrival order, mode×length-class + mode×ok coverage, smoke/regress virtual sequences), directed showcase ("123456789" FCS + good/corrupt check frame) + corners (single-byte, all-zero, all-0xFF, back-to-back zero-bubble) + constrained-random mixed-mode regression with single-bit-corrupted check frames, SVA (fixed-latency contract, result-caused-by-eop, generate-mode ok, sop/eop⇒valid, no-X) |
day23-crc32_codec/ |
| 24 | UVM SECDED (72,64) Extended-Hamming ECC Encoder/Decoder Verification | Parameterized Single-Error-Correct / Double-Error-Detect extended-Hamming ECC engine — the integrity guard inside memory (every ECC DRAM DIMM, cache line, register file, on-die SRAM): where a CRC only detects wire corruption, an ECC code corrects it in place. Showcased at the classic (72,64) geometry (64 data + 8 check bits): HAM = smallest r with 2^r ≥ DW+r+1 Hamming parity bits at power-of-two positions + one overall parity bit lifting plain Hamming (SEC) to SECDED, textbook construction so an independent model is bit-exact (verified in Python over 200k words × {0,1,2} flips before RTL). Per-op ENCODE (data→codeword) / DECODE (received word→corrected data + raw syndrome + sbe/dbe verdict) at fixed latency LAT=PIPE, zero-bubble; decode classifies on {P,S} = {overall-parity, syndrome}: 0/0 clean, 1/· single-bit corrected (sbe), 0/≠0 double-bit detected uncorrectable (dbe). Full UVM env — driver that golden-encodes then injects nflip faults, request/result-pairing monitor, FIFO golden-model scoreboard checking {op,code,data,syndrome,sbe,dbe} bit-for-bit in arrival order (model mirrors the DUT's exact correction so even the double-bit "correction" matches), op×error-class{none,single,double} + syndrome-zero coverage, smoke/regress virtual sequences — plus directed showcase (encode → clean/1-bit/2-bit decode) + corners (all-zero, all-ones, Hamming-parity-bit / overall-parity-bit / data-bit flips, back-to-back zero-bubble) + constrained-random 0/1/2-flip fault campaign, SVA (fixed-latency contract, result-caused-by-request, sbe/dbe mutually exclusive, ENCODE-never-errors, no-X) |
day24-secded_ecc/ |
| 25 | UVM Rotation-Mode CORDIC (Hardware sin/cos & Vector Rotator) Verification | Fully-pipelined rotation-mode CORDIC — the multiplier-free shift-and-add vector rotator behind every hardware sin/cos generator, polar⇄rectangular converter, DDS/QAM/SDR phase rotator, and FFT twiddle-multiply: NITER=16 registered micro-rotations by ±atan(2^-i) drive the angle accumulator to zero so (x,y) ends up rotated by the requested angle and scaled by the constant CORDIC gain K≈1.64676 (x_out≈K·(x·cos−y·sin), y_out≈K·(x·sin+y·cos); preload x=round(2^13/K)=4975,y=0 to read cos/sin directly), fixed latency LAT=NITER+1=17, zero-bubble; a combinational quadrant-fold pre-stage maps any angle in [-π,π] into [-π/2,π/2] (native convergence is only ` |
z |
| 26 | UVM I²C Master Controller Verification | Single-master open-drain I²C controller (the two-wire SDA/SCL bus behind every board-level sensor / EEPROM / RTC / codec / PMIC) — the classic serial link that completes UART (Day 4) and SPI (Day 11), and whose distinctive verification challenge is the bidirectional wired-AND open-drain bus: a device never drives a hard ‘1’, only pulls low or releases to a pull-up, SDA must be stable while SCL is high and change only while SCL is low, and START/STOP are defined by the illegal-looking SDA-transition-while-SCL-high. DUT does one single-byte 7-bit-addressed transaction per start: WRITE = START·{addr,W}·[ACK]·data·[ACK]·STOP, READ = START·{addr,R}·[ACK]·data(slave)·masterNACK·STOP, raising ack_error when the address is not ACKed; programmable bit rate (DIV, SCL period 4·DIV clks) via a four-quarter-per-bit scheme so SDA only moves in the SCL-low quarter. Full UVM env — transaction-level driver (programs the slave read byte, pulses start, waits done) + monitor (latches the request at launch, publishes {ack_error,rd_data,slave-captured-write-byte} at done), independent transaction-level golden reference model reused by scoreboard (ack_error + read byte == slave memory + written byte == slave capture, in arrival order) and coverage, a behavioral open-drain I²C slave model (START/STOP detect, address-match ACK/NACK, write capture, MSB-first read playback) as the bus far end, rw×ack cross + data-class {0x00,0xFF,mid} coverage, smoke/regress virtual sequences — plus directed showcase (write, read, address-NACK on both R/W, data corners) + constrained-random regression (208 checks PASS on Icarus), SVA (done one-cycle pulse, done-inside-busy, no-X on bus while busy) |
day26-i2c_master/ |
| 27 | UVM Self-Synchronizing Scrambler/Descrambler (10GBASE-R PCS) Verification | Parameterized WIDTH-bit-parallel multiplicative (self-synchronizing) scrambler/descrambler — the SerDes physical-layer data-whitening block (IEEE 802.3 10GBASE-R PCS, generator G(x)=1+x^39+x^58, 58-bit state) that guarantees clock-recovery transitions and spreads the line spectrum; the SerDes companion to the link-layer CRC (Day 23) / ECC (Day 24) and the serial buses UART/SPI/I²C. One RTL module covers both directions via MODE_DESCRAMBLE (only the bit fed into the register differs), with the WIDTH serial steps unrolled in always_comb (the classic parallelize-the-LFSR exercise). The headline verified property is self-synchronization: the descrambler is deliberately reset to a different seed than the scrambler yet re-derives the transmitter state from the received bits alone and recovers the payload exactly from word ceil(58/8)=8 (58 received bits) on. Full UVM env — one-word/cycle zero-bubble driver + input monitor + midpoint/endpoint output monitor, independent bit-serial golden reference model (a different implementation from the parallel RTL, pinned to 28 Python Known-Answer vectors) reused by scoreboard (scrambled bit-exact + descrambled bit-exact + self-sync recovery == original once locked) and coverage, data-class×wire-error + lock-state coverage, smoke/regress virtual sequences — plus directed showcase (self-sync recovery from a wrong seed = the captured waveform, all-zero whitening) + corners (valid-gap hold, single-bit wire error → bounded 0/39/58 error burst → automatic re-lock, all-ones burst) + constrained-random regression (~4000 words, 0 errors on Icarus), SVA (per-stage fixed-latency out_valid==prev in_valid, no-X) |
day27-scrambler_descrambler/ |
| 28 | UVM IEEE-754 binary32 Floating-Point Adder/Subtractor Verification | Fully-pipelined IEEE-754 binary32 (single-precision) floating-point adder/subtractor — the block inside every FPU, GPU shader core, DSP MAC and neural-net accumulator, and the canonical example of a design whose happy path is trivial while its corner space is enormous: alignment (the smaller operand shifted right by the exponent difference, with everything past the end OR-ed into a sticky bit so a 2^-100 term still nudges the rounding of a 2^100 one), cancellation (a-b with a≈b destroying up to 24 significand bits and needing a full-width leading-zero normalise), round-to-nearest-EVEN on {L,G,sticky} (exact ties rounding toward the even significand, a round-up carrying straight out of the significand into exponent++), subnormals (no hidden bit + fixed effective exponent on input; normalisation clamped at the exponent floor on output; subnormal→normal round-up and normal→subnormal cancellation), and specials (signed zeros with (-0)+(-0)=-0 but (+0)+(-0)=+0, x+(-x)=+0, infinity arithmetic, (+inf)+(-inf)→invalid, NaN precedence over inf, overflow→inf, canonical qNaN 0x7FC00000 so the result is a pure function of the operands) — three register stages, fixed latency LAT=3, one result per cycle zero-bubble, plus the four exception flags {inv,ovf,unf,inx}. The methodological centre of gravity is "what checks the checker?": a rounder's reference model is as easy to get subtly wrong as the RTL, so the golden model is pinned to the host CPU's own IEEE-754 hardware — docs/gen_kat.py cross-checks a Python model against numpy float32 bit-exactly over 400k+ randomised ops plus an exhaustive small-exponent sweep and emits a 48-row Known-Answer Table of numpy's answers; kat_selfcheck() replays it through the SystemVerilog model before any DUT result is judged; the KAT is then replayed through the RTL; and the RTL was separately driven against 200 000 numpy-derived vectors (result + all four flags): 0 mismatches. Full UVM env — one-op/cycle driver + latency-independent monitor publishing requests and results on separate ports, FIFO-pairing reference-model scoreboard (word + all four flags, arrival order, readable float-form mismatch reports), coverage collector downstream of the scoreboard so operand class can cross result class, virtual sequencer + smoke/regress virtual sequences — plus directed showcase (the captured waveform) + KAT replay + a 16x16x{add,sub}=512 landmark cross-product + a half-ULP tie campaign (alternating even/odd retained LSB, plus quarter- and three-quarter-ULP neighbours) + the subnormal exponent floor + the overflow boundary + kind-shaped constrained-random regression (5958 ops, 0 mismatches on Icarus, 382 subnormal and 172 infinite results), operand-class×result-class / alignment-distance / flag coverage with four crosses, SVA (fixed-latency contract, causality, canonical-NaN-only, ovf⇒inx∧inf, inv⇒qNaN, no-X) — and one proven invariant asserted rather than assumed: since the exact sum of two binary32 values is always a multiple of 2^-149, addition can never round inside the subnormal range, so underflow is unreachable (out_unf must always be 0 — true for add/sub, NOT for multiply/divide) |
day28-fp_adder_subtractor/ |
| 29 | UVM 8b/10b Line-Code Encoder/Decoder Verification | The SerDes physical-layer line code behind Gigabit Ethernet (802.3 cl.36), PCIe gen1/2, SATA, DisplayPort and Fibre Channel — the layer underneath the CRC (Day 23), ECC (Day 24) and scrambler (Day 27): it maps each byte to a 10-bit codeword so the wire gets DC balance (4/5/6 ones per word, running disparity pinned to ±1 forever, so an AC-coupled link can pass it), transition density (no run > 5 bits, so the CDR never starves) and framing (12 control K symbols outside the 256 data codewords, three carrying the comma 0011111/1100000 that by construction only occurs symbol-aligned — how a receiver finds symbol boundaries in a raw bit stream). Encoder = 5b/6b + 3b/4b sub-block tables with RD threaded through both halves in sequence, plus the three exceptions that carry all the subtlety: the balanced-but-still-alternating entries D.07 and D.x.3, the alternate D.x.A7 3b/4b encoding at six x values, and control sub-blocks that alternate even when balanced. Receiver = decode-then-verify-by-re-encode (reverse sub-block tables recover a candidate in O(1), then the candidate is pushed back through the encoder's own rules and compared with what arrived) making it strict — it rejects sub-block pairs no transmitter can emit — and classifying every possible word as clean / disparity error (a codeword, wrong polarity for RD) / code error (not a codeword), with RD advanced from the bits that arrived so corruption costs a transient, self-correcting RD disagreement. The methodology centre of gravity is "a table code is wrong in ways that still work" — a transposed bit gives RTL whose encoder and decoder share the typo, round-trip all 256 bytes, and violate the line code on the wire — so the tables are proved, not transcribed: docs/gen_kat.py checks the five defining properties exhaustively (DC balance, bounded RD, run ≤ 5 across all ~143 000 legal codeword junctions, unique decodability, comma uniqueness/alignment/non-manufacture) and caught 2714 violations from exactly the two balanced-alternating entries on its first run; it also derives the standard's K.28.7 restriction (the 64 successors that would break run ≤ 5 or forge a comma) rather than assuming it. The golden model then contains no rules at all — a flat 1024-entry encode ROM plus a 2048-entry decode table built by brute-force inversion — so a DUT rule bug cannot hide in it, and property_selfcheck() + a 48-vector KAT re-prove the model inside the simulator before any DUT result is judged. Full UVM env — one-symbol/cycle zero-bubble driver, request/transmit/receive monitors, dual-queue reference-model scoreboard (codeword, wire word, both RDs, kerr, comma, recovered symbol, both error verdicts), coverage downstream of the scoreboard so symbol class crosses result verdict, smoke/regress virtual sequences — plus directed showcase (the captured waveform: comma framing, a caught bit error, and an unencodable request whose all-zero word knocks the receiver's RD out of step, surfacing one symbol later then self-correcting) + all 256 data bytes + all 12 K symbols from both RD states + the alternate-encoding corners + a bit-flip walk across all ten wire positions + a single-bit error detection-latency sweep that measures rather than assumes (60 isolated flips: 39 flagged immediately, 21 flagged exactly 5 symbols later when the first RD-sensitive symbol arrives, 0 never flagged) + pseudo-random regression (4944 symbols, 0 mismatches on Icarus), SVA (fixed-latency contract, DC balance, run-length across junctions with the derived K.28.7 exemption, comma provenance, error-class exclusivity, RD stability, no-X) |
day29-line_code_8b10b/ |
| 30 | UVM IEEE 1149.1 JTAG TAP Controller Verification | The most widely implemented state machine in digital hardware — the four-wire JTAG Test Access Port (TCK/TMS/TDI/TDO) inside nearly every chip made since 1990: how a bare board is tested before firmware exists, how a CPU is halted and single-stepped, how an FPGA is loaded, how an unknown device is identified. Full IEEE 1149.1 TAP — the sixteen-state controller driven by TMS alone (position in the state diagram is the entire protocol; there are no packets, addresses or handshakes), a 4-bit instruction register, and four data-register chains (BYPASS 1 bit, IDCODE 32, boundary-scan BSR_LEN, user USER_LEN) with the decode that selects between them: EXTEST, SAMPLE/PRELOAD, IDCODE, USER, CLAMP, BYPASS, and ten unimplemented opcodes that the standard requires to fall through to BYPASS. Three things make it a near-perfect DV subject rather than a trivial FSM. The state diagram is the specification — sixteen states, thirty-two arcs, and the promise the whole standard rests on: five TCK clocks with TMS high reach Test-Logic-Reset from anywhere, which is a property over all sixteen starting states, not a waveform. Both clock edges carry meaning — TMS/TDI sampling, the state transition, capture and shift on the rising edge; the update latches and TDO on the falling edge, so a parallel output never moves while the shift path does. And the register action at an edge belongs to the state the controller was in before it, so Capture-DR→Shift-DR captures on the first edge and shifts on the second — off by one edge and every symptom is a wrong bit ten cycles downstream of the cause. It also carries the series' highest ratio of mandatory small print to gate count, all of it verified: Capture-IR must load a pattern with LSB=1 (how a tester tells a live TAP from a chain stuck at zero), IDCODE bit 0 must be 1, an unimplemented opcode must select BYPASS, Pause-DR/Pause-IR must be transparent to a tester that steps away mid-chain, and CLAMP must select BYPASS's one-bit register while still driving the boundary — the single instruction where chain selection and boundary drive disagree, and the line a checker that assumes they move together fails on. Verified two ways on purpose. A cycle-exact scoreboard steps a pure-function whole-cycle reference model (ref_tap_cycle, written from the standard's diagram, structurally nothing like the RTL) once per rising edge and compares eight signals on every rising and every falling edge — state, IR shift register, TDO, tdo_en, latched instruction, both update latches, boundary drive; and a second, model-independent transaction scoreboard reassembles whole scans from the state sequence and restates the requirements in a different form (IDCODE constant + bit 0, boundary captured pin_in as it stood at the Capture-DR edge, the last chain_len bits shifted in reaching the update latch, BYPASS/CLAMP/unimplemented being exactly one flip-flop of delay, the Capture-IR LSB, the last four IR bits becoming the instruction) — so a model and DUT sharing one misreading cannot both pass. ref_selfcheck() re-proves seven mandatory properties inside the simulator (five-TMS reset from all sixteen states, all sixteen reachable by breadth-first walk, the Capture-IR LSB, all ten unimplemented opcodes landing on BYPASS, CLAMP's split, end-to-end scan of each chain) before a single DUT result is judged. Full UVM env — two agents, because a real device does not hold still while it is scanned: the TAP agent walks the diagram while a pin agent keeps the mission-side capture sources moving underneath it, forked by virtual sequences (join_any/disable fork, pin sequences running forever so the TAP side sets each phase's length) — one atomic rising-edge pin monitor carrying this cycle's stimulus and last cycle's complete result (a falling-edge monitor would sample TDO one edge before the edge that changes it, and pairing two same-timestep streams races), a protocol-level scan monitor, 12 sequences, smoke/regress virtual sequences — plus 16 directed scenarios (TRST_n, five-TMS reset from Shift-DR, IDCODE with no IR scan first, the Capture-IR pattern, BYPASS, an unimplemented opcode, the real SAMPLE→PRELOAD→EXTEST→CLAMP board-test flow, the user register, chain isolation, Pause-DR, Pause-IR, Select-IR-Scan's three-clock path home, all sixteen opcodes, TRST_n mid-shift) + a 6000-cycle random TMS/TDI walk (legal stimulus precisely because the checker is driven off the pins rather than the testbench's intent — it abandons scans mid-chain and lingers where no directed test goes) + 300 random complete scans: 28 512 edges checked, 0 mismatches, 16/16 states and 32/32 transitions on Icarus, with a coverage hole failing the run. Coverage crosses the sixteen states with TMS to enumerate all thirty-two diagram arcs; 7 SVA in the DUT + 12 SVA and 6 cover properties in the interface. Mutation-tested: four one-line DUT slips — Capture-IR dropping its mandatory LSB, unimplemented opcodes selecting the boundary register, one wrong next-state entry, and the update latch loading on the rising edge instead of the falling — are all caught, the last of them invisible to any transaction-level check (the final scan content is identical; only when the device's output pins move changes), which is why the checker is cycle-exact |
day30-jtag_tap_controller/ |
| 31 | UVM Write-Back / Write-Allocate Cache Controller Verification | The first block most engineers meet where the design is deliberately, continuously wrong and that is the point: after a store hits a write-back cache, DRAM holds the old value, and it is supposed to. A direct-mapped, write-allocate, blocking cache controller (8 sets x 4 words/line, 25-bit tag, byte strobes) with the full FSM - `IDLE -> LOOKUP -> {RESP | EVICT -> FILL -> ALLOC -> RESP}plus anFSCAN/FWBmaintenance walk - where a store that misses generates a *read* burst (write-allocate), a conflicting access to a dirty line writes the **whole** line back to the **resident** tag's address before it can fill the new one, and a flush cleans every dirty line **without invalidating** it. Two tags over one index thrash on every access, so eviction is one line of stimulus rather than a rare corner. What makes it a genuine DV problem rather than an FSM exercise is that **checking the CPU port is not enough**: a cache can return perfect load data forever while quietly writing the wrong line to the wrong address behind your back, and nothing on the response channel will ever notice. So the golden model keeps **two memory images** -ref_arch[], the architectural value a load must return, and ref_back[], what DRAM should physically contain - which are equal everywhere *except* inside a resident dirty line, and eviction/flush is precisely the event that reconciles them; a single-image model cannot express the bug class that matters most. The scoreboard checks four independent things: every response (data **and** an exact hit/miss prediction, not a range); **physical memory after every flush**, compared word for word against a mirror rebuilt from *observed memory-port writes alone*; the **traffic itself** (mem writes == (evicts + flush_wbs) x LINE_WORDS, mem reads == fills x LINE_WORDS) so a cache that writes back twice or drops a beat fails even when the data is right; and the handshake protocol. Reset is modelled **honestly**, not conveniently - it clears valid/dirty and therefore *discards* every store not yet written back, so a load afterwards legitimately returns the old data; ref_hw_reset()rolls the architectural view back rather than relaxing the check, because that shortcut is exactly how a real data-loss bug reaches silicon.ref_selfcheck()re-proves ten model invariants inside the simulator before a single DUT result is judged. Full UVM env - **two agents**, because the slave side is not a passive wire: the CPU agent drives loads/stores/flushes and ownsrst_n(resetting a cache full of dirty lines is under test, and a reset that could only happen at time zero would never reach it), while the memory agent's driver **is** the backing memory and its monitor is the scoreboard's only window onto what the cache actually wrote to DRAM. The memory response policy is a **sequence item**, not a config field, socache_regress_vseqcan run the directed scenarios against an instant always-ready memory - a failure there is unambiguously the cache - thenkill()that policy mid-test and re-run the same design against 20-70% stall rates and 0-8 cycle read latencies, which is exactly where fill/evict interaction bugs live. Addresses randomise as(tag, set, word)rather than as flat 32-bit numbers, because "same set, different tag" is the interesting stimulus for a direct-mapped cache and is trivial to constrain in that form; a **locality term** keeps half the random accesses on the previous line, without which the stream is ~88% misses and the hit path - the one a real workload takes most often - is barely exercised. 8 SVA in the DUT (including *a hit costs no memory traffic*) + 6 in the interface constraining **both** sides of the wire; coverage crosses op x hit/miss (read-miss is the fill path, write-miss is the write-allocate path), every set, tag and word offset, all 16 strobe patterns, hit/miss **transition pairs**, and memory direction x word offset so a burst that drops its first or last beat cannot hide. 18 directed scenarios + 2000 constrained-random accesses with backpressure, periodic flushes and a mid-stream reset: **2075 accesses, 1167 hits / 908 misses, 3624 memory reads and 2972 writes all reconciled beat-for-beat, 0 mismatches on Icarus**, with any coverage hole *failing the run*. **Mutation-tested**: eight one-line DUT slips - flush leaving lines dirty, flush invalidating, allocate ignoring byte strobes, writeback using the new tag instead of the resident one, an index-only tag compare, a fill dropping its last word, an eviction writing 3 of 4 words, and a flush skipping the last set - are all caught; a ninth (*eviction forgets to cleardirty*) is honestly reported as an **equivalent mutant**, since ALLOC` reassigns that bit unconditionally on the next state |
| 32 | UVM MESI Snooping Cache-Coherence Verification | Day 31 verified one write-back cache; this is what happens when a second one sits next to it. Two MESI L1s on a shared snoop bus (round-robin arbiter, wired-OR snoop response, cache-to-cache flush, backing-memory port) - and the bug class that appears the moment there are two caches is the one with no local symptom at all: core 0 writes a line, core 1 reads the same address and gets the stale value from DRAM, and both caches behaved exactly as designed. Nothing on either CPU port is out of spec; the error exists only in the relationship between them. That makes coherence a genuinely different verification problem rather than a bigger one, because there is no expected output to compare against - feed the same two instruction streams in twice and the caches legitimately end up in different states, since the interleaving is chosen by the bus arbiter and not by the testbench. So nothing here checks a value against a prediction of what the DUT will do; it checks invariants, in three independent layers a bug must survive all of. (1) The data-value invariant, black-box and order-agnostic: every bus transaction is globally serialised and each core has one access outstanding, so completion order is a valid total order, and against it the rule is absolute - a load returns the value of the most recent store - checked on all 2924 completions. Completion order is legal rather than convenient precisely because SWMR makes a same-cycle read-hit and write-hit to one address mutually exclusive: the ordering the checker relies on is guaranteed by the property it is checking. (2) The state invariants, white-box and deliberately model-free, read straight out of both caches' tag/state arrays on every edge - SWMR (an M or E copy must be the only copy), no-two-dirty, and sharer agreement; model-free because the model updates its architectural view at completion while the RTL updates its arrays one to two cycles earlier, so an every-cycle model comparison would flag legal behaviour across that skew. (3) State prediction and full reconciliation at quiesce, where the model - a flat table applying the transition rules, structurally nothing like the RTL's FSM - re-derives every cache's state from the observed bus event stream, with pmem[] rebuilt from observed memory-port writes alone, because a cache that returns perfect load data forever while writing the right data to the wrong address is the bug that matters most. Plus exact traffic reconciliation (mem writes == flushes + writebacks, mem reads == fetches - cache-supplied: 810 == 282+528, 890 == 1172-282), so a cache that writes back twice or fetches a line another cache already owned fails even when every value is right. The headline property is why E exists: a read miss nobody answers installs E, not S, so a later store goes silently to M with zero bus transactions - verified as a traffic property, since installing S instead leaves the design functionally perfect, every load correct, every private store now paying for a pointless BusUpgr, and a value-comparing scoreboard entirely silent. Two design decisions came from verification: eff_state reconciles the CPU lookup with a snoop landing the same cycle (so an invalidation turns a hit into a miss rather than a write to a line just taken away), and cpu_ack is combinational so the announcement and the commit are the same edge - with a separate response state any checker would apply a racing invalidation to the wrong version of the line. The nastiest corner is the upgrade race: both cores hold S, both store, the loser's queued BusUpgr is a lie by the time it is granted and must become a full BusRdX. Full UVM env - two ACTIVE CPU agents (coherence bugs only exist between cores; a single-agent environment cannot produce one) + a memory agent whose driver IS the memory and whose monitor is the only window onto DRAM, its response policy a sequence item so the regression runs directed scenarios against an instant memory then re-runs the same design against 20-70% stalls and 1-8 cycle reads, + a passive bus agent; a cycle-binned scoreboard that stamps every event with its cycle and processes a cycle only once closed, in a fixed order (launches -> memory write -> address phase -> completion -> CPU completions -> invariants), because UVM does not order analysis writes within a time step and a snoop landing with a completion must be applied first; coverage downstream of the scoreboard so op crosses the state the access found, closing on all ten arcs of the MESI state diagram with a missing arc failing the run. ref_selfcheck() re-proves 7 protocol properties inside the simulator before any DUT result is judged, and reset is modelled honestly - it discards every un-written-back store and rolls the architectural view back. 22 scenarios + 2000 constrained-random accesses across four memory behaviours including a mid-stream reset: 2924 accesses, 13803 cycles of SWMR, 1797 bus transactions, 123 silent E->M upgrades, 282 cache-to-cache flushes, memory traffic reconciled exactly, 0 errors, 0 coverage holes on Icarus. Mutation-tested: nine one-line coherence slips - MESI degraded to MSI, a shared line claimed exclusively, remote read invalidating instead of downgrading, remote store downgrading instead of invalidating, a dirty owner that never flushes, a writeback using the new tag, a store on S treated as a hit, a queued BusUpgr never downgraded, and an index-only tag compare - are all caught, by six different checks, so no layer of the checker is redundant with another |
day32-mesi_cache_coherence/ |
| 33 | UVM NoC Router Verification | Parameterized 3×3 ready/valid NoC router with per-input elastic buffers and independent per-output round-robin arbitration; three active source agents plus a sequenced sink/backpressure agent; golden destination function and per-output/per-source queue scoreboard checking exact routing, data, packet-end, loss, duplication, and source ordering while permitting any legal inter-source merge; directed all-to-one contention + constrained-random traffic coordinated by a virtual sequence; source×destination×last coverage; SVA for stable stalled transfers, legal destinations, and known output payloads; portable Icarus regression with a real captured waveform | day33-noc_router/ |
| 34 | UVM Instruction-TLB Verification | Parameterized fully associative I-TLB with ASIDs, global mappings, 4 KiB/2 MiB pages, execute permission, first-invalid/round-robin replacement, and selective/global invalidation; complete UVM agent, virtual sequence, independent shadow-table scoreboard, op×result and page-size×global coverage, SVA, directed CPU-front-end corners plus constrained-random replacement/invalidation stress; portable Icarus regression with a real captured waveform | day34-itlb_verification/ |
| 35 | UVM PCIe-Style Replay Buffer Verification | Parameterized circular replay buffer retaining sent packets until cumulative ACK; NAK restart from any outstanding sequence; complete UVM agent, virtual sequence, retained/send-queue scoreboard, event×occupancy coverage, SVA, directed backpressure/full/mid-window replay corners plus constrained-random bursts and sequence wrap; portable Icarus regression with a real captured waveform | day35-pcie_replay_buffer/ |
| 36 | UVM AXI Multi-ID Read Reorder Verification | Parameterized tagged reorder engine accepting multiple outstanding AXI-style reads; arbitrary out-of-order memory completion with strict in-order-per-ID retirement and legal cross-ID bypass; two active UVM agents coordinated by a virtual sequence; independent per-ID FIFO golden scoreboard; ID×error, occupancy, and backpressure coverage; SVA for stalled-channel stability, live-tag completion, and bounds; directed same-ID inversion plus constrained-random tag shuffling; portable Icarus regression with a real captured waveform | day36-axi_read_reorder/ |
| 37 | UVM CHI-Style Coherent Snoop-Filter Verification | Parameterized directory slice for ReadShared/ReadUnique/Evict; exact targeted-snoop and sharer-state checking with an independent shadow directory; requester plus response-flow agents coordinated by a virtual sequence; operation×node coverage; SVA for self-snoop exclusion, unique ownership, and stalled-response stability; directed dirty-owner/invalidation corners plus constrained-random replacement stress; portable Icarus regression with a real captured waveform | day37-chi_snoop_filter/ |
| 38 | UVM Scatter-Gather DMA Descriptor Engine Verification | Parameterized memory data mover with descriptor and active memory UVM agents coordinated by a virtual sequence; golden source-memory scoreboard for address/data/order/status; length×error and stall coverage; SVA for stable backpressured channels and completion; directed error/final-beat corners plus constrained-random transfers; portable Icarus regression with a real captured waveform | day38-scatter_gather_dma/ |
| 39 | UVM DDR Bank-Command Scheduler Verification | Parameterized open-page DDR scheduler translating requests into ACT/RD/WR/PRE; request and command-flow UVM agents coordinated by a virtual sequence; independent cycle-aware shadow-bank scoreboard for open-row state and tRCD/tRP/tRAS; command×bank and row-hit/conflict coverage; SVA for timing legality and stable backpressure; directed plus constrained-random traffic; portable Icarus regression with a real captured waveform | day39-ddr_bank_scheduler/ |
| 40 | UVM Two-Level Page-Table Walker Verification | Parameterized Sv32-style MMU page-table walker with 4 KiB and 4 MiB leaves; request and PTE-memory responder agents coordinated by a virtual sequence; independent VPN/PTE/permission scoreboard; access×result and leaf-level coverage; SVA for decoupled-channel stability and response consistency; directed invalid/permission/misalignment faults plus constrained-random walks and stalls; portable Icarus regression with a real captured waveform | day40-page_table_walker/ |
| 41 | UVM Gshare Branch-Predictor Verification | Parameterized global-history XOR predictor with saturating two-bit PHT; prediction and resolution UVM agents coordinated by a virtual sequence; independent shadow-PHT/history scoreboard; direction×accuracy and index coverage; SVA for index, mispredict, recovery, and known metadata; directed counter-saturation/aliasing plus constrained-random branches; portable Icarus regression with a real captured waveform | day41-gshare_branch_predictor/ |
| 42 | UVM Power-Domain Isolation and Retention Controller Verification | Parameterized low-power sequencer for save, isolate, power-off, wake, restore, and de-isolate; command and acknowledgment UVM agents coordinated by a virtual sequence; independent cycle-exact FSM scoreboard; state×power coverage; SVA safety invariants; directed timeout corners plus constrained-random acknowledgment delays; portable Icarus regression with a real captured waveform | day42-power_domain_controller/ |
| 43 | UVM Credit-Based High-Speed Link Controller Verification | Parameterized flit transmitter with bounded downstream credits; independent flit and credit-return UVM agents coordinated by a virtual sequence; atomic cycle monitor and golden accounting/payload scoreboard; occupancy×flow coverage; SVA for credit safety and blocked-request stability; directed drain/recovery/simultaneous-flow corners plus constrained-random traffic; portable Icarus regression with a real captured waveform | day43-credit_link_controller/ |
| 44 | UVM March C- SRAM BIST Controller Verification | Parameterized synthesizable March C- controller with decoupled SRAM command/response channels; control and reactive memory UVM agents coordinated by a virtual sequence; independent phase/address scoreboard; phase×operation and edge-address coverage; SVA for stable stalls and read-response ordering; clean-memory plus injected stuck-at-fault scenarios under constrained-random backpressure/latency; portable Icarus regression with a real captured waveform | day44-march_c_memory_bist/ |