Skip to content

ยง 3.1.5. NOR Flash

Digital NOR-style flash following the common device architecture. Programming clears selected bits; block erase restores ones. It is not SRAM with a longer write delay, and it is not a NAND page/block controller.

Component Description Structural Behavioral
NORFlashCell Nonvolatile digital bit, program 1โ†’0, erase to 1 Yes No
NORFlashRow<C> Shared row selection/erase and per-column programming Yes Yes
NORFlashStorageBank<W> Cell rows and selected-row column sensing Yes Yes
NORFlashCommandControl<W> Write-enable latch and timed command phases Yes No
NORFlash<W> Complete word-read/program, block-erase device Yes Yes

The write-enable latch, busy interval, one-way programming, and block erase are recognizable NOR-flash behaviors. The Winbond W25Q80BV data sheet is a real-device reference, not this component's pin/command specification: this simulator uses a parallel educational command port, not SPI opcodes or the data sheet's page-program protocol.

Configuration

Width W, capacity N, and words-per-row K follow 3.1.

Parameter Default Meaning / constraints
block_words (B) 2 Erase granularity; whole rows, divides N, Bโ‰คN
phase_ticks (P) 32 Phase spacing, 32โ€ฆ10,000
program_ticks 128 Delay before program pulse; Pโ€ฆ1,000,000
erase_ticks 256 Delay before erase pulse; at least program_ticks, at most 10,000,000

The default simulation starts with every bit erased to one. This is an explicit initial-image assumption; it is not a claim that an arbitrary physical flash chip always contains ones when powered up. No per-cell refresh is required. Persistence across simulator recreation/file storage, wear, disturb, power-loss behavior, and erase/program voltage generation are outside this model.

The references below follow the FF/SRAM pattern. Compile the C++ examples in page order: larger references compose the earlier ones. They cover binary controls, state, outputs, and operation deadlines without gate propagation or analog behavior; they are not registered simulator implementations. Construction parameters must satisfy the documented geometry/timing constraints. Every recorded test checkpoint is included with its number and absolute time.

The configuration type is NORFlashConfig. Catalog contracts are memory.nor-flash.cell, row, bank.W, command-control.W, and device.W under the memory.nor-flash. prefix. A standalone row takes columns; banks, controllers, and devices take the geometry/timing configuration. The cell has no parameters. Only public bank/device wrappers are C++ width templates; the command controller is catalog-created.

3.1.5.1. NORFlashCell

One digital nonvolatile bit with separate program and erase operations.

IO pins

Pin Direction Width Description
WL Input 1 Row selection for programming
PROGRAM Input 1 Program excitation, qualified by WL
ERASE Input 1 Erase independently of WL
D Input 1 Program value: 0 clears, 1 preserves
Q Output 1 Stored bit

Behavior

Initially erased (Q=1). Programming performs Q AND D; it cannot turn zero back to one. ERASE restores one independently of WL, unless programming is simultaneously enabled, which makes Q unknown. The cell has no command port, write-enable latch, block policy, or timer.

C++ example

Binary controls with an optional stored bit (empty means X). Startup wiring qualification is handled separately by the simulator.

#include <optional>
struct NORFlashCellReference {
    std::optional<bool> q = true;
    void update(bool wl, bool program, bool erase, std::optional<bool> data) {
        const bool enabled = wl && program;
        if (erase) q = enabled ? std::nullopt : std::optional(true);
        else if (enabled) {
            if (q == false || data == false) q = false;
            else if (q == true && data == true) q = true;
            else q.reset();
        }
    }
};

Unknown inputs and timing

Unknown program data cannot undo Q=0; it makes Q=1 unknown. An unknown erase loses certainty. Unknown WL/PROGRAM conservatively make a possible write unknown unless a known zero enable excludes it or Q is already zero. Z is treated as unknown, not retained charge. At startup, the erased value is held until the first fully binary WL/PROGRAM/ERASE tuple; later unknown controls are not ignored. Output delay is one primitive tick.

Implementation

Structural implementation

Terminal digital nonvolatile-charge primitive. Program and erase transitions represent storage rules, not floating-gate voltage, tunneling, wear, or disturb. A second behavioral-fidelity copy is not registered.

