§ 3.1.4. ROM¶
Immutable read-only storage following the common cell/row/bank/device architecture. This is a digital mask-ROM-style model, not a writable EEPROM.
| Component | Description | Structural | Behavioral |
|---|---|---|---|
ROMCell |
One fixed construction-time bit | Yes | Yes |
ROMRow<C> |
C fixed bits in column order | Yes | Yes |
ROMStorageBank<W> |
Rows plus one selected-row sensor per column | Yes | Yes |
ROMAddressControl |
Decode address and chip/output enables | Yes | No |
ROM<W> |
Complete asynchronous read-only device | Yes | Yes |
Configuration¶
Width W, capacity N, and words-per-row K follow 3.1. image_hex contains consecutive bytes as pairs of hexadecimal digits, starting at byte address zero. No spaces or prefixes are accepted. The remaining capacity is initialized to zero; an odd-length, non-hex, or oversized image is rejected.
For example, image_hex="a53c81ff" gives four 8-bit words A5, 3C, 81, FF, two 16-bit words 3CA5, FF81, or one 32-bit word FF813CA5. This is little-endian byte packing. Device pins use word addresses, not byte addresses. Contents cannot be altered by reset, write commands, or a debug load after construction.
ROM uses the same component-reference pattern as FF and SRAM. The C++ examples describe binary pin behavior for validated construction parameters, including invalid addresses and disabled outputs, without simulator event scheduling. They are not registered simulator implementations. Compile in page order; tables contain every recorded checkpoint, with its number and time.
The cell's catalog parameter is value; a standalone row uses contents. Banks and devices use ROMDeviceConfig (depth_words, words_per_row, image_hex, record_history). The address controller accepts only geometry parameters; it has no image or history. Register names are memory.rom.cell, row, address-control, bank.W, and device.W under the memory.rom. prefix. Only the public bank/device wrappers are C++ width templates; row dimensions are runtime values.
3.1.4.1. ROMCell¶
One immutable construction-time bit.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
Q |
Output | 1 | Fixed configured bit; no input pins |
Behavior¶
The value parameter is 0 or 1 (default 0). It cannot be changed by an input, clock, reset, or debug load.
C++ example¶
Simplified binary behavior; simulation scheduling and four-state handling are described below.
Unknown inputs and timing¶
The output starts unresolved until the initial simulation event propagates, then is always the configured binary value. Both implementations schedule their first output even though there are no inputs.
Implementation¶
Structural implementation¶
A ConstantValue<1> child named MASK_BIT drives Q. This represents a fixed connection, not a flip-flop or a transistor-level mask-ROM cell.
Behavioral implementation¶
A terminal constant-output component publishes the configured value without the child.
The behavioral cell's visualizer shows Q as the programmed bit, using its recorded value. Selecting the structural implementation shows the fixed connection instead.
Examples¶
All 1 recorded rows of ROMCellTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (3f3be5125c460b70). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | QExpected output · 1 bit |
|---|---|---|
#0fixed-one | 0 | 1 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
The example constructs value=1 and checks Q. Zero-valued cells also occur in the row and bank examples.
Embedded simulation¶
The standalone ROMCellTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.
Source and tests¶
| Test | Coverage |
|---|---|
ROMCellTest |
The complete standalone sequence shown above |
MemoryDeviceContractTest |
Structural/behavioral agreement at settled checkpoints, including mixed hierarchy selection |
3.1.4.2. ROMRow<C>¶
C fixed cells ordered by physical column.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
Q_c |
Output | 1 each | Fixed value of column c, 0 ≤ c < C; no inputs |
Behavior¶
The contents parameter contains 1–512 characters, each 0 or 1; default "0000". Characters are in increasing column order: "1010" means Q_0=1, Q_1=0, Q_2=1, Q_3=0, not an MSB-first integer. Selection belongs to the bank, not the row.
C++ example¶
Simplified binary behavior; simulation scheduling and four-state handling are described below.
#include <string>
#include <vector>
std::vector<bool> rom_row(const std::string& contents) {
std::vector<bool> q;
for (char bit : contents) q.push_back(bit == '1');
return q; // The factory has already validated a nonempty binary string.
}
Unknown inputs and timing¶
Invalid characters, an empty row, or more than 512 columns are rejected at construction. Outputs settle from their initial events; valid ROM contents do not acquire X during reads.
Implementation¶
Structural implementation¶
Contains CELL_0 through CELL_(C−1), each a registered ROMCell. Cells are arranged left to right. A structural row may select behavioral cells.
Behavioral implementation¶
Retains the construction string and publishes each column directly, with the same startup and ordering contract.
Examples¶
All 1 recorded rows of ROMRowTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (3f3be5125c460b70). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | Q_0Expected output · 1 bit |
Q_1Expected output · 1 bit |
Q_2Expected output · 1 bit |
Q_3Expected output · 1 bit |
|---|---|---|---|---|---|
#0fixed-row | 0 | 1 |
0 |
1 |
0 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
The four-column example uses contents="1010" and checks every output in the initial settled checkpoint.
Embedded simulation¶
The standalone ROMRowTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.
Open ROMRow<C> in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
ROMRowTest |
The complete standalone sequence shown above |
MemoryDeviceContractTest |
Structural/behavioral agreement at settled checkpoints, including mixed hierarchy selection |
3.1.4.3. ROMStorageBank<W>¶
Immutable rows with shared selected-row sensing.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
WL_r |
Input | 1 each | Row selection, 0 ≤ r < N/K |
COL_c |
Output | 1 each | Sensed bit, 0 ≤ c < W×K |
Behavior¶
Exactly one binary wordline must be high. Each output then gives the corresponding column of that row. All-low, multi-row, or unknown selection returns X. The bank has no address decoding, output-enable, or write interface.
C++ example¶
Binary wordlines for any validated W/N/K geometry. The image is in byte-address order, with a zero-filled tail. Output columns use LSB-first order; empty optionals denote invalid row selection.
#include <vector>
#include <cstdint>
#include <optional>
std::vector<std::optional<bool>> rom_bank(unsigned width, unsigned slots,
const std::vector<std::uint8_t>& image, const std::vector<bool>& wl) {
std::vector<std::optional<bool>> columns(width * slots);
unsigned count = 0;
std::size_t row = 0;
for (std::size_t r = 0; r < wl.size(); ++r) if (wl[r]) { ++count; row = r; }
if (count != 1) return columns;
for (std::size_t c = 0; c < columns.size(); ++c) {
const auto byte = row * columns.size() / 8 + c / 8;
columns[c] = byte < image.size() && ((image[byte] >> (c % 8)) & 1u);
}
return columns;
}
Unknown inputs and timing¶
An unknown wordline invalidates the entire selection; it is not treated as zero. Unselected cell values do not affect a valid selection. Scalar row/column interfaces limit standalone banks of either fidelity to 4,096 cells. The structural sensing path adds propagation delay.
Implementation¶
Structural implementation¶
ROW_r contains W×K fixed cells. Each COLUMN_c is a StaticReadColumn connected to column c of every row. Rows are stacked; sensing blocks align under their cells.
Behavioral implementation¶
Reads the fixed image bits directly after validating one-hot selection. It keeps the same expanded pins, geometry limits, and image interpretation.
Examples¶
All 3 recorded rows of ROMStorageBankTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (3f3be5125c460b70). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | WL_0Input · 1 bit |
WL_1Input · 1 bit |
COL_0Expected output · 1 bit |
COL_1Expected output · 1 bit |
COL_10Expected output · 1 bit |
COL_11Expected output · 1 bit |
COL_12Expected output · 1 bit |
COL_13Expected output · 1 bit |
COL_14Expected output · 1 bit |
COL_15Expected output · 1 bit |
COL_2Expected output · 1 bit |
COL_3Expected output · 1 bit |
COL_4Expected output · 1 bit |
COL_5Expected output · 1 bit |
COL_6Expected output · 1 bit |
COL_7Expected output · 1 bit |
COL_8Expected output · 1 bit |
COL_9Expected output · 1 bit |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#0idle | 1 | 0 |
0 |
X |
not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked | not checked |
#1row-0 | 3 | 1 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
#2row-1 | 5 | 0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
The image is A5 3C 81 FF. The test first selects no row, then selects row zero and row one, checking all 16 sensed columns for each valid row.
Embedded simulation¶
The standalone ROMStorageBankTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.
Open ROMStorageBank<W> in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
ROMStorageBankTest |
The complete standalone sequence shown above |
MemoryDeviceContractTest |
Structural/behavioral agreement at settled checkpoints, including mixed hierarchy selection |
3.1.4.4. ROMAddressControl¶
Address decomposition and active-low read qualification.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
WORD_ADDR |
Input | 32 | Word address A |
CE_N |
Input | 1 | Active-low chip enable |
OE_N |
Input | 1 | Active-low output enable |
ROW_ADDR |
Output | 32 | A/K for a valid address, otherwise X |
COLUMN_ADDR |
Output | 32 | A%K for a valid address, otherwise X |
ROW_ENABLE |
Output | 1 | CE_N=0 and valid address; independent of OE_N |
OUTPUT_ENABLE |
Output | 1 | Qualified read, disabled output, or X |
Behavior¶
For a binary address in [0,N), compute its row and word slot. Chip deselection disables the row. OE_N only controls publication: a valid selected row can remain active with its output disabled. A high CE_N or OE_N dominates other unknown inputs and releases the device output.
C++ example¶
Binary address/enables; nullopt represents an unknown output-enable or address.
#include <cstdint>
#include <optional>
struct ROMAddressReference {
std::optional<std::uint32_t> row, slot;
bool row_enable;
std::optional<bool> output_enable;
};
ROMAddressReference rom_address(std::uint32_t a, unsigned n, unsigned k,
bool ce_n, bool oe_n) {
const bool valid = a < n; // n and k are validated geometry.
return {valid ? std::optional(a / k) : std::nullopt,
valid ? std::optional(a % k) : std::nullopt,
!ce_n && valid,
ce_n || oe_n ? std::optional(false)
: valid ? std::optional(true) : std::nullopt};
}
Unknown inputs and timing¶
Unknown or out-of-range addresses never wrap. They produce X row/column addresses and a low ROW_ENABLE. OUTPUT_ENABLE is low if either enable is high, high only if both are low and the address is valid, otherwise X. This is a one-tick digital primitive.
Implementation¶
Structural implementation¶
A terminal combinational primitive computes selection and decomposes the address. It stores no image and has no clock. The row decoder and output buffer are separate components in the complete device.
Examples¶
All 7 recorded rows of ROMAddressControlTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (3f3be5125c460b70). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CE_NInput · 1 bit |
OE_NInput · 1 bit |
WORD_ADDRInput · 32 bit |
COLUMN_ADDRExpected output · 32 bit |
OUTPUT_ENABLEExpected output · 1 bit |
ROW_ADDRExpected output · 32 bit |
ROW_ENABLEExpected output · 1 bit |
|---|---|---|---|---|---|---|---|---|
#0disabled | 1 | 1 |
0 |
0x00000003 |
not checked | 0 |
not checked | 0 |
#1select-last-word | 3 | 0 |
0 |
0x00000003 |
0x00000001 |
1 |
0x00000001 |
1 |
#2invalid-address | 5 | 0 |
0 |
0x00000004 |
not checked | X |
not checked | 0 |
#3output-disabled-row-selected | 7 | 0 |
1 |
0x00000001 |
not checked | 0 |
not checked | 1 |
#4unknown-address-disabled | 9 | 0 |
1 |
0bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
not checked | 0 |
not checked | 0 |
#5unknown-enable | 11 | 0 |
X |
0x00000001 |
not checked | X |
not checked | 1 |
#6chip-disable-dominates | 13 | 1 |
X |
0x00000001 |
not checked | 0 |
not checked | 0 |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
The sequence checks chip deselection, the last word (A=3 → row 1, slot 1), and the first invalid address A=4. Additional cases exercise OE_N independently and unknown controls.
Embedded simulation¶
The standalone ROMAddressControlTest opens this component as MEMORY_ROOT. This component has one registered structural implementation.
Open ROMAddressControl in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
ROMAddressControlTest |
The complete standalone sequence shown above |
MemoryDeviceContractTest |
Integration in the new structural devices and comparison with their compact implementations |
3.1.4.5. ROM<W>¶
Complete asynchronous, word-addressed read-only device.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
WORD_ADDR |
Input | 32 | Word index, 0…N−1 |
CE_N |
Input | 1 | Active-low chip enable |
OE_N |
Input | 1 | Active-low output enable |
READ_DATA |
Output | W | Selected immutable word, X, or Z |
Behavior¶
No clock or command is required. With both enables low and a valid word address, publish the corresponding little-endian word. Either enable high releases the output. There are no write pins or reset operation.
C++ example¶
Binary read path for W=8/16/32, including little-endian byte assembly and the zero-filled image tail. The explicit result distinguishes valid data, high impedance, and an invalid address. Capacity is in words; image is in bytes and has already passed construction-time length/hex validation.
#include <cstdint>
#include <vector>
struct ROMReadReference {
enum class State { Data, HighZ, Unknown } state;
std::uint32_t data = 0;
};
template<unsigned W = 8>
ROMReadReference rom_read(const std::vector<std::uint8_t>& image, std::size_t words,
std::uint32_t address, bool ce_n, bool oe_n) {
static_assert(W == 8 || W == 16 || W == 32);
using S = ROMReadReference::State;
if (ce_n || oe_n) return {S::HighZ};
if (address >= words) return {S::Unknown};
std::uint32_t data = 0;
for (unsigned byte = 0; byte < W / 8; ++byte) {
auto a = std::size_t(address) * (W / 8) + byte;
if (a < image.size()) data |= std::uint32_t(image[a]) << (8 * byte);
}
return {S::Data, data};
}
Unknown inputs and timing¶
Enabled reads with an unknown address/control or an out-of-range address return X. A known disabled enable still returns Z. Read after the combinational paths settle; structural and compact propagation times differ. Image validation occurs before building the device.
Implementation¶
Structural implementation¶
ACCESS_CONTROL drives ROW_DECODE and output qualification. STORAGE contains fixed rows and their column sensors; COLUMN_SELECT chooses one W-bit slot; OUTPUT drives READ_DATA. There is no write distributor or erase block.
Behavioral implementation¶
Uses packed, zero-initialized MemoryStorage with the construction image prefix loaded once. The memory inspector is read-only; loadMemoryBytes rejects changes. This implementation supports large capacities without expanding cells. record_history=0 disables backing-store history, not wire history.
Examples¶
All 8 recorded rows of ROMTest, in checkpoint order. Outputs are test expectations verified against the simulation. Time is the absolute settled checkpoint time in simulator units, not milliseconds or CPU cycles.
Default scenario profile: canonical-default-preview / structural (3f3be5125c460b70). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CE_NInput · 1 bit |
OE_NInput · 1 bit |
WORD_ADDRInput · 32 bit |
READ_DATAExpected output · 8 bit |
|---|---|---|---|---|---|
#0disabled | 11 | 1 |
0 |
0x00000000 |
0bZZZZZZZZ |
#1word-0 | 19 | 0 |
0 |
0x00000000 |
0xA5 |
#2word-1 | 27 | 0 |
0 |
0x00000001 |
0x3C |
#3word-2 | 36 | 0 |
0 |
0x00000002 |
0x81 |
#4word-3 | 43 | 0 |
0 |
0x00000003 |
0xFF |
#5out-of-range | 53 | 0 |
0 |
0x00000004 |
0bXXXXXXXX |
#6unknown-address | 54 | 0 |
0 |
0bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
0bXXXXXXXX |
#7output-disabled | 57 | 0 |
1 |
0bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
0bZZZZZZZZ |
Scroll within the table for all rows and pins. Buses use hexadecimal; values containing X/Z use MSB-first binary. Inputs show the declared values in effect at each checkpoint, including retained inputs. Sequential tests also replay preparation changes between checkpoints, such as lowering the clock. Use the matching checkpoint label in the simulation below.
The example reads all four bytes of A5 3C 81 FF, checks out-of-range and unknown addresses, and disables the output. The displayed values and times come directly from the recorded test.
Embedded simulation¶
The standalone ROMTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.
Source and tests¶
| Test | Coverage |
|---|---|
ROMTest |
The complete standalone sequence shown above |
MemoryDeviceContractTest |
W=8/16/32, K=1/2/4, image packing/zero tail, mixed fidelity, immutable debug interface, invalid configurations, and compact allocation |
MemoryDeviceDocumentationTest |
Compile the exact references; test row conflicts, address/output controls, 8/16/32-bit image reads, little-endian packing, zero-filled tails and invalid addresses |