Structural VHDL

Roles

Traditional Schematic view of design

To represent communication between design entities which are CONCURRENTLY active.  

Simple Structural Example

 

entity  XOR 
        port  ( a,  b :  in bit;  y : out bit );
end XOR;
architecture  nand_gates  of  XOR  is
        signal  s0, s1, s2:     bit;
        component  nand 
                port ( a, b:  in bit;  y:  out bit );
                end;
        for all: nand use entity asic.nand2(behavioral);
begin
        U1:     nand  port map ( a, b, s0 );
        U2:     nand  port map ( a, s0, s1);
        U3:     nand  port map ( b, s0, s2);
        U4:     nand  port map ( s1, s2, y);
end  nand_gates;

Component Declarations

Difference between Components and Entities

Component Instantiation

Creation of Structural Architecture Bodies

General form for Component Instantiation

generic map ( interface_list );
port map ( interface_list );
 

-- Component declarations can be done directly in an 
-- Architecture, but large collections of component
-- declarations are better kept in a package.
-- You then "get at" those declaration by naming the
-- package in a USE statement.
package logic_family is
component And2 port ( i1, i2 : in bit; z : out bit ); end component;
component And3 port ( i1, i2, i3 : in bit; z : out bit ); end component;
component Nor2 port ( i1, i2 : in bit; z : out bit ); end component;
component Nor3 port ( i1, i2, i3 : in bit; z : out bit ); end component;
component Xor2 port ( i1, i2 : in bit; z : out bit ); end component;
component Nand2 port ( i1, i2 : in bit; z : out bit ); end component;
component Inverter port ( i1 : in bit; z : out bit ); end component;
end logic_family;
use work.logic_family.all;
entity ALU_slice is port ( func_sel : in bit_vector ( 0 to 3 );
        mode : in bit; X, Y, Cy_in : in bit; F : out bit; Cy_out : out bit );
end ALU_slice;
architecture Structure of ALU_slice is


signal Cy_not, Ynot, Mnot : bit ; signal va, vb, vc, vd, ve, vf, vg, vh, vi, vj : bit;

begin

--note the instance labels!

end Structure;

Note the use of subscripted members of a bit vector in connecting components.
 
 

Port Map

Two ways to establish the association between the formal and actual parameters:
 
By Order     If the component declaration was
component Nor2 port ( i1, i2 : in  bit;  z : out bit );
end component;


then the instantiation
               U5:     Nor2    port map ( za,zb,ze );


connects za to i1, zb to i2, and ze to out bit z.
 
 
The syntax is as follows:
Example:
CPU:  Microprocessor 
        port map ( Address_bus => Addr,
                Data_bus => Data,
                MRQ     => MemReq,
                IORQ    => IO_Req,
                WR_bar  =>  RWb,
                CLK     =>  Clock,
                RFSH_bar =>  open,
                HALT_bar =>  open
                ) ;


Open is a reserved word to be used wherever component ports are not connected to anything.

Binding actual constants to formal generics is performed in exactly the same fashion as for ports.
While ports must be connected using signals, the inputs to generics must be constants.
Example of uses of generics in structural VHDL:
 

        -- timing specifications
        -- dimensions
Mem:  RAM 
        generic map (
                wordsize => 16;
                memsize => 2**adrs'length;
                t_access => 15 ns;
                t_cycle => 25 ns        );


The values being passed to the generics may come from constants declared in this architecture, from constants in packages known to this architecture, or may be specific to this instance.
 
The actual part of the association for a generic can (and often should) be an expression.

Instantiation of Regular Structures

label: for index in discrete_range generate
             concurrent_statement (s)
             end generate;

The index is implicitly declared by its use in the for. It may be referenced only within the generate block it encloses.
The discrete_range is evaluated at the build step. It may be the range attribute of some signal, or may be of the form:
 

constant_expr TO constant_expr

 constant_expr DOWNTO constant_expr

It must always be possible to evaluate constant expressions at the BUILD step.

 
label: if condition_expression then generate
concurrent_statement (s)
end generate;
 

Here the condition_expression is evaluated during the BUILD step, and must be a constant expression -- although the constant expression will probably contain one or more generics in it.
 
Iteration
 
Example: An N-bit wide shift register is being assembled from one bit Shift_Slice cells.

signal C : bit_vector ( 0 to REGSIZE-1 );
 -- where REGSIZE is a generic parameter for the design
 
begin
        sreg: for i in 0 to REGSIZE-1 generate
                s0: if i = 0 generate
                        t0: Shift_Slice
                                generic map (tprop)
                                port map (clk,enb,S_in, C(i), Q(i));
                        end generate;
                si: if i > 0 and i < REGSIZE-1 generate
                        ti: Shift_Slice
                                generic map (tprop)
                                port map (clk,enb,C(i-1), C(i), Q(i));
                        end generate;
                sn: if i = REGSIZE-1 generate
                        tn: Shift_Slice
                                generic map (tprop)
                                port map (clk,enb,C(i-1), S_out, Q(i));
                        end generate;
        end generate; -- for loop
 . . . . .
end;
 
Notes:
 The index i exists only inside the loop, and cannot be redefined. No explicit declaration of the index is required.
 Every for - generate and if-generate statement must have a label.
 Remember that every component instantiation must have a label, too.




 