The visualizer shows the recorded stored bit Q and WL/PROGRAM/ERASE indicators. These are cell signals, not the device controller's busy state, and update when scrubbing backward or forward.

Examples

All 7 recorded rows of NORFlashCellTest, 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 DInput ยท 1 bit ERASEInput ยท 1 bit PROGRAMInput ยท 1 bit WLInput ยท 1 bit QExpected output ยท 1 bit
#0erased1 1 0 0 0 1
#1program-zero3 0 0 1 1 0
#2one-cannot-undo-program4 1 0 1 1 0
#3release5 1 0 0 0 0
#4erase7 1 1 0 0 1
#5hold-erased8 1 0 0 0 1
#6unknown-program-data10 X 0 1 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.

Checks erased one, programming zero, the inability to program that zero back to one, release, erase, and programming with unknown data.

Embedded simulation

The standalone NORFlashCellTest opens this component as MEMORY_ROOT. This component has one registered structural implementation.

Open NORFlashCell in the simulator

Source and tests

Test Coverage
NORFlashCellTest The complete standalone sequence shown above
MemoryDeviceContractTest Integration in the new structural devices and comparison with their compact implementations

3.1.5.2. NORFlashRow<C>

C flash cells sharing row selection and row erase.

IO pins

Pin Direction Width Description
WL Input 1 Shared program selection
ERASE Input 1 Erase all cells in this row
PROGRAM_c, D_c Input 1 each Column program enable/value
Q_c Output 1 each Stored bits, 0 โ‰ค c < C

Behavior

columns=C accepts 1โ€“512 (default 4). Each cell follows the NORFlashCell transition rule. Programming can affect columns independently. ERASE reaches all cells; device-level control selects all rows of an erase block. This row alone does not enforce block granularity.

C++ example

Composition of the cell reference above. Each column retains its own state.

#include <array>
#include <cstddef>
#include <optional>
template<class Cell, std::size_t C>
void flash_row_update(std::array<Cell, C>& cells, bool wl, bool erase,
                      const std::array<bool, C>& program,
                      const std::array<std::optional<bool>, C>& data) {
    for (std::size_t c = 0; c < C; ++c)
        cells[c].update(wl, program[c], erase, data[c]);
}

Unknown inputs and timing

Initial state, startup qualification, conflicts, and X/Z handling are per-cell. Unknown shared erase can affect the whole row. Outputs settle after each cell update; there is no row-level program-latency timer.

Implementation

Structural implementation

CELL_0 through CELL_(Cโˆ’1) share WL and ERASE. Program/data are per-column. Cells are arranged horizontally in numeric column order.

Behavioral implementation

Stores C four-state values and per-cell startup-qualification flags. It applies the same charge transition rule directly; it is not freely writable RAM.

Examples

All 4 recorded rows of NORFlashRowTest, 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 D_0Input ยท 1 bit D_1Input ยท 1 bit ERASEInput ยท 1 bit PROGRAM_0Input ยท 1 bit PROGRAM_1Input ยท 1 bit WLInput ยท 1 bit Q_0Expected output ยท 1 bit Q_1Expected output ยท 1 bit
#0erased1 0 0 0 0 0 0 1 1
#1program-one-column3 0 0 0 1 0 1 0 1
#2release4 0 0 0 0 0 0 0 not checked
#3erase-row6 0 0 1 0 0 0 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 two-column row starts erased, programs only column zero while preserving column one, releases programming, then erases both.

Embedded simulation

The standalone NORFlashRowTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.

Open NORFlashRow<C> in the simulator

Source and tests

Test Coverage
NORFlashRowTest The complete standalone sequence shown above
MemoryDeviceContractTest Structural/behavioral agreement at settled checkpoints, including mixed hierarchy selection

3.1.5.3. NORFlashStorageBank<W>

Flash rows with shared read sensing and independent row erase lines.

IO pins

Pin Direction Width Description
WL_r Input 1 each Read/program row selection, 0 โ‰ค r < N/K
ERASE_r Input 1 each Erase every cell in row r
DRIVE_c, DATA_c Input 1 each Column program controls/data
COL_c Output 1 each Selected stored bits, 0 โ‰ค c < Wร—K

