# `cv_gemv_axi` register map

AXI4-Lite, 32-bit data, 12-bit byte address. Generated by `integration/scripts/gen_ipxact.py`.

## Access policy

- Byte address, 32-bit registers; address bits [1:0] are ignored (AXI4-Lite accesses are full width).
- AWPROT/ARPROT are accepted and ignored.
- AW and W are accepted independently, in either order or in the same cycle; one write executes once both are held and the previous B response has been accepted. One write and one read every two cycles at most; BVALID/RVALID stay asserted with stable payload until BREADY/RREADY.
- Unmapped address: read returns 0x00000000 with SLVERR; write has no effect, returns SLVERR and sets ERR.ADDR_ERR.
- Write to a read-only register: no effect, SLVERR, ERR.ADDR_ERR.
- Write-only locations read as 0x00000000 with OKAY.
- WSTRB: register fields live in byte lane 0 unless stated; a write without WSTRB[0] leaves byte-0 fields unchanged (OKAY).
- Reads have no side effects.

## Registers

| Offset | Name | Access | Reset | Fields | Description |
|---|---|---|---|---|---|
| 0x000 | ID | RO | `0x4356474D` | [31:0] ID | Identification, ASCII "CVGM". |
| 0x004 | VERSION | RO | `0x00010000` | [31:16] MAJOR<br>[15:8] MINOR<br>[7:0] PATCH | Wrapper version 1.0.0. |
| 0x008 | PARAM_ROWS | RO | `ROWS` | [31:0] ROWS | Parameter ROWS. |
| 0x00C | PARAM_COLS | RO | `COLS` | [31:0] COLS | Parameter COLS. |
| 0x010 | PARAM_CFG | RO | `(RESULT_STREAM << 17) \| P` | [15:0] P<br>[17] RESULT_STREAM | Parameters P and RESULT_STREAM. Bit 16 is an implementation configuration flag documented in the evaluation-licence register map. |
| 0x014 | PARAM_BEATS | RO | `(2 << 16) \| (((P * 12 + 31) / 32) << 8) \| P` | [7:0] WEIGHT_BEATS<br>[15:8] META_BEATS<br>[23:16] QUERY_BEATS | AXI4-Stream beats per memory word. |
| 0x018 | W_DEPTH | RO | `(ROWS / P) * (COLS / 8)` | [31:0] DEPTH | Weight memory depth in words. |
| 0x01C | M_DEPTH | RO | `(ROWS / P) * (COLS / 32)` | [31:0] DEPTH | Metadata memory depth in words. |
| 0x020 | Q_DEPTH | RO | `COLS / 8` | [31:0] DEPTH | Query memory depth in words. |
| 0x024 | R_BLOCKS | RO | `ROWS / P` | [31:0] BLOCKS | Result blocks of P rows. |
| 0x040 | CTRL | WO | `0x00000000` | [0] START<br>[1] RSTREAM | Command register (byte lane 0). Reads return 0. Writing both bits is rejected. |
| 0x044 | STATUS | RO | `0x00000001` | [0] CFG_READY<br>[1] BUSY<br>[2] RESULT_VALID<br>[3] ERROR<br>[4] START_PENDING<br>[5] LOAD_ACTIVE<br>[6] WINDOW_VALID<br>[7] RSTREAM_ACTIVE<br>[9:8] LOAD_DEST<br>[10] IRQ | Live status (reset value shown). |
| 0x048 | ERR | W1C | `0x00000000` | [0] PARTIAL_WORD<br>[1] OVERRUN<br>[2] BAD_DEST<br>[3] DEST_MISMATCH<br>[4] START_REJECT<br>[5] RESULT_REJECT<br>[6] ADDR_ERR | Sticky error flags; write 1 to clear (byte lane 0). A new event in the same cycle wins. |
| 0x04C | INT_STATUS | W1C | `0x00000000` | [0] DONE<br>[1] RSTREAM_DONE | Interrupt status; write 1 to clear. |
| 0x050 | INT_ENABLE | RW | `0x00000000` | [0] DONE<br>[1] RSTREAM_DONE | Interrupt enable; irq = \|(INT_STATUS & INT_ENABLE), registered (one cycle). |
| 0x054 | CYCLES | RO | `0x00000000` | [31:0] CYCLES | Device resident_cycles of the last command (core cycle_count + 1); 0 after reset and START. |
| 0x05C | LOAD_WORDS | RO | `0x00000000` | [31:0] COUNT | Memory words written through the load port since reset (wraps). |
| 0x060 | W_BASE | RW | `0x00000000` | [AW-1:0] BASE | Start word address of each weight packet (all byte lanes honoured). |
| 0x064 | M_BASE | RW | `0x00000000` | [MW-1:0] BASE | Start word address of each metadata packet. |
| 0x068 | Q_BASE | RW | `0x00000000` | [QAW-1:0] BASE | Start word address of each query packet. |
| 0x06C | LOAD_PTR | RO | `0x00000000` | [PTRW-1:0] PTR | Next word address of the active or last load packet. |
| 0x070 | RESULT_SEL | RW | `0x00000000` | [RBW-1:0] BLOCK | Writing selects result block b (rows b*P..b*P+P-1) and reads it into RESULT_DATA. Rejected (SLVERR, ERR.RESULT_REJECT, value unchanged) unless RESULT_VALID=1, b < R_BLOCKS, no START pending and no result stream active. |
| 0x100..0x100 + 4*(P-1) | RESULT_DATA | RO xP | `0x00000000` | [31:0] ROW | Rows of the selected block: element l is row RESULT_SEL*P + l (signed 32-bit, saturated). Read with SLVERR and value 0 while STATUS.WINDOW_VALID=0. |

