Click here to return to the HDL info page. | (last edit: 1. october 2012) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

## VHDL Math Tricks## IntroductionVHDL is a strongly typed language. Success in VHDL depends on understanding the types and overloaded operators provided by the standard and numeric packages.These pages gives a short tutorial on: **VHDL Types & Packages****Strong Typing Rules****Converting between Std_logic_vector, unsigned & signed****Ambiguous Expressions****Arithmetic Coding Considerations****Math Tricks**
## Common VHDL Types
## Packages for Numeric Operations- numeric_std -- IEEE standard
- Defines types signed, unsigned
- Defines arithmetic, comparison, and logic operators for these types
- std_logic_arith -- Synopsys, a defacto industry standard
- Defines types signed, unsigned
- Defines arithmetic, and comparison operators for these types
- std_logic_unsigned -- Synopsys, a defacto industry standard
- Defines arithmetic and comparison operators for std_logic_vector
## Using IEEE Numeric_Std
## Using Synopsys Std_Logic_Arith
## Unsigned and Signed Types- Used to represent numeric values:
- Usage similar to std_logic_vector:
- Type definitions identical to std_logic_vector
- How are the types distinguished from each other?
- How do these generate unsigned and signed arithmetic?
- For each operator, a unique function is called
- This feature is called Operator Overloading:
- An operator symbol or subprogram name can be used more than once as long as calls are differentiable.
## Overloading Basics- Simplified view of overloading provided by VHDL packages
- For a detailed view of VHDL's overloading, get the VHDL Types and Operators Quick Reference card at: http://www.SynthWorks.com/papers
## Overloading Examples
## Strong Typing Implications- Size and type of target (left) = size and type of expression (right)
- Each operation returns a result that has a specific size based on rules of the operation. The table below summarizes these rules.
## Strong Typing Implications
## Type Conversions- VHDL is dependent on overloaded operators and conversions
- What conversion functions are needed?
- Signed & Unsigned (elements) <=> Std_Logic
- Signed & Unsigned <=> Std_Logic_Vector
- Signed & Unsigned <=> Integer
- Std_Logic_vector <=> Integer
- VHDL Built-In Conversions
- Automatic Type Conversion
- Conversion by Type Casting
- Conversion functions located in Numeric_Std
## Automatic Type Conversion: Unsigned, Signed <=> Std_Logic- Two types convert automatically when both are subtypes of the same type
- Converting between std_ulogic and std_logic is automatic
- Elements of Signed, Unsigned, and std_logic_vector = std_logic
- Elements of these types convert automatically to std_ulogic or std_logic
## Type Casting: Unsigned, Signed <=> Std_Logic_Vector- Use type casting to convert equal sized arrays when:
- Elements have a common base type (i.e. std_logic)
- Indices have a common base type (i.e. Integer)
- Unsigned, Signed <=> Std_Logic_Vector
- Motivation, Unsigned - Unsigned = Signed?
## Numeric_Std Conversions: Unsigned, Signed <=> Integer- Converting to and from integer requires a conversion function.
- Unsigned, Signed => Integer
- Integer => Unsigned, Signed
- Motivation (indexing an array of an array):
## Std_Logic_Arith Conversions: Unsigned, Signed <=> Integer- Converting to and from integer requires a conversion function.
- Unsigned, Signed => Integer
- Integer => Unsigned, Signed
- Motivation (indexing an array of an array):
## Std_Logic_Vector <=> IntegerConverting between std_logic_vector and integer is a two step process: Unsigned_int <= to_integer( unsigned( A_slv )); Signed_int <= to_integer( signed( B_slv )); .Numeric_Std: Std_Logic_Vector => Integer . Numeric_Std: Integer => Std_Logic_Vector C_slv <= std_logic_vector( to_unsigned( Unsigned_int, 8 )); D_slv <= std_logic_vector( to_signed( Signed_int, 8 )); signal A_slv, C_slv : std_logic_vector (7 downto 0) ; signal Unsigned_int : integer range 0 to 255 ; signal B_slv, D_slv : std_logic_vector( 7 downto 0) ; signal Signed_int : integer range -128 to 127;## Ambiguous Expressions. An expression / statement is ambiguous if more than one operator symbol or subprogram can match its arguments. . Std_Logic_Arith defines the following two functions: function "+" (L, R: SIGNED) return SIGNED; function "+" (L: SIGNED; R: UNSIGNED) return SIGNED; . The following expression is ambiguous and an error: Z_sv <= A_sv + "1010" ; Is "1010" Signed or Unsigned "1010" = -6 or 10 . Issues typically only arise when using literals. . How do we solve this problem?## Std_Logic_Arith: Ambiguous Expressions. VHDL type qualifier (type_name') is a mechanism that specifies the type of an operand or return value of a subprogram (or operator). Z_sv <= A_sv + signed'("1010") ; -- Z_sv <= A_sv + signed("1010") ; .Leaving out the ' is an error: Effects all numeric operators in std_logic_arith . Without ', it is type casting. Use type casting for: Z_sv <= A_sv + signed(B_slv) ; . Recommended solution, use integer: Z_sv <= A_sv - 6 ;## Addition OperatorsAddition Operators: + - . Arrays with Arrays: Add_uv <= A_uv + B_uv ; Sub_uv <= C_uv - D_uv ;## Use Integers with Care. Synthesis tools create a 32-bit wide resources for unconstrained integers signal Y_int, A_int, B_int : integer ; . . . Y_int <= A_int + B_int ; . Do not use unconstrained integers for synthesis . Specify a range with integers: signal A_int, B_int: integer range -8 to 7; signal Y_int : integer range -16 to 15 ; . . . Y_int <= A_int + B_int ; . Recommendation: Use integers only as constants or literals Y_uv <= A_uv + 17 ;## Comparison OperatorsComparison Operators: = /= > >= < <= . Comparison operators return type boolean . Std_Logic is our basic type for design. . How do we convert from boolean to std_logic? . AGeB <= '1' when (A_uv >= B_uv) else '0'; AEq15 <= '1' when (A_uv = "1111" ) else '0'; Arrays with Arrays: . Arrays with Integers (special part of arithmetic packages): DEq15 <= '1' when (D_uv = 15 ) else '0'; Input arrays are extended to be the same lengthResult = Boolean## Multiplication and DivisionMultiplication Operators: * / mod rem . Array Multiplication signal A_uv, B_uv : unsigned( 7 downto 0) ; signal Z_uv : unsigned(15 downto 0) ; . . . Z_uv <= A_uv * B_uv;## Adder with Carry Out SynthWorksUnsigned Algorithm: Unsigned Code: ------------------- '0', A(3:0) + '0', B(3:0) ------------------- CarryOut, Result(3:0) Y5 <= ('0' & A) + ('0' & B); Y <= Y5(3 downto 0) ; Co <= Y5(4) ; signal A, B, Y : unsigned(3 downto 0); signal Y5 : unsigned(4 downto 0) ; signal Co : std_logic ;## Adder with Carry Insignal A, B, Y : unsigned(3 downto 0); signal Y5 : unsigned(4 downto 0) ; signal CarryIn : std_logic ; Desired Result: Algorithm A(3:0) + B(3:0) + CarryIn ------------------- A(3:0), '1' + B(3:0), CarryIn ------------------- Result(4:1), Unused Example: Carry = 0 Carry = 1 -------- 0010, 1 0001, 0 -------- 0011, 1 -------- 0010, 1 0001, 1 -------- 0100, 0 Result Code: Y5 <= (A & '1') + (B & CarryIn); Y <= Y5(4 downto 1) ;## ALU Functions. ALU1: . Three implementations OpSel Function 00 A + B 01 C + D 10 E + F 11 G + H . Tool Driven Resource Sharing . Code Driven Resource Sharing . Defeating Resource Sharing . Since OpSel can select only one addition at a time, the operators are mutually exclusive.## Possible Solutions to ALU 1As Specified: Optimal results: A A CB E G D Z OpSel i0 i1 o sel i2 i3 i0 i1 o sel i2 i3 Z E F B D G F OpSel H H OpSel . This transformation of operators is called Resource Sharing i0 i1 O sel i2 i3## ALU 1: Tool DrivenToolDrvnProc : process (OpSel,A,B,C,D,E,F,G,H) begin case OpSel is when "00" => Z <= A + B ; when "01" => Z <= C + D ; when "10" => Z <= E + F ; when "11" => Z <= G + H ; when others => Z <= (others => 'X') ; end case ; end process ; -- ToolDrvnProc . Important: to ensure resource sharing, operators must be coded in the same process, and same code (case or if) structure. . Any potential issues with this?## ALU 1: Code DrivenX <= Mux4(OpSel, A, C, E, G) ; Y <= Mux4(OpSel, B, D, F, H) ; Z <= X + Y ; . Best Synthesis, use for: . Sharing arithmetic operators . Sharing comparison operators . Sharing complex function calls . Resource sharing often is not possible when using third party arithmetic logic. Lewis Copyright © 2003 SynthWorks Design Inc. All Rights Reserved. MAPLD 2003 P29 SynthWorks## ALU 1: Defeating Resource Sharing *. Bad Code will defeat Resource Sharing. BadAluProc: process (OpSel, A, B, C, D, E, F, G, H) begin if (OpSel = "00") then Z <= A + B; end if; if (OpSel = "01") then Z <= C + D; end if; if (OpSel = "10") then Z <= E + F; end if; if (OpSel = "11") then Z <= G + H; end if; end process ; Uses "end if", rather than "elsif" . * Not Recommended, synthesis tool may create a separate resource for each adder.## Defeating Resource Sharing. When does this happen? case StateReg is when S1 => if (in1 = '1') then Z <= A + B ; . . . end if ; when S2 => if (in2 = '1') then Z <= C + D ; . . . end if ; . . . when Sn => . . . when others => . Separate statemachines and resources Statemach : process(...) begin -- generate function -- select logic (OpSel) end process ; Resources : process(...) begin -- code: -- arithmetic operators -- comparison operators end process ; |