Behavior

Exactly one binary WL selects a row for reading. Each cell programs only when its WL and column DRIVE are high. ERASE_r is independent of WL_r. Multiple selected rows invalidate sensed outputs but can still expose those rows to programming; the caller must supply legal controls. Block policy belongs to the device, not this bank.

C++ example

The whole bank composes the cell reference and the static read-column rule. It updates every program/erase input and publishes every column, including invalid row selection.

#include <vector>
#include <cstddef>
#include <optional>
struct FlashBankReference {
    std::vector<std::vector<NORFlashCellReference>> rows;
    std::vector<std::optional<bool>> columns;
    FlashBankReference(std::size_t r, std::size_t c)
        : rows(r, std::vector<NORFlashCellReference>(c)), columns(c) {}
    void update(const std::vector<bool>& wl, const std::vector<bool>& erase,
                const std::vector<bool>& drive,
                const std::vector<std::optional<bool>>& data) {
        for (std::size_t c = 0; c < columns.size(); ++c) {
            unsigned count = 0;
            columns[c].reset();
            for (std::size_t r = 0; r < rows.size(); ++r) {
                rows[r][c].update(wl.at(r), drive.at(c), erase.at(r), data.at(c));
                if (wl[r]) { ++count; columns[c] = rows[r][c].q; }
            }
            if (count != 1) columns[c].reset();
        }
    }
};

Unknown inputs and timing

No selected row, conflicting selections, or unknown WL yields X on COL. Cell writes/erase retain their own conservative X/Z rules. Both bank fidelities retain scalar row/column pins and the 4,096-cell limit; large-capacity use belongs at device level.

Implementation

Structural implementation

ROW_r contains Wร—K flash cells. COLUMN_c is a StaticReadColumn shared across rows. Columns align under the same numbered cell in every row. Device control asserts ERASE_r for all rows in one block.

Behavioral implementation

Uses a bounded bit vector and startup flags, applying cell transitions before selecting the read columns. Read selection and storage mutation remain separate, matching the expanded bank.

Examples

All 7 recorded rows of NORFlashStorageBankTest, 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 DATA_0Input ยท 1 bit DATA_1Input ยท 1 bit DATA_10Input ยท 1 bit DATA_11Input ยท 1 bit DATA_12Input ยท 1 bit DATA_13Input ยท 1 bit DATA_14Input ยท 1 bit DATA_15Input ยท 1 bit DATA_2Input ยท 1 bit DATA_3Input ยท 1 bit DATA_4Input ยท 1 bit DATA_5Input ยท 1 bit DATA_6Input ยท 1 bit DATA_7Input ยท 1 bit DATA_8Input ยท 1 bit DATA_9Input ยท 1 bit DRIVE_0Input ยท 1 bit DRIVE_1Input ยท 1 bit DRIVE_10Input ยท 1 bit DRIVE_11Input ยท 1 bit DRIVE_12Input ยท 1 bit DRIVE_13Input ยท 1 bit DRIVE_14Input ยท 1 bit DRIVE_15Input ยท 1 bit DRIVE_2Input ยท 1 bit DRIVE_3Input ยท 1 bit DRIVE_4Input ยท 1 bit DRIVE_5Input ยท 1 bit DRIVE_6Input ยท 1 bit DRIVE_7Input ยท 1 bit DRIVE_8Input ยท 1 bit DRIVE_9Input ยท 1 bit ERASE_0Input ยท 1 bit ERASE_1Input ยท 1 bit 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
#0deselected1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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
#1read-erased-row3 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 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
#2program-column-zero6 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 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
#3release-driver7 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 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
#4other-row-unmodified9 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 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
#5erase-first-row11 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 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
#6read-first-row-again12 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 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

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.

Reads an erased row, programs column zero, checks another row remains erased, erases the first row, and reads it again.

Embedded simulation

The standalone NORFlashStorageBankTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.

Open NORFlashStorageBank<W> in the simulator

Source and tests

Test Coverage
NORFlashStorageBankTest The complete standalone sequence shown above
MemoryDeviceContractTest Structural/behavioral agreement at settled checkpoints, including mixed hierarchy selection

3.1.5.4. NORFlashCommandControl<W>

