Lec5 - Counters Modified
Lec5 - Counters Modified
circuits
LECTURE 5
Libraries
Libraries provide an alternative to explicit component declaration
Standard Library (STD) – Implicit
Working Library (work) – Implicit
Resource Libraries
IEEE developed libraries
library
library ieee;
ieee;
Intel FPGA component libraries use
use ieee.std_logic_1164.all;
ieee.std_logic_1164.all;
Any library of design units that are referenced in a design
Libraries are structured in one or more packages that contain the
declaration of types, functions and components
Components within a declared package do not need to be re-
declared within the architecture.
User-defined packages are common (component reuse)
Referencing libraries and
packages
Syntax:
library <name>;
use <name>.<package_name>.all;
library clause:
Defines the library name that can be reference
Is a symbolic name to a path/directory
use clause
Specifies the package and object in the library that
you have specified in the library clause
All packages used must be compiled
The WORK library
The fact that the work library is implicit in all designs, provides an
library work; -- library is where we save our design
alternative way--to(.vhd
instantiate
use work.all; file &components
compiler & within an entity
simulator etc files)
This notation is called direct instantiation or entity instantiation, to
differentiate from the component instantiation described before
It relies on the fact that components declared in a library do not
need to be re-declared in the architecture
Libraries - IEEE
The ieee library contains several packages:
std_logic_1164
std_logic_textio Packages that contain
std_logic_arith types and functions for
std_logic_signed circuit design, synthesis,
std_logic_unsigned and simulation
Packages designed to replace
numeric_bit
STD_LOGIC for synthesis of
numeric_std
arithmetic functions
math_real
Non-synthesizable (mostly) functions
math_complex
on real and complex numbers
Packages –
std_logic_1164
This package contains the definition of types:
std_ulogic std_ulogic_vector
std_logic std_logic_vector
For these types, it (re-)defines the logic functions:
and nand or xor xnor not
After a series of “hacks”, the IEEE developed a new package
Packages – numeric_std
This package contains the definition of the following synthesizable
types and functions:
The signed and unsigned types
The logic functions: and, or, nand, nor, not, xor, xnor
The arithmetic functions: +, -, *, /, rem, mod
The comparison functions: <, <=, >, >=, =, /=
The shift functions: shift_left, shift_right, rotate_left,
rotate_right
Several type conversion functions
Note that these functions are only defined for signed and
unsigned types (and not, for example, for std_logic_vector)
Once the package has been declared on top of your VHDL file,
these functions can be used without additional declarations
Complex operators
One of the key features of VHDL is the possibility of using complex
operators rather than relying only on logic gates
The arithmetic functions: +, -, *, /, mod, rem, abs
The comparison functions: <, <=, >, >=, =, /=
The shift functions: shift, rotate
Using these operators is fundamental for the design of complex
circuits (particularly in datapaths)
However, arithmetic and comparison operators have different
meaning and different hardware implementations depending on
the type of signal they are applied to
Synthesizable VHDL –
NUMERIC.STD
Using the IEEE.numeric_std package and the signed and
unsigned types allows you to use complex operations on data
IEEE libraries being defined for synthesis, these operators are fully
synthesizable: they will be transformed into an (optimized)
hardware implementation by the synthesis tools. Their use is
highly recommended for synthesizable VHDL (much better control
of arithmetic operations)
But be careful! The definition may not necessarily always meet
your needs as a designer – for example, the + operator does not
explicitly define a carry out value
function "+" (L, R: UNSIGNED) return UNSIGNED;
-- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1
downto 0).
-- Result: Adds two UNSIGNED vectors that may be of
different lengths
Synthesizable VHDL – NUMERIC_STD
In hardware, SIGNED and UNSIGNED are exactly equivalent to
STD_LOGIC_VECTOR, but carry additional information for the
synthesis tools, so are not quite identical
In order to use an operator (or a function) on a signal, the operator
must be defined for the specific type of the signal. For example,
from numeric_std:
function "+" (L: UNSIGNED,R: UNSIGNED) return UNSIGNED;
function "+" (L: SIGNED, R: SIGNED) return SIGNED;
function "+" (L: UNSIGNED;R: NATURAL) return UNSIGNED;
function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
function "+" (L: INTEGER; R: SIGNED) return SIGNED;
function "+" (L: SIGNED; R: INTEGER) return SIGNED;
to_signed(value,num_bits);
For example:
Note that the vector must not have multiple possible integer values. Hence:
signal my_vector : std_logic_vector(7 downto 0);
signal my_integer : integer;
[...]
my_integer <= to_integer(my_vector); -- ILLEGAL
is illegal, but
signal my_vector : unsigned(7 downto 0);
signal my_integer : integer;
[...]
my_integer <= to_integer(my_vector);
is correct.
Type casting
When converting between similar vectors of the same size,
type casting is used:
Why do we
need
unsigned?
Counters – 8-bit
unlimited
entity CNT_8BIT is
port (CLK, EN, RST : in STD_LOGIC;
Q : out UNSIGNED(7 downto 0));
end CNT_8BIT;
(1)
end CNT_10;
(1)
end CNT_10;
(1)
architecture arch of CNT_10 is
signal Qint : UNSIGNED(3 downto 0);
begin
CNT_DEC : process (CLK)
begin
if (Qint = 10) then
Qint <= "0000";
elsif (rising_edge(CLK)) then
if (RST = '1') then
Qint <= (others => '0');
else
if (EN = '1') then
Qint <= (Qint + 1);
end if;
end if;
end if;
end if;
end process CNT_DEC;
WRON
Q <= Qint;
end arch; G
Shift Registers
2
Right Shift: A movement of data from left 5 to
right in the shift register (toward the LSB).
One bit shift per clock pulse.
Left Shift: A movement of data from right to
left in the shift register (toward the MSB). One
bit shift per clock pulse.
Rotation: Serial shifting (right or left) with
the output of the last FF connected to the
input of the first. Results in continuous
circulation of SR data.
Shift Registers
26
Shift Registers
27
Serial Shift Register (SR)
2
A 4-Bit Left Shift Register. 8
DIN is shifted into the LSB FF and shifted toward the
MSB.
Q3 D3 Q2 D2 Q1 D1 Q0 D0 DIN
MSB LSB
Q3 D3 Q2 D2 Q1 D1 Q0 D0 DIN
MSB LSB
Q3 D3 Q2 D2 Q1 D1 Q0 D0 DIN
MSB LSB
Q3 D3 Q2 D2 Q1 D1 Q0 D0 DIN
MSB LSB
Q3 D3 Q2 D2 Q1 D1 Q0 D0 DIN
MSB LSB
Q3 Q2 Q1 Q0
Q3 Q2 Q1 Q0
Arrays
An array in VHDL is a type that represents collection
of objects of the same type. Its declaration must
include the size and the type of object:
type myarray is array (31 downto 0) of integer;
signal array1: myarray;
Arrays are extremely useful constructs. Some of the
standard and IEEE types are arrays (string,
bit_vector, std_logic_array, signed, unsigned).
These types are defined in the respective packages
and do not need to be re-declared. For example:
signal array1: STD_LOGIC_VECTOR (31 downto 0);
is equivalent to
type my_vector_type is array (31 downto 0) of STD_LOGIC;
signal my_vector : my_vector_type;
Note that in hardware only one-dimensional arrays
make any sense! (with a couple of exceptions )
Arrays
Arrays can be declared in either direction and with any
finite bound:
input array1: in STD_LOGIC_VECTOR (31 downto 0);
signal array2: STD_LOGIC_VECTOR (1 to 3);
as long as the bounds make sense:
input array1: in STD_LOGIC_VECTOR (0 downto 6); --ILLEGAL
signal array2: STD_LOGIC_VECTOR (3 to 0); --ILLEGAL
For synthesizable VHDL, the use of to is strongly
discouraged!
Any “slice” of an array can be assigned, including a
single element, as long as the two sides have the same
size:
array2(1) <= '0';
array2 <= array1(2 downto 0);
array1(15 downto 8) <= "01010101";
Once a direction has been declared, it cannot be
changed:
Arrays
signal array1: STD_LOGIC_VECTOR (4 downto 0);
signal array2: STD_LOGIC_VECTOR (2 downto 0);
signal a,b,c: STD_LOGIC;
signal array3: STD_LOGIC_VECTOR (1 downto 0);
Arrays can be defined with the concatenation operator
&:
array2 <= a & b & c; -- order is important (downto)
array1 <= array3 & array2; -- order is important (downto)