Array and Records in VHDL

Composite Data Type:

In addition to predefined type, VHDL also allow us to use  array and record types in our VHDL designs. This can provide us with a more structured design which is easier to maintain.

These are of two types:

  1. Array

  2. Record: records are like structures in C language. They allow us to use different types

Array:

An array is a collection / group of elements of the same type as a single object. Array can be of any type In VHDL. Array can be one dimension, two dimension and multi dimension. 

Syntax:

type <type_name> is array (<range> ) of <type> ;

the <range> field in the above example can be built using the downto and to VHDL keywords

Type of Arrays

  1. Constrained type array
  2. Unconstrained type  array
Constraied type of array

An array whose range is defined at the time of declaration of the array object

type type_name is array (range) of element_type;

example-1

Type data_bus is ARRAY (0 to 31) of bit;                           — 32-bit data_bus

Each element of array can be accessed by array index:

Variable x : data_bus;                    — 1x is of type data_bus of 32 bit

Variable y: bit;                               –2

           In the above code,

line-1 declares variable x of type data_bus which is an array, so x is also an array of 32-bits data_bus.

line-2 declare an  object y is of type bit can hold ‘0’ or ‘1’ which can be assigned to only one of the line of x data_bus

Then we can use following assignement :

x(0) := y;       — Write to bus x(0)

Or

y := x(15);     — read from bus line x(15) and assign it to variable y

example-2

type NIBBLE is array (3 downto 0) of std_ulogic;            –1

signal A_BUS : NIBBLE;                                                        –2

type RAM is array (0 to 31) of integer range 0 to 255;     –3

signal RAM_0 : RAM;                                                              –4

line 1 above is used to declare NIBBLE as an array  of type std_ulogic,

line-2 declares an object A_BUS of type NIBBLE, so A_Bus is also of 4-bit wide

line-3 another array RAM 256 words each of 32-bit wide

line-4 creates a signal RAM_O of type RAM of size 256 x 32

Unconstraied type of array

An array whose range is undefined, and to be assigned at the time of its use i.e when declaring objects of this type.

The following code shows how to use unconstrained array

type <type_name> is array (natural range<>) of <type>;  — (1)

type <type_name> is array (positive range<>) of <type>;  — (2)

syntax (1) above creates a zero based unconstrained array, whereas syntax (2) above creates an unconstrained (non-zero based) array

example:

Note here that for uncontrained array, the range is defined when declaring objects of this type. see line number 2  for delaring two objects ( variable) of type INT_ARRAY

type INT_ARRAY is array (integer range <>) of integer;   –1

variable INT_TABLE: INT_ARRAY(0 to 9);                         –2

variable LOC_BUS : std_ulogic_vector(7 downto 0);         –3

Concatenation and Slicing of Arrays

an arry can also be formed by concatenating multi 1-bit objects. code at line-1 concates four bits A_BIT, B_BIT, C_BIT, D_BIT to form an array A_BUS of 4-bits line-2 is an equalivalent of line1. line-2 uses concatenation operator &

A_BUS <= (A_BIT, B_BIT, C_BIT, D_BIT);            –1

A_BUS <= (A_BIT & B_BIT & C_BIT & D_BIT);  –2 an equivalent assignment of the above line of code

A_BUS <= A_BUS(2 downto 0) & A_BUS(3);    — rotate A_BUS to the left, i.e. it concatenates A_BUS(3) with A_BUS (2 downto 0) to form a A_BUS of nibbl4(4-bit size)

Arrays of arrays (Multidimentional Array)

The multidimentional or an array f array is  useful for memories, vector tables, etc. The following code example first creates an array NIBBLE of size 4 std_ulogic. Then line-2 creates another array MEM of size 8 NIBBLES. thus creating array of array i.e. 8×4. try understanding the following code

type NIBBLE is array (3 downto 0) of std_ulogic;   -- 1
type MEM is array (0 to 7) of NIBBLE;     -- 2 an array "array of array" type
variable MEM8X4 : MEM;                   --3 creates object MEM8x4 of type MEM
now we can initialize the whole MEM8x4 array i.e. 8 rows of 4-bits as: 
MEM8X4 := ("0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111");
Individual words can be accessed for reading or writing by their index as:
MEM8X4(5) := "0110";    -- initialising row 6 of MEM8x4
MEM8X4(6) (0) := '0';   -- -- initializing bit-0 of row-0 with '0'
variable x : bit
MEM8x4(1)(0) := x       -- Write row-1 bit 0 with the value from x
x := MEM8x4(1)(3)       -- Read into x from  MSB of row-1 of MEM8x4

RECORD:

A record is used to contain values of different types. It is like a structure in ‘C’ programming language. A record contains objects of different type. In digital design, we often have a large group of related signals that make up some complex bus or protocol, like PCIe, AXI, DDR, etc. It is then desired to apply some operation to the entire group of signals, such as pipelining them, muxing them, putting them into a fifo, or using them in a port in some level of the design. This is when records really shine.This also makes the VHDL code easier to understand and maintain. Some of the usage of records are:

  1. Records are used to simplify entities and port maps in VHDL.
  2. Records may contain elements of different types. (std_logic, integer, etc)
  3. Records are similar to structures in C.
  4. Records used across multiple files should be kept in a single package file.
  5. Signals defined as records can be initialized.
  6. It is possible to create an array of records.

Syntax

type my_profile is RECORD

–declarations of objects of different types

end records

example:

architecture record_example of rec_entity is

type rec_exmpl is record

a: std_logic;

b: std_logic_vectro(15 downto 0);

end record rec_exmpl

— declare the record variable

signal sig_name is rec_exmpl;

— architectre begin

begin

— accessing record members

sig_name.a >= enable;

sig_name.b >= halfword_vec;

— there are two ways of updating the record constants

i. Name binding: It is a recomended way of declaring values of each filed of record. For the above structure, we can declare zero cnstant as :

constant zero_rec_exmpl : rec_exmpl :=(

a >= ‘0’;

b >= (others => ‘0’);

);

ii. Positional binding: It is not a recomended way of declaring the constant record. However the way of declaring constants using  positional binding is given below:

constant one_rec_exmpl : rec_exmpl :=(

a >= ‘1’;

b >= (others => ‘1’);

);

Array of Records

It is possible to declare array of records in VHDL. each record of an array can be initialized with their index or using the others=> ‘  ‘ method of initialization. example below creates an array of the record declared above.

type arr_rec is array (natural range 0 to 255) of rec_exmpl

— we can declare the constants both way the name and positinal as:

constant arr_record1 : rec_exmpl (

1    =>  one_rec_exmpl;      — initializing record-1 with one_rec_exmpl (declared above)

2   => (a => ‘1’; b=> x”0123″; — initializing record-2

3  =>  (a=> ‘0’ ; b => x”1234″ ; — initializing record-3

others => zero_rec_exmpl      — initializing rest of all records upto record number 255

);

Other examples like FIFO, RAM etc can be implemented using the records

A fifo for example can not be written when full, and similarily cannot be read when empty. So two signals could be used as flags to mark as read and write flags.

 

Questions

  • Write short note on  Arrays, Records:

  • Write short note on composite data types.

  • What is type conversion? Explain with example.

  • Write short note on aliases.

Leave a Reply

Top
error: Content is protected !!