Write-enable latch, request capture, and program/erase sequencing.

IO pins

Pin Direction Width Description
CLK Input 1 Strict 0โ†’1 command edge
CMD Input 3 Device command code
WORD_ADDR Input 32 Word address or address within erase block
WRITE_DATA Input W Program payload
WRITE_MASK Input W/8 Program byte enables
BUSY, ERROR, READ_VALID, WRITE_ENABLED Output 1 each Device status
ROW_ADDR, COLUMN_ADDR Output 32 each Latched address decomposed into row/slot
DATA Output W Latched program data
MASK Output W/8 Latched byte enables
ROW_ENABLE, PROGRAM_ENABLE, OUTPUT_ENABLE Output 1 each Selection, program pulse, read publication
ERASE_r Output 1 each Pulse for every row in the selected block

Behavior

Implements the command table in NORFlash below without storing array data. WREN sets the write-enable latch (WEL); WRDI clears it. An accepted PROGRAM or ERASE consumes WEL immediately, including a zero-mask program. A rejected request preserves WEL. Latched address/data/mask remain stable while busy.

C++ example

All binary commands and control outputs are represented. Geometry and positive timing parameters are prevalidated. Call on input changes and every due; valid drives both READ_VALID and OUTPUT_ENABLE, wel drives WRITE_ENABLED, and select drives ROW_ENABLE. There is no reset pin.

#include <cstdint>
#include <vector>
#include <optional>
template<std::size_t W> struct FlashControlReference {
    struct Inputs {
        bool clock = false;
        unsigned cmd = 0;
        std::uint32_t address = 0, data = 0;
        unsigned mask = 0;
    };
    std::size_t depth, slots, block, ticks, program_ticks, erase_ticks, due = 0;
    unsigned command = 0, stage = 0;
    std::uint32_t address = 0;
    bool busy = false, error = false, wel = false, valid = false;
    bool program = false, erase = false, select = false;
    std::optional<bool> previous_clock; // First observed high is not a 0->1 edge.
    unsigned mask = 0;
    std::vector<std::optional<bool>> data = std::vector<std::optional<bool>>(W);
    FlashControlReference(std::size_t n, std::size_t k, std::size_t block_words,
                          std::size_t phase, std::size_t prog, std::size_t er)
        : depth(n), slots(k), block(block_words), ticks(phase), program_ticks(prog), erase_ticks(er) {}
    std::size_t row() const { return address / slots; }
    std::size_t col() const { return address % slots; }
    bool erase_row(std::size_t r) const {
        return erase && (r * slots) / block == address / block;
    }
    void update(std::size_t now, const Inputs& in) {
        if (due && now >= due) {
            due = 0; ++stage;
            if (command == 1) { valid = true; busy = false; }
            else if (stage == 1) {
                program = command == 2; erase = command == 3; due = now + ticks;
            } else if (stage == 2) {
                program = erase = select = false; due = now + ticks;
            } else busy = false;
        }
        const bool edge = previous_clock == false && in.clock;
        previous_clock = in.clock;
        if (!edge || in.cmd == 0) return; // NOP holds WEL, error and read-valid.
        if (busy) { error = true; return; } // Existing command still completes.
        if (in.cmd > 5 || (in.cmd <= 3 && in.address >= depth) ||
            ((in.cmd == 2 || in.cmd == 3) && !wel)) {
            error = true; valid = false; return;
        }
        error = valid = select = false;
        if (in.cmd == 4 || in.cmd == 5) { wel = in.cmd == 4; return; }
        command = in.cmd; stage = 0; address = in.address;
        busy = true; select = command != 3;
        if (command == 1) due = now + ticks;
        else {
            wel = false;
            for (unsigned b = 0; b < W; ++b) data[b] = bool((in.data >> b) & 1u);
            mask = in.mask;
            due = now + (command == 2 ? program_ticks : erase_ticks);
        }
    }
};

Unknown inputs and timing

Only 0โ†’1 CLK is an edge. Unknown CMD is rejected; address must be binary for READ/PROGRAM/ERASE and mask must be binary for PROGRAM. Unknown data is permitted. NOP/WREN/WRDI ignore address/data/mask; ERASE ignores data/mask. Idle rejection invalidates old read data. Busy rejection sets ERROR without replacing the scheduled operation. Completion is processed before an edge at the same internal deadline.

