====== Advanced Synthesis ====== ===== Parametrization ===== {{:courses:system_design:synthesis:folie291_constantandgeneric.svg?nolink&350|Constant and Generic}} * Constant C identical in all referencing units * Generic G different but constant within each entity * Input signal S set/changed in operation (different operation modes) === Notes === Once you have finished a design, you hope that you will be able to use at least parts of the VHDL code in other designs as well. (Re-Use) This is certainly possible as long as you can adopt the VHDL code via copy/paste. But if the function has to be changed slightly, the designer will have to adapt the VHDL code. To make this adaption easier and less error prone, VHDL provides several ways of parameterizing a design or a module, that means the behavior description depends on some parameters. The value of these parameters can then be set differently in different implementations or even on the fly during operation. The intention is that by changing the parameter the behavior will change accordingly. ===== Parameterization via Constants ===== package T_PACK is constant MAX_VALUE:integer := 15; end T_PACK; use WORK.T_PACK.all; entity COUNTER_C is port(..., COUNT : buffer integer range 0 to MAX_VALUE); end COUNTER_C; architecture RTL of COUNTER_C is begin process(CLK) begin if CLK’event and CLK=’1’ then if RESET=’1’ then COUNT <= 0; elsif ENABLE=’1’ then if COUNT < MAX_VALUE then COUNT <= COUNT + 1; else COUNT <= 0; end if; end if; end if; end process; end RTL; * Constants are fixed for the complete design * Instantiations of COUNTER_C produce exactly the same counter * Parametric signals in port map === Notes === One way to parameterize a design is to use constants. The example shows a counter with reset and enable. The counter is free wheeling when enabled. The maximum value (MAX_VALUE) is set by a constant which is defined and given a value in the package T_PACK. Wherever COUNTER_C is built in (by use of a component declaration and component instantiation) the counter range is fixed (from 0 to the value specified in the package). ===== Parameterization via Generics(1) ===== entity COUNTER_G is generic (MAX_VALUE: integer :=15); port(... -- default value COUNT : buffer integer range 0 to MAX_VALUE); end COUNTER_G; architecture RTL of COUNTER_G is begin process(CLK) begin if CLK’event and CLK=’1’ then if RESET=’1’ then COUNT <= 0; elsif ENABLE=’1’ then if COUNT < MAX_VALUE then COUNT <= COUNT + 1; else COUNT <= 0 ; end if; end if; end if; end process; end RTL; * Generics are defined in the entity declaration * Treated as constants in the architecture * Default values * Parametric signals in port map === Notes === If you want to instantiate counters with different counter ranges in one design you will have to switch to generics. Generics are defined like the ports in the entity definition and receive their values during the step of component instantiation. Therefore, in addition to the port map, a generic map is required to provide these values. Generics may be given a default value in the generic clause which will be used if the generic is not explicitly assigned a value. ===== Parameterization via Generics(2) ===== entity TWO_COUNTERS IS port(...); end entity; architecture RTL of TWO_COUNTERS is component COUNTER_G generic (MAX_VALUE:integer := 15); port(...); end component; begin COUNTER1 : COUNTER_G port map (...); -- MAX_VALUE with -- default value COUNTER2 : COUNTER_G generic map (MAX_VALUE => 31) port map (...); ... end RTL; * Different values for different instantiations * Instantiation with default value * Instantiation with generic map Every instantiation needs a label Only generics of type integer are supported by synthesis tools === Notes === The component declaration is as usual except that you must not forget the generic clause. But how does the instantiation of COUNTER_G work? If default values were defined for the generics, the component instantiation does not need a generic map (COUNTER1). The most useful feature is that entities using generics can be instantiated with different values for the generics within the same module. The default value can be overwritten by setting the generic to an explicit value in the generic map of the component instantiation (COUNTER2). Only integer type generics are synthesizable! ===== GENERATE Statement ===== entity GENERATE_COUNTER IS port(...); end entity; architecture RTL of GENERATE_COUNTER is component COUNTER_G generic (MAX_VALUE:integer := 15); port(...); end component; begin GEN: for K in 2 to 5 generate COUNTER : COUNTER_G generic map (MAX_VALUE => 2**K-1) port map (...); end generate; . . . end RTL; * ’for generate’ needs a label * "loop" for concurrent statements (component instantiations, signal assignments) * Several instantiations of the same component * Different values for generics * Loop variable implicitly declared === Notes === When a component has to be instantiated several times, the way described above would be exhaustive. The generate statement provides a shortcut to this problem. Within a ’for...generate...’ loop concurrent statements can be iterated. This applies not only to repeated component instantiations but also to concurrent signal assignments. The loop variable is declared implicitly, again, and can only be read, e.g. as generic value.Value assignments will lead to an error. ===== Conditional GENERATE Statement ===== entity GENERATE_COUNTER IS port(...); end entity; architecture RTL of GENERATE_COUNTER is component COUNTER_G generic (MAX_VALUE:integer := 15); port(...); end component; begin GEN: for K in 1 to 8 generate COND1: if K<=5 generate COUNTER : COUNTER_G generic map (MAX_VALUE => 2**K-1) port map (...); end generate; COND2: if K>5 and FLAG generate MAX : COUNTER_G generic map (MAX_VALUE => 31) port map (...); end generate; end generate; . . . end RTL; * If condition is true then generate ... * No elsif / else paths * Each generate needs a label === Notes === To make the generate statement even more powerful you can use an if-generate statement which allows to execute the concurrent statements subject to the value of a boolean expression. In contrast to conditional signal assignments or the sequential if statement, elsif and else paths are not permitted. In the example, 8 counters are instantiated. For K=1...5 the maximum counter value is calculated according to the formula 2^K-1, i.e. 1, 3, 7, 15, 31. For higher index values the maximum counter values remains 31. It is also possible to evaluate constants or generics of the own entity in the expression of the if condition. Constants and generics are very profitable when configuring a module before synthesizing. ===== Parameterization via Signals ===== entity COUNTER_S is port(MAX_VALUE : in integer range 0 to 1023 . . .); end COUNTER_S; architecture RTL of COUNTER_S is begin process(CLK) begin if CLK’event and CLK=’1’ then if RESET=’1’ then COUNT <= 0; elsif ENABLE=’1’ then if COUNT < MAX_VALUE then COUNT <= COUNT+1; else COUNT <= 0 ; end if; end if; end if; end process; end RTL; * Set different modes in operation (cf. MAX_VALUE) * No parametric signals in port map === Notes === If it is necessary to switch parameters during operation, the only solution is to feed these parameters via signals into the module. -> additonally input port(s) needed The counter range in the example above can be set to values between 1 and 1023 during operation. For that reason, an overhead of hardware is generated to provide this flexibility in functionality. The signal MAX_VALUE must be stable when the active clock edge occurs. If this cannot be guaranteed, storing elements will have to be created, which hold the current value of MAX_VALUE and are updated at certain times, only.