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.
Standards & specifications
- Governing standard
- IEEE Std 1076 (VHDL)(opens IEEE in a new tab)
Defines the VHDL language — types, the simulation cycle, and the semantics a conforming analyser and simulator must implement. Synthesis restrictions and vendor coding rules are tool behaviour, not language rules.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the VHDL curriculum.
