8. Parameterized Design

  • Goal: Design reuse

    • Ideally, we want to design some common modules that can be shared by many applications.
    • Since every application is different, it is desirable that a module can be customized to some degree to meet the specific need of an application.
    • Customization is normally specified by explicit or implicit parameters
  • Width Parameters

    • The widths of data signals normally can be modified to meet different requirement.
    • The width parameters of a parameterized design specify the sizes (i.e., number of bits) of the relevant data signal.
  • Feature Parameters

    • Specify the structure or organization of a design.
    • Defined on an ad hoc basis.
    • To include or exclude certain functionalities (i.e., features) from implementation or to select one particular version of the implementation

8.1. Generics

  • The generic construct of VHDL is a mechanism to pass information into an entity and a component.

    • They are first declared in entity and component declaration and later assigned a value during component instantiation
entity para_binary_counter is
    generic (WIDTH: natural);
    port (
       clk, reset: in  std_logic;
      q: out  std_logic_vector(WIDTH-1 downto 0)
    );
end entity para_binary_counter;
  • After the declaration, the generic can be used in the associated architecture bodies.

  • A generic cannot be modified inside the architecture body and thus functions like a constant

    • It is sometimes referred to as a generic constant.
architecture arch of para_binary_counter is
    signal reg, reg_next : std_logic_vector (WIDTH-1 downto 0);
begin
    process (clk, reset) is
    begin
          if reset = ‘1’ then
            reg <= (others =>’0’);
          elsif clk’event and clk=‘1’ then
        reg <= reg_next;
          end if;
    end process;
-- next-state logic
    reg_next <= reg + 1;
    q <= std_logic_vector(reg);
end architecture arch;
  • To use the parameterized free-running binary counter in a hierarchical design, a similar component declaration should be included in the architecture declaration.
  • The generic can then be assigned a value in the generic mapping section when a component instance is instantiated.
  • Example of the use of generics
../_images/c8_Reduced_xor.jpg

Parameterized reduced-xor circuit using a generic

8.2. Array attribute

  • A VHDL attribute provides information about a named item, such as a data type or a signal.

  • We have used the ’event attribute, as in clk’event, express the changing edge of the clk signal.

  • A set of attributes is associated with an object of an array data type. Let s be a signal with an array data type.

    • s’left, s’right: the left and right bounds of the index range of s.
    • s’low, s’high: the lower and upper bounds of the index range of s.
    • s’length: the length of the index range of s.
    • s’range: the index range of s.
    • s’reverse_range: the reversed index range of s.

The attributes can be applied to the signal defined with std_logic_vector, unsigned and signed:

signal s1: std_logic_vector (31 downto 0);
signal s2: std_logic_vector (8 to 15);
../_images/c8_code.jpg

Parameterized reduced-xor circuit using an attribute

  • The range of the for loop can also be expressed as:

    • for i in a’low+1 to a’high loop
    • for i in a’right+1 to a’left loop
  • The last signal assignment y <= tmp (tmp’left);

8.3. Unconstrained Array

  • Unconstrained array is defined as an array type with specified data type of the index value, but without specified exact bounds of the index value.
  • Example: type  std_logic_vector is array (natural range <>) of std_logic
  • Similarly, we have unsigned and signed data types.
  • If an object is declared with an unconstrained array data type, we must specify its index range when the data type is used, as 15 downto 0 in signal x: std_logic_vector(15 downto 0);
  • A special case: the unconstrained array can be declared without specifying the range in port declaration.
  • Example:
  • Since no range is specified for d and q, the boundaries of the two signal will not be check in the analysis stage.

Parameterized reduced-xor circuit using an unconstrained array

The code appears to be correct at first glance

  • If we map the a signal to an actual signal with the type of std_logic_vector of 8 bits during component instantiation, we may have a to be:
std_logic_vector(7 downto 0);
std_logic_vector(0 to 7);
std_logic_vector(15 downto 8);
std_logic_vector(8 to 15);
  • The code does not work properly for the last two formats.

Improved parameterized reduced-xor circuit using an unconstrained array

8.4. Comparison

  • The unconstrained array mechanism uses attributes to infer the relevant information from the actual signal.

    • More general and flexible than the generic mechanism, but also
    • More opportunities for errors.
    • Requires comprehensive error-checking code
  • Generic mechanism is preferred, unless a module is extremely general and widely used.

    • More rigid
    • It clearly specifies the range, direction and width of each signal and avoids many subtle erroneous conditions.

8.5. Generate Statement

  • The generate statements are concurrent statements with embedded internal concurrent statement, which can be interpreted as a circuit part.

  • Two types of generated statements:

    • for generate statement: used to create a circuit by replicating the hardware part
    • conditional or if generate statement: used to specify whether or not to create an optional hardware part.

8.5.1. For Generate Statement

  • Many digital circuits can be implemented as a repetitive composition of basic building blocks, exhibiting a regular structure, such as a one-dimensional cascading chain, a tree-shaped connection or a two-dimensional mesh.
  • For generate statement syntax
gen_label:  -- mandatory to identify to this    -- particular generate statement
    for loop_index in loop_range generate
          concurrent statements;                             -- describe a stage of the iterative circuit
    end generate;
  • The loop_range has to be static. It is normally specified by the width parameters.

Examples

Binary decoder

  • A binary n-to- 2 n decoder is circuit that asserts one of the 2 n possible output signal according to an n bit input signal.
  • One way to view the binary decoder is to treat each bit of the decoded output as the result of a constant comparator.
../_images/c8_Binary_decoder.jpg

Parameterized binary decoder using a for generate statement

../_images/c8_Reduced_xor2.jpg

Parameterized reduced-xor circuit using a for generate statement