Recursion
Iteration is the common form for instantiation of regular structures, but recursion can be useful, too.
Example

 entity decoder is
generic (N : integer);
 port ( sel : bit_vector ( 1 to N );
 Y : bit_vector (1 to 2**N) );
 end decoder;
 
architecture recursive_form of decoder is
 
signal nsel : bit;
 
component and2 port (i1,i2: bit; y: out bit); end component;
omponent inverter port (i1: bit; y: out bit); end component;
component decoder
generic ( n : integer );
port (sel : bit_vector; y: out bit_vector);
end component;
 
begin
   inv: inverter port map (sel(N), nsel);
   ase: if N=1 generate
                Y(1) <= sel(1);
                Y(2) <= nsel;
                end generate;
 
   recurse: if N>1 generate
        b1: block
                signal temp : bit_vector ( 1 to 2**(N-1) );
              begin
                dcd: decoder generic map (N-1)
                        port map (sel(1 to N-1), temp);
                drv: for i in 1 to 2**(N-1) generate
                        s1: and2 port map (temp(i),sel(N),Y(2*(i-1)+1) );
                        s2: and2 port map (temp(i), nsel , Y(2*i) );
                        end generate;
        end block;
   end generate;
end recursive_form;

 
Example:

	component Inverter
	component And3
	component Xor2

. . .
for U7 : Inverter use entity Work.Invert ( DF_Arch);   for U1, U2: And3 use entity TTL.And3 (DF_Arch); for others: And3 use entity LSTTL.And3 (DF_Arch);   for all : Xor2 use entity STTL.Xor2 (DF_Arch);
 .  .  .
begin -- the architectural body   Use of Port Maps and Generic Maps in Configuration Specification   The entities to be used for a component may not match exactly. The names of the component ports do not have to match the names used in the entity interface definition, and some of the ports of the entity may not be used.   Example: entity acia is         port                 ( -- System side data : inout byte; address : in adrs_vector; irq : out bit; bus_busy: inout bit; bus_req: out bit; data_valid: inout bit;   -- Asynchronous side xmit : out bit; recv : in bit; r_strobe: in bit; async_clk: in bit ); end acia ;   component   sys_slot  port ( -- Asynchronous side recv : in bit; strobe: in bit;   -- System side D : inout byte; A : in adrs_vector;   IRQ : out bit;   busy: inout bit;   rq: out bit;   dav: inout bit   ); end component;   -- Now the configuration is given by   for slot1, slot2 : sys_slot use entity std_cell.acia(n3703); port map (-- System side data => D, address => A, irq => IRQ, bus_busy => busy, bus_req => rq, data_valid => dav,   -- Asynchronous side xmit => OPEN, recv => recv, r_strobe => strobe, async_clk => OPEN );

 
Normally the actuals are the component port names. However, it is legal to create default connections in the component configuration -- e.g. power and ground connections, or to a global clock.
 Configuration Bodies
 It is possible create a separate unit to describe what entities and architectures are to be used in a design without having to embed that information in the design itself. This is especially useful when there are several choices of parts to be used.
 

 
A configuration body is separated from the entities, architectures, and packages it configures. It may be created to direct the build program in assembling a design from its parts.
 
configuration config_name of entity_name is
 declarations
 configuration_block
 end config_name;
 
A configuration block is a more general form of the configuration specification capability described above, and has the form:
 
for block_spec -- this is a block configuration
 use binding_indication(s)
block_configuration
 component_configuration
 end for;
 Example
 

 

library ieee; use ieee.std_logic_1164.all;
entity mem_board is
        port ( data : inout std_logic_vector;
        address: in std_logic_vector;
        nOE, nWR : in std_logic );
  
end mem_board;
architecture S1 of mem_board is
signal selectbits : std_logic_vector(0 to 1); 
signal csel : std_logic_vector(0 to 3); 
signal mem_adrs : std_logic_vector(0 to 17);
component ram
port ( d : inout std_logic;
adrs : in std_logic_vector; 
CS,nOE,nWR : in std_logic); 
end component; 
begin
assert selectbits'length + mem_adrs'length = address'length
report "Address lines to/inside Memboard do not match." 
severity ERROR;
D: for i in data'range generate 
A: for j in csel'range generate 
Uxy: ram port map (data(i), mem_adrs, csel(j), nOE, nWR); 
end generate;   -- for j
end generate;   -- for i
end S1; 
  
configuration FGD of mem_board is
        for S1
                for all: ram
                        use entity Fujitsu.Generic_Ram(Dynamic);
                end for;
        end for;
 end FGD; 
 

 
use work.all;
configuration struct1 of TLC_TEST is
        for Test        -- where the outermost entity is TLC_Test 
                        -- and Test is an architecture implementing it. 
                for Controller : TLC use
                        entity work.Traffic_Light_Controller (Structure1); 
                        -- instance Controller of component TLC in 
                        -- TLC_TEST(Test) is to have this entity in it. 
                        for Structure1 
                                 -- specifying the timer section of this arch.
                                 for Timer_Struct : Timer_Section use
                                        entity work.Timer (Behavior); 
                                end for; 
                        end for; 
                end for; 
        end for; 
end struct1;