Table of Contents

Design Reuse

Overview

Design Reuse

Notes

Reuse means to fall back on existing problem solutions.

Every design engineer will try to apply previous VHDL code to the current situation. This is fairly simple because all details of the implementation are already known and consequently the code can be easily changed.

Why Reuse?

Notes

Reuse of previous designed modules on a bigger scale has become a necessity since the designer productivity can not keep pace with the advances in the field of technology.

Currently, the complexity of integrated circuits increases at a rate of approximately 60% per year whereas the designer productivity increases just by 20%. The only way to fill this gap is to reduce the design effort by reusing existing solutions.

Design for Reuse

Notes

Old designs, however, can not simply be collected in a reuse library to provide the desired standard solutions.

As developers that are not familiar with the internals shall be able to use the parts of the library, the documentation must be extremely detailed.

Additionally, the code must be written with reusability in mind because modifications might consume more time than a complete redesign.

This means that the VHDL must not rely on short term settings like technology or tool features.

Possible applications have to be covered via parameterizable behavior, i.e. the code itself needs not to be modified. Thus, simple structures and standard solutions have the biggest reuse potential.

Bad Example

library IEEE;
use IEEE.std_logic_1164.all;
-- synopsys packages
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity ZERO_COUNT is
  port(DATA_IN: in std_logic_vector (7 downto 0);
       CNT, ONES : out
             std_logic_vector (3 downto 0));
end ZERO_COUNT;
architecture RTL of ZERO_COUNT is
begin
   CNT_PROC : process(DATA_IN)
     variable CNT_TEMP : integer range 0 to 8;
   begin
     CNT_TEMP := 0;
     for I in 0 to 7 loop
       If DATA_IN(I) =0then
          CNT_TEMP := CNT_TEMP + 1;
       end if;
   end loop;
   CNT<= conv_std_logic_vector(CNT_TEMP,4);
   ONES<= 8-conv_std_logic_vector(CNT_TEMP,4);
 end process;
end RTL;

Bad Example

Notes

The difference in design philosophy shall be demonstrated at an example module that has to count the number of ’0’ and ’1’ elements in a bit vector.

The first version is a straight forward implementation of the specification. Synopsys packages are used for bit vector arithmetic based on ’std_logic_vector’.

Although these packages are frequently used in industry, they are not standardized. Because the vector widths from the actual task are hard coded, it is not possible to place an identical module in a different environment.

Good Example (1/2)

library IEEE;
use IEEE.std_logic_1164.all; use IEEE.numeric_std.all;
package BITCOUNT is
  procedure COUNT(VECTOR: in std_logic_vector;
        VALUE: in std_logic;
        signal RESULT: out std_logic_vector);
end BITCOUNT;
package body BITCOUNT is
  procedure COUNT(VECTOR: in std_logic_vector;
        VALUE: in std_logic;
        signal RESULT: out std_logic_vector) is
     variable COUNT: integer;
     variable MAXVALUE: unsigned(RESULT’length-1 downto 0);
  begin
   COUNT := 0; MAXVALUE := (others =>1);
   for I in VECTOR’range loop
     if VECTOR(I) = VALUE then
       COUNT := COUNT + 1;
     end if;
  end loop;
  if COUNT > MAXVALUE then
     RESULT <= (others =>1);
  else
     RESULT <= std_logic_vector(to_unsigned(
                                COUNT, RESULT’length));
  end if;
 end COUNT;
end BITCOUNT;

Notes

The counting of specific values within a vector is a very basic function that should be implemented as a subprogram.

This subprogram should be placed in a package in order to make it easily accessible.

Subprograms may use unconstrained formal parameters which allows for parameterizability without much of additional effort.

Good Example (2/2)

library IEEE;
use IEEE.std_logic_1164.all;
use WORK.BITCOUNT.all;
 
entity ZERO_COUNT is
   generic(D_WIDTH : integer := 8;
           C_WIDTH : integer := 4;
           COUNT_1S : integer range 0 to 1 := 1);
port(DATA_IN : in
           std_logic_vector(D_WIDTH-1 downto 0);
     CNT, ONES : out
           std_logic_vector(C_WIDTH-1 downto 0));
end ZERO_COUNT;
 
architecture RTL of ZERO_COUNT is
begin
  COUNT(DATA_IN, ’0’, CNT);
 
   CNT_ONES: if COUNT_1S=1 generate
     COUNT(DATA_IN, ’1’, ONES);
   end generate CNT_ONES;
end RTL;

Notes

In order to fulfil the requirements, an entity/architecture pair must be created that shows the specified behavior.

The new entity has generic parameters that may be used to define port width.

Their default values allow a drop in replacement of the old design without the necessity of a generic map.

While the first two parameters are used to set the data width, the third parameter COUNT_1S affects the behavior of the module.

It allows to turn of the counting of ’1’ elements.

The ’if … generate’ construct is used to reduce the amount of hardware that gets synthesized.