## Fields

- `ID.ID` (RO, reset `0x4356474D`): Constant.
- `PARAM_CFG.P` (RO, reset `P`): Row engines (8 lanes each).
- `PARAM_CFG.RESULT_STREAM` (RO, reset `RESULT_STREAM`): 1: m_axis result stream present.
- `PARAM_BEATS.WEIGHT_BEATS` (RO, reset `P`): Beats per P*32-bit weight word.
- `PARAM_BEATS.META_BEATS` (RO, reset `(P * 12 + 31) / 32`): Beats per P*12-bit metadata word.
- `PARAM_BEATS.QUERY_BEATS` (RO, reset `0x00000002`): Beats per 64-bit query word.
- `CTRL.START` (WO, reset `0x00000000`): 1: start a command. Rejected (SLVERR, ERR.START_REJECT) while BUSY, START_PENDING, LOAD_ACTIVE or RSTREAM_ACTIVE.
- `CTRL.RSTREAM` (WO, reset `0x00000000`): 1: stream all ROWS results on m_axis. Rejected (SLVERR, ERR.RESULT_REJECT) unless RESULT_VALID=1 and no START is pending and no stream is active.
- `STATUS.CFG_READY` (RO, reset `0x00000001`): Device idle and out of reset: loads are accepted.
- `STATUS.BUSY` (RO, reset `0x00000000`): Command executing or START pending.
- `STATUS.RESULT_VALID` (RO, reset `0x00000000`): The last command completed; results are resident.
- `STATUS.ERROR` (RO, reset `0x00000000`): ERR != 0.
- `STATUS.START_PENDING` (RO, reset `0x00000000`): START accepted, command not yet started by the device.
- `STATUS.LOAD_ACTIVE` (RO, reset `0x00000000`): A load packet has started and TLAST has not been received.
- `STATUS.WINDOW_VALID` (RO, reset `0x00000000`): RESULT_DATA holds the block selected by RESULT_SEL.
- `STATUS.RSTREAM_ACTIVE` (RO, reset `0x00000000`): Result stream in progress.
- `STATUS.LOAD_DEST` (RO, reset `0x00000000`): TDEST of the active or last load packet.
- `STATUS.IRQ` (RO, reset `0x00000000`): State of the irq output.
- `ERR.PARTIAL_WORD` (W1C, reset `0x00000000`): TLAST before the last beat of a word; the partial word is discarded.
- `ERR.OVERRUN` (W1C, reset `0x00000000`): Word address at or beyond the destination depth; the word is discarded.
- `ERR.BAD_DEST` (W1C, reset `0x00000000`): TDEST=3; beats are consumed and discarded.
- `ERR.DEST_MISMATCH` (W1C, reset `0x00000000`): TDEST changed inside a packet; beats follow the latched destination.
- `ERR.START_REJECT` (W1C, reset `0x00000000`): START rejected (or both CTRL bits written).
- `ERR.RESULT_REJECT` (W1C, reset `0x00000000`): RESULT_SEL or RSTREAM rejected.
- `ERR.ADDR_ERR` (W1C, reset `0x00000000`): Write to an unmapped or read-only address.
- `INT_STATUS.DONE` (W1C, reset `0x00000000`): Command completed (results resident).
- `INT_STATUS.RSTREAM_DONE` (W1C, reset `0x00000000`): Last result beat accepted on m_axis.
- `W_BASE.BASE` (RW, reset `0x00000000`): Width ceil(log2(W_DEPTH)).
- `M_BASE.BASE` (RW, reset `0x00000000`): Width ceil(log2(M_DEPTH)), at least 1.
- `Q_BASE.BASE` (RW, reset `0x00000000`): Width ceil(log2(Q_DEPTH)).

Field widths: AW = ceil(log2(W_DEPTH)), MW = max(1, ceil(log2(M_DEPTH))), QAW = ceil(log2(Q_DEPTH)), PTRW = max(AW, MW, QAW) + 1 = AW + 1, RBW = max(1, ceil(log2(R_BLOCKS))). At ROWS=32, COLS=128, P=8: AW=6, MW=4, QAW=4, PTRW=7, RBW=2.

Any offset not listed is unmapped.