Implementation

Structural implementation

Terminal digital FSM with write-enable state and timed pulses, not a gate-expanded sequencer. ERASE_r covers the rows whose words belong to WORD_ADDR / block_words. Because it exposes one erase pin per row, this standalone controller retains the expanded geometry limit. Compact complete devices use internal state without those pins.

Examples

All 41 recorded rows of NORFlashCommandControlTest, 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 CLKInput ยท 1 bit CMDInput ยท 3 bit WORD_ADDRInput ยท 32 bit WRITE_DATAInput ยท 8 bit WRITE_MASKInput ยท 1 bit BUSYExpected output ยท 1 bit COLUMN_ADDRExpected output ยท 32 bit DATAExpected output ยท 8 bit ERASE_0Expected output ยท 1 bit ERASE_1Expected output ยท 1 bit ERRORExpected output ยท 1 bit MASKExpected output ยท 1 bit OUTPUT_ENABLEExpected output ยท 1 bit PROGRAM_ENABLEExpected output ยท 1 bit READ_VALIDExpected output ยท 1 bit ROW_ADDRExpected output ยท 32 bit ROW_ENABLEExpected output ยท 1 bit WRITE_ENABLEDExpected output ยท 1 bit
#0ready-erased1 0 0x0 0x00000000 0x81 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 0
#1read-erased-setup2 0 0x1 0x00000000 0x81 1 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
#2read-erased36 1 0x1 0x00000000 0x81 1 0 not checked not checked not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked
#3program-without-enable-setup37 0 0x2 0x00000000 0x81 1 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
#4program-without-enable39 1 0x2 0x00000000 0x81 1 0 not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked not checked not checked
#5write-enable-setup40 0 0x4 0x00000000 0x81 1 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
#6write-enable42 1 0x4 0x00000000 0x81 1 0 not checked not checked not checked not checked 0 not checked not checked not checked not checked not checked not checked 1
#7program-word-setup43 0 0x2 0x00000000 0x81 1 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
#8program-word237 1 0x2 0x00000000 0x81 1 0 not checked not checked not checked not checked 0 not checked not checked not checked not checked not checked not checked 0
#9read-programmed-setup238 0 0x1 0x00000000 0x81 1 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
#10read-programmed272 1 0x1 0x00000000 0x81 1 0 not checked not checked not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked
#11enable-again-setup273 0 0x4 0x00000000 0x81 1 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
#12enable-again275 1 0x4 0x00000000 0x81 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#13cannot-program-zero-to-one-setup276 0 0x2 0x00000000 0xFF 1 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
#14cannot-program-zero-to-one470 1 0x2 0x00000000 0xFF 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#15read-unchanged-setup471 0 0x1 0x00000000 0xFF 1 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
#16read-unchanged505 1 0x1 0x00000000 0xFF 1 0 not checked not checked not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked
#17enable-other-block-setup506 0 0x4 0x00000000 0xFF 1 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
#18enable-other-block508 1 0x4 0x00000000 0xFF 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#19program-other-block-setup509 0 0x2 0x00000002 0x78 1 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
#20program-other-block703 1 0x2 0x00000002 0x78 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#21enable-erase-setup704 0 0x4 0x00000000 0x78 1 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
#22enable-erase706 1 0x4 0x00000000 0x78 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#23erase-block-zero-setup707 0 0x3 0x00000000 0x78 1 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
#24erase-block-zero1029 1 0x3 0x00000000 0x78 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 0
#25read-erased-again-setup1030 0 0x1 0x00000000 0x78 1 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
#26read-erased-again1064 1 0x1 0x00000000 0x78 1 0 not checked not checked not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked
#27other-block-survives-setup1065 0 0x1 0x00000002 0x78 1 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
#28other-block-survives1099 1 0x1 0x00000002 0x78 1 0 not checked not checked not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked
#29unknown-command-setup1100 0 0bXXX 0x00000002 0x78 1 not checked not checked not checked not checked not checked not checked not checked not checked not checked 1 not checked not checked not checked
#30unknown-command-rejected1102 1 0bXXX 0x00000002 0x78 1 0 not checked not checked not checked not checked 1 not checked 0 not checked 0 not checked not checked not checked
#31nop-preserves-error-setup1103 0 0x0 0x00000000 0x78 1 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
#32nop-preserves-error1104 1 0x0 0x00000000 0x78 1 0 not checked not checked not checked not checked 1 not checked not checked not checked 0 not checked not checked not checked
#33invalid-address-setup1105 0 0x1 0x00000004 0x78 1 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
#34invalid-address1106 1 0x1 0x00000004 0x78 1 0 not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked not checked not checked
#35reserved-command-setup1107 0 0x7 0x00000000 0x78 1 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
#36reserved-command1108 1 0x7 0x00000000 0x78 1 0 not checked not checked not checked not checked 1 not checked not checked not checked not checked not checked not checked not checked
#37enable-then-disable-setup1109 0 0x4 0x00000000 0x78 1 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
#38enable-then-disable1111 1 0x4 0x00000000 0x78 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked
#39write-disable-setup1112 0 0x5 0x00000000 0x78 1 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
#40write-disable1114 1 0x5 0x00000000 0x78 1 0 not checked not checked not checked not checked not checked not checked not checked not checked not checked not checked 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 control example follows the full device command stream, checking write-enable, errors, read qualification, and completion. It includes unknown-command rejection and NOP error preservation.

