VHDL · Chapter 13.1 · Advanced Data Structures
Arrays of Records
An array of records is a table of structured entries, and it is one of the most useful composite structures in VHDL. A record bundles related fields such as data, valid, and tag into one entry, and an array makes a numbered collection of them. Together they model the things real designs are full of, including a register file with N entries that each hold a value plus status bits, a scoreboard or descriptor table, and per-channel state in a multi-channel block. You access a field of one entry by indexing the array and then naming the field, and you iterate the whole table with a for loop or a for-generate. This lesson covers declaring arrays of records, indexing and updating entries, iterating over them, and what they become in hardware, from flip-flops for a register file to inferred RAM when wide and deep.
Foundation14 min readVHDLRecordsArraysRegister FileData StructuresRTL
1. Engineering intuition — a table whose rows have structure
Plenty of hardware is a table where every row carries more than a single value. A register file row is a data
word plus a valid bit plus maybe a tag. A scoreboard entry is a result plus a status. A channel's state is
several fields together. You could keep parallel arrays — one for data, one for valid, one for tag — but they
drift and obscure intent. An array of records says it directly: one array, each element a structured entry.
Now "entry i" is a single thing you read, write, and reason about as a unit, with named fields — exactly how you
think about the table.
2. Formal explanation — declaring and indexing an array of records
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- one entry = a record of fields
type entry_t is record
data : std_logic_vector(31 downto 0);
valid : std_logic;
tag : std_logic_vector(3 downto 0);
end record;
-- a TABLE = an array of those entries
type file_t is array (0 to 15) of entry_t; -- 16 structured entries
signal regfile : file_t;
-- ACCESS: index the array, then select a field.
-- regfile(i).data -- read field 'data' of entry i
-- regfile(i).valid <= '1'; -- write one field of one entry
-- regfile(i) <= an_entry; -- write a whole entry at onceAn array of records composes the two aggregate types: declare a record for the entry, then an array of
that record. Access is arr(index).field — index to the entry, then select the field — and you may read/write a
single field, or assign a whole entry as one record value.
3. Production usage — a small register file with status
process (clk) begin
if rising_edge(clk) then
if rst = '1' then
for i in regfile'range loop
regfile(i).valid <= '0'; -- iterate entries to clear status
end loop;
else
if we = '1' then
regfile(to_integer(unsigned(waddr))).data <= wdata; -- write fields of one entry
regfile(to_integer(unsigned(waddr))).valid <= '1';
regfile(to_integer(unsigned(waddr))).tag <= wtag;
end if;
end if;
end if;
end process;
rdata <= regfile(to_integer(unsigned(raddr))).data; -- read a field of the selected entry
rvalid <= regfile(to_integer(unsigned(raddr))).valid;What hardware does this become? A register file: 16 entries, each holding a 32-bit value, a valid bit, and
a 4-bit tag in flip-flops — addressed for read and write. Iterating with the for loop (e.g. to clear all valids
on reset) replicates that clear across entries. If the table is wide and deep, a synthesizer may map it to
distributed or block RAM instead of discrete flops (memory-modeling module covers the inference rules); the
structure — a table of structured rows — is the same either way.
4. Structural interpretation — a table of structured entries
5. Simulation interpretation — writing and reading one entry's fields
Write entry 2's fields, then read them back
8 cycles6. Debugging example — parallel arrays that drifted (or the wrong field)
Expected: each entry's fields stay consistent. Observed: an entry's data updated but its valid did
not (or vice versa), or a field was written on the wrong entry. Root cause: the design used parallel
arrays (data_arr, valid_arr, tag_arr) updated in separate places that drifted out of sync, or an index/
field slip wrote the wrong location — exactly the bookkeeping an array of records removes. Fix: model the
table as one array of records so an entry's fields live together and are written as a unit (regfile(i) <= entry or grouped field writes under one index), keeping them consistent by construction. Engineering
takeaway: when several per-entry values must stay together, use an array of records, not parallel arrays — one
indexed entry keeps its fields synchronized and makes the access read like the intent.
-- BUG: parallel arrays drift — data and valid updated separately.
-- data_arr(i) <= wdata; -- somewhere
-- valid_arr(j) <= '1'; -- elsewhere, different index → inconsistent entry
-- FIX: one array of records; fields of an entry stay together under one index.
regfile(i).data <= wdata; regfile(i).valid <= '1'; -- same entry, consistent7. Common mistakes & what to watch for
- Parallel arrays instead of an array of records. They drift; bundle per-entry fields into a record so they stay consistent under one index.
- Index/field slips.
arr(i).field— make sure the index selects the intended entry and the field name is right; a wrong index corrupts another entry. - Forgetting to initialize/clear status fields. Iterate entries (
for i in arr'range) to reset valid/status on reset. - Assuming flip-flops for large tables. Wide, deep arrays of records may infer RAM with its read-latency rules; check the inference for big tables.
- Whole-entry vs field writes. Decide whether to assign a full record or individual fields; mixing them carelessly can leave fields stale.
8. Engineering insight & continuity
An array of records models a table of structured entries — the natural shape of register files, scoreboards, descriptor tables, and per-channel state — keeping each entry's fields together under one index and synthesizing to a register file or inferred RAM. It replaces fragile parallel arrays with one coherent structure. Opening Module 13, this is the first of the composite data structures; the next lesson goes further into shape — Multidimensional and Nested Arrays — for tables indexed by more than one dimension, like memories of words or matrices.