====== Design Reuse ====== ===== Overview ===== {{:courses:system_design:project_management:folie389_designreuse.svg?nolink&600|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? ===== * Continuous growth of complexity (approx. 60% per year) * Limited increase of designer productivity (approx. 20% per year) * ⇒ Gap between technology and product capabilities * Reuse: * Readily available solutions for specific problems (micro controllers, bus interfaces, signal processors, etc.) * Reduced amount of verification effort * Prerequisite for System-on-a-Chip (SoC) === 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 ===== * Traditional approach: copy, paste and modify * Difficult to maintain * Risk of bug propagation * Reuse concepts * System specific constant definition in packages * Standard data types at interface * Internal use of problem specific data types for runtime error checking * Subprograms for common features: easy scalability -> unconstrained formal parameters; flexibility → embedding in architectures * Self contained modules for complex functions * General requirements * Technology independency * Tool independency (simulation, synthesis) * Parameterization with constants and generics * Detailed documentation === 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) = ’0’ then 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; {{:courses:system_design:project_management:folie392_badexample.svg?nolink&300|Bad Example}} * Use of Synopsys packages * not standardized (quasi-standard) * might not be available in other tools * Hard coded values (vector ranges) * not usable in applications with different bus width === 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; * Standardized packages * Counter functionality as subprogram * Synchronous / combinational circuit * Unconstrained formal parameters * Hardcoded ranges replaced by VHDL attributes * Overflow handling in case the output vector is too small === 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; * Parameterized interface via generics * Additional generic to control module behavior * if ... generate statement to avoid unnecessary hardware overhead === 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.