Skip to content

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

array_of_records.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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 once

An 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

regfile_with_status.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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

array of records as a register file: indexed entries each with data, valid, and tag fieldswrite entryread fieldwaddr → entry iindex selects one entryentry 0{data, valid, tag}entry i{data, valid, tag} ← writeentry N-1{data, valid, tag}read fieldregfile(raddr).data12
An array of records is a table of structured entries. Each entry bundles fields — here data, valid, and tag — and the array makes a numbered collection of them, indexed as regfile(i) with field access regfile(i).field. Writing addresses one entry and sets its fields; reading selects an entry and returns a field; iterating with a for loop touches every entry (for example, clearing all valid bits on reset). It synthesizes to a register file of flip-flops, or inferred RAM when wide and deep. This is a structured-storage layout; the waveform below shows writing and reading one entry's fields.

5. Simulation interpretation — writing and reading one entry's fields

Write entry 2's fields, then read them back

8 cycles
Write entry 2's fields, then read them backwe=1, waddr=2: write entry 2 → {data=0xA5, valid=1, tag=...}we=1, waddr=2: write e…read entry 2: data=0xA5, valid=1 — the whole structured entry updated togetherread entry 2: data=0xA…clkwe01000000waddr02222222wdata0A5A5A5A5A5A5A5raddr22222222rdata0000A5A5A5A5A5A5rvalid00111111t0t1t2t3t4t5t6t7
Writing entry 2 sets its data and valid fields in one clocked update; reading entry 2 returns those fields. The record keeps the entry's fields together — data and valid move as a unit — while the array index selects which entry. This is the register-file behaviour an array of records captures directly.

6. 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.

one_array_not_parallel.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- 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, consistent

7. 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.