architecture gen_linear_arch of reduced_xor is
    signal tmp: std_logic_vector(WIDTH-1 downto 0);
begin
    tmp(0) <= a(0);
    xor_gen:
          for i in 1 to (WIDTH-1) generate
        tmp(i) <= a(i) xor tmp(i-1);
          end generate;
     y <= tmp(WIDTH-1);
end architecture gen_linear_arch;
  • In an iterative structure, the boundary stages interface to the external input and output signals, and sometimes their connections are different from the regular blocks.

8.5.2. Conditional Generate Statement

  • The conditional generate statement is used to specify an optional circuit that can be included or excluded in the final implementation.
  • Conditional generate statement syntax
    gen_label:      -- mandatory
    if boolean_exp generate -- boolean_exp must be static
          concurrent statements;
end generate;
  • There is no else branch in conditional generate statement.
  • If we want to include one of the two possible circuits in an implementation, we must use two separate if generate statements.

Reduced-xor circuit revisited

  • One common use of the conditional generate statement is to describe the “irregular” stages in a for generate statement.
  • For example, two statements tmp(0) <= a(0); y <= tmp(WIDTH-1); are used to rename the input and output signals in the for generate statement examples.
  • To eliminate these statements, we can use conditional generate statements inside the for generate statement.

Parameterized reduced-xor circuit with a conditional generate statement

Examples

Up-or-down free-running binary counter

  • An up-or-down binary counter is a counter that can be instantiated in a specific mode.
  • Note that the “or” here means that only one mode of operation, either counting up or counting down but not both, can be implemented in the final circuit.
../_images/c8_Binary_counter.jpg
  • We use the UP generic as the feature parameter to specify the desired mode.

Up-or-down free-running binary counter

Up-and-down free-running binary counter

Counter with an optional output buffer

  • An output buffer can remove glitches from the signal.
  • Since the buffer is only needed for certain application, it will be convenient to include the buffer as an optional part of the circuit.
../_images/c8_Counter_with_buffer.jpg

Counter with an optional output buffer

8.6. Comparison

  • To create a circuit with a selectable feature:

    • use conditional generate statement
    • a full-featured circuit with some input control signal connected to constant values to permanently enable the desired feature
    • use the configuration construct
  • Assume we need a 16-bit up counter in a design.

count16up: up_or_down_counter
      generic map (WIDTH => 16, UP =>1)
      port map (clk => clk, reset => reset, q=>q);
count16up: up_and_down_counter
      generic map (WIDTH => 16)
      port map (clk => clk, reset => reset, mode => ‘1’, q=>q);

Difference

  • The up-or-down counter instance

    • creates a circuit with only the needed features.
    • The selected portion of code is passed to the synthesis stage, i.e., the synthesis software only needs to synthesize the selected portion.
  • The up-and-down counter instance

    • creates a circuit that consists of all features and uses an external control signal to selectively enable a portion of the circuit.
    • The entire VHDL code is passed to synthesis stage. The synthesis software eliminates the unused portion through logic optimization.
  • In general, use of the feature parameters and conditional generate statement is better than the full-featured approach.

  • The selected hardware creation can also be achieved by configuration where multiple architecture bodies are constructed, each containing a specific feature, e.g., architectures up_arch and down_arch of the same entity updown_counter, for counting up and counting down, respectively.

  • And the following instantiation can be used to select the counting up circuit.

count16up: work.updown_counter(up_arch)
          generic map(WIDTH =>16)
          port map (clk => clk, reset => reset, q => q);

Up-or-down counter with two architecture bodies

  • Conversely, we can merge the logic from several architecture bodies into a single body and use a feature generic and conditional generate conditions to select the desired portion.

  • There is no rule about when to use a feature parameter and when to use a configuration construct. In general,

    • code with a feature parameter is more difficult to develop and comprehend, but on the other hand, if we use a separate architecture body for each distinctive feature, the number of architecture bodies will grow exponentially and becomes difficult to manage.
    • when a feature parameter leads to significant modification or addition of the no-feature codes and starts to make the code incomprehensible, it is probably a good idea to use separate architecture bodies and the configuration construct.

8.7. For Loop Statement

  • The for loop statement is a sequential statement and is the only sequential loop construct that can be synthesized.
for index in loop_range loop    --loop_range must be static
      sequential statements;
end loop;
  • The basic way to synthesize a for loop statement is to unroll or flatten the loop. Unrolling a loop means to replace the loop structure by explicitly listing all iterations.

Examples

Binary decoder

The code is very similar to the for generate version

architecture loop_arch of bin_decoder is
begin
    process (a)
    begin
          for i in 0 to (2**WIDTH-1) loop
if i = to_integer(unsigned(a)) then code(i) <= ‘1’;
        else code(i) <= ‘0’;
        end if;
          end loop;
      end process;
end architecture gen_arch;

Examples

Reduced-xor circuit

For loop version: For generate version:

Examples

Priority Encoder

  • Recall that a signal can be assigned with multiple times inside process and only the last assignment takes effect.
  • A priority encoder is a circuit that returns the binary code of the highest-priority request.
  • Assume that the input is an array of r(WIDTH-1 downto 0), and r(WIDTH-1) has the highest priority.

8.8. Comparison

  • Both the for generate and for loop statements are used to describe replicated structures.

  • For generate statement:

    • can only use concurrent statements.
    • start a design with a conceptual diagram of a few stages; the diagram is used to identify the basic building block and connection pattern, and then the code of the loop body is derived.
  • For loop statement:

    • can only use sequential statements.
    • the body of the loop statement can be more general and versatile.
    • may lead to unnecessarily complex implementation or even an unsynthesizable description.