§ 3.1.1. Flip-Flop Storage¶
This section specifies flip-flop storage from feedback gates to an addressable memory. An SR latch leads to a gated D latch, an edge-triggered flip-flop, and a write-enabled cell. Cells form words, words form a storage bank, and address/control/read circuitry completes the memory device. These components store state; their outputs depend on earlier inputs as well as the current inputs.
The word, bank, and device here are memory components: a word has a write mask per byte and is reached through an address. The whole-word registers and state bits used by the RV32I circuitry are built from the same cell but are storage, not memory; they have no address or byte mask and are documented in 4.3.1.
| Component | Description | Structural | Behavioral |
|---|---|---|---|
SRLatch |
Holds one bit using active-low set and reset inputs | Yes | No |
GatedDLatch |
Follows a data input while enabled and holds it while disabled | Yes | No |
DFlipFlop |
Captures a data bit on the rising clock edge | Yes | No |
FlipFlopCell |
Adds write enable to a D flip-flop so a clock edge can either write or retain the stored bit | Yes | Yes |
FFWord<W> |
Stores one W-bit word with a write enable for each byte | Yes | Yes |
FFStorageBank<W> |
Groups a configurable number of words with shared data and separate word write enables | Yes | Yes |
FFMemory<W> |
Adds word addressing, access checks, and read selection to an FF storage bank | Yes | Yes |
These columns indicate actual simulator implementations; the simplified C++ examples below are not counted. Cells, words, banks, and complete FF memories each support structural and behavioral selection. Structural remains the default.
The FF memory controller connects this native device to the shared transaction protocol. FF storage itself does not require a controller.
Conventions¶
- Pin widths are listed in each table. FF memory words and banks use
W = 8, 16, 32.Nis the number of words.0and1are binary logic,Xis unknown, andZis high impedance.Zis not a third stored binary value; gates interpret it as unknown logic. S_BARandR_BARare active-low. The other components'RSTis active-high and asynchronous: asserting it clears state without waiting for a clock edge, after gate propagation.- State is not guaranteed to start at zero. Establish a known state with set/reset before relying on it. Every recorded scenario below starts with reset.
- Behavior tables describe settled outputs. A rising edge means
CLKchanges from0to1; a sustained high level is not another edge. Keep data and control inputs stable around the edge and allow propagation to finish. - These are digital timing models, not analog metastability or transistor-voltage models. Their delays are simulator units, not calibrated device timings.
The simplified C++ examples describe binary behavior, not the simulator implementation. They assume reset has already established zero storage and, for clocked components, CLK = 0. Call update for each input change, including falling clock edges. They omit propagation delays and X/Z handling and can be compiled together in the order shown.
Each examples table contains every recorded checkpoint of its embedded scenario, with a zero-based number, the timeline label, and the absolute simulator time. Inputs are the values in effect at that checkpoint, including retained values. Preparation actions between checkpoints are replayed by the simulator; a table is not a sequence of independent truth-table inputs. Each component has its own standalone scenario, including the bank.
3.1.1.1. SRLatch¶
SRLatch stores one bit using feedback between two NAND gates. It has no clock or data input: set and reset directly select the stored state.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
S_BAR |
Input | 1 | Active-low set: requests Q = 1 |
R_BAR |
Input | 1 | Active-low reset: requests Q = 0 |
Q |
Output | 1 | Stored bit |
Q_BAR |
Output | 1 | Complement of Q in a valid, settled state |
Behavior¶
S_BAR |
R_BAR |
Settled Q |
Settled Q_BAR |
Operation |
|---|---|---|---|---|
| 1 | 0 | 0 | 1 | Reset |
| 0 | 1 | 1 | 0 | Set |
| 1 | 1 | Previous Q |
Previous Q_BAR |
Hold a previously established valid state |
| 0 | 0 | 1 | 1 | Invalid storage condition: outputs are not complementary |
The invalid input pair does not produce a simulator exception: both NAND outputs settle to 1. However, releasing both inputs together does not specify a reliable stored bit. The recorded scenario recovers by selecting reset explicitly. Do not use simultaneous release as a way to choose a state.
C++ example¶
#include <stdexcept>
struct SRLatchReference {
bool q = false;
bool q_bar = true;
void update(bool s_bar, bool r_bar) {
if (!s_bar && !r_bar) {
q = q_bar = true; // Invalid storage condition.
} else if (!s_bar) {
q = true;
q_bar = false;
} else if (!r_bar) {
q = false;
q_bar = true;
} else if (q == q_bar) {
throw std::logic_error("Release from invalid state is unspecified");
} // Otherwise hold the valid state.
}
};
The exception is a guard in this example only. The simulator runs the actual NAND feedback circuit instead.
Unknown inputs and timing¶
The two NAND gates apply their normal four-state rules. Outputs are not automatically complementary during propagation, invalid input combinations, or unknown states. The recorded high-z-set-input checkpoint drives S_BAR = Z after a known reset state with R_BAR = 1; both outputs become X. recover-from-high-z demonstrates recovery through reset.
Implementation¶
Structural implementation¶
| Internal component | Count | Connection |
|---|---|---|
NANDGate |
2 | NAND_Q and NAND_Q_BAR feed each other's second input |
The feedback connections implement
These are feedback equations, not two ordinary C++ assignments evaluated once. Gate events propagate until the circuit settles.
Examples¶
All 8 recorded rows of SRLatchTest, 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 (175230e5d834592b). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | R_BARInput · 1 bit |
S_BARInput · 1 bit |
QExpected output · 1 bit |
Q_BARExpected output · 1 bit |
|---|---|---|---|---|---|
#0reset | 3 | 0 |
1 |
0 |
1 |
#1hold-reset | 5 | 1 |
1 |
0 |
1 |
#2set | 9 | 1 |
0 |
1 |
0 |
#3hold-set | 11 | 1 |
1 |
1 |
0 |
#4invalid | 14 | 0 |
0 |
1 |
1 |
#5recover-reset | 17 | 0 |
1 |
0 |
1 |
#6high-z-set-input | 21 | 1 |
Z |
X |
X |
#7recover-from-high-z | 25 | 0 |
1 |
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.
set followed by hold-set demonstrates retention after the set input becomes inactive. invalid deliberately exercises both active inputs, and recover-reset restores complementary outputs.
Embedded simulation¶
SRLatchTest has eight recorded checkpoints. Inspect NAND_Q, NAND_Q_BAR, and their feedback wires between checkpoints to distinguish propagation from the final stored state.
Source and tests¶
| Test | Coverage |
|---|---|
SRLatchTest / srLatchSpec() |
Eight checkpoints: reset, hold, set, invalid inputs, explicit recovery, and high-impedance input propagation |
3.1.1.2. GatedDLatch¶
GatedDLatch adds a data input and an enable input to SRLatch. With EN = 1, it is transparent: changing D changes the stored value after propagation. With EN = 0, it holds its state.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
D |
Input | 1 | Data to store while enabled |
EN |
Input | 1 | Active-high transparency enable; not an edge-triggered clock |
RST |
Input | 1 | Active-high asynchronous reset |
Q |
Output | 1 | Stored bit |
Q_BAR |
Output | 1 | Complement of Q in a valid, settled state |
Behavior¶
Here and below, “any” means either binary value, not an X input.
RST |
EN |
D |
Next settled Q |
|---|---|---|---|
| 1 | Any | Any | 0 |
| 0 | 0 | Any | Previous Q |
| 0 | 1 | 0 | 0 |
| 0 | 1 | 1 | 1 |
Reset takes priority over enable and data. Releasing reset while EN = 1 lets D propagate again; releasing it while disabled leaves the reset value stored.
C++ example¶
struct GatedDLatchReference {
bool q = false;
void update(bool d, bool en, bool rst) {
if (rst) q = false;
else if (en) q = d;
}
bool q_bar() const { return !q; }
};
Unknown inputs and timing¶
The implementation evaluates the actual gates. For a known enabled latch with reset inactive, D = X or D = Z can make both outputs unknown. Asserting reset restores Q = 0, Q_BAR = 1, including after these unknown-data cases. The binary table does not specify every combination of unknown enable/reset inputs.
Implementation¶
Structural implementation¶
| Internal component | Count | Function |
|---|---|---|
NOTGate |
2 | Invert D and RST |
NANDGate |
2 | Generate the active-low set/reset requests from D and EN |
ORGate |
1 | Disable the set request while reset is asserted |
ANDGate |
1 | Force the reset request active while reset is asserted |
SRLatch |
1 | STATE holds the bit and supplies both outputs |
The inputs to STATE are
For settled binary inputs, the gating prevents data and enable from requesting set and reset simultaneously.
Examples¶
All 12 recorded rows of GatedDLatchTest, 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 (77eec9d88233a6de). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | DInput · 1 bit |
ENInput · 1 bit |
RSTInput · 1 bit |
QExpected output · 1 bit |
Q_BARExpected output · 1 bit |
|---|---|---|---|---|---|---|
#0reset | 5 | 0 |
0 |
1 |
0 |
1 |
#1release-reset | 9 | 0 |
0 |
0 |
0 |
1 |
#2disabled-hold | 12 | 1 |
0 |
0 |
0 |
1 |
#3transparent-high | 18 | 1 |
1 |
0 |
1 |
0 |
#4transparent-low | 25 | 0 |
1 |
0 |
0 |
1 |
#5disable | 29 | 0 |
0 |
0 |
0 |
1 |
#6hold-low | 32 | 1 |
0 |
0 |
0 |
1 |
#7re-enable | 38 | 1 |
1 |
0 |
1 |
0 |
#8transparent-unknown | 45 | X |
1 |
0 |
X |
X |
#9reset-unknown | 51 | X |
1 |
1 |
0 |
1 |
#10transparent-high-z | 56 | Z |
1 |
0 |
X |
X |
#11reset-high-z | 62 | Z |
1 |
1 |
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.
transparent-high and transparent-low change Q while enable remains active. disable and hold-low show that a later change of D does not change the stored bit while disabled.
Embedded simulation¶
GatedDLatchTest has 12 checkpoints, including transparent X/Z inputs and reset recovery. Expand STATE to inspect the same SRLatch from 3.1.1.1 inside the input gating.
Open GatedDLatch in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
GatedDLatchTest / gatedDLatchSpec() |
12 checkpoints: reset, disabled retention, enabled data changes, re-enable, and unknown/high-impedance data with reset recovery |
3.1.1.3. DFlipFlop¶
DFlipFlop combines two gated D latches to capture data on the rising clock edge. Unlike GatedDLatch, it does not keep following D throughout a high clock level.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
D |
Input | 1 | Data to capture on a rising edge |
CLK |
Input | 1 | Clock; capture occurs on 0 → 1 |
RST |
Input | 1 | Active-high asynchronous reset of both internal latches |
Q |
Output | 1 | Captured bit |
Q_BAR |
Output | 1 | Complement of Q in a valid, settled state |
Behavior¶
RST |
Clock event | Next settled Q |
|---|---|---|
| 1 | Any or none | 0 |
| 0 | Rising edge | D prepared before the edge |
| 0 | Falling edge | Previous Q |
| 0 | No edge | Previous Q |
The component has no write-enable pin. Every valid rising edge captures data. Changing D while CLK stays high must not be treated as another write.
C++ example¶
struct DFlipFlopReference {
bool q = false;
bool previous_clk = false;
void update(bool d, bool clk, bool rst) {
if (rst) q = false;
else if (!previous_clk && clk) q = d;
previous_clk = clk;
}
bool q_bar() const { return !q; }
};
Unknown inputs and timing¶
The recorded sequence captures X and Z data as unknown state and then recovers through reset. This does not establish analog setup/hold limits or define every ambiguous clock transition. Preparing data, allowing it to settle with CLK = 0, and then raising the clock is the sequence used by the tests.
Implementation¶
Structural implementation¶
| Internal component | Count | Function |
|---|---|---|
NOTGate |
1 | NOT_CLK produces the master's enable |
GatedDLatch |
2 | MASTER receives D; SLAVE receives MASTER.Q and drives the outputs |
- While
CLK = 0,MASTERis enabled andSLAVEholds its output. - At the rising edge,
MASTERcloses andSLAVEopens, transferring the prepared value toQ. - While
CLK = 1,MASTERholds its value, so later input changes do not pass through toQ. - At the falling edge,
SLAVEcloses andMASTERstarts preparing the next value.
RST connects to both latches. The clock inverter and latch gates have propagation delays; this is a structural digital model, not an ideal zero-delay edge detector.
Examples¶
All 14 recorded rows of DFlipFlopTest, 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 (4b69afe2687c9499). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CLKInput · 1 bit |
DInput · 1 bit |
RSTInput · 1 bit |
QExpected output · 1 bit |
Q_BARExpected output · 1 bit |
|---|---|---|---|---|---|---|
#0reset | 6 | 0 |
0 |
1 |
0 |
1 |
#1release-reset | 10 | 0 |
0 |
0 |
0 |
1 |
#2prepare-one | 16 | 0 |
1 |
0 |
0 |
1 |
#3capture-one | 22 | 1 |
1 |
0 |
1 |
0 |
#4ignore-high-data-change | 25 | 1 |
0 |
0 |
1 |
0 |
#5falling-edge | 33 | 0 |
0 |
0 |
1 |
0 |
#6capture-zero | 39 | 1 |
0 |
0 |
0 |
1 |
#7open-master | 44 | 0 |
0 |
0 |
0 |
1 |
#8prepare-unknown | 50 | 0 |
X |
0 |
0 |
1 |
#9capture-unknown | 56 | 1 |
X |
0 |
X |
X |
#10reset-unknown | 64 | 1 |
X |
1 |
0 |
1 |
#11prepare-high-z | 71 | 0 |
Z |
0 |
0 |
1 |
#12capture-high-z | 77 | 1 |
Z |
0 |
X |
X |
#13reset-high-z | 85 | 1 |
Z |
1 |
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.
capture-one records a rising-edge capture. ignore-high-data-change and falling-edge retain that value. Only capture-zero, the next rising edge, changes Q to the prepared zero.
Embedded simulation¶
DFlipFlopTest has 14 checkpoints. Inspect MASTER.Q and SLAVE.Q around prepare-one and capture-one to see the distinction between preparing a value internally and changing the external output.
Open DFlipFlop in the simulator
Source and tests¶
| Test | Coverage |
|---|---|
DFlipFlopTest / dFlipFlopSpec() |
14 checkpoints: reset, input preparation, rising-edge capture, high-level and falling-edge retention, and X/Z capture with reset recovery |
3.1.1.4. FlipFlopCell¶
FlipFlopCell is a one-bit, write-enabled register. It combines DFlipFlop with a multiplexer that chooses between new data and the currently stored bit. FFWord<W> groups these cells into independently enabled byte lanes.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
D |
Input | 1 | New data to capture when writing |
WE |
Input | 1 | Active-high write enable |
CLK |
Input | 1 | Clock; an enabled write occurs on 0 → 1 |
RST |
Input | 1 | Active-high asynchronous reset |
Q |
Output | 1 | Stored bit; this component does not expose Q_BAR |
Behavior¶
RST |
Clock event | WE |
Next settled Q |
|---|---|---|---|
| 1 | Any or none | Any | 0 |
| 0 | Rising edge | 1 | D prepared before the edge |
| 0 | Rising edge | 0 | Previous Q |
| 0 | No rising edge | Any | Previous Q |
Reset has priority over writing. WE = 1 alone does not write: a rising edge is also required. The cell has no address input, read enable, refresh operation, or completion signal. Its stored value is continuously available at Q, subject to propagation delays.
C++ example¶
struct FlipFlopCellReference {
bool q = false;
bool previous_clk = false;
void update(bool d, bool we, bool clk, bool rst) {
if (rst) q = false;
else if (!previous_clk && clk && we) q = d;
previous_clk = clk;
}
};
Unknown inputs and timing¶
The recorded contract includes the following cases in both registered implementations:
- An enabled rising edge captures
D = XorD = ZasQ = X. - Asserting reset recovers a known zero from unknown state.
- With a stored zero and no clock edge, an uncertain reset preserves zero in the tested sequence.
- On a rising edge with
WE = X, a stored zero andD = 0preserve zero; a stored zero andD = 1produce unknown state.
These are tested sequences, not a claim of exhaustive equivalence for arbitrary unknown clocks, simultaneous input changes, or all four-state histories. The behavioral form uses delay tables characterized from the gates. In the compared sequences it does not publish earlier than the structural form, although table-only timing can be slower.
Implementation¶
Structural implementation¶
| Internal component | Count | Connection |
|---|---|---|
Mux2to1 |
1 | WRITE_MUX.A = STATE.Q, WRITE_MUX.B = D, WRITE_MUX.SEL = WE |
DFlipFlop |
1 | STATE.D = WRITE_MUX.OUT; receives CLK and RST; drives Q |
For binary inputs, the data presented to the internal flip-flop is
The clock is not gated by WE. The flip-flop still captures on a disabled rising edge, but it captures its own previous value through the feedback path.
Behavioral implementation¶
FlipFlopCellBehavioral stores one LogicValue and the preceding clock value, both initially unknown. It retains the FlipFlopCell public type and pins without internal gates. When built through the catalog, Q uses gate-derived clock-to-output timing rather than a fixed one-tick publication delay.
Each evaluation gives reset priority. With reset low, a known CLK = 0 → 1 transition captures D when WE = 1 and retains the stored value when WE = 0. Captured X or Z becomes X. On that edge, an unknown write enable follows the structural AND/OR feedback mux: only an old zero and a new zero preserve zero; every other combination produces X, including two ones. An unknown reset merges the stored value with zero. The evaluator remembers the current clock after every evaluation.
FlipFlopCellTest runs the same state sequence against the structural and behavioral implementations and compares their checkpoint outputs. This validates the recorded sequences, not every possible four-state history. Checkpoint times can differ, so the table below describes the default structural run.
Examples¶
All 13 recorded rows of FlipFlopCellTest, 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 (452b10db460aab11). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CLKInput · 1 bit |
DInput · 1 bit |
RSTInput · 1 bit |
WEInput · 1 bit |
QExpected output · 1 bit |
|---|---|---|---|---|---|---|
#0reset | 9 | 0 |
0 |
1 |
0 |
0 |
#1hold-disabled-edge | 20 | 1 |
1 |
0 |
0 |
0 |
#2write-one | 39 | 1 |
1 |
0 |
1 |
1 |
#3no-level-capture | 44 | 1 |
0 |
0 |
1 |
1 |
#4write-zero | 58 | 1 |
0 |
0 |
1 |
0 |
#5hold-zero | 71 | 1 |
1 |
0 |
0 |
0 |
#6capture-unknown-data | 90 | 1 |
X |
0 |
1 |
X |
#7reset-clears-unknown | 102 | 0 |
X |
1 |
1 |
0 |
#8unknown-reset-preserves-zero | 107 | 0 |
X |
X |
1 |
0 |
#9unknown-write-enable-agrees | 126 | 1 |
0 |
0 |
X |
0 |
#10unknown-write-enable | 145 | 1 |
1 |
0 |
X |
X |
#11reset-before-high-z | 157 | 0 |
1 |
1 |
X |
0 |
#12capture-high-z-as-unknown | 168 | 1 |
Z |
0 |
1 |
X |
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.
hold-disabled-edge and write-one contrast the two write-enable values. no-level-capture changes D while the clock remains high and confirms that the stored one is retained. The test lowers the clock between enabled captures even when that preparation does not have a separate checkpoint.
Embedded simulation¶
FlipFlopCellTest has 13 checkpoints covering reset, write, hold, and selected unknown-input cases. Expand STATE to follow the complete construction back through the two gated latches and their SR latches.
Open FlipFlopCell in the simulator
Source and tests¶
- Interface:
FlipFlopCell.hpp - Structural implementation:
FlipFlopCell.cpp - Behavioral implementation:
FlipFlopCellBehavioral.cpp
| Test | Coverage |
|---|---|
FlipFlopCellTest / flipFlopCellSpec() |
13 checkpoints run against structural and behavioral implementations: reset, enabled capture, disabled retention, no high-level capture, and selected X/Z cases |
3.1.1.5. FFWord<W>¶
FFWord<W> stores one word using W instances of FlipFlopCell. All cells share the clock and reset. Byte write enables decide which groups of eight cells capture new data. There is no address input because this component stores only one word.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
WRITE_DATA |
Input | W | New word; bits 7:0 are the lowest byte |
WRITE_MASK |
Input | W/8 | Bit b enables writing byte b |
WE |
Input | 1 | Enables the masked write on a rising edge |
CLK |
Input | 1 | Rising-edge write clock |
RST |
Input | 1 | Active-high asynchronous clear of every bit |
Q |
Output | W | Continuously available stored word |
Behavior¶
For byte b, the cell write enable is WE AND WRITE_MASK[b].
| Condition | Next stored byte b |
|---|---|
RST = 1 |
Zero, regardless of clock, mask, or WE |
RST = 0, rising edge, WE = 1, mask bit b = 1 |
Byte b of WRITE_DATA |
| Otherwise | Previous byte b |
WRITE_MASK = 0 preserves the whole word. A high clock level is not another edge. For FFWord<32>, mask 0b0101 updates bytes 0 and 2 and retains bytes 1 and 3. Masking never packs or shifts the input bytes.
C++ example¶
#include <cstddef>
#include <cstdint>
template<std::size_t W>
struct FFWordReference {
static_assert(W == 8 || W == 16 || W == 32);
std::uint32_t q = 0;
bool previous_clk = false;
void update(std::uint32_t data, std::uint8_t mask,
bool we, bool clk, bool rst) {
if (rst) q = 0;
else if (!previous_clk && clk && we) {
for (std::size_t b = 0; b < W / 8; ++b) {
const auto lane = std::uint32_t{0xff} << (8 * b);
if (mask & (1u << b))
q = (q & ~lane) | (data & lane);
}
}
previous_clk = clk;
}
};
Only the lowest W data bits and W/8 mask bits participate, matching the hardware pin widths. Unlike the simulator's unknown power-up state, this binary example starts after reset.
Unknown inputs and timing¶
Structural words inherit each cell's unknown-state behavior and gate delays. The behavioral word also starts unknown and stores captured X/Z data as X. Reset restores known zero. FFWordContractTest checks unknown startup and captured unknown data as well as binary operation.
The structural/behavioral equivalence guarantee is for known-binary controls at settled checkpoints, with data and mask prepared before the edge. It does not promise identical transients or exhaustive agreement for uncertain clocks and controls.
Implementation¶
Structural implementation¶
| Internal component | Count | Responsibility |
|---|---|---|
BitSplitter<W> |
1 | DATA exposes individual write-data bits |
BitSplitter<W/8> |
1 | MASK exposes byte enable bits |
ANDGate |
W/8 | BYTE_b combines each mask bit with WE |
FlipFlopCell |
W | CELL_b stores each bit; created through its selectable family |
BitJoiner<W> |
1 | OUTPUT packs the stored bits into Q |
ConstantValue<1> |
1 | ZERO is a retained compatibility node; it does not drive FF storage |
Input splitters have their existing one-tick delay. Output packing is zero-delay wiring. This grouping adds no pipeline stage. Structural words may contain behavioral cells without changing the word's pins.
Behavioral implementation¶
FFWordBehavioral<W> stores W logic values and the previous clock, initially unknown. Reset clears all bits; an enabled known rising edge replaces the enabled byte lanes. It has no child cells; a catalog-selected word schedules Q using the delay table characterized from its structural counterpart.
When neither the write enable nor the byte mask definitely disables a lane, an ambiguous enable follows the cell's AND/OR feedback mux: only old zero/new zero stays zero; every other combination becomes X. Unknown reset merges each stored bit with zero. Equivalence is checked at settled checkpoints, not during gate propagation.
Examples¶
All 30 recorded rows of FFWordTest, 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 (1be28d8115a568f0). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CLKInput · 1 bit |
RSTInput · 1 bit |
WEInput · 1 bit |
WRITE_DATAInput · 16 bit |
WRITE_MASKInput · 2 bit |
QExpected output · 16 bit |
|---|---|---|---|---|---|---|---|
#0reset | 9 | 0 |
1 |
0 |
0x0000 |
0x0 |
0x0000 |
#1release-reset | 13 | 0 |
0 |
0 |
0x0000 |
0x0 |
0x0000 |
#2mask-0-setup | 16 | 0 |
0 |
0 |
0x3C81 |
0x0 |
0x0000 |
#3mask-0-enable | 18 | 0 |
0 |
1 |
0x3C81 |
0x0 |
0x0000 |
#4mask-0-write-edge | 23 | 1 |
0 |
1 |
0x3C81 |
0x0 |
0x0000 |
#5mask-0-high-is-not-edge | 26 | 1 |
0 |
1 |
0xC37E |
0x0 |
0x0000 |
#6mask-0-falling-is-not-write | 31 | 0 |
0 |
0 |
0xC37E |
0x0 |
0x0000 |
#7mask-0-disabled-edge | 36 | 1 |
0 |
0 |
0xC37E |
0x0 |
0x0000 |
#8mask-1-setup | 41 | 0 |
0 |
0 |
0x0FC4 |
0x1 |
0x0000 |
#9mask-1-enable | 50 | 0 |
0 |
1 |
0x0FC4 |
0x1 |
0x0000 |
#10mask-1-write-edge | 56 | 1 |
0 |
1 |
0x0FC4 |
0x1 |
0x00C4 |
#11mask-1-high-is-not-edge | 62 | 1 |
0 |
1 |
0xF03B |
0x1 |
0x00C4 |
#12mask-1-falling-is-not-write | 73 | 0 |
0 |
0 |
0xF03B |
0x1 |
0x00C4 |
#13mask-1-disabled-edge | 78 | 1 |
0 |
0 |
0xF03B |
0x1 |
0x00C4 |
#14mask-2-setup | 83 | 0 |
0 |
0 |
0x5A0B |
0x2 |
0x00C4 |
#15mask-2-enable | 92 | 0 |
0 |
1 |
0x5A0B |
0x2 |
0x00C4 |
#16mask-2-write-edge | 98 | 1 |
0 |
1 |
0x5A0B |
0x2 |
0x5AC4 |
#17mask-2-high-is-not-edge | 104 | 1 |
0 |
1 |
0xA5F4 |
0x2 |
0x5AC4 |
#18mask-2-falling-is-not-write | 115 | 0 |
0 |
0 |
0xA5F4 |
0x2 |
0x5AC4 |
#19mask-2-disabled-edge | 120 | 1 |
0 |
0 |
0xA5F4 |
0x2 |
0x5AC4 |
#20mask-3-setup | 125 | 0 |
0 |
0 |
0xA54E |
0x3 |
0x5AC4 |
#21mask-3-enable | 137 | 0 |
0 |
1 |
0xA54E |
0x3 |
0x5AC4 |
#22mask-3-write-edge | 143 | 1 |
0 |
1 |
0xA54E |
0x3 |
0xA54E |
#23mask-3-high-is-not-edge | 149 | 1 |
0 |
1 |
0x5AB1 |
0x3 |
0xA54E |
#24mask-3-falling-is-not-write | 160 | 0 |
0 |
0 |
0x5AB1 |
0x3 |
0xA54E |
#25mask-3-disabled-edge | 165 | 1 |
0 |
0 |
0x5AB1 |
0x3 |
0xA54E |
#26asynchronous-reset | 173 | 1 |
1 |
1 |
0x5AB1 |
0x3 |
0x0000 |
#27reset-priority-low | 177 | 0 |
1 |
1 |
0x5AB1 |
0x3 |
0x0000 |
#28reset-priority-edge | 181 | 1 |
1 |
1 |
0x5AB1 |
0x3 |
0x0000 |
#29release-without-edge | 185 | 1 |
0 |
1 |
0x5AB1 |
0x3 |
0x0000 |
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 embedded word is 16 bits, so its four masks are 00, 01, 10, and 11. mask-1-write-edge writes only the low byte (Q = 0x00C4); mask-2-write-edge changes the upper byte while retaining that low byte (Q = 0x5AC4). The high-is-not-edge and disabled-edge checkpoints retain each result. The final reset checkpoints clear both bytes, including while writing is enabled.
Embedded simulation¶
FFWordTest has 30 checkpoints. Inspect BYTE_0, BYTE_1, and the corresponding cell groups. The explorer can select behavioral fidelity for the word or individual cells; the table records the default structural run.
Source and tests¶
- Structural interface and implementation:
FFWord.hpp - Behavioral implementation:
FFWordBehavioral.hpp - Family registration:
FFMemory.cpp
| Test | Coverage |
|---|---|
FFWordTest / wordSpec() |
30 checkpoints for a 16-bit word, covering all four byte masks, hold behavior, and reset |
FFWordContractTest |
All masks at widths 8/16/32; structural and behavioral words; structural words containing behavioral cells; unknown startup and captured unknown data |
3.1.1.6. FFStorageBank<W>¶
FFStorageBank<W> groups N words. It distributes common write data, byte mask, clock, and reset, while keeping a separate write enable and output for each word. It does not decode an address, choose a read word, or implement a bus protocol. Here, “bank” is a storage grouping, not a DRAM command/timing model.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
WRITE_DATA |
Input | W | Shared data presented to every word |
WRITE_MASK |
Input | W/8 | Shared byte write mask |
CLK |
Input | 1 | Shared rising-edge write clock |
RST |
Input | 1 | Asynchronously clears every word |
WRITE_n |
Input | 1 each | Write enable for word n, for n = 0 through N−1 |
WORD_n |
Output | W each | Current contents of word n, for n = 0 through N−1 |
N is a construction-time word count, not another template parameter. The family accepts depth_words (default 4), with 1 <= N <= 4096 / W in both implementations. Structural storage creates exactly N words, including for non-power-of-two depths. The behavioral bank removes those child components but retains every WRITE_n and WORD_n pin; it is not an unlimited-capacity addressable memory.
Behavior¶
Each word follows §3.1.1.5 with WE = WRITE_n. A rising edge updates the enabled byte lanes of every word whose WRITE_n = 1; all other lanes hold. All WORD_n outputs are continuously available.
The bank does not enforce a one-hot write selection. Multiple high enables would write the same input data to multiple words. In FFMemory, address decoding and access control produce at most one high word enable for a known valid address. Reset clears every word regardless of those enables.
C++ example¶
#include <vector>
template<std::size_t W>
struct FFStorageBankReference {
std::vector<FFWordReference<W>> words;
explicit FFStorageBankReference(std::size_t count) {
if (count == 0 || count > 4096 / W)
throw std::invalid_argument("Invalid bank depth");
words.resize(count);
}
void update(std::uint32_t data, std::uint8_t mask,
const std::vector<bool>& write, bool clk, bool rst) {
if (write.size() != words.size())
throw std::invalid_argument("One write enable per word required");
for (std::size_t n = 0; n < words.size(); ++n)
words[n].update(data, mask, write[n], clk, rst);
}
};
words[n].q corresponds to WORD_n. The exceptions guard construction and the example's vector representation; the simulator exposes a fixed set of pins after construction.
Unknown inputs and timing¶
The structural bank adds no scheduling algorithm of its own: unknown-state behavior and capture timing belong to its words and their selected implementations. Common clock/reset fan out to all words. The behavioral bank starts with unknown bits and clock, captures X/Z data as X, and uses gate-derived output and clock-to-output delays when selected through the catalog.
Equivalence is defined for settled checkpoints with known-binary controls and data/masks/enables prepared before the rising edge. Tests also cover unknown startup, selected-word X capture, unselected-word retention, and reset recovery. They do not establish identical gate transients or exhaustive equivalence for uncertain clocks and controls.
Implementation¶
Structural implementation¶
| Internal component | Count | Responsibility |
|---|---|---|
FFWord<W> |
N | WORD_0 through WORD_(N−1) hold the words |
Each child receives the shared inputs, its own WRITE_n, and drives its matching output. Words are created through their registered family, so each word can be structural or behavioral.
Behavioral implementation¶
FFStorageBankBehavioral<W> stores N arrays of W logic values and one previous clock value, without child components. On a known rising edge it independently applies each word's enable and the shared byte mask. Multiple enabled words capture the same positioned data; the implementation does not reduce the enable pins to a single selected index.
Its uncertain-control rules match the behavioral word: for a lane that is not definitely disabled, ambiguous write enables or mask bits preserve zero only for old zero/new zero, following the cell's gate mux. Other combinations become X. Unknown reset merges stored bits with zero. A definite reset clears every word regardless of enable or mask.
The registered contract is memory.ff.bank.W. Its pin schema is generated from depth_words, so construction validates all N enables and outputs for both implementations. Selecting behavioral fidelity for FFMemory.STORAGE hides only the bank's words and cells; ADDRESS_DECODE, ACCESS_CONTROL, and READ_SELECT remain structural and visible.
Examples¶
All 134 recorded rows of FFStorageBankTest, 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 (091f63bdebf4ca14). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CLKInput · 1 bit |
RSTInput · 1 bit |
WRITE_0Input · 1 bit |
WRITE_1Input · 1 bit |
WRITE_2Input · 1 bit |
WRITE_DATAInput · 16 bit |
WRITE_MASKInput · 2 bit |
WORD_0Expected output · 16 bit |
WORD_1Expected output · 16 bit |
WORD_2Expected output · 16 bit |
|---|---|---|---|---|---|---|---|---|---|---|---|
#0reset | 9 | 0 |
1 |
0 |
0 |
0 |
0x0000 |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#1release-reset | 13 | 0 |
0 |
0 |
0 |
0 |
0x0000 |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#2select-0-mask-0-setup | 16 | 0 |
0 |
0 |
0 |
0 |
0x3C81 |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#3select-0-mask-0-write-edge | 21 | 1 |
0 |
0 |
0 |
0 |
0x3C81 |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#4select-0-mask-0-high-is-not-edge | 24 | 1 |
0 |
0 |
0 |
0 |
0xC37E |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#5select-0-mask-0-falling-is-not-write | 29 | 0 |
0 |
0 |
0 |
0 |
0xC37E |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#6select-0-mask-1-setup | 32 | 0 |
0 |
0 |
0 |
0 |
0x3889 |
0x1 |
0x0000 |
0x0000 |
0x0000 |
#7select-0-mask-1-write-edge | 37 | 1 |
0 |
0 |
0 |
0 |
0x3889 |
0x1 |
0x0000 |
0x0000 |
0x0000 |
#8select-0-mask-1-high-is-not-edge | 40 | 1 |
0 |
0 |
0 |
0 |
0xC776 |
0x1 |
0x0000 |
0x0000 |
0x0000 |
#9select-0-mask-1-falling-is-not-write | 45 | 0 |
0 |
0 |
0 |
0 |
0xC776 |
0x1 |
0x0000 |
0x0000 |
0x0000 |
#10select-0-mask-2-setup | 48 | 0 |
0 |
0 |
0 |
0 |
0x3491 |
0x2 |
0x0000 |
0x0000 |
0x0000 |
#11select-0-mask-2-write-edge | 53 | 1 |
0 |
0 |
0 |
0 |
0x3491 |
0x2 |
0x0000 |
0x0000 |
0x0000 |
#12select-0-mask-2-high-is-not-edge | 56 | 1 |
0 |
0 |
0 |
0 |
0xCB6E |
0x2 |
0x0000 |
0x0000 |
0x0000 |
#13select-0-mask-2-falling-is-not-write | 61 | 0 |
0 |
0 |
0 |
0 |
0xCB6E |
0x2 |
0x0000 |
0x0000 |
0x0000 |
#14select-0-mask-3-setup | 64 | 0 |
0 |
0 |
0 |
0 |
0x3099 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#15select-0-mask-3-write-edge | 69 | 1 |
0 |
0 |
0 |
0 |
0x3099 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#16select-0-mask-3-high-is-not-edge | 72 | 1 |
0 |
0 |
0 |
0 |
0xCF66 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#17select-0-mask-3-falling-is-not-write | 77 | 0 |
0 |
0 |
0 |
0 |
0xCF66 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#18select-1-mask-0-setup | 89 | 0 |
0 |
1 |
0 |
0 |
0x0FC4 |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#19select-1-mask-0-write-edge | 94 | 1 |
0 |
1 |
0 |
0 |
0x0FC4 |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#20select-1-mask-0-high-is-not-edge | 97 | 1 |
0 |
1 |
0 |
0 |
0xF03B |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#21select-1-mask-0-falling-is-not-write | 102 | 0 |
0 |
1 |
0 |
0 |
0xF03B |
0x0 |
0x0000 |
0x0000 |
0x0000 |
#22select-1-mask-1-setup | 112 | 0 |
0 |
1 |
0 |
0 |
0x0BCC |
0x1 |
0x0000 |
0x0000 |
0x0000 |
#23select-1-mask-1-write-edge | 118 | 1 |
0 |
1 |
0 |
0 |
0x0BCC |
0x1 |
0x00CC |
0x0000 |
0x0000 |
#24select-1-mask-1-high-is-not-edge | 124 | 1 |
0 |
1 |
0 |
0 |
0xF433 |
0x1 |
0x00CC |
0x0000 |
0x0000 |
#25select-1-mask-1-falling-is-not-write | 132 | 0 |
0 |
1 |
0 |
0 |
0xF433 |
0x1 |
0x00CC |
0x0000 |
0x0000 |
#26select-1-mask-2-setup | 144 | 0 |
0 |
1 |
0 |
0 |
0x07D4 |
0x2 |
0x00CC |
0x0000 |
0x0000 |
#27select-1-mask-2-write-edge | 150 | 1 |
0 |
1 |
0 |
0 |
0x07D4 |
0x2 |
0x07CC |
0x0000 |
0x0000 |
#28select-1-mask-2-high-is-not-edge | 156 | 1 |
0 |
1 |
0 |
0 |
0xF82B |
0x2 |
0x07CC |
0x0000 |
0x0000 |
#29select-1-mask-2-falling-is-not-write | 164 | 0 |
0 |
1 |
0 |
0 |
0xF82B |
0x2 |
0x07CC |
0x0000 |
0x0000 |
#30select-1-mask-3-setup | 175 | 0 |
0 |
1 |
0 |
0 |
0x03DC |
0x3 |
0x07CC |
0x0000 |
0x0000 |
#31select-1-mask-3-write-edge | 181 | 1 |
0 |
1 |
0 |
0 |
0x03DC |
0x3 |
0x03DC |
0x0000 |
0x0000 |
#32select-1-mask-3-high-is-not-edge | 187 | 1 |
0 |
1 |
0 |
0 |
0xFC23 |
0x3 |
0x03DC |
0x0000 |
0x0000 |
#33select-1-mask-3-falling-is-not-write | 195 | 0 |
0 |
1 |
0 |
0 |
0xFC23 |
0x3 |
0x03DC |
0x0000 |
0x0000 |
#34select-2-mask-0-setup | 207 | 0 |
0 |
0 |
1 |
0 |
0x5A0B |
0x0 |
0x03DC |
0x0000 |
0x0000 |
#35select-2-mask-0-write-edge | 212 | 1 |
0 |
0 |
1 |
0 |
0x5A0B |
0x0 |
0x03DC |
0x0000 |
0x0000 |
#36select-2-mask-0-high-is-not-edge | 215 | 1 |
0 |
0 |
1 |
0 |
0xA5F4 |
0x0 |
0x03DC |
0x0000 |
0x0000 |
#37select-2-mask-0-falling-is-not-write | 220 | 0 |
0 |
0 |
1 |
0 |
0xA5F4 |
0x0 |
0x03DC |
0x0000 |
0x0000 |
#38select-2-mask-1-setup | 230 | 0 |
0 |
0 |
1 |
0 |
0x5E03 |
0x1 |
0x03DC |
0x0000 |
0x0000 |
#39select-2-mask-1-write-edge | 236 | 1 |
0 |
0 |
1 |
0 |
0x5E03 |
0x1 |
0x03DC |
0x0003 |
0x0000 |
#40select-2-mask-1-high-is-not-edge | 242 | 1 |
0 |
0 |
1 |
0 |
0xA1FC |
0x1 |
0x03DC |
0x0003 |
0x0000 |
#41select-2-mask-1-falling-is-not-write | 250 | 0 |
0 |
0 |
1 |
0 |
0xA1FC |
0x1 |
0x03DC |
0x0003 |
0x0000 |
#42select-2-mask-2-setup | 262 | 0 |
0 |
0 |
1 |
0 |
0x521B |
0x2 |
0x03DC |
0x0003 |
0x0000 |
#43select-2-mask-2-write-edge | 268 | 1 |
0 |
0 |
1 |
0 |
0x521B |
0x2 |
0x03DC |
0x5203 |
0x0000 |
#44select-2-mask-2-high-is-not-edge | 274 | 1 |
0 |
0 |
1 |
0 |
0xADE4 |
0x2 |
0x03DC |
0x5203 |
0x0000 |
#45select-2-mask-2-falling-is-not-write | 282 | 0 |
0 |
0 |
1 |
0 |
0xADE4 |
0x2 |
0x03DC |
0x5203 |
0x0000 |
#46select-2-mask-3-setup | 293 | 0 |
0 |
0 |
1 |
0 |
0x5613 |
0x3 |
0x03DC |
0x5203 |
0x0000 |
#47select-2-mask-3-write-edge | 299 | 1 |
0 |
0 |
1 |
0 |
0x5613 |
0x3 |
0x03DC |
0x5613 |
0x0000 |
#48select-2-mask-3-high-is-not-edge | 305 | 1 |
0 |
0 |
1 |
0 |
0xA9EC |
0x3 |
0x03DC |
0x5613 |
0x0000 |
#49select-2-mask-3-falling-is-not-write | 313 | 0 |
0 |
0 |
1 |
0 |
0xA9EC |
0x3 |
0x03DC |
0x5613 |
0x0000 |
#50select-3-mask-0-setup | 325 | 0 |
0 |
1 |
1 |
0 |
0xA54E |
0x0 |
0x03DC |
0x5613 |
0x0000 |
#51select-3-mask-0-write-edge | 330 | 1 |
0 |
1 |
1 |
0 |
0xA54E |
0x0 |
0x03DC |
0x5613 |
0x0000 |
#52select-3-mask-0-high-is-not-edge | 333 | 1 |
0 |
1 |
1 |
0 |
0x5AB1 |
0x0 |
0x03DC |
0x5613 |
0x0000 |
#53select-3-mask-0-falling-is-not-write | 338 | 0 |
0 |
1 |
1 |
0 |
0x5AB1 |
0x0 |
0x03DC |
0x5613 |
0x0000 |
#54select-3-mask-1-setup | 351 | 0 |
0 |
1 |
1 |
0 |
0xA146 |
0x1 |
0x03DC |
0x5613 |
0x0000 |
#55select-3-mask-1-write-edge | 357 | 1 |
0 |
1 |
1 |
0 |
0xA146 |
0x1 |
0x0346 |
0x5646 |
0x0000 |
#56select-3-mask-1-high-is-not-edge | 363 | 1 |
0 |
1 |
1 |
0 |
0x5EB9 |
0x1 |
0x0346 |
0x5646 |
0x0000 |
#57select-3-mask-1-falling-is-not-write | 371 | 0 |
0 |
1 |
1 |
0 |
0x5EB9 |
0x1 |
0x0346 |
0x5646 |
0x0000 |
#58select-3-mask-2-setup | 384 | 0 |
0 |
1 |
1 |
0 |
0xAD5E |
0x2 |
0x0346 |
0x5646 |
0x0000 |
#59select-3-mask-2-write-edge | 390 | 1 |
0 |
1 |
1 |
0 |
0xAD5E |
0x2 |
0xAD46 |
0xAD46 |
0x0000 |
#60select-3-mask-2-high-is-not-edge | 396 | 1 |
0 |
1 |
1 |
0 |
0x52A1 |
0x2 |
0xAD46 |
0xAD46 |
0x0000 |
#61select-3-mask-2-falling-is-not-write | 404 | 0 |
0 |
1 |
1 |
0 |
0x52A1 |
0x2 |
0xAD46 |
0xAD46 |
0x0000 |
#62select-3-mask-3-setup | 415 | 0 |
0 |
1 |
1 |
0 |
0xA956 |
0x3 |
0xAD46 |
0xAD46 |
0x0000 |
#63select-3-mask-3-write-edge | 421 | 1 |
0 |
1 |
1 |
0 |
0xA956 |
0x3 |
0xA956 |
0xA956 |
0x0000 |
#64select-3-mask-3-high-is-not-edge | 427 | 1 |
0 |
1 |
1 |
0 |
0x56A9 |
0x3 |
0xA956 |
0xA956 |
0x0000 |
#65select-3-mask-3-falling-is-not-write | 435 | 0 |
0 |
1 |
1 |
0 |
0x56A9 |
0x3 |
0xA956 |
0xA956 |
0x0000 |
#66select-4-mask-0-setup | 447 | 0 |
0 |
0 |
0 |
1 |
0xF195 |
0x0 |
0xA956 |
0xA956 |
0x0000 |
#67select-4-mask-0-write-edge | 452 | 1 |
0 |
0 |
0 |
1 |
0xF195 |
0x0 |
0xA956 |
0xA956 |
0x0000 |
#68select-4-mask-0-high-is-not-edge | 455 | 1 |
0 |
0 |
0 |
1 |
0x0E6A |
0x0 |
0xA956 |
0xA956 |
0x0000 |
#69select-4-mask-0-falling-is-not-write | 460 | 0 |
0 |
0 |
0 |
1 |
0x0E6A |
0x0 |
0xA956 |
0xA956 |
0x0000 |
#70select-4-mask-1-setup | 470 | 0 |
0 |
0 |
0 |
1 |
0xF59D |
0x1 |
0xA956 |
0xA956 |
0x0000 |
#71select-4-mask-1-write-edge | 476 | 1 |
0 |
0 |
0 |
1 |
0xF59D |
0x1 |
0xA956 |
0xA956 |
0x009D |
#72select-4-mask-1-high-is-not-edge | 482 | 1 |
0 |
0 |
0 |
1 |
0x0A62 |
0x1 |
0xA956 |
0xA956 |
0x009D |
#73select-4-mask-1-falling-is-not-write | 490 | 0 |
0 |
0 |
0 |
1 |
0x0A62 |
0x1 |
0xA956 |
0xA956 |
0x009D |
#74select-4-mask-2-setup | 501 | 0 |
0 |
0 |
0 |
1 |
0xF985 |
0x2 |
0xA956 |
0xA956 |
0x009D |
#75select-4-mask-2-write-edge | 507 | 1 |
0 |
0 |
0 |
1 |
0xF985 |
0x2 |
0xA956 |
0xA956 |
0xF99D |
#76select-4-mask-2-high-is-not-edge | 513 | 1 |
0 |
0 |
0 |
1 |
0x067A |
0x2 |
0xA956 |
0xA956 |
0xF99D |
#77select-4-mask-2-falling-is-not-write | 521 | 0 |
0 |
0 |
0 |
1 |
0x067A |
0x2 |
0xA956 |
0xA956 |
0xF99D |
#78select-4-mask-3-setup | 534 | 0 |
0 |
0 |
0 |
1 |
0xFD8D |
0x3 |
0xA956 |
0xA956 |
0xF99D |
#79select-4-mask-3-write-edge | 540 | 1 |
0 |
0 |
0 |
1 |
0xFD8D |
0x3 |
0xA956 |
0xA956 |
0xFD8D |
#80select-4-mask-3-high-is-not-edge | 546 | 1 |
0 |
0 |
0 |
1 |
0x0272 |
0x3 |
0xA956 |
0xA956 |
0xFD8D |
#81select-4-mask-3-falling-is-not-write | 554 | 0 |
0 |
0 |
0 |
1 |
0x0272 |
0x3 |
0xA956 |
0xA956 |
0xFD8D |
#82select-5-mask-0-setup | 566 | 0 |
0 |
1 |
0 |
1 |
0x3CD8 |
0x0 |
0xA956 |
0xA956 |
0xFD8D |
#83select-5-mask-0-write-edge | 571 | 1 |
0 |
1 |
0 |
1 |
0x3CD8 |
0x0 |
0xA956 |
0xA956 |
0xFD8D |
#84select-5-mask-0-high-is-not-edge | 574 | 1 |
0 |
1 |
0 |
1 |
0xC327 |
0x0 |
0xA956 |
0xA956 |
0xFD8D |
#85select-5-mask-0-falling-is-not-write | 579 | 0 |
0 |
1 |
0 |
1 |
0xC327 |
0x0 |
0xA956 |
0xA956 |
0xFD8D |
#86select-5-mask-1-setup | 592 | 0 |
0 |
1 |
0 |
1 |
0x38D0 |
0x1 |
0xA956 |
0xA956 |
0xFD8D |
#87select-5-mask-1-write-edge | 598 | 1 |
0 |
1 |
0 |
1 |
0x38D0 |
0x1 |
0xA9D0 |
0xA956 |
0xFDD0 |
#88select-5-mask-1-high-is-not-edge | 604 | 1 |
0 |
1 |
0 |
1 |
0xC72F |
0x1 |
0xA9D0 |
0xA956 |
0xFDD0 |
#89select-5-mask-1-falling-is-not-write | 612 | 0 |
0 |
1 |
0 |
1 |
0xC72F |
0x1 |
0xA9D0 |
0xA956 |
0xFDD0 |
#90select-5-mask-2-setup | 625 | 0 |
0 |
1 |
0 |
1 |
0x34C8 |
0x2 |
0xA9D0 |
0xA956 |
0xFDD0 |
#91select-5-mask-2-write-edge | 631 | 1 |
0 |
1 |
0 |
1 |
0x34C8 |
0x2 |
0x34D0 |
0xA956 |
0x34D0 |
#92select-5-mask-2-high-is-not-edge | 637 | 1 |
0 |
1 |
0 |
1 |
0xCB37 |
0x2 |
0x34D0 |
0xA956 |
0x34D0 |
#93select-5-mask-2-falling-is-not-write | 645 | 0 |
0 |
1 |
0 |
1 |
0xCB37 |
0x2 |
0x34D0 |
0xA956 |
0x34D0 |
#94select-5-mask-3-setup | 658 | 0 |
0 |
1 |
0 |
1 |
0x30C0 |
0x3 |
0x34D0 |
0xA956 |
0x34D0 |
#95select-5-mask-3-write-edge | 664 | 1 |
0 |
1 |
0 |
1 |
0x30C0 |
0x3 |
0x30C0 |
0xA956 |
0x30C0 |
#96select-5-mask-3-high-is-not-edge | 670 | 1 |
0 |
1 |
0 |
1 |
0xCF3F |
0x3 |
0x30C0 |
0xA956 |
0x30C0 |
#97select-5-mask-3-falling-is-not-write | 678 | 0 |
0 |
1 |
0 |
1 |
0xCF3F |
0x3 |
0x30C0 |
0xA956 |
0x30C0 |
#98select-6-mask-0-setup | 690 | 0 |
0 |
0 |
1 |
1 |
0x0F1F |
0x0 |
0x30C0 |
0xA956 |
0x30C0 |
#99select-6-mask-0-write-edge | 695 | 1 |
0 |
0 |
1 |
1 |
0x0F1F |
0x0 |
0x30C0 |
0xA956 |
0x30C0 |
#100select-6-mask-0-high-is-not-edge | 698 | 1 |
0 |
0 |
1 |
1 |
0xF0E0 |
0x0 |
0x30C0 |
0xA956 |
0x30C0 |
#101select-6-mask-0-falling-is-not-write | 703 | 0 |
0 |
0 |
1 |
1 |
0xF0E0 |
0x0 |
0x30C0 |
0xA956 |
0x30C0 |
#102select-6-mask-1-setup | 716 | 0 |
0 |
0 |
1 |
1 |
0x0B17 |
0x1 |
0x30C0 |
0xA956 |
0x30C0 |
#103select-6-mask-1-write-edge | 722 | 1 |
0 |
0 |
1 |
1 |
0x0B17 |
0x1 |
0x30C0 |
0xA917 |
0x3017 |
#104select-6-mask-1-high-is-not-edge | 728 | 1 |
0 |
0 |
1 |
1 |
0xF4E8 |
0x1 |
0x30C0 |
0xA917 |
0x3017 |
#105select-6-mask-1-falling-is-not-write | 736 | 0 |
0 |
0 |
1 |
1 |
0xF4E8 |
0x1 |
0x30C0 |
0xA917 |
0x3017 |
#106select-6-mask-2-setup | 749 | 0 |
0 |
0 |
1 |
1 |
0x070F |
0x2 |
0x30C0 |
0xA917 |
0x3017 |
#107select-6-mask-2-write-edge | 755 | 1 |
0 |
0 |
1 |
1 |
0x070F |
0x2 |
0x30C0 |
0x0717 |
0x0717 |
#108select-6-mask-2-high-is-not-edge | 761 | 1 |
0 |
0 |
1 |
1 |
0xF8F0 |
0x2 |
0x30C0 |
0x0717 |
0x0717 |
#109select-6-mask-2-falling-is-not-write | 769 | 0 |
0 |
0 |
1 |
1 |
0xF8F0 |
0x2 |
0x30C0 |
0x0717 |
0x0717 |
#110select-6-mask-3-setup | 782 | 0 |
0 |
0 |
1 |
1 |
0x0307 |
0x3 |
0x30C0 |
0x0717 |
0x0717 |
#111select-6-mask-3-write-edge | 788 | 1 |
0 |
0 |
1 |
1 |
0x0307 |
0x3 |
0x30C0 |
0x0307 |
0x0307 |
#112select-6-mask-3-high-is-not-edge | 794 | 1 |
0 |
0 |
1 |
1 |
0xFCF8 |
0x3 |
0x30C0 |
0x0307 |
0x0307 |
#113select-6-mask-3-falling-is-not-write | 802 | 0 |
0 |
0 |
1 |
1 |
0xFCF8 |
0x3 |
0x30C0 |
0x0307 |
0x0307 |
#114select-7-mask-0-setup | 814 | 0 |
0 |
1 |
1 |
1 |
0x5A62 |
0x0 |
0x30C0 |
0x0307 |
0x0307 |
#115select-7-mask-0-write-edge | 819 | 1 |
0 |
1 |
1 |
1 |
0x5A62 |
0x0 |
0x30C0 |
0x0307 |
0x0307 |
#116select-7-mask-0-high-is-not-edge | 822 | 1 |
0 |
1 |
1 |
1 |
0xA59D |
0x0 |
0x30C0 |
0x0307 |
0x0307 |
#117select-7-mask-0-falling-is-not-write | 827 | 0 |
0 |
1 |
1 |
1 |
0xA59D |
0x0 |
0x30C0 |
0x0307 |
0x0307 |
#118select-7-mask-1-setup | 840 | 0 |
0 |
1 |
1 |
1 |
0x5E6A |
0x1 |
0x30C0 |
0x0307 |
0x0307 |
#119select-7-mask-1-write-edge | 846 | 1 |
0 |
1 |
1 |
1 |
0x5E6A |
0x1 |
0x306A |
0x036A |
0x036A |
#120select-7-mask-1-high-is-not-edge | 852 | 1 |
0 |
1 |
1 |
1 |
0xA195 |
0x1 |
0x306A |
0x036A |
0x036A |
#121select-7-mask-1-falling-is-not-write | 860 | 0 |
0 |
1 |
1 |
1 |
0xA195 |
0x1 |
0x306A |
0x036A |
0x036A |
#122select-7-mask-2-setup | 873 | 0 |
0 |
1 |
1 |
1 |
0x5272 |
0x2 |
0x306A |
0x036A |
0x036A |
#123select-7-mask-2-write-edge | 879 | 1 |
0 |
1 |
1 |
1 |
0x5272 |
0x2 |
0x526A |
0x526A |
0x526A |
#124select-7-mask-2-high-is-not-edge | 885 | 1 |
0 |
1 |
1 |
1 |
0xAD8D |
0x2 |
0x526A |
0x526A |
0x526A |
#125select-7-mask-2-falling-is-not-write | 893 | 0 |
0 |
1 |
1 |
1 |
0xAD8D |
0x2 |
0x526A |
0x526A |
0x526A |
#126select-7-mask-3-setup | 904 | 0 |
0 |
1 |
1 |
1 |
0x567A |
0x3 |
0x526A |
0x526A |
0x526A |
#127select-7-mask-3-write-edge | 910 | 1 |
0 |
1 |
1 |
1 |
0x567A |
0x3 |
0x567A |
0x567A |
0x567A |
#128select-7-mask-3-high-is-not-edge | 916 | 1 |
0 |
1 |
1 |
1 |
0xA985 |
0x3 |
0x567A |
0x567A |
0x567A |
#129select-7-mask-3-falling-is-not-write | 924 | 0 |
0 |
1 |
1 |
1 |
0xA985 |
0x3 |
0x567A |
0x567A |
0x567A |
#130asynchronous-reset | 931 | 0 |
1 |
1 |
1 |
1 |
0xA985 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#131reset-priority-edge | 935 | 1 |
1 |
1 |
1 |
1 |
0xA985 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#132release-without-edge | 939 | 1 |
0 |
1 |
1 |
1 |
0xA985 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
#133reset-again | 943 | 1 |
1 |
1 |
1 |
1 |
0xA985 |
0x3 |
0x0000 |
0x0000 |
0x0000 |
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 embedded bank has three 16-bit words. Its 134 checkpoints cover all eight word-enable combinations and all four byte masks, followed by reset checks. Every WORD_n is an asserted root output, including words that should retain their old contents.
In a label such as select-5-mask-1-write-edge, select-5 means binary 101: WRITE_0 and WRITE_2 are high, while WRITE_1 is low. Mask 01 updates only the low byte of words 0 and 2. Word 1 and the upper bytes retain their previous values. Selection 0 writes nothing; selection 7 enables all three words; mask 0 writes no bytes even when words are enabled.
Each selection/mask pair has four checkpoints: setup prepares inputs with a low clock, write-edge captures enabled bytes, high-is-not-edge changes the data without another capture, and falling-is-not-write lowers the clock without writing. The final four checkpoints check asynchronous reset, reset priority at an edge, release without an edge, and another reset.
Embedded simulation¶
FFStorageBankTest opens the bank itself as FF_STORAGE_BANK_ROOT, displayed as FFStorageBank<16,3>. Expand WORD_0 to inspect its cells. The explorer can select behavioral fidelity for the entire bank, individual words, or individual cells. The table records the default structural profile; alternative fidelities can have different checkpoint times.
Open FFStorageBank in the simulator
Source and tests¶
- Structural interface and implementation:
FFStorageBank.hpp - Behavioral implementation:
FFStorageBankBehavioral.hpp - Family and parameterized pin registration:
FFMemory.cpp
| Test | Coverage |
|---|---|
FFStorageBankTest / bankSpec() |
134 standalone checkpoints for three 16-bit words, all word-enable combinations and byte masks, retention, and reset |
FFStorageBankContractTest |
Widths 8/16/32 and depths 1/3/7; independent and simultaneous writes; all byte masks; structural/behavioral and mixed-word/cell equivalence; selected unknown cases; depth bounds and exact parameterized pin validation |
FFMemoryFidelityTest |
Bank-level behavioral selection inside structural devices, alongside word/cell/device selections |
DocumentationExamplesTest |
Compiles the binary bank example, replays every standalone bank row, and also checks internal bank signals in the complete memory scenario |
3.1.1.7. FFMemory<W>¶
FFMemory<W> is the complete addressable FF device. It adds one shared word address, access checking, and a read multiplexer to FFStorageBank<W>. The structural implementation exposes those blocks; the behavioral implementation keeps the same device pins without expanding words or cells. Its decoder and read selector reuse the gate-construction routines described in 3.1.0. Helper Components, without changing their FF-specific pins, range checks, or zero-on-disabled-read behavior.
IO pins¶
| Pin | Direction | Width | Description |
|---|---|---|---|
WORD_ADDR |
Input | 32 | Word index, not a byte address |
WRITE_DATA |
Input | W | Positioned bytes to write into the selected word |
WRITE_MASK |
Input | W/8 | Bit b enables byte b of that word |
WE |
Input | 1 | Enables writing on a rising clock edge |
READ_EN |
Input | 1 | Enables the asynchronous read output |
CLK |
Input | 1 | Rising-edge write clock |
RST |
Input | 1 | Active-high asynchronous clear of all stored words |
READ_DATA |
Output | W | Selected word, or zero for a disabled/known invalid read |
FAULT |
Output | 1 | Active read/write address is outside the configured depth |
There is no READY pin or request/response handshake. The caller must allow propagation to settle. Reads and writes use the same address.
Behavior¶
For known binary controls, let in_range = WORD_ADDR < depth_words.
| Operation | Result |
|---|---|
READ_EN = 0 |
READ_DATA = 0; contents are unchanged by disabling reads |
READ_EN = 1, in range |
READ_DATA follows the selected stored word after propagation, without a clock edge |
READ_EN = 1, out of range |
READ_DATA = 0, FAULT = 1 |
Rising edge, WE = 1, in range, RST = 0 |
Write the mask-enabled bytes of the selected word |
WE = 1, out of range |
No word is written; FAULT = 1, even before an edge |
READ_EN = WE = 0 |
FAULT = 0, regardless of address |
RST = 1 |
Clear all words; address/read/fault logic still follows its inputs |
In particular, FAULT = (READ_EN OR WE) AND NOT in_range; a zero write mask does not exempt an active invalid address. A valid simultaneous read/write observes the old word before the edge and the updated word after propagation. Reset is a storage clear, not an instruction to force READ_EN, WE, or FAULT low.
Width is fixed by FFMemory<W>; depth is supplied through MemoryConfig. For example, FFMemory<32> with .depth_words = 4 stores 16 bytes, while FFMemory<8> with the same depth stores 4 bytes. Word index 2 identifies the third word in both; its byte offset is 2 * W/8.
| Configuration | Meaning and limits |
|---|---|
depth_words |
N words; default 4. Non-power-of-two depths are supported. Structural expansion is limited to 4096 cells: at most 512/256/128 words for W = 8/16/32 |
read_delay_ticks |
Behavioral output delay in simulator ticks, not CPU cycles, for a device built without a proven delay table. Devices built through the catalog use the table proven on their gates instead. Default 1; structural selection requires 1 but retains its actual gate propagation delays |
initial_value |
Default unknown. Structural selection requires unknown startup; behavioral storage also supports configured initial fill |
record_history |
Controls behavioral backing-store history, not the simulator's separate wire/pin history |
Larger memories use the behavioral device rather than expanding every cell. This is a simulator resource limit, not a physical FF capacity claim.
C++ example¶
template<std::size_t W>
struct FFMemoryReference {
FFStorageBankReference<W> storage;
std::uint32_t read_data = 0;
bool fault = false;
explicit FFMemoryReference(std::size_t count) : storage(count) {}
void update(std::uint32_t address, std::uint32_t data,
std::uint8_t mask, bool we, bool read_en,
bool clk, bool rst) {
const bool valid = address < storage.words.size();
std::vector<bool> write(storage.words.size(), false);
if (valid && we) write[address] = true;
storage.update(data, mask, write, clk, rst);
read_data = read_en && valid ? storage.words[address].q : 0;
fault = (read_en || we) && !valid;
}
};
This example exposes the binary composition: decode one write enable, update the bank, then select the read result. It uses the preceding small bank's depth guard. The scalable simulator implementation does not allocate this vector of word components.
Unknown inputs and timing¶
Unwritten storage is initially X; asserting reset establishes zero. Gate-level propagation determines structural intermediate values. The behavioral device suppresses writes with ambiguous controls, address, or mask; an unknown read enable or enabled unknown address produces unknown read data. Ambiguous active access controls/address/mask can produce unknown FAULT. Captured Z is stored as X; an unknown reset makes the behavioral storage unknown.
The shared equivalence contract is settled binary behavior, not all four-state histories. A catalog-selected behavioral device uses the delay table characterized from the structural decoder, controls, cells, and read muxes; read_delay_ticks applies only without such a table. The table is a per-path contract, and multi-input histories beyond the comparisons are not exhaustively proven. Keep write address, data, mask, and WE stable before the capture edge.
Implementation¶
Structural implementation¶
| Block | Inputs → outputs | Responsibility |
|---|---|---|
MemoryAddressDecoder |
WORD_ADDR → IN_RANGE, VALID_n, SELECT_b |
Validate the full 32-bit index, identify each valid word, and supply read-mux address bits |
MemoryAccessControl |
IN_RANGE, VALID_n, WE, READ_EN → WRITE_n, READ_VALID, FAULT |
Gate each word write enable, permit valid reads, and flag active out-of-range accesses |
FFStorageBank<W> |
Shared data/mask/clock/reset and WRITE_n → WORD_n |
Hold exactly N words as specified in §3.1.1.6 |
MemoryReadSelector<W> |
WORD_n, SELECT_b, READ_VALID → READ_DATA |
Select the addressed word through mux trees and gate the result |
The decoder checks high address bits as well as the bits used for selection: an invalid index must not alias a valid word. Non-power-of-two depths have no extra storage cells; missing read-mux leaves are zero. A one-word device needs range checking but no word-selection decoder gates or read-selection muxes. These three address/control/read helper blocks are structural only; the bank's word/cell children remain selectable.
Behavioral implementation¶
FFMemoryBehavioral<W> implements the compact FF device. It uses MemoryStorage for values, known-bit masks, optional history, and setup-time image loading. Writes occur on rising edges and reset clears storage. The public display type remains FFMemory8, FFMemory16, or FFMemory32.
MemoryContainer is the implementation and MemoryStorage is its host-side backing store; they are not extra hardware layers inside the structural bank. Image loading and backing-store inspection are available on the behavioral device. The structural device instead exposes its actual word/cell pins.
Fidelity can be selected at four boundaries: the whole device, its bank, individual words, or individual cells. FFMemoryFidelityTest compares these combinations at settled checkpoints. Collapsing a parent removes its visible children; saved child choices remain available when structural expansion is restored.
Examples¶
All 52 recorded rows of FFMemoryTest, 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 (5627bf74381b9d40). Changing fidelity or the circuit can change these times.
| Checkpointzero-based number · timeline label | Timesimulator units | CLKInput · 1 bit |
READ_ENInput · 1 bit |
RSTInput · 1 bit |
WEInput · 1 bit |
WORD_ADDRInput · 32 bit |
WRITE_DATAInput · 8 bit |
WRITE_MASKInput · 1 bit |
FAULTExpected output · 1 bit |
READ_DATAExpected output · 8 bit |
|---|---|---|---|---|---|---|---|---|---|---|
#0initial-disabled | 9 | 0 |
0 |
1 |
0 |
0x00000000 |
0x00 |
1 |
0 |
0x00 |
#1release-reset | 13 | 0 |
0 |
0 |
0 |
0x00000000 |
0x00 |
1 |
0 |
0x00 |
#2setup-0 | 16 | 0 |
0 |
0 |
0 |
0x00000000 |
0x81 |
1 |
0 |
0x00 |
#3write-enable-0 | 26 | 0 |
0 |
0 |
1 |
0x00000000 |
0x81 |
1 |
0 |
0x00 |
#4write-edge-0 | 35 | 1 |
0 |
0 |
1 |
0x00000000 |
0x81 |
1 |
0 |
0x00 |
#5finish-write-0 | 46 | 0 |
0 |
0 |
0 |
0x00000000 |
0x81 |
1 |
0 |
0x00 |
#6read-0 | 49 | 0 |
1 |
0 |
0 |
0x00000000 |
0x81 |
1 |
0 |
0x81 |
#7setup-1 | 57 | 0 |
0 |
0 |
0 |
0x00000001 |
0x80 |
1 |
0 |
0x00 |
#8write-enable-1 | 67 | 0 |
0 |
0 |
1 |
0x00000001 |
0x80 |
1 |
0 |
0x00 |
#9write-edge-1 | 76 | 1 |
0 |
0 |
1 |
0x00000001 |
0x80 |
1 |
0 |
0x00 |
#10finish-write-1 | 87 | 0 |
0 |
0 |
0 |
0x00000001 |
0x80 |
1 |
0 |
0x00 |
#11read-1 | 90 | 0 |
1 |
0 |
0 |
0x00000001 |
0x80 |
1 |
0 |
0x80 |
#12setup-2 | 96 | 0 |
0 |
0 |
0 |
0x00000002 |
0x83 |
1 |
0 |
0x00 |
#13write-enable-2 | 106 | 0 |
0 |
0 |
1 |
0x00000002 |
0x83 |
1 |
0 |
0x00 |
#14write-edge-2 | 115 | 1 |
0 |
0 |
1 |
0x00000002 |
0x83 |
1 |
0 |
0x00 |
#15finish-write-2 | 126 | 0 |
0 |
0 |
0 |
0x00000002 |
0x83 |
1 |
0 |
0x00 |
#16read-2 | 129 | 0 |
1 |
0 |
0 |
0x00000002 |
0x83 |
1 |
0 |
0x83 |
#17setup-3 | 137 | 0 |
0 |
0 |
0 |
0x00000003 |
0x82 |
1 |
0 |
0x00 |
#18write-enable-3 | 147 | 0 |
0 |
0 |
1 |
0x00000003 |
0x82 |
1 |
0 |
0x00 |
#19write-edge-3 | 156 | 1 |
0 |
0 |
1 |
0x00000003 |
0x82 |
1 |
0 |
0x00 |
#20finish-write-3 | 167 | 0 |
0 |
0 |
0 |
0x00000003 |
0x82 |
1 |
0 |
0x00 |
#21read-3 | 170 | 0 |
1 |
0 |
0 |
0x00000003 |
0x82 |
1 |
0 |
0x82 |
#22read-back-3 | 171 | 0 |
1 |
0 |
0 |
0x00000003 |
0x82 |
1 |
0 |
0x82 |
#23read-back-2 | 179 | 0 |
1 |
0 |
0 |
0x00000002 |
0x82 |
1 |
0 |
0x83 |
#24read-back-1 | 187 | 0 |
1 |
0 |
0 |
0x00000001 |
0x82 |
1 |
0 |
0x80 |
#25read-back-0 | 195 | 0 |
1 |
0 |
0 |
0x00000000 |
0x82 |
1 |
0 |
0x81 |
#26invalid-4-read | 205 | 0 |
1 |
0 |
0 |
0x00000004 |
0x82 |
1 |
1 |
0x00 |
#27invalid-4-disabled | 208 | 0 |
0 |
0 |
0 |
0x00000004 |
0x82 |
1 |
0 |
0x00 |
#28invalid-4-write-enable | 211 | 0 |
0 |
0 |
1 |
0x00000004 |
0x00 |
1 |
1 |
0x00 |
#29invalid-4-write-edge | 216 | 1 |
0 |
0 |
1 |
0x00000004 |
0x00 |
1 |
1 |
0x00 |
#30invalid-4-write-end | 221 | 0 |
0 |
0 |
0 |
0x00000004 |
0x00 |
1 |
0 |
0x00 |
#31invalid-2147483648-read | 228 | 0 |
1 |
0 |
0 |
0x80000000 |
0x00 |
1 |
1 |
0x00 |
#32invalid-2147483648-disabled | 231 | 0 |
0 |
0 |
0 |
0x80000000 |
0x00 |
1 |
0 |
0x00 |
#33invalid-2147483648-write-enable | 234 | 0 |
0 |
0 |
1 |
0x80000000 |
0x00 |
1 |
1 |
0x00 |
#34invalid-2147483648-write-edge | 239 | 1 |
0 |
0 |
1 |
0x80000000 |
0x00 |
1 |
1 |
0x00 |
#35invalid-2147483648-write-end | 244 | 0 |
0 |
0 |
0 |
0x80000000 |
0x00 |
1 |
0 |
0x00 |
#36invalid-4294967295-read | 252 | 0 |
1 |
0 |
0 |
0xFFFFFFFF |
0x00 |
1 |
1 |
0x00 |
#37invalid-4294967295-disabled | 255 | 0 |
0 |
0 |
0 |
0xFFFFFFFF |
0x00 |
1 |
0 |
0x00 |
#38invalid-4294967295-write-enable | 258 | 0 |
0 |
0 |
1 |
0xFFFFFFFF |
0x00 |
1 |
1 |
0x00 |
#39invalid-4294967295-write-edge | 263 | 1 |
0 |
0 |
1 |
0xFFFFFFFF |
0x00 |
1 |
1 |
0x00 |
#40invalid-4294967295-write-end | 268 | 0 |
0 |
0 |
0 |
0xFFFFFFFF |
0x00 |
1 |
0 |
0x00 |
#41after-invalid-writes-3 | 278 | 0 |
1 |
0 |
0 |
0x00000003 |
0x00 |
1 |
0 |
0x82 |
#42after-invalid-writes-2 | 286 | 0 |
1 |
0 |
0 |
0x00000002 |
0x00 |
1 |
0 |
0x83 |
#43after-invalid-writes-1 | 294 | 0 |
1 |
0 |
0 |
0x00000001 |
0x00 |
1 |
0 |
0x80 |
#44after-invalid-writes-0 | 302 | 0 |
1 |
0 |
0 |
0x00000000 |
0x00 |
1 |
0 |
0x81 |
#45disable-after-range-checks | 305 | 0 |
0 |
0 |
0 |
0x00000000 |
0x00 |
1 |
0 |
0x00 |
#46masked-setup | 308 | 0 |
0 |
0 |
0 |
0x00000000 |
0x78 |
1 |
0 |
0x00 |
#47masked-enable | 321 | 0 |
0 |
0 |
1 |
0x00000000 |
0x78 |
1 |
0 |
0x00 |
#48masked-edge | 331 | 1 |
0 |
0 |
1 |
0x00000000 |
0x78 |
1 |
0 |
0x00 |
#49masked-end | 342 | 0 |
0 |
0 |
0 |
0x00000000 |
0x78 |
1 |
0 |
0x00 |
#50masked-read | 345 | 0 |
1 |
0 |
0 |
0x00000000 |
0x78 |
1 |
0 |
0x78 |
#51reset-retention | 355 | 0 |
1 |
1 |
0 |
0x00000000 |
0x78 |
1 |
0 |
0x00 |
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 embedded device is 8 bits wide with four words. Its 52 checkpoints write 0x81, 0x80, 0x83, and 0x82, read all words back, attempt out-of-range reads/writes, and verify that rejected writes did not corrupt valid words. masked-read returns 0x78; at W = 8 the one-byte mask covers the whole word, so use §3.1.1.5 for partial-word masking. reset-retention confirms that FF memory clears to zero rather than retaining its contents.
Embedded simulation¶
Inspect the four root blocks, then open STORAGE to see the bank structure described in §3.1.1.6. This device uses four 8-bit words rather than the standalone bank example's three 16-bit words. Changing WORD_ADDR affects the decoder and read selection, while the stored words remain in place. The full table uses the default structural profile; choosing a behavioral implementation can change checkpoint times.
Open FFMemory in the simulator
Source and tests¶
- Structural interface and implementation:
FFMemory.hpp - Shared device pins and configuration:
MemoryArrayInterface.hpp - Address/control/read blocks:
MemoryArrayBlocks.hpp - Behavioral implementation:
FFMemoryBehavioral.hpp
| Test | Coverage |
|---|---|
FFMemoryTest |
The 52 device checkpoints shown above, run against structural and behavioral implementations |
FFMemoryContractTest |
Widths 8/16/32 and depths 1/2/3/4/7/8/16/32/33; masking, addressing, rejected writes, configuration limits, reset, behavioral history/loading, and representative equivalence |
FFMemoryFidelityTest |
Fully structural, behavioral-cell, behavioral-word, and behavioral-device selections; mixed exact-path overrides; large compact devices |
FFMemoryBindingsTest |
Factory/inspector interfaces and unchanged structural output-transition fixtures |
This completes the FF storage device. SRAM, DRAM, and flash require their own storage/device behavior; their future implementations need not share the FF cell or word interface.