Embedded simulation

The standalone NORFlashCommandControlTest opens this component as MEMORY_ROOT. This component has one registered structural implementation.

Open NORFlashCommandControl<W> in the simulator

Source and tests

Test Coverage
NORFlashCommandControlTest The complete standalone sequence shown above
MemoryDeviceTimingTest Intermediate BUSY, busy-command rejection, and latched program payload in both complete-device fidelities

3.1.5.5. NORFlash<W>

Complete word-read/program, block-erase NOR-style device.

IO pins

Pin Direction Width Description
CLK Input 1 Strict 0โ†’1 command edge
CMD Input 3 Command code below
WORD_ADDR Input 32 Word address or word inside an erase block
WRITE_DATA Input W Program payload
WRITE_MASK Input W/8 Enabled program bytes
BUSY Output 1 Read/program/erase in progress
ERROR Output 1 Rejected request; next accepted non-NOP clears it
WRITE_ENABLED Output 1 Current write-enable latch
READ_VALID Output 1 Completed read available
READ_DATA Output W Valid word, otherwise Z

Behavior

Reads are word-addressed. Programming only clears bits within enabled bytes. Erase resets every word in the containing B-word block; an aligned block-base address is not required.

Commands and timing

CMD Operation Preconditions / effect Sequencer completion
0 NOP Ignore other inputs; preserve status None
1 READ Valid word address P ticks
2 PROGRAM Valid address, WEL=1, binary mask; consume WEL program_ticks + 2P
3 ERASE Valid address, WEL=1; consume WEL; erase containing B-word block erase_ticks + 2P
4 WREN Set WEL; address/data/mask ignored Accepted edge
5 WRDI Clear WEL; address/data/mask ignored Accepted edge
6โ€“7 Reserved Reject ERROR

Program/erase wait their configured delay, assert the corresponding pulse for P ticks, then release it and wait P more ticks before clearing BUSY. Read waits P. Output wire propagation and structural gate settling add to sequencer deadlines. These are model ticks, not chip performance claims.

Requests are latched at acceptance. Non-NOP commands while BUSY are rejected; they neither cancel nor replace the active operation. WREN is required again after every accepted PROGRAM or ERASE, including a zero-mask program. A rejected command does not consume WEL. NOP preserves status; an accepted non-NOP clears the previous ERROR and read-valid state. A read remains valid until superseded or invalidated. Initial unknown clock followed by high does not count as a rising edge.

C++ example

The native device composes the bank and command control above. W is 8/16/32; capacity, row width, erase-block size, and timing are construction parameters. This includes reads, WREN/WRDI, errors, zero masks, delayed program/erase, and stable state while busyโ€”not merely the final array mutation.

