Array – basics

Array, a collection of values of the same type, is very useful representation of data in VHDL. It is helpful during creating memory blocks (FIFOs, shift registers, RAM, ROM) or in designs where exist duplicated data flows, pipes or blocks (many ADC channels, filters etc).  They can be used in synchronous designs as well as in combinational. But using it in combinational parts, sometimes for specific solution, it is very important to be aware how the code will be interpreted and synthesized.

To use the array object in the code, we need to do following steps:

  1. declare a new type
  2. declare signal of a new type
  3. use it properly in the code

Array declaration

type array_type_name is array (elements_range) of elements_type;


array_type_name – name of a new array type,
elements_range – number of elements in the array,
elements_type – type of each element in the array.

Example of usage

This line creates a new array type with 4 elements, where every element is a 12-bit width std_logic_vector type:

type arr_adcin is array (0 to 4-1) of std_logic_vector(12-1 downto 0);

After declaring a new type, we can create signals of a new type:

signal signal_name : arr_adcin;

At the end, the new signal can be used in a project. Below, basic example shows how to do that.

library IEEE;
use IEEE.STD_LOGIC_1164.all;

package arr_pkg is

   constant C_PKG_ADC_CH_NUM  : natural :=  4;
   constant C_PKG_ADC_WIDTH   : natural := 12;
   type t_arr_AdcData is array (0 to C_PKG_ADC_CH_NUM-1) of std_logic_vector(C_PKG_ADC_WIDTH-1 downto 0);

end arr_pkg;

-- BODY -- 
package body arr_pkg is
end arr_pkg;

-- dummy block
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.arr_pkg.all;

entity DummyBlock is
   generic (
      G_WIDTH  : natural := C_PKG_ADC_WIDTH
   port (
      clk	: in std_logic;
      rst	: in std_logic;

      iv_data	: in std_logic_vector(G_WIDTH-1 downto 0);
      ov_data	: out std_logic_vector(G_WIDTH-1 downto 0)
end DummyBlock;

architecture DummyBlock_bhv of DummyBlock is 


   -- we can do here some nice stuff with data
   -- but now we will just send input to output
   -- assign inputs to "array cells"
   ov_data  <= iv_data;

end DummyBlock_bhv;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.arr_pkg.all;

entity arrays is
   generic (
      C_ADC_CH_NUM   : natural := C_PKG_ADC_CH_NUM;
      G_WIDTH        : natural := C_PKG_ADC_WIDTH
   port (
      clk	: in std_logic;
      rst	: in std_logic;

      iv_adc0	: in std_logic_vector(G_WIDTH-1 downto 0);
      iv_adc1	: in std_logic_vector(G_WIDTH-1 downto 0);
      iv_adc2	: in std_logic_vector(G_WIDTH-1 downto 0);
      iv_adc3 	: in std_logic_vector(G_WIDTH-1 downto 0);

      ov_data0	: out std_logic_vector(G_WIDTH-1 downto 0);
      ov_data1	: out std_logic_vector(G_WIDTH-1 downto 0);
      ov_data2	: out std_logic_vector(G_WIDTH-1 downto 0);
      ov_data3	: out std_logic_vector(G_WIDTH-1 downto 0)
end arrays;

architecture arrays_bhv of arrays is 

   signal arr_AdcData	: t_arr_AdcData;
   signal arr_DB_data   : t_arr_AdcData;

   -- assign inputs to "array cells"
   arr_AdcData(0) <= iv_adc0;
   arr_AdcData(1) <= iv_adc1;
   arr_AdcData(2) <= iv_adc2;
   arr_AdcData(3) <= iv_adc3;
   -- send data through blocks
   -- for every "array cell" exists another instantiation of DummyBlock
   GEN_DB: for I in 0 to C_ADC_CH_NUM-1 generate
      DummyBlock_inst : entity work.DummyBlock  
         port map (
            clk	   => clk,
            rst	   => rst,
            iv_data  => arr_AdcData(I),
            ov_data  => arr_DB_data(I)
   end generate GEN_DB;
   ov_data0 <= arr_AdcData(0);
   ov_data1 <= arr_AdcData(1);
   ov_data2 <= arr_AdcData(2);
   ov_data3 <= arr_AdcData(3);

end arrays_bhv;

As can be seen, it is much easier to create many identical data flows with an array type. Array usage is similar as in high-level languages. Every cell of an array is easily accessible by index value. Every cell can be used separately. With arrays, the code is much cleaner and more understandable.



Please, by aware that array itself does not optimize anything (timings or resources) but makes code much more readable and flexible (and that is what I always fight for). Array does not create any registers. It just groups similar single signals, which makes them easier to use.

*** *** ***

All source codes used in that post (with testbench) you can find on

*** *** ***


Leave a Reply

Your email address will not be published. Required fields are marked *