![]() |
![]() |
VHDL descriptions are mapped to combinatorial logic by the creation of blocks of logic. A statement or an operator in a VHDL function can represent a block of combinatorial logic or, in some cases, a latch or register.
The statements shown in the following example represent four logic blocks.
if (B < 10)
Y = A + B;
else
Y = A+ 10;
The logic blocks created by Foundation Express are custom-built for their environment. That is, if A and B are 4-bit quantities, a 4-bit adder is built. If A and B are 9-bit quantities, a 9-bit adder is built. Because Foundation Express incorporates a large set of these customized logic blocks, it can translate most VHDL statements and operators.
A design's structure influences the size and complexity of the resulting synthesized circuit. These sections help you understand the following concepts.
Foundation Express gives you significant control over the preoptimization structure, or organization of components, in your design. Whether or not your design structure is preserved after optimization depends on the options you select.
You control design structure with your ordering of assignment statements and your use of variables. Each VHDL signal assignment, process, or component instantiation implies a piece of logic. Each variable or signal implies a wire. By using these constructs, you can connect entities in any configuration.
The following two examples show two possible descriptions of an adder's carry chain. The figure following the examples illustrates the resulting design.
-- A is the addend
-- B is the augend
-- C is the carry
-- Cin is the carry in
C0 <= (A0 and B0) or
((A0 or B0) and Cin);
C1 <= (A1 and B1) or
((A1 or B1) and C0);
The following example shows a carry-lookahead chain.
-- Ps are propagate
-- Gs are generate
p0 <= a0 or b0;
g0 <= a0 and b0;
p1 <= a1 or b1;
g1 <= a1 and b1;
c0 <= g0 or (p0 and cin);
c1 <= g1 or (p1 and g0) or
(p1 and p0 and cin);
Another way to control the structure of a design is to use parentheses to define logic groupings. The following example describes a 4-input adder grouping. The figure following the example illustrates the resulting design.
Z <= (A + B) + C + D;
The following example describes a 4-input adder grouping that is structured with parentheses. The figure following the example illustrates the design.
Z <= (A + B) + (C + D);
In many circumstances, you can improve the quality of synthesized circuits by better describing your high-level knowledge of a circuit. Foundation Express cannot always derive details of a circuit architecture. Any additional architectural information you can provide to Foundation Express can result in a more efficient circuit.
Foundation Express uses the properties of arithmetic operators (such as the associative and commutative properties of addition) to rearrange an expression so that it results in an optimized implementation. You can also use arithmetic properties to control the choice of implementation for an expression. Three forms of arithmetic optimization are discussed in this section.
If your goal is to speed up your design, arithmetic optimization can minimize the delay through an expression tree by rearranging the sequence of the operations. Consider the statement in the following example.
Z <= A + B + C + D;
The parser performs each addition in order, as though parentheses were placed within the expression as follows.
Z <= ((A + B) + C) + D);
The parser constructs the expression tree shown in the following figure.
To determine the delay through an expression tree, Foundation Express considers the arrival times of each signal in the expression. If the arrival times of all the signals are the same, the length of the critical path of the expression in the previous example of a simple arithmetic expression equals three adder delays. The critical path delay can be reduced to two adder delays if you insert parentheses as follows.
Z <= (A + B) + (C + D);
The parser constructs the subexpression tree as shown in the following figure.
Suppose signals B, C, and D arrive at the same time and signal A arrives last. The expression tree that produces the minimum delay is shown in the following figure.
You can use parentheses in expressions to exercise more control over the way expression trees are constructed. Parentheses are regarded as user directives that force an expression tree to use the groupings inside the parentheses. The expression tree cannot be rearranged in a way that violates these groupings.
To illustrate the effect of parentheses on the construction of an expression tree, consider the following example.
Q <= ((A + (B + C)) + D + E) + F;
The parentheses in the expression in the above example define the following subexpressions.
1 (B + C)
2 (A + (B + C))
3 ((A + (B + C)) + D + E)
These subexpressions must be preserved in the expression tree. The default expression tree for the above example is shown in the following figure.
When Foundation Express performs arithmetic optimization, it considers how to handle the overflow from carry bits during addition. The optimized structure of an expression tree is affected by the bit-widths you declare for storing intermediate results. For example, suppose you write an expression that adds two 4-bit numbers and stores the result in a 4-bit register. If the result of the addition overflows the 4-bit output, the most significant bits are truncated. The following example shows how Foundation Express handles overflow characteristics.
t <= a + b; --a and b are 4-bit numbers
z <= t + c; --c is a 6-bit number
In the above example, three variables are added (a + b + c). A temporary variable, t, holds the intermediate result of a + b. If t is declared as a 4-bit variable, the overflow bits from the addition of a + b are truncated. The parser determines the default structure of the expression tree, which is shown in the following figure.
Now suppose the addition is performed without a temporary variable (z = a + b + c). Foundation Express determines that five bits are needed to store the intermediate result of the addition, so no overflow condition exists. The results of the final addition might be different from the first case, where a 4-bit temporary variable is declared that truncates the result of the intermediate addition. Therefore, these two expression trees do not always yield the same result. The expression tree for the second case is shown in the following figure.
Subexpressions consist of two or more variables in an expression. If the same subexpression appears in more than one equation, you might want to share these operations to reduce the area of your circuit.
You can force common subexpressions to be shared by declaring a temporary variable to store the subexpression, then use the temporary variable wherever you want to repeat the subexpression. The following example shows a group of simple additions that use the common subexpression (a + b).
temp <= a + b;
x <= temp;
y <= temp + c;
Instead of manually forcing common subexpressions to be shared, you can let Foundation Express automatically determine whether sharing common subexpressions improves your circuit. You do not need to declare a temporary variable to hold the common subexpression in this case.
In some cases, sharing common subexpressions results in more adders being built. Consider the following example, where A + B is a common subexpression.
if cond1
Y <= A + B;
else
Y <= C + D;
end;
if cond2
Z <= E + F;
else
Z <= A + B;
end;
If the common subexpression A + B is shared, three adders are needed to implement this section of code.
(A + B)
(C + D)
(E + F)
If the common subexpression is not shared, only two adders are needed: one to implement the additions A + B and C + D and one to implement the additions E + F and A + B.
Foundation Express analyzes common subexpressions during the resource sharing phase of the compile process and considers area costs and timing characteristics. To turn off the sharing of common subexpressions for the current design, use the constraint manager. The default is TRUE.
Y <= A + B + C;
Z <= D + A + B;
The parser does not recognize A + B as a common subexpression, because it parses the second equation as (D + A) + B. You can force the parser to recognize the common subexpression by rewriting the second assignment statement as follows.
Z <= A + B + D;
or
Z <= D + (A + B);
Note: You do not have to rewrite the assignment statement, because Foundation Express recognizes common subexpressions automatically.
The adder in the following example sums the 8-bit value of A (a BYTE) with the 8-bit value of TEMP. TEMP's value is either B, which is used only when it is less than 16, or C, which is a 4-bit value (a NIBBLE).Therefore, the upper four bits of TEMP are always 0. Foundation Express cannot derive this fact, because TEMP is declared with type BYTE.
You can simplify the synthesized circuit by changing the declared type of TEMP to NIBBLE (a 4-bit value). With this modification, half adders, rather than full adders, are required to implement the top four bits of the adder circuit, which figure, Function with One Adder Schematic, illustrates.
function ADD_IT_16 (A, B: BYTE; C: NIBBLE) return BYTE is
variable TEMP: BYTE;
begin
if B < 16 then
TEMP <= B;
else
TEMP <= C;
end if;
return A + TEMP;
end;
The following example shows how this change in TEMP's declaration can yield a significant savings in circuit area, which the figure following the example illustrates.
function ADD_IT_16 (A, B: BYTE; C: NIBBLE)
return BYTE is
variable TEMP: NIBBLE; -- Now only 4 bits
begin
if B < 16 then
TEMP <= NIBBLE(B); -- Cast BYTE to NIBBLE
else
TEMP <= C;
end if;
return A + TEMP; -- Single adder
end;
You can also apply design knowledge in sequential designs. Often you can make strong assertions about the value of a signal in a particular state of a finite-state machine. You can describe this information to Foundation Express. The following example shows the VHDL description of a simple state machine that uses two processes.
package STATES is
type STATE_TYPE is (SET0, HOLD0, SET1);
end STATES;
use work.STATES.all;
entity MACHINE is
port(X, CLOCK: in BIT;
CURRENT_STATE: buffer STATE_TYPE;
Z: buffer BIT);
end MACHINE;
architecture BEHAVIOR of MACHINE is
signal NEXT_STATE: STATE_TYPE;
signal PREVIOUS_Z: BIT;begin
-- Process to hold combinatorial logic.
COMBIN: process(CURRENT_STATE, X, PREVIOUS_Z)
begin
case CURRENT_STATE is
when SET0 =>
Z <= '0'; -- Set Z to '0'
NEXT_STATE <= HOLD0;
when HOLD0 =>
Z <= PREVIOUS_Z; -- Hold value of Z
if X = '0' then
NEXT_STATE <= HOLD0;
else
NEXT_STATE <= SET1;
end if;
when SET1 => -- Set Z to '1'
Z <= '1';
NEXT_STATE <= SET0;
end case;
end process COMBIN;
-- Process to hold synchronous elements (flip-flops).
SYNCH: process
begin
wait until CLOCK'event and CLOCK = '1';
CURRENT_STATE <= NEXT_STATE;
PREVIOUS_Z <= Z;
end process SYNCH;
end BEHAVIOR;
The following figure shows a schematic of a simple state machine with two processes.In the state hold0, the output Z retains its value from the previous state. To accomplish this, you insert a flip-flop to hold the PREVIOUS_Z. However, you can make some assertions about the value of Z. In state HOLD0, the value of Z is always 0. You can deduce this from the fact that the state HOLD0 is entered only from the state SET0, where Z is always assigned `0.'
The following example shows how you can change the VHDL description to use this assertion, resulting in a simpler circuit. The figure following the example illustrates the circuit.
package STATES is
type STATE_TYPE is (SET0, HOLD0, SET1);
end STATES;
use work.STATES.all;
entity MACHINE is
port(X, CLOCK: in BIT;
CURRENT_STATE: buffer STATE_TYPE;
Z: buffer BIT);
end MACHINE;
architecture BEHAVIOR of MACHINE is
signal NEXT_STATE: STATE_TYPE;
begin
-- Combinatorial logic.
COMBIN: process(CURRENT_STATE, X)
begin
case CURRENT_STATE is
when SET0 =>
Z <= '0'; -- Set Z to '0'
NEXT_STATE <= HOLD0;
when HOLD0 =>
Z <= '0'; -- Hold Z at '0'
if X = '0' then
NEXT_STATE <= HOLD0;
else
NEXT_STATE <= SET1;
end if;
when SET1 => -- Set Z to '1'
Z <= '1';
NEXT_STATE <= SET0;
end case;
end process COMBIN;
-- Process to hold synchronous elements (flip-flops)
SYNCH: process
begin
wait until CLOCK'event and CLOCK = '1';
CURRENT_STATE <= NEXT_STATE;
end process SYNCH;
end BEHAVIOR;
Constant propagation is the compile-time evaluation of expressions containing constants. Foundation Express uses constant propagation to reduce the amount of hardware required to implement operators. For example, a + operator with a constant 1 as one of its arguments causes an incrementer to be built, rather than a general adder. If both arguments of + or any other operator are constants, no hardware is constructed, because the expression's value is calculated by Foundation Express and inserted directly in the circuit.
Other operators that benefit from constant propagation include comparators and shifters. Shifting a vector by a constant amount requires no logic to implement; it requires only a reshuffling (rewiring) of bits.
The efficiency of a synthesized design depends primarily on how you describe its component structure. The optimization of individual components, especially those made from random logic, produces similar results from two very different descriptions. Therefore, concentrate the majority of your design effort on the implied component hierarchy (as discussed in the preceding sections) rather than on the logical descriptions. The Design Descriptions chapter discusses how to define a VHDL design hierarchy.
Foundation Express supports many shorthand VHDL expressions. There is no benefit to using a verbose syntax when a shorter description is adequate. The following example shows four equivalent groups of statements.
signal A, B, C: BIT_VECTOR(3 downto 0);
. . .
C <= A and B;
------------------------------------
C(3 downto 0) <= A(3 downto 0) and B(3 downto 0);
------------------------------------
C(3) <= A(3) and B(3);
C(2) <= A(2) and B(2);
C(1) <= A(1) and B(1);
C(0) <= A(0) and B(0);
------------------------------------
for I in 3 downto 0 loop
C(I) <= A(I) and B(I);
end loop;