#include <cstdint>
#include <vector>
template<std::size_t W> struct FlashReference {
    static_assert(W == 8 || W == 16 || W == 32);
    FlashControlReference<W> control;
    FlashBankReference bank;
    bool high_z = true;
    std::vector<std::optional<bool>> read_data = std::vector<std::optional<bool>>(W);
    FlashReference(std::size_t words, std::size_t slots, std::size_t block,
                    std::size_t ticks, std::size_t program, std::size_t erase)
        : control(words, slots, block, ticks, program, erase), bank(words / slots, W * slots) {}
    void update(std::size_t now, const typename FlashControlReference<W>::Inputs& in) {
        control.update(now, in);
        std::vector<bool> wl(bank.rows.size(), false), erase(bank.rows.size());
        std::vector<bool> drive(bank.columns.size());
        std::vector<std::optional<bool>> data(bank.columns.size());
        if (control.select) wl[control.row()] = true;
        for (std::size_t r = 0; r < erase.size(); ++r) erase[r] = control.erase_row(r);
        for (std::size_t c = 0; c < drive.size(); ++c) {
            data[c] = control.data[c % W];
            drive[c] = control.program && c / W == control.col() &&
                       (control.mask & (1u << ((c % W) / 8)));
        }
        bank.update(wl, erase, drive, data);
        high_z = !control.valid;
        for (std::size_t b = 0; b < W; ++b)
            read_data[b] = high_z ? std::nullopt : bank.columns[control.col() * W + b];
    }
    // BUSY / ERROR / READ_VALID / WRITE_ENABLED = control.busy / error / valid / wel.
    // Next scheduled phase: control.due (0 means none).
};

Unknown inputs and timing

Command validation follows NORFlashCommandControl. Enabled program data bits may become X; an already-zero bit remains zero. Masked-off bytes ignore data, including X/Z. NOP preserves status; unknown idle commands invalidate previous read-valid like reserved codes. Wait for BUSY and propagation to settle. Timing parameters are abstract simulator units, not manufacturer performance figures.

Implementation

Structural implementation

COMMAND_CONTROL drives ROW_DECODE, write pulses, and per-row erase. STORAGE exposes the cell matrix and shared read columns. COLUMN_SELECT reads one word; WRITE_DRIVERS qualifies program bits; OUTPUT releases READ_DATA when invalid. All rows of the selected erase block receive the erase pulse.

Behavioral implementation

Uses initially erased packed MemoryStorage and the same command sequencer, with a separately implemented storage data path. Program applies four-state AND within enabled bytes; erase writes ones one word at a time to bound temporary allocation. Read-only inspector history can be disabled for scale; debug loading cannot bypass WREN/PROGRAM/ERASE.

Examples

