Reuse

Packages & Reuse

Package structure, public APIs, versioning, tests, documentation, and reusable Livt design units.

Hardware projects often reuse the same ideas: stream interfaces, register banks, UARTs, FIFOs, parsers, protocol adapters, test fixtures, and vendor wrappers. Packages are how reusable Livt code can move between projects.

A package is more than a folder of source files. It should provide a clear public API, tests, versioning, and documentation.

What Belongs in a Package

A good package contains a coherent capability:

  • a protocol interface and helpers
  • a reusable component
  • a family of related components
  • a simulation fixture
  • a vendor wrapper
  • shared constants and types

Avoid packages that are just miscellaneous utilities. Reuse works best when the package has a clear domain.

Package vs IP

In FPGA workflows, "IP" often means a reusable hardware block, sometimes with vendor-specific configuration and generated files. A Livt package can contain IP, but the concepts are not identical.

A Livt package may include:

  • Livt source code
  • interfaces
  • tests
  • documentation
  • wrapped VHDL
  • vendor integration notes

An IP block is usually one reusable hardware asset. A package is the delivery and maintenance unit around reusable code.

Pre-compiled VHDL shipped directly inside packages is a planned reuse workflow. Until that workflow is documented as available for the compiler release you use, publish Livt source, tests, wrappers, and clear integration instructions instead of relying on packaged generated VHDL.

Public APIs

The public API of a package is what users should depend on:

  • public components
  • public interfaces
  • public constants
  • documented constructor parameters
  • documented functions and fields

Everything else should be treated as implementation detail. If users depend on private structure, the package becomes hard to change.

Versioning

Reusable hardware code needs versioning. A small change to a signal direction, constructor parameter, reset behavior, or latency can break users.

When changing a package, ask:

  • Did a public interface change?
  • Did a component constructor change?
  • Did timing or latency change?
  • Did reset behavior change?
  • Did generated VHDL ports change?

If the answer is yes, document the change clearly and update the version in a way that signals compatibility.

Tests in Packages

A package should carry its own tests. Tests are what make reuse safe:

text
my-stream-package/
|-- src/
|   |-- IByteStream.lvt
|   `-- StreamBuffer.lvt
`-- tests/
    `-- StreamBufferTest.lvt

The package tests should verify the public contract, not every private detail. Users need confidence that the package behaves as advertised.

Documentation

Document the things a user needs to know:

  • what the package provides
  • how to instantiate the main components
  • what interfaces mean
  • timing assumptions
  • reset behavior
  • simulation-only utilities
  • vendor requirements

Short examples are often more useful than long prose. Show the smallest correct usage first.

Reuse Guidelines

Before extracting code into a package, make sure the boundary is stable. Code that is still changing rapidly may be easier to keep inside the application until the shape is clearer.

Extract a package when:

  • at least two projects or subsystems need the same code
  • the interface is stable
  • the tests are strong enough to protect users
  • the package has a clear owner

Summary

Packages turn local design work into reusable hardware assets. Treat package APIs with care: document them, test them, version them, and keep implementation details private.