PART 6
Utilities_for_high_level_descriptions
declarations
enumeration
scalars
physical
arrays
files, simple IO
composites
subtypes
aliasing
arrays
types
signals
- In General:
- Language aspects will be discussed
- Examples will clarify language aspects
- Hardware related examples are used
- Attributes are important in modeling
- Utilities.types.scalars
- TYPE qit IS ('0', '1', 'Z', 'X');
- New type for multi-value logic system
- qit is type identifier
- '0', '1', 'Z', 'X' are enumeration elements
- This is enumeration type definition
- '0' is default initial values
- Let's assume qit goes in basic_utilities
- Utilities.types.scalars
- Can develop logic gates using qit values system
- NOT and NAND tables in qit
Utilities.types.scalars
- USE WORK.basic_utilities.ALL;
- ENTITY inv_q IS
- GENERIC (tplh : TIME := 5 NS; tphl : TIME := 3 NS);
- PORT (i1 : IN qit; o1 : OUT qit);
- END inv_q;
- --
- ARCHITECTURE double_delay OF inv_q IS
- BEGIN
- o1 <= '1' AFTER tplh WHEN i1 = '0' ELSE
- '0' AFTER tphl WHEN i1 = '1' OR i1 = 'Z' ELSE
- 'X' AFTER tplh;
- END double_delay;
- USE WORK.basic_utilities.ALL;
- ENTITY nand2_q IS
- GENERIC (tplh : TIME := 7 NS; tphl : TIME := 5 NS);
- PORT (i1, i2 : IN qit; o1 : OUT qit);
- END nand2_q;
- --
- ARCHITECTURE double_delay OF nand2_q IS
- BEGIN
- o1 <= '1' AFTER tplh WHEN i1 = '0' OR i2 = '0' ELSE
- '0' AFTER tphl WHEN (i1 = '1' AND i2 = '1') OR
- (i1 = '1' AND i2 = 'Z') OR
- (i1 = 'Z' AND i2 = '1') OR
- (i1 = 'Z' AND i2 = 'Z') ELSE
- 'X' AFTER tplh;
- END double_delay;
- INV and NAND2 gates using qit
- Use conditional signal assignments
- Double_delay values are used
- Utilities.types.scalars
- Syntax for the new constructs
- Utilities.types.scalars
- USE WORK.basic_utilities.ALL; -- FROM PACKAGE USE : qit
- ENTITY inv_rc IS
- GENERIC (c_load : REAL := 0.066E-12); -- Farads
- PORT (i1 : IN qit; o1 : OUT qit);
- CONSTANT rpu : REAL := 25000.0; -- Ohms
- CONSTANT rpd : REAL := 15000.0; -- Ohms
- END inv_rc;
- --
- ARCHITECTURE double_delay OF inv_rc IS
- CONSTANT tplh : TIME := INTEGER ( rpu * c_load * 1.0E15) * 3 FS;
- CONSTANT tphl : TIME := INTEGER ( rpd * c_load * 1.0E15) * 3 FS;
- BEGIN
- o1 <= '1' AFTER tplh WHEN i1 = '0' ELSE
- '0' AFTER tphl WHEN i1 = '1' OR i1 = 'Z' ELSE 'X' AFTER tplh;
- END double_delay;
- Other types can be used for signals, constants and variables
- Example shows use of REAL
- Time is calculated from R and C values
- Utilities.types.scalars
- CONSTANT tplh : TIME := INTEGER (rpu* c_load* 1.0E15)*3 FS;
- REAL rpu multiplied by REAL c_load
- 1.0E15 provides FS scaling
- INTEGER(...) converts REAL to INTEGER
- INTEGER and REAL are closely-related types
- 3*RC is for the exponential delay
- Utilities.types.scalars
- TYPE capacitance IS RANGE 0 TO 1E16
- UNITS
- ffr; -- Femto Farads (base unit)
- pfr = 1000 ffr;
- nfr = 1000 pfr;
- ufr = 1000 nfr;
- mfr = 1000 ufr;
- far = 1000 mfr;
- kfr = 1000 far;
- END UNITS;
- TYPE resistance IS RANGE 0 TO 1E16
- UNITS
- l_o; -- Milli-Ohms (base unit)
- ohms = 1000 l_o;
- k_o = 1000 ohms;
- m_o = 1000 k_o;
- g_o = 1000 m_o;
- END UNITS;
- Use physical types for better correspondence
- Capacitance for C values
- Resistance for R values
- Put both type definitions in basic_utilities
- Utilities.types.scalars
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE : qit, resistance, capacitance
- ENTITY inv_rc IS
- GENERIC (c_load : capacitance := 66 ffr);
- PORT (i1 : IN qit; o1 : OUT qit);
- CONSTANT rpu : resistance := 25000 ohms;
- CONSTANT rpd : resistance := 15000 ohms;
- END inv_rc;
- --
- ARCHITECTURE double_delay OF inv_rc IS
- CONSTANT tplh : TIME := (rpu / 1 l_o) * (c_load / 1 ffr) * 3 FS / 1000;
- CONSTANT tphl : TIME := (rpd / 1 l_o) * (c_load / 1 ffr) * 3 FS / 1000;
- BEGIN
- o1 <= '1' AFTER tplh WHEN i1 = '0' ELSE
- '0' AFTER tphl WHEN i1 = '1' OR i1 = 'Z' ELSE
- 'X' AFTER tplh;
- END double_delay;
- Use physical R and C types
- Equation converts values to their base units
- l_o * ffr requires 10 -18 adjustment
- Utilities.type.arrays
- TYPE qit_nibble IS ARRAY ( 3 DOWNTO 0 ) OF qit;
- TYPE qit_byte IS ARRAY ( 7 DOWNTO 0 ) OF qit;
- TYPE qit_word IS ARRAY ( 15 DOWNTO 0 ) OF qit;
- TYPE qit_4by8 IS ARRAY ( 3 DOWNTO 0, 0 TO 7 ) OF qit;
- TYPE qit_nibble_by_8 IS ARRAY ( 0 TO 7 ) OF qit_nibble;
- SIGNAL sq8 : qit_byte := "ZZZZZZZZ";
- sq8 <= "Z101000Z";
- Various array types can be based on qit
- Type qit_4by8 is two dimensional
- Type qit_nibble_by_8 is one dimensional of qit_nibble
- qit_4by8 and qit_nibble_by_8 specify different indexings
- String of enumeration elements forms an array
- The sq8 signal is initialized to "ZZZZZZZZ"
- Signal value can consist of a string of enumaration elements
- Utilities.type.arrays
- Syntax of array type declaration
- Utilities.type.arrays
- TYPE qit_nibble IS ARRAY ( 3 DOWNTO 0 ) OF qit;
- TYPE qit_byte IS ARRAY ( 7 DOWNTO 0 ) OF qit;
- TYPE qit_word IS ARRAY ( 15 DOWNTO 0 ) OF qit;
- TYPE qit_4by8 IS ARRAY ( 3 DOWNTO 0, 0 TO 7 ) OF qit;
- TYPE qit_nibble_by_8 IS ARRAY ( 0 TO 7 ) OF qit_nibble;
- SIGNAL sq1 : qit;
- SIGNAL sq4 : qit_nibble;
- SIGNAL sq8 : qit_byte;
- SIGNAL sq16 : qit_word;
- SIGNAL sq_4_8 : qit_4by8;
- SIGNAL sq_nibble_8 : qit_nibble_by_8;
- sq8 <= sq16 (11 DOWNTO 4); -- middle 8 bit slice of sq16 to sq8
- sq16 (15 DOWNTO 12) <= sq4; -- sq4 into left 4 bit slice of sq16
- sq1 <= sq_4_8 (0, 7); -- lower right bit of sq_4_8 to sq1
- sq4 <= sq_nibble_8 (2); -- third nibble of sq_nibble_8 into sq4
- sq8 <= sq8 (0) & sq8 (7 DOWNTO 1); -- right rotate sq8
- sq4 <= sq8 (2) & sq8 (3) & sq8 (4) & sq8 (5); -- reversing sq8 into sq4
- Signal declarations based on defined types
- Examples of signal assignments
- Concatenation operator can be used for shift and rotate
- Direction of indexing must be as declared
- Utilities.type.arrays
- TYPE qit_nibble IS ARRAY ( 3 DOWNTO 0 ) OF qit;
- TYPE qit_byte IS ARRAY ( 7 DOWNTO 0 ) OF qit;
- SIGNAL sq4 : qit_nibble;
- SIGNAL sq8 : qit_byte;
- Use concatenation if reversing is required
- Utilities.types.arrays
- TYPE qit_4by8 IS ARRAY ( 3 DOWNTO 0, 0 TO 7 ) OF qit;
- SIGNAL sq_4_8 : qit_4by8 :=
- (
- ( '0', '0', '1', '1', 'Z', 'Z', 'X', 'X' ), -- sq_4_8 (3, 0 TO 7)
- ( 'X', 'X', '0', '0', '1', '1', 'Z', 'Z' ), -- sq_4_8 (2, 0 TO 7)
- ( 'Z', 'Z', 'X', 'X', '0', '0', '1', '1' ), -- sq_4_8 (1, 0 TO 7)
- ( '1', '1', 'Z', 'Z', 'X', 'X', '0', '0' ) -- sq_4_8 (0, 0 TO 7)
- );
- Use nested parenthesis for multidimensional arrays
- Deepest set of parenthesis corresponds to right most index
- Example shows initialization of sq_4_8
- Type of signal is two dimensional qit_4by8
- Utilities.types.indexing
- TYPE qit_2d IS ARRAY (qit, qit) OF qit;
- Can use enumaration types for indexing
- If qc is a signal of type qit_char,
- TYPE qit_char IS ARRAY (CHARACTER) OF qit;
- Then, qc('A') indexes a qit value in the qc array
- Use qit for indexing
- Upper left most element is indexed by ('0','0')
- Put qit_2d in basic_utilities
- Utilities.types.indexing
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE: qit, qit_2d
- ENTITY nand2_q IS
- GENERIC (tplh : TIME := 7 NS; tphl : TIME := 5 NS);
- PORT (i1, i2 : IN qit; o1 : OUT qit);
- END nand2_q;
- --
- ARCHITECTURE average_delay OF nand2_q IS
- CONSTANT qit_nand2_table : qit_2d := (
- -- '0' '1' 'Z' 'X'
- -- ---------------------------------------------
- ('1', '1', '1', '1'), -- '0'
- ('1', '0', '0', 'X'), -- '1'
- ('1', '0', '0', 'X'), -- 'Z'
- ('1', 'X', 'X', 'X')); --'X'
- BEGIN
- o1 <= qit_nand2_table (i1, i2) AFTER (tplh + tphl) / 2;
- END average_delay;
- Example shows NAND2 using qit_2d
- Constant values are set according to NAND table
- Utilities.arrays.unconstrained
- TYPE BIT_VECTOR IS ARRAY (NATURAL RANGE <>) OF BIT;
- TYPE integer_vector IS ARRAY (NATURAL RANGE <>) of INTEGER;
- NATURAL is defined in STD 0 TO 2147483047
- BIT_VECTOR is defined in STD
- Can index BIT_VECTOR with any NATURAL range
- We define unconstrained integer_vector
- Utilities.arrays.unconstrained
- Syntax details of unconstrained array declarations
- Utilities.arrays.unconstrained
- PROCEDURE apply_data (
- SIGNAL target : OUT BIT_VECTOR;
- CONSTANT values : IN integer_vector; CONSTANT period : IN TIME)
- IS
- VARIABLE buf : BIT_VECTOR (target'RANGE);
- BEGIN
- FOR i IN values'RANGE LOOP
- int2bin (values(i), buf);
- target <= TRANSPORT buf AFTER i * period;
- END LOOP;
- END apply_data;
- Example shows use of unconstrained:
- target : BIT_VECTOR
- values : integer_vector
- Use 'RANGE to look up passed range
- Range will be determined when procedure is called
- Utilities.arrays.unconstrained
ENTITY n_bit_comparator IS
PORT (a, b : IN BIT_VECTOR; gt, eq, lt : IN BIT;
a_gt_b, a_eq_b, a_lt_b : OUT BIT);
END n_bit_comparator;
--
ARCHITECTURE structural OF n_bit_comparator IS
COMPONENT comp1
PORT (a, b, gt, eq, lt : IN BIT; a_gt_b, a_eq_b, a_lt_b : OUT BIT);
END COMPONENT;
FOR ALL : comp1 USE ENTITY WORK.bit_comparator (functional);
CONSTANT n : INTEGER := a'LENGTH;
SIGNAL im : BIT_VECTOR ( 0 TO (n-1)*3-1);
BEGIN
c_all: FOR i IN 0 TO n-1 GENERATE
l: IF i = 0 GENERATE
least: comp1 PORT MAP (a(i), b(i), gt, eq, lt, im(0), im(1), im(2) );
END GENERATE;
m: IF i = n-1 GENERATE
most: comp1 PORT MAP
(a(i), b(i), im(i*3-3), im(i*3-2), im(i*3-1), a_gt_b, a_eq_b, a_lt_b);
END GENERATE;
r: IF i > 0 AND i < n-1 GENERATE
rest: comp1 PORT MAP
(a(i), b(i), im(i*3-3), im(i*3-2), im(i*3-1), im(i*3+0), im(i*3+1), im(i*3+2) );
END GENERATE;
END GENERATE;
END structural;
- A new unconstrained comparator is shown
- Size of input vectors are not specified
- Comparator length is a'LENGTH
- Size will be determined when instantiated
- Utilities.arrays.unconstrained
- ENTITY n_bit_comparator_test_bench IS
- END n_bit_comparator_test_bench ;
- --
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE : apply_data which uses integer_vector
- ARCHITECTURE procedural OF n_bit_comparator_test_bench IS
- COMPONENT comp_n PORT (a, b : IN bit_vector;
- gt, eq, lt : IN BIT;
- a_gt_b, a_eq_b, a_lt_b : OUT BIT);
- END COMPONENT;
- FOR a1 : comp_n USE ENTITY WORK.n_bit_comparator(structural);
- SIGNAL a, b : BIT_VECTOR (5 DOWNTO 0);
- SIGNAL eql, lss, gtr : BIT;
- SIGNAL vdd : BIT := '1';
- SIGNAL gnd : BIT := '0';
- BEGIN
- a1: comp_n PORT MAP (a, b, gnd, vdd, gnd, gtr, eql, lss);
- apply_data (a, 00&15&57&17, 500 NS);
- apply_data (b, 00&43&14&45&11&21&44&11, 500 NS);
- END procedural;
- Testbench applies data to comparator
- SIGNAL a determines size of comparator
- SIGNAL a determines target size of apply_data
- SIGNAL b determines target size of apply_data
- Concatenated integers form integer_vector
- Utilities.types.IO
- File type declaration:
- TYPE logic_data IS FILE OF CHARACTER;
- File declaration:
- FILE input_logic_value_file : logic_data IS IN "input.dat";
- Usage:
- READ (input_logic_values_file, x_char);
- Declare a file type indicating type of data
- Declare a file indicating type, mode, logical_name
- Use READ, WRITE, ENDFILE on a declared file
- Utilities.types.IO
- -- File Type logic_data is Visible
- PROCEDURE assign_bits (
- SIGNAL target : OUT BIT; file_name : IN STRING; period : IN TIME)
- IS
- VARIABLE char : CHARACTER;
- VARIABLE current : TIME := 0 NS;
- FILE input_value_file : logic_data IS IN file_name;
- BEGIN
- WHILE NOT ENDFILE (input_value_file) LOOP
- READ (input_value_file, char);
- IF char = '0' OR char = '1' THEN
- current := current + period;
- IF char = '0' THEN
- target <= TRANSPORT '0' AFTER current;
- ELSIF char = '1' THEN
- target <= TRANSPORT '1' AFTER current;
- END IF;
- END IF;
- END LOOP;
- END assign_bits;
- Example shows use of file for data input
- Read character, find binary values, schedule to target
- Using assign_bits in a testbench can be done as:
- assign_bits (a_signal, "afile.bit", 1500NS)
- Utilities.overloading
- VHDL allows Overloading subprograms
- Overloading : Operand types determine exact function
- Use overloading to redefine operators
- Use overloading for various logic values systems
- Use overloading with user defined subprograms
- Utilities.overloading
- Use qit AND, OR, NOT table to overload operators
- Utilities.overloading
- -- Type and subprogram declarations:
- TYPE qit IS ('0', '1', 'Z', 'X');
- TYPE qit_2d IS ARRAY (qit, qit) OF qit;
- TYPE qit_1d IS ARRAY (qit) OF qit;
- --
- FUNCTION "AND" (a, b : qit) RETURN qit;
- FUNCTION "OR" (a, b : qit) RETURN qit;
- FUNCTION "NOT" (a : qit) RETURN qit;
- -- Subprogram body
- FUNCTION "OR" (a, b : qit) RETURN qit IS
- CONSTANT qit_or_table : qit_2d := (
- ('0','1','1','X'),
- ('1','1','1','1'),
- ('1','1','1','1'),
- ('X','1','1','X'));
- BEGIN
- RETURN qit_or_table (a, b);
- END "OR";
- --
- FUNCTION "NOT" (a : qit) RETURN qit IS
- CONSTANT qit_not_table : qit_1d := ('1','0','0','X');
- BEGIN
- RETURN qit_not_table (a);
- END "NOT";
- New AND is called if called with qit operands
- Overload "OR" similarly
- Add to basic_utilities
- Utilities.overloading.example
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE: qit, "NOT"
- ENTITY inv_q IS
- GENERIC (tplh : TIME := 5 NS; tphl : TIME := 3 NS);
- PORT (i1 : IN qit; o1 ; OUT qit);
- END inv_q;
- --
- ARCHITECTURE average_delay OF inv_q IS
- BEGIN
- o1 <= NOT i1 AFTER (tplh + tphl) / 2;
- END average_delay;
- ------------------------------------------------------------
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE: qit, "AND"
- ENTITY nand2_q IS
- GENERIC (tplh : TIME := 7 NS; tphl : TIME := 5 NS);
- PORT (i1, i2 : IN qit; o1 : OUT qit);
- END nand2_q;
- --
- ARCHITECTURE average_delay OF nand2_q IS
- BEGIN
- o1 <= NOT ( i1 AND i2 ) AFTER (tplh + tphl) / 2;
- END average_delay;
- New gates based of qit logic values system
- New gates use overloaded operators
- Utilities.overloading
- -- Subprogram declaration:
- FUNCTION "*" (a : resistance; b : capacitance) RETURN TIME;
- -- Subprogram body
- FUNCTION "*" (a : resistance; b : capacitance) RETURN TIME IS
- BEGIN
- RETURN ( ( a / 1 l_o) * ( b / 1 ffr ) * 1 FS ) / 1000;
- END "*";
- Overload * to calculate RC time
- Turn resistance to its base unit
- Turn capacitance to its base unit
- FS/1000 compensates for l_o * ffr
- Utilities.overloading.example
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE: qit, capacitance, resistance, "*"
- ENTITY inv_rc IS
- GENERIC (c_load : capacitance := 66 ffr);
- PORT (i1 : IN qit; o1 : OUT qit);
- CONSTANT rpu : resistance := 25 k_o;
- CONSTANT rpd : resistance := 15 k_o;
- END inv_rc;
- --
- USE WORK.basic_utilities.ALL;
- ARCHITECTURE double_delay OF inv_rc IS
- CONSTANT tplh : TIME := rpu * c_load * 3;
- CONSTANT tphl : TIME := rpd * c_load * 3;
- BEGIN
- o1 <= '1' AFTER tplh WHEN i1 = '0' ELSE
- '0' AFTER tphl WHEN i1 = '1' OR i1 = 'Z' ELSE
- 'X' AFTER tplh;
- END double_delay;
- New "*" simplifies calculation of tplh
- Must keep the same order
- Utilities.overloading.example
- -- Type and subprogram declaration:
- TYPE qit IS ('0', '1', 'Z', 'X');
- TYPE logic_data IS FILE OF CHARACTER;
- PROCEDURE assign_bits ( SIGNAL target : OUT qit;
- file_name : IN STRING; period : IN TME);
- -- Subprogram body
- PROCEDURE assign_bits (
- SIGNAL target : OUT qit; file_name : IN STRING; period : IN TIME)
- IS
- VARIABLE char : CHARACTER;
- VARIABLE current : TIME := 0 NS;
- FILE input_value_file : logic_data IS IN file_name;
- BEGIN
- WHILE NOT ENDFILE (input_value_file) LOOP
- READ (input_value_file, char);
- current := current + period;
- CASE char IS
- WHEN '0' => target <= TRANSPORT '0' AFTER current;
- WHEN '1' => target <= TRANSPORT '1' AFTER current;
- WHEN 'Z' | 'z' => target <= TRANSPORT 'Z' AFTER current;
- WHEN 'X' | 'x' => target <= TRANSPORT 'X' AFTER current;
- WHEN OTHERS => current := current - period;
- END CASE;
- END LOOP;
- END assign_bits;
- Can overload any user defined function
- New assign_bits assigns qits
- A case statement converts characters to qit
- Utilities.overloading.example
- USE WORK.basic_utilities.ALL;
- -- FROM PACKAGE USE: qit, capacitance, resistance, assign_bits (Fig. 6.28)
- ENTITY tester IS
- END tester;
- --
- ARCHITECTURE input_output OF tester IS
- COMPONENT inv
- GENERIC (c_load : capacitance := 11 ffr);
- PORT (i1 : IN qit; o1 : OUT qit);
- END COMPONENT;
- FOR ALL : inv USE ENTITY WORK.inv_rc(double_delay);
- SIGNAL a, z : qit;
- BEGIN
- assign_bits (a, "data.qit", 500 NS);
- i1 : inv PORT MAP (a, z);
- END input_output;
- Using assign_bits to assign qits to a
- Tester tests inv_rc(double_delay)
- Utilities.overloading.example
- Syntax of case statement
- OTHERS accounts for all those not mentioned above
- Utilities.type_issues
- Define subtype of a base type
- A composite type consisting of elements of other types
- Used for renaming
- Utilities.type_issues.subtype
- SUBTYPE compatible_nibble_bits IS BIT_VECTOR (3 DOWNTO 0);
- TYPE nibble_bits IS ARRAY (3 DOWNTO 0) OF BIT;
- SUBTYPE ten_value_logic IS INTEGER RANGE 0 TO 9;
- Subtype of type is fully compatible with type
- compatible_nibble_bits is compatible with any BIT_VECTOR
- nibble_bits is not compatible with BIT_VECTOR
- ten_value_logic is compatible with any INTEGER
- Utilities.type_issues.subtype
- SUBTYPE tit IS qit RANGE '0' TO 'Z';
- SUBTYPE bin IS qit RANGE '0' TO '1';
- tit and bin and qit are fully compatible
- Can assign tit to qit, qit to bin
- Can assign bin to qit, bin to tit
- Utilities.type_issues.records
- TYPE a_new_record_type IS RECORD
- id1, id2 : type_1;
- id3 : array_type_2;
- id4, id5, id6 : record_type_3;
- END RECORD;
- Records and arrays are composite types
- A record type definition creates a record type
- A record contains several element_declarations
- Utilities.type_issues.records
- TYPE opcode IS (sta, lda, add, sub, and, nop, jmp, jsr);
- TYPE mode IS RANGE 0 TO 3
- TYPE address IS BIT_VECTOR (10 DOWNTO 0);
- TYPE instruction_format IS RECORD
- opc : opcode;
- mde : mode;
- adr : address;
- END RECORD;
- Example shows instruction format declarations
- Element types are opcode, mode, and address
- Assume visibility of opcode, mode, and address declarations
- Utilities.type_issues.records
- TYPE opcode IS (sta, lda, add, sub, and, nop, jmp, jsr);
- TYPE mode IS RANGE 0 TO 3
- TYPE address IS BIT_VECTOR (10 DOWNTO 0);
- --
- TYPE instruction_format IS RECORD
- opc : opcode;
- mde : mode;
- adr : address;
- END RECORD;
- SIGNAL instr : instruction_format := (nop, 0, "00000000000");
- instr.opc <= lda;
- instr.mde <= 2;
- instr.adr <= "00011110000";
- . . .
- instr <= (lda, 2, "00011110000")
- Using instruction_format type, the instr SIGNAL is declared
- Initial values are put in parenthesis
- The order is that of elements in record
- Value assignment can be done to individual elements
- Value assignment can be done to all elements
- Utilities.type_issues.records
- TYPE line IS RECORD
- val : BIT;
- load : capacitance;
- END RECORD
- -- Assume visibility of Resistance, Capacitance and Line (as above)
- ENTITY nand_l IS
- PORT (i1, i2 : INOUT line; o1 : INOUT line);
- END nand_l
- --
- ARCHITECTURE load_dependent OF nand_l IS
- CONSTANT rpu : resistance := 15 k_o;
- CONSTANT rpd : resistance := 10 k_o;
- BEGIN
- i1.load <= 60 ffr;
- i2.load <= 70 ffr;
- o1.val <= '1' AFTER rpu * o1.load WHEN i1.val AND i2.val = '1' ELSE
- '0' AFTER rpd * o1.load;
- END load_dependent;
- Example shows load dependent timing calculation
- Inputs report capacitance to outputs
- Output delay is calculated using capacitance at output
- The complete solution is more involved than the above
- Utilities.type_issues.aliasing
- ALIAS c_flag : BIT IS flag_register (3);
- ALIAS v_flag : BIT IS flag_register (2);
- ALIAS n_flag : BIT IS flag_register (1);
- ALIAS z_flag : BIT IS flag_register (0);
- Alias declaration selects part of an object
- Use for renaming, for convenience
- Can be used on the right hand side and the left hand side
- Utilities.type_issues.aliasing
- ALIAS page :
- BIT_VECTOR (2 DOWNTO 0) IS instr.adr (10 DOWNTO 8);
- ALIAS offset :
- BIT_VECTOR (7 DOWNTO 0) IS instr.adr (7 DOWNTO 0);
- page <= "001"; -- 3 bits
- offset <= X"F1"; -- 8 bits
- offset <= B"1111_0001"; -- 8 bits
- Use aliasing to separately name page and offset
- All references to page refer to 10:8 of address
- All references to offset refer to 7:0 of address
- Hex and equivalent Binary strings are shown
- X, B, and O are called base identifier
- Use _ for separation
- Utilities.attributes.predefined
- array_or_type_or_signal_name'ATTRIBUTE_NAME
- Three types of attributes
- Attributes for arrays
- Attributes for types
- Attributes for signals
- Pronounce ' as tick
- Utilities.attributes.predefined.arrays
- TYPE qit_4by8 IS ARRAY (3 DOWNTO 0, 0 TO 7) OF qit;
- SIGNAL sq_4_8 : qit_4by8;
- 'RANGE and 'LENGTH have been introduced
- Examples refer to sq_4_8 array signal
- Follow attribute by ( ) to specify index
- Utilities.attributes.predefined.type
- TYPE qit IS ('0', '1', 'Z', 'X');
- SUBTYPE tit IS qit RANGE '0' TO 'Z';
- Type attribute, example refersto qit and tit
- Utilities.attributes.predefined.type
- FOR the enumeration types:
- 'PRED 'LEFTOF
- 'SUCC 'RIGHOF
- 'LEFT 'LOW
- 'RIGHT 'HIGH
- Position wise, enumeration elements are in ascending order
- For types with ascending range low to high is left to right
- Above pairs are equivalent for enumeration types
- Utilities.attributes.predefined.signal
- SIGNAL s1 : BIT;
- All examples refer to s1 as above
- Utilities.attributes.predefined.signal
- SIGNAL s1 : BIT;
- All examples refer to s1 as above
- Utilities.attributes.predefined.signal
- Signal attribute examples
- Attributes resulting in signal are in bold
- Attributes resulting in BIT are
- Attributes resulting in BOOLEAN are
- Utilities.attributes.predefined.signal
- ENTITY find_out IS END find_out;
- --
- ARCHITECTURE comparing OF find_out IS
- SIGNAL c, x1, x2, diff : BIT :='0';
- BEGIN
- c <= '0', '1' AFTER 60 NS, '0' AFTER 120 NS;
- x1 <= '1' AFTER 6 NS WHEN c'EVENT ELSE x1;
- x2 <= '1' AFTER 6 NS WHEN NOT c'STABLE ELSE x2;
- diff <= x1 XOR x2;
- END comparing
- ns c x1 x2 diff c'STABLE
- -------------------------------------
- 0 0 0 0 0 true
- 60 1 0 0 0 false
- 60+d 1 0 0 0 true
- 66 1 1 0 0 true
- 66+d 1 1 0 1 true
- 120 0 1 0 1 false
- 120+d 0 1 0 1 true
- c'EVENT is value
- c'STABLE is signal
- c'STABLE changes twice for a change on c
- Utilities.attributes.predefined.signal
- ENTITY brief_d_flip_flop IS
- PORT (d, c : IN BIT; q : OUT BIT);
- END brief_d_flip_flop;
- --
- ARCHITECTURE falling_edge OF brief_d_flip_flop IS
- SIGNAL tmp : BIT;
- BEGIN
- tmp <= d WHEN (c = '0' AND NOT c'STABLE) ELSE tmp;
- q <= tmp AFTER 8 NS;
- END falling_edge;
- Example shows a falling edge d_flip_flop
- Utilities.attributes.predefined.signal
- ENTITY brief_t_flip_flop IS
- PORT (t : IN BIT; q : OUT BIT);
- END brief_t_flip_flop;
- --
- ARCHITECTURE toggle OF brief_t_flip_flop IS
- SIGNAL tmp : BIT;
- BEGIN
- tmp <= NOT tmp WHEN (
- (t = '0' AND NOT t' STABLE) AND (t'DELAYED' STABLE(20 NS))
- ) ELSE tmp;
- q <= tmp AFTER 8 NS;
- END toggle;
- T flipflop toggles when pulse on t > 20 NS
- t = '0' AND NOT t'STABLE checks fall on t
- t' DELAYED'STABLE (20 NS) check for 20 NS before fall
- t'DELAYED is attributed because it is signal
- Utilities.attributes.user_defined
- CAN ATTRIBUTE:
- ENTITY ARCHITECTURE CONFIGURATION
- PROCEDURE FUNCTION PACKAGE
- TYPE SUBTYPE CONSTANT
- SIGNAL VARIABLE COMPONENT
- LABEL
- Can give user_defined attributes to an entity class
- Needs attribute declaration
- Needs attribute specification
- Utilities.attributes.user_defined
- ATTRIBUTE sub_dir : STRING;
- . . .
- ATTRIBUTE sub_dir OF brief_d_flip_flop : ENTITY IS "/user/vhdl";
- ATTRIBUTE del_val : TIME;
- . . .
- ATTRIBUTE del_val of s : SIGNAL IS 5 NS;
- An attribute must be declared before it can be specified
- Declaration and specification have different syntax
- sub_dir is declared
- Attribute is specified for:
- ENTITY brief_d_flip_flop
- del_val is declared
- Attribute is specified for:
- SIGNAL s
- Utilities.attributes.user_defined
- PACKAGE utility_attributes IS
- TYPE timing IS RECORD
- rise, fall : TIME;
- END RECORD;
- ATTRIBUTE delay : timing;
- ATTRIBUTE sub_dir : STRING;
- END utility_attributes;
- --
- USE WORK.utility_attributes.ALL;
- -- FROM PACKAGE USE: delay, sub_dir
- ENTITY brief_d_flip_flop IS
- PORT (d, c : IN BIT; q : OUT BIT);
- ATTRIBUTE sub_dir OF brief_d_flip_flop : ENTITY IS "/user/vhdl";
- ATTRIBUTE delay OF q : SIGNAL IS (8 NS, 10 NS);
- END brief_d_flip_flop;
- --
- ARCHITECTURE attributed_falling_edge OF brief_d_flip_flop IS
- SIGNAL tmp : BIT;
- BEGIN
- tmp <= d WHEN ( c = '0' AND NOT c' SATBLE ) ELSE tmp;
- q <= '1' AFTER q'delay.rise WHEN tmp = '1' ELSE
- '0' AFTER q'delay.fall;
- END attributed_falling_edge;
- Assume utility_attributes is visible
- Two examples of attributes are shown
- Utilities.package
- PACKAGE basic_utilities IS
- TYPE qit IS ('0', '1', 'Z', 'X');
- TYPE qit_2d IS ARRAY (qit, qit) OF qit;
- TYPE qit_1d IS ARRAY (qit) OF qit;
- TYPE qit_vector IS ARRAY (NATURAL RANGE <>) OF qit;
- SUBTYPE tit IS qit RANGE '0' TO 'Z';
- TYPE tit_vector IS ARRAY (NATURAL RANGE <>) OF tit;
- TYPE integer_vector IS ARRAY (NATURAL RANGE <>) OF INTEGER;
- TYPE logic_data IS FILE OF CHARACTER;
- TYPE capacitance IS RANGE 0 TO 1E16
- UNITS
- ffr; -- Femto Farads (base unit)
- pfr = 1000 ffr;
- nfr = 1000 pfr;
- ufr = 1000 nfr;
- mfr = 1000 ufr;
- far = 1000 mfr;
- kfr = 1000 far;
- END UNITS;
- TYPE resistance IS RANGE 0 TO 1E16
- UNITS
- l_o; -- Milli-Ohms (base unit)
- ohms = 1000 l_o;
- k_o = 1000 ohms;
- m_o = 1000 k_o;
- g_o = 1000 m_o;
- END UNITS;
- FUNCTION fgl (w, x, gl : BIT) RETURN BIT;
- FUNCTION feq (w, x, eq : BIT) RETURN BIT;
- PROCEDURE bin2int (bin : IN BIT_VECTOR; int : OUT INTEGER);
- PROCEDURE int2bin (int : IN INTEGER; bin : OUT BIT_VECTOR);
- PROCEDURE apply_data (
- SIGNAL target : OUT BIT_VECTOR;
- CONSTANT values : IN integer_vector; CONSTANT period : IN TIME);
- PROCEDURE assign_bits (
- SIGNAL s : OUT BIT; file_name : IN STRING; period : IN TIME);
- PROCEDURE assign_bits (
- SIGNAL s : OUT qit; file_name : IN STRING; period : IN TIME);
- FUNCTION "AND" (a, b : qit) RETURN qit;
- FUNCTION "OR" (a, b : qit) RETURN qit;
- FUNCTION "NOT" (a : qit) RETURN qit;
- FUNCTION "*" (a : resistance; b : capacitance) RETURN TIME;
- END basic_utilities;
- Continuing development of basis_utilities
Example.LFSR
- Use LFSR for pseudo random bit generation
- Use for signature analysis
- Design an unconstrained configurable LFSR
- Pass polynomial via generics
- Pass seed via generics
- Associate parallel output to determine size
- Will use simple gates for the design of LFSR
Example.LFSR
ENTITY inv_t IS
GENERIC (tplh : TIME := 5 NS; tphl : TIME := 3 NS);
PORT (i1 : IN BIT := '1'; o1 : OUT BIT := '1');
END inv_t;
ARCHITECTURE average_delay OF inv_t IS
BEGIN
o1 <= NOT i1 AFTER (tplh + tphl) /2;
END average_delay;
ENTITY nand2_t IS
GENERIC (init : BIT; tplh : TIME := 6 NS; tphl : TIME := 4 NS);
PORT (i1, i2 : IN BIT := '1'; o1 :OUT BIT := init);
END nand2_t;
ARCHITECTURE average_delay OF nand2_t IS
BEGIN
o1 <= i1 NAND i2 AFTER (tplh + tphl) / 2;
END average_delay;
ENTITY xor_t IS
GENERIC (tplh : TIME := 6 NS; tphl : TIME := 4 NS);
PORT (i1, i2 : IN BIT; o1 : OUT BIT);
END xor_t;
ARCHITECTURE average_delay OF xor_t IS
BEGIN
o1 <= i1 xor i2 AFTER (tplh + tphl) / 2;
END average_delay;
- An LFSR design based on simple gates
- NAND gate includes initial value
- Initialization will be done for stabilizing latches
Example. LFSR
ENTITY sr_latch IS
GENERIC (init_q : BIT);
PORT (s, r, clk : IN BIT; q, qbar : OUT BIT);
END sr_latch;
--
ARCHITECTURE gate_level OF sr_latch IS
COMPONENT n2
GENERIC (init : BIT; tplh : TIME := 6 NS; tphl : TIME := 4 NS);
PORT (i1, i2 : IN BIT; o1 : OUT BIT);
END COMPONENT;
SIGNAL im1, im2, im3, im4 : BIT;
BEGIN
g1 : n2 GENERIC MAP (init => '1') PORT MAP (s, clk, im1);
g2 : n2 GENERIC MAP (init => '1') PORT MAP (r, clk, im2);
g3 : n2 GENERIC MAP (init => init_q) PORT MAP (im1, im4, im3);
g4 : n2 GENERIC MAP (init => NOT init_q) PORT MAP (im3, im2, im4);
q <= im3;
qbar <= im4;
END gate_level;
- Build latch with four NAND gates
- The g3 and g4 gates form the cross-coupled structure
- init_q and NOT init_q for q and q_bar outputs
- Only init generic of NAND is given a value
- All other generics assume OPEN
Example.LFSR
ENTITY Dflipflop IS
GENERIC (init : BIT);
PORT (d, clk : IN BIT; q : OUT BIT := init);
END Dflipflop;
--
ARCHITECTURE sr_based OF Dflipflop IS
COMPONENT sr
GENERIC (init_q : BIT);
PORT (s, r, clk : IN BIT; q, qbar : OUT BIT);
END COMPONENT;
COMPONENT n1
PORT (i1 : IN BIT; o1 : OUT BIT);
END COMPONENT;
SIGNAL q1, q1_bar, d_bar, c_bar : BIT;
BEGIN
c1 : sr GENERIC MAP (init) PORT MAP (d, d_bar, clk, q1, q1_bar);
c2 : n1 PORT MAP(d,d_bar);
c3 : sr GENERIC MAP (init) PORT MAP (q1, q1_bar, c_bar, q, OPEN);
c4 : n1 PORT MAP (clk, c_bar);
END sr_based;
- Use two latches in a master_slave DFF
- Complement clock for slave
Example. LFSR
ENTITY LFSR IS
GENERIC (seed, poly : BIT_VECTOR);
PORT (clk : IN BIT; parallel : OUT BIT_VECTOR; serial : OUT BIT);
END LFSR;
--
ARCHITECTURE hardware OF LFSR IS
COMPONENT df
GENERIC (init : BIT); PORT (d,clk : IN BIT;q : OUT BIT);
END COMPONENT;
COMPONENT x PORT (i1, i2 : IN BIT; o1 : OUT BIT);
END COMPONENT;
SIGNAL ims : BIT_VECTOR (poly'RANGE);
SIGNAL ins : BIT_VECTOR (seed'RANGE);
CONSTANT index1 : INTEGER := poly'LEFT;
CONSTANT index2 : INTEGER := poly'RIGHT;
CONSTANT index3 : INTEGER := seed'LEFT;
CONSTANT index4 : INTEGER := seed'RIGHT;
BEGIN
ins (index4) <= ims (index2); ims (index1) <= ins (index3);
e1 : FOR i IN (poly'LENGTH - 2) DOWNTO 0 GENERATE
di : df GENERIC MAP (seed (i)) PORT MAP (ims (i), clk, ims (i+1));
END GENERATE;
e2 : FOR j IN (poly'LENGTH - 2) DOWNTO 1 GENERATE
e3 : IF (poly (j) = '1') GENERATE
fb : x PORT MAP (ims (j), ins (j), ins (j-1));
END GENERATE;
e4:IF (poly (j) = '0') GENERATE ins (j-1) <= ins (j);
END GENERATE;
END GENERATE;
serial <= ims (ims'RIGHT); parallel <= ims;
END hardware;
- Use DFF and XOR for LFSR
- Generate statements build LFSR
- Seed is passed to init values
- Polynomial determines XOR connections
Example. LFSR
USE WORK.ALL;
--
CONFIGURATION randomgenerating OF LFSR IS
FOR hardware
FOR e1
FOR di : df
USE ENTITY WORK.Dflipflop(sr_based);
FOR sr_based
FOR c1,c3 : sr USE ENTITY WORK.sr_latch(gate_level);
FOR gate_level
FOR ALL : n2 USE ENTITY WORK.nand2_t(average_delay);
END FOR;
END FOR;
END FOR;
FOR c2, c4 : n1 USE ENTITY WORK.inv_t(average_delay);
END FOR;
END FOR;
END FOR;
END FOR; -- e1
FOR e2
FOR e3
FOR fb : x USE ENTITY WORK.xor_t(average_delay);
END FOR;
END FOR; -- e3
END FOR; -- e2
END FOR;
END randomgenerating;
- Configuration declaration binds all sub components
Example. LFSR
ENTITY LFSR_testbench IS
END LFSR_testbench;
--
ARCHITECTURE structural OF LFSR_testbench IS
COMPONENT rng
GENERIC(seed,poly : BIT_VECTOR);
PORT(clk : IN BIT;parallel :OUT BIT_VECTOR(0 to 4); serial :OUT BIT);
END COMPONENT;
FOR random_number_generator:rng
USE CONFIGURATION WORK.randomgenerating;
SIGNAL p : BIT_VECTOR(0 TO 4);
SIGNAL clk,s : BIT;
BEGIN
random_number_generator : rng
GENERIC MAP("1101","11011")
PORT MAP(clk,p,s);
clk <=NOT clk AFTER 100 NS;
END structural;
- Testbench shows a simple usage
- Generic map determines seed and polynomial
- Instantiating rng generates random bits on s
- Random parallel vector is generate on p
Utilities_for_high_level_descriptions.conclusions
1. Outline: Introduction, Organization, Outline
2. Review: Behavioral description, Using process statements, Top-down design, Using available components, Wiring predefined components, Wiring from bottom to top, Generation of testbench data, Using procedures
3. VHDL_Timing: Modeling requirements, Objects & classes, Signals & variables, Concurrent & sequential assignments, Events, transactions & delta delays, Delay modeling, Sequential placement of transactions, Conventions
4. Structural_Description_of_Hardware: Wiring parts into larger designs, Start with primitives, Wire gates into general purpose components, Use iterative constructs, Generate testbenches, Show binding alternatives, Use gate-based components for a larger design
5. Design_Organization: Subprograms, Packaging, Parameter specification, Parametrization, Top level configuration, Design libraries, A complete example
7. Dataflow: Constructs for dataflow descriptions, Multiplexing and clocking, Multiple assignments, State machines, Open collector gates, A complete dataflow example, Load dependent timing
8. Behavioral_Descriptions: Constructs for sequential descriptions, Assertion for behavioral checks, Handshaking constructs, Timing control, Formatted I/O, MSI parts, A complete MSI based design
9. STANDARDS: MVL9: logic value system, Logic type, Operators, Conversions; VHDL'93: Operators, Delay model, Instantiation, Binding, Attributes, Signal assignments, Report, Postponed process
to the top of the Document