All 41 recorded rows of NORFlashTest, 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 CLKInput ยท 1 bit CMDInput ยท 3 bit WORD_ADDRInput ยท 32 bit WRITE_DATAInput ยท 8 bit WRITE_MASKInput ยท 1 bit BUSYExpected output ยท 1 bit ERRORExpected output ยท 1 bit READ_DATAExpected output ยท 8 bit READ_VALIDExpected output ยท 1 bit WRITE_ENABLEDExpected output ยท 1 bit
#0ready-erased11 0 0x0 0x00000000 0x81 1 0 not checked not checked not checked 0
#1read-erased-setup12 0 0x1 0x00000000 0x81 1 not checked not checked not checked not checked not checked
#2read-erased47 1 0x1 0x00000000 0x81 1 0 not checked 0xFF 1 not checked
#3program-without-enable-setup48 0 0x2 0x00000000 0x81 1 not checked not checked not checked not checked not checked
#4program-without-enable51 1 0x2 0x00000000 0x81 1 0 1 not checked not checked not checked
#5write-enable-setup52 0 0x4 0x00000000 0x81 1 not checked not checked not checked not checked not checked
#6write-enable59 1 0x4 0x00000000 0x81 1 0 0 not checked not checked 1
#7program-word-setup60 0 0x2 0x00000000 0x81 1 not checked not checked not checked not checked not checked
#8program-word254 1 0x2 0x00000000 0x81 1 0 0 not checked not checked 0
#9read-programmed-setup255 0 0x1 0x00000000 0x81 1 not checked not checked not checked not checked not checked
#10read-programmed290 1 0x1 0x00000000 0x81 1 0 not checked 0x81 1 not checked
#11enable-again-setup291 0 0x4 0x00000000 0x81 1 not checked not checked not checked not checked not checked
#12enable-again298 1 0x4 0x00000000 0x81 1 0 not checked not checked not checked not checked
#13cannot-program-zero-to-one-setup299 0 0x2 0x00000000 0xFF 1 not checked not checked not checked not checked not checked
#14cannot-program-zero-to-one493 1 0x2 0x00000000 0xFF 1 0 not checked not checked not checked not checked
#15read-unchanged-setup494 0 0x1 0x00000000 0xFF 1 not checked not checked not checked not checked not checked
#16read-unchanged529 1 0x1 0x00000000 0xFF 1 0 not checked 0x81 1 not checked
#17enable-other-block-setup530 0 0x4 0x00000000 0xFF 1 not checked not checked not checked not checked not checked
#18enable-other-block537 1 0x4 0x00000000 0xFF 1 0 not checked not checked not checked not checked
#19program-other-block-setup538 0 0x2 0x00000002 0x78 1 not checked not checked not checked not checked not checked
#20program-other-block732 1 0x2 0x00000002 0x78 1 0 not checked not checked not checked not checked
#21enable-erase-setup733 0 0x4 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#22enable-erase735 1 0x4 0x00000000 0x78 1 0 not checked not checked not checked not checked
#23erase-block-zero-setup736 0 0x3 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#24erase-block-zero1058 1 0x3 0x00000000 0x78 1 0 not checked not checked not checked 0
#25read-erased-again-setup1059 0 0x1 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#26read-erased-again1094 1 0x1 0x00000000 0x78 1 0 not checked 0xFF 1 not checked
#27other-block-survives-setup1095 0 0x1 0x00000002 0x78 1 not checked not checked not checked not checked not checked
#28other-block-survives1130 1 0x1 0x00000002 0x78 1 0 not checked 0x78 1 not checked
#29unknown-command-setup1131 0 0bXXX 0x00000002 0x78 1 not checked not checked not checked 1 not checked
#30unknown-command-rejected1134 1 0bXXX 0x00000002 0x78 1 0 1 0bZZZZZZZZ 0 not checked
#31nop-preserves-error-setup1135 0 0x0 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#32nop-preserves-error1136 1 0x0 0x00000000 0x78 1 0 1 not checked 0 not checked
#33invalid-address-setup1137 0 0x1 0x00000004 0x78 1 not checked not checked not checked not checked not checked
#34invalid-address1138 1 0x1 0x00000004 0x78 1 0 1 not checked not checked not checked
#35reserved-command-setup1139 0 0x7 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#36reserved-command1140 1 0x7 0x00000000 0x78 1 0 1 not checked not checked not checked
#37enable-then-disable-setup1141 0 0x4 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#38enable-then-disable1148 1 0x4 0x00000000 0x78 1 0 not checked not checked not checked not checked
#39write-disable-setup1149 0 0x5 0x00000000 0x78 1 not checked not checked not checked not checked not checked
#40write-disable1151 1 0x5 0x00000000 0x78 1 0 not checked not checked 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.

Rejects programming without WREN, programs 0x81, confirms programming 0xFF cannot restore cleared bits, programs 0x78 in another block, then erases the first block while preserving the second. Also checks invalid/unknown/reserved commands, NOP status preservation, and WRDI.

Embedded simulation

The standalone NORFlashTest opens this component as MEMORY_ROOT. Use the explorer to compare structural and behavioral implementations.

Open NORFlash<W> in the simulator

Source and tests

Test Coverage
NORFlashTest The complete standalone sequence shown above
MemoryDeviceContractTest Width/geometry and mixed-fidelity checks, seeded byte-mask/program oracle, readonly history, allocation limits
MemoryDeviceTimingTest Early BUSY, in-flight command rejection, latched data, and finite event queues
MemoryDeviceDocumentationTest Compile the exact references; test W=8/16/32, masks, WREN/WRDI, delayed program/erase, block isolation, conflicts and completion edges; replay native command/device binary-input prefixes