Skip to content
VLSI Mentor

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 fieldswaddr → entry iindex selects one entryentry 0{data, valid, tag}entry i{data, valid, tag} ← writeentry N-1{data, valid, tag}read fieldregfile(raddr).datawrite entryread field12
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 entry2 → {data=0xA5, valid=1,tag=...}read entry 2: data=0xA5, valid=1 — the whole structured entry updated togetherread entry 2: data=0xA5,valid=1 — the wholestructured entry updated…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.

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.