Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cb93e3e
Fix lm_util_pkg helper function bugs
aca-logimentor Jul 6, 2026
f1be738
Fix clock_measure CDC chain and measurement window
aca-logimentor Jul 6, 2026
11e1e7f
Widen lm_util_bitsum output to fit the all-ones count
aca-logimentor Jul 6, 2026
6dffb0f
Fix pulse_stretch unit lengths, polarity and retrigger behavior
aca-logimentor Jul 6, 2026
d8864c4
Fix delay_pulse and delay_var pulse delay, polarity and dv_o
aca-logimentor Jul 6, 2026
1c54f7b
Fix counter down direction and test the load path
aca-logimentor Jul 6, 2026
54200bd
Harden synchronizer chains for synthesis
aca-logimentor Jul 6, 2026
4ea20ae
Extend regression coverage and update changelog
aca-logimentor Jul 6, 2026
8f74af8
Make CDC synthesis attributes multi-vendor and document constraints
aca-logimentor Jul 6, 2026
f3ae6a8
Avoid integer overflow in the counter watchdog range check
aca-logimentor Jul 6, 2026
394cf2b
Prevent pulse delay retrigger on long inputs and align dv_o
aca-logimentor Jul 6, 2026
cc219e3
Pin GHDL 6.0.0 and VUnit 4.7.1 for the regression
aca-logimentor Oct 17, 2026
d6384b9
Reject unsupported delay_var architectures for unit delay
aca-logimentor Oct 17, 2026
ae96b7e
Track the request level during reset in ccd_sync_bus
aca-logimentor Oct 17, 2026
a6278ef
Fix invalid Tcl in the Quartus and Lattice constraint examples
aca-logimentor Oct 17, 2026
151bde1
Make clock_mux synthesizable in Quartus again
aca-logimentor Oct 17, 2026
e829d84
Keep the clock_measure ready synchronizer free of reset logic
aca-logimentor Oct 17, 2026
73609c3
Check synchronizer structure in vendor synthesis
aca-logimentor Oct 17, 2026
6d8605b
Keep bus indices literal in the braced Quartus examples
aca-logimentor Oct 17, 2026
6a18fdf
Select CDC constraint examples by signal name and check them
aca-logimentor Oct 17, 2026
e4e5952
Prepare the v0.1.0 changelog and record vendor verification
aca-logimentor Oct 17, 2026
9536e85
Publish no clock_measure value before a complete post-reset window
aca-logimentor Oct 18, 2026
2c62920
Format large values in f_string_format without integer overflow
aca-logimentor Oct 18, 2026
a01e9d1
Fail synthesis checks that read an incomplete report
aca-logimentor Oct 18, 2026
340cbaa
Mark unverified vendor attributes in place and clarify the reset cut
aca-logimentor Oct 18, 2026
0f3910e
Record the report completeness rule of the synthesis checks in the ch…
aca-logimentor Oct 18, 2026
bea5fcf
Log every elaboration check case to a file
aca-logimentor Oct 18, 2026
e0f7af2
Link one executable per elaboration check case
aca-logimentor Oct 18, 2026
a1bc0c6
Explain why the clock_measure flush lengths must not be shortened
aca-logimentor Oct 18, 2026
341fae9
Round the f_string_format fraction on the exact product
aca-logimentor Oct 18, 2026
eb889c9
State the f_string_format rounding contract and test it exactly
aca-logimentor Oct 18, 2026
f3079e5
Require complete Quartus table panels before concluding an absence
aca-logimentor Oct 18, 2026
f293465
Require every Quartus panel a check reads, and validate its borders
aca-logimentor Oct 18, 2026
b321aea
Check f_string_format inputs before any computation
aca-logimentor Oct 18, 2026
b42e4fc
Release v0.1.0
aca-logimentor Oct 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ jobs:
cache: pip

- name: Install GHDL
run: |
sudo apt-get update
sudo apt-get install -y ghdl
uses: ghdl/setup-ghdl@75eff367dadc0cd06454a118db0b458d44fdc3c3 # v1.5.1
with:
version: v6.0.0
backend: llvm

- name: Install Python dependencies
run: |
Expand All @@ -71,7 +72,13 @@ jobs:
- name: Show tool versions
run: |
python --version
ghdl --version
python -m pip show vunit_hdl | grep -E '^(Name|Version):'
ghdl --version | tee ghdl_version.txt
grep -q '^GHDL 6\.0\.0 ' ghdl_version.txt || { echo "::error::GHDL 6.0.0 required"; exit 1; }
grep -qi 'llvm' ghdl_version.txt || { echo "::error::GHDL LLVM backend required"; exit 1; }

- name: Run negative elaboration checks
run: python sim/scripts/check_elab_failures.py

- name: Run fast VUnit regression
run: >
Expand Down
144 changes: 143 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,103 @@
# Changelog

## Unreleased
## v0.1.0 - 2026-10-18

First tagged version.

### Breaking Changes

- CRC `match_o` is now a held level instead of a one-cycle idle-cleared pulse.
It clears on reset, `init_i`, or the next checked data update. Designs that
require a pulse should qualify or edge-detect it at the protocol boundary that
marks the end of the CRC field.
- `lm_util_bitsum` output `bitsum_o` is now `f_ceil_log2(g_din_w + 1)` bits wide
(one bit wider for power-of-two input widths), so the all-ones count no
longer wraps to zero.
- `lm_util_counter` down direction now counts `g_wd_timer-1 .. 0` with reset
loading `g_wd_timer-1` and the watchdog pulse on 0, symmetric to the up
direction. Previously it underflowed from 0 through the full register range.
- `lm_util_pulse_stretch` input pulse is defined active high (`g_out_level`
only sets the output polarity). Stretch mode now adds exactly
`g_pulse_overlength` cycles after the input falling edge and is retriggered
by a new rising edge; fixed-length mode produces a pulse also for
`g_pulse_length = 1` and ignores edges arriving while the window is running.
- `lm_util_delay_pulse` and the `lm_util_delay_var` pulse architecture trigger
on the pulse leading edge, so pulses wider than one clock cycle are delayed
from their leading edge and an input held active beyond the delay cannot
retrigger a second output pulse; reset drives the output to the inactive
level of the configured polarity in every delay configuration. In the
`lm_util_delay_var` pulse architecture `dv_o` pulses together with the
delayed output pulse, consistent with the SRL architecture.
- `lm_util_delay_var` with `g_delay_max = 1` and `g_arch_type = C_LM_PULSE`
follows the pulse architecture: leading-edge trigger, one-cycle output
pulse with `dv_o`, inactive output level on reset. It was a plain register
that reset the output to `'0'` and passed a held input through.
- `lm_util_delay_var` rejects any `g_arch_type` other than `C_LM_SRL` and
`C_LM_PULSE` at elaboration, for every `g_delay_max` (the never-implemented
"mem" architecture included). Previously `g_delay_max = 1` accepted any
value.
- `lm_util_ccd_resync` stops elaboration with `severity failure` when
`g_meta_levels < 2` (was `severity error`, which some flows only report).
`lm_util_ccd_sync_pulse` now does the same for `g_delay_len < 2`.
- `lm_util_pkg` functions that returned wrong results now return the correct
ones, which changes the result for callers that relied on the old values:
- `f_div_ceil_2pwr` returns the next power of two for any ratio; it returned
non-powers of two once the ceiling ratio needed more than 64 increments
(ratios above about 128), and returns 1 for a ratio of 1 or less;
- `f_smallest(t_natural_arr)` returns the smallest element instead of
always 0, and `natural'high` for an empty array;
- `f_is_power_of_two` returns `false` for 0 and negative inputs instead of
failing;
- `f_string_substr` no longer reports an error for valid substrings (the
bounds check was inverted);
- `f_string_format` follows a stated rounding contract: the exact binary
value of the real is rounded to `precision` digits, exact halves away
from zero. A literal is first the nearest real, so `9.9995` with
precision 3 gives `"9.999"` (the real is 9.99949999999999938893...); it
gave `"10.000"` by rounding the scaled product a second time. With
precision 0 the result has no decimal point (`"3"` for 2.5); it was the
truncated integer part followed by a rounding digit (`"2.1"` for 2.7).
An integer part above `integer'high` or a precision above 9 stops with
a failure instead of returning a wrong string; a magnitude of `2**31` or
more is rejected before any intermediate computation. The exact rounding
assumes IEEE 754 binary64 reals with every operation rounded on its own
(verified with GHDL 6.0.0 LLVM).

### Fixed

- `lm_util_clock_measure`: the toggle synchronizer third stage sampled the
first (possibly metastable) stage and the edge detector compared against it;
the reported frequency missed the window-closing cycle (off by one). A
reset no longer publishes a stale value: a measurement pending at the
reset, the ready transition forced by the measured-domain reset (also when
it arrives after the release because the measured clock is slow or
stopped) and pre-reset values still in the synchronizer stages are ignored
until the stages have been reloaded after the release. The synchronizer
stages carry no reset logic, so synthesis tools see (and time) the whole
chain.
- `lm_util_delay_var`: `dv_o` is now driven for `g_delay_max = 1` and in the
pulse architecture (where it pulses with the delayed output); a runtime
delay of 1 is supported in pulse mode.
- `lm_util_pkg`: `f_div_ceil(time, time)` no longer truncates sub-ns
remainders; `f_string_format` carries a rounded-up fraction into the
integer part (0.9995 with precision 3 gives `"1.000"`, it gave
`"0.1000"`), formats any integer part up to `integer'high` (the value is
not scaled by `10**precision` as a whole) and no longer rounds twice when
the scaled fraction lands on a decimal half (`0.0065` with precision 3
gives `"0.006"`); the unsupported-operation
guard in `f_vector_tree` can actually fire.
- `lm_util_ccd_sync_bus`: the request edge detector tracks the
resynchronized request during reset. A request held asserted across the
input-domain reset release is not detected as a new rising edge, and a
request whose resynchronized rising edge arrives on the first cycle after
the release is transferred (it was dropped, so `out_rdy_o` never pulsed).
- `lm_util_clock_measure` publishes the first value after a reset only when a
complete window has been measured: the first 1 s tick after the reset opens
the window and the second one closes it (about 2 s after the release). It
published the partial first window, counted from the reset release, at the
first tick.
- Constraint examples: the Quartus and Lattice examples of `lm_util_ccd_resync`
were not valid Tcl (`[0]` outside braces is a command substitution).

### Changed

Expand All @@ -16,3 +106,55 @@
- The parallel CRC reflected-input mode now reflects bits within each byte
rather than reversing the whole input word.
- CRC engines support 4- to 64-bit polynomials.
- Synchronizer chains (`lm_util_ccd_resync`, `lm_util_ccd_sync_pulse`,
`lm_util_async_reset`, `lm_util_clock_measure`, `lm_util_clock_mux`) carry
synthesis attributes for all supported vendors so the flops stay discrete:
`async_reg`/`shreg_extract` (Vivado), `syn_preserve`/`syn_srlstyle`
(Synplify/LSE), and `altera_attribute` synchronizer identification
(Quartus). The `lm_util_clock_mux` anti-glitch keep intent is expressed per
tool (`keep` string for Vivado, `syn_keep` for Synplify/LSE and Quartus,
which turns it into `IGNORE_LCELL_BUFFERS` and
`REMOVE_REDUNDANT_LOGIC_CELLS` off). The Vivado and Quartus attributes are verified by vendor
synthesis (Vivado 2023.1, Quartus Prime Lite 23.1std on MAX 10); the
Synplify Pro / Lattice LSE attributes follow the vendor documentation but
have not been verified with those tools, nor with Synplify Pro for
Microchip Libero.
- CDC constraint examples: every CDC module header lists Vivado (XDC) and
Quartus (SDC) constraints that select registers and pins by internal
signal names only, so they apply to every instance and survive a library
or entity rename. The user guide adds an example, the behavior of these
constraints under asynchronous clock groups as observed with Vivado
2023.1, and the verification status per tool.
- Vendor synthesis runner (`tools/synth/run_vendor_synth.py`): structural
checks on the Vivado netlist (each synchronizer stage an `FD*` cell with
`ASYNC_REG`, no SRL) and on the Quartus reports (chain identified as a
user-specified synchronizer, no shift-register inference); negative cases
that must fail each check; loading of the published constraint examples
with a check for empty collections and ignored exceptions; a clear error
when the configured Quartus family or device, or the Vivado part, is not
installed. Report hints no longer scan the generated scripts, and a failed
check always fails the run. A check that passes when something is absent
(no SRL, no shift-register packing, no invalid or ignored exception) first
requires an open, non-empty Vivado netlist or a complete and recognized
Quartus report; otherwise it fails with an `LM_ERROR`, as does a check
missing from the check report. A Quartus table panel that a check reads
(register packing, exceptions summary, chain statistics, synthesis
summary) must be complete when present: column header, data rows and
closing border, with whole-line borders aligned with the rows. Only the
register packing panel may be absent. Negative cases that empty or truncate a report, or gut
the register packing panel, show it.
- Simulation: the reference simulator is GHDL 6.0.0 (LLVM backend), pinned
in CI with `ghdl/setup-ghdl`; `vunit_hdl` is pinned to 4.7.1;
`sim/scripts/check_elab_failures.py` checks that invalid generics and
inputs that `f_string_format` cannot format stop elaboration with the
intended message.
- Test coverage: counter down/load modes, pulse_stretch active-low output and
unit lengths, delay_pulse multi-cycle pulses, delay_var unit delay max and
pulse delay 1 (also in pulse mode with `g_delay_max = 1`, both pulse
levels, and inputs held longer than the delay), bitsum power-of-two widths,
clock_measure steady-state window and reset behavior (reset length and
phase, slow and stopped measured clock), `f_string_format` (large values,
carry, sign, precision 0, and exact reference vectors: 1500 in the fast
and 20000 in the full regression), and a new `lm_util_ccd_sync_bus`
testbench are now exercised; previously disabled failing configurations
are re-enabled.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ library.
- [User guide](docs/user_guide.md): module functionality, instantiation
template, generic configuration notes, simulation flow, synthesis compile
examples, and local vendor synthesis report generation.
- [Changelog](CHANGELOG.md): compatibility notes and unreleased changes.
- [Changelog](CHANGELOG.md): release notes and compatibility notes.
- [Vendor synthesis smoke tests](tools/synth/README.md): local Vivado, Quartus,
and Diamond campaign runner.
- [VHDL coding standard](docs/LM_VHDL_coding_standard.md): style rules used by
Expand Down
Loading