EE332 Digital System Design¶
Dr. Yu Yajun
Associate Professor, Department of Electrical and Electronic Engineering
Southern University of Science and Technology
Office: S236, South Tower, Engineering Building
Phone: 8801 8557
Email: yuyj@sustech.edu.cn
Text Book¶
P.P. Chu, RTL hardware design using VHDL, John Wiley & Sons, 2006.
Reference Book¶
- Yalamanchili, VHDL: A Starter ‘ s Guide, Prentice Hall, 2005
- Charles H. Roth, Jr. and Lizy Kurian John: Digital Systems Design with VHDL, Publishing house of electronics Industry
Introduction¶
Table of Contents
Digital system design¶
- Examples of Digital System: system level, or more accurately, register transfer level (RTL).



Abstraction¶
A key method of managing complexity is to describe a system in several levels of abstraction.
An abstraction is a simplified model of the system, showing only the selected features and ignoring the associated details.
- Transistor level
- Gate level
- Register transfer (RT) level
- Processor level
System Representation (View)¶
View: different perspectives of a system
Behavior view¶
- describe the functionalities and i/o behavior
- treat the system as a black box
Structural view¶
- describe the internal implementation (components and interconnections)
- essentially block diagram
Physical view¶
- add more info to structural view: component size, component location, routing wires
- e.g. layout of a printed circuit board
What is VHDL¶
VHSIC Hardware Description Language (VHDL)¶
- Very High-Speed Integrated Circuit program (VHSIC)
- A computer language for documenting and simulating circuits, and describing circuits for synthesis.
- A high level programming language with specialized constructs for modeling hardware.
History of VHDL¶
- Intermetrics, TI and IBM under US DoD contract 1983-1985: VHDL 7.2
- IEEE standardization: VHDL 1076-1987
- First synthesized chip, IBM 1988
- IEEE Restandardization: VHDL 1076-1993
- Minor change in standard 2000 and 2002
- VHDL standard IEEE 1076-2008 published in Jan 2009
The role of HDL¶
- Formal documentation
- Input to a simulator
- Input to a synthesizer
Basic VHDL concept¶

Entity¶
It defines an interface to a component
It names the entity, and
It describes the input and output ports that can be seen from the outside
- Mode of signals (i.e. in and out)
- Type of signals (i.e. bit)
Possible modes for signals of entity ports

Architecture¶
- It defines the relationships between the inputs and outputs of a design entity.
- It consists of a declaration section followed by a collection of concurrent statements.
- It may be expressed in terms of behavior, data flow, or structure.
- It provides an “internal view” of a component.
Examples
NAND2 Gate


S <= A and B;
C <= not S;
C <= not S;
S <= A and B;
These two codes will produce the same result.
Architecture:Behavior style
architecture BEHAVIOR of NAND2 is
begin
process (A,B) is
begin
if (A=‘1’ and B=‘1’) then
C <= ‘0’;
else
if (A=‘0’ and B=‘0’) or (A=‘0’ and B=‘1’)
or (A=‘1’ and B=‘0’) then
C <= ‘1’;
end if;
end if;
end process;
end architecture BEHAVIOR;
Data Objects and Operands¶
Table of Contents
Data objects¶
An object in VHDL is a named item that holds the value of a specific data type.
Four kinds of data objects
- Signals
- Constants
- Variables
- File
For describing logic circuits, the most important data objects are signals. They represent the logic signals (wires) in the circuit.
Signal data objects¶
- A signal is an object that holds the current and possible future values of the object.
- They occur as inputs and outputs in port descriptions, as signals in architecture, etc.
Where can signal data objects be declared?
- Entity declaration
- Declarative section of an architecture
- Cannot be in a process
entity nand2 is
port (A, B: in bit;
C : out bit );
end entity nand2;
architecture dataflow of nand2 is
signal S: bit;
begin
S <= A and B;
C <= not S;
end architecture dataflow;
How to declare a signal?
signal signal_name : signal_type [:= initial_value];
Examples:
signal status : std_logic := ‘0’;
signal data : std_logic_vector (31 downto 0);
Signal assignment
A signal assignment schedules a new value to occur at some future time. The current value of the signal is never changed. If no specific value of time is specified the default value is infinitesimally small value of time into the future called delta time. Signals are assigned using the “<=“ operator. e.g.
X1 <= ‘1’ after 10ns;
SR1 <= 5 after 5ns;
X2 <= ‘0’ after 10ns, ‘1’ after 20ns, ‘0’ after 30ns;
X5 <= ‘1’;

The figure above shows the timing implied by the statements shown in the previous slides assuming that all statements executed at time t.
Variable data objects¶
Variables are used to hold temporary data.
Where to declare a variable?
within the processes, functions and procedures in which they are used
How to declare a variable?
variable variable_name : variable_type [:= initial_value];
Examples:
variable address : bit_vector (15 downto 0) := x”0000”;
variable index: integer range 0 to 10 := 0;
Variable assignment
In contrast to signal assignment, a variable assignment takes effect immediately. Variables are assigned using the “:=“ operator. e.g.
A := ‘1’;
ROM_A(5) := ROM_A(0);
STAR_COLOR := GREEN;
Constant data objects¶
A constant is an object which is initialized to a specific value when it is created, and which cannot be subsequently modified. Where can constants be declared?
- Declarative section of an architecture
- Declarative section of a process
How to declare a constant?
constant constant_name : constant_type [:= initial_value];
Examples:
constant yes : boolean := TRUE;
constant msb : integer := 5;
Data types¶
The type of a signal, variable, or constant object specifies:
- the range of values it may take
- the set of operations that can be performed on it.
The VHDL language supports a predefined standard set of type definitions as well as enables the definition of new types by users.
8 types commonly used:
bit
bit_vector
integer
boolean
array
enumeration
std_logic
std_logic_vector
Bit and Bit_vector
Bit type has two values, ‘0’ and ‘1’.
Example:
signal a : bit := ‘0’;
variable b : bit ;
Bit_vector is an array where each element is of type bit.
Example:
signal c : bit_vector (3 downto 0) := “1000”; -- recommended
signal d : bit_vector (0 to 3) := “1000”;
INTEGER type: INTEGER type represents positive, negative numbers and 0.
By default, an INTEGER signal has 32 bits and can represent numbers from -231 to 231-1. The code does not specifically give the number of bits in the signal.
Integers with fewer bits than 32 can be declared, using the RANGE keyword.
Example:
signal x : integer range -128 to 127;
This defines x as an eight-bit signed number.
BOOLEAN type
An object of type BOOLEAN can have the values TRUE or FALSE, where TRUE is equivalent to 1 and FALSE to 0.
Example:
signal flag : boolean;
constant correct : boolean := TRUE;
ENUMERATION type
An ENUMERATION type is defined by listing all possible values of that type. All of the values of an enumeration type are user-defined.
type enumerated_type_name is (name {, name});
The most common example of using the ENUMERATION type is for specifying the states for a finite-state machine.
Example:
type State_type is (stateA, stateB, stateC);
signal y : State_type := stateB ;
When the code is translated by the VHDL compiler, it automatically assigns bit patterns (codes) to represent stateA, stateB and stateC.
ARRAY type
ARRAY types group one or more elements of the same type together as a single object.
type array_type_name is array (index_range) of element_type;
Example:
type byte is array (7 downto 0) of bit;
type word is array (15 downto 0) of bit;
type memory is array ( 0 to 4095 ) of word;
signal program_counter: word := ”0101010101010101”;
variable data_memory: memory;
To refer individual elements of array:
- program_counter(5 downto 0) accesses the 6 LSBs of program_counter.
- data_memory(0) accesses the first record in memory.
std_logic and std_logic_vector
std_logic provides more flexibility than the bit. To use, you must include the two statements:
library ieee;
use ieee.std_logic_1164.all;
std_logic_vector type represents an array of std_logic objects.
type std_logic is
(
‘U’, -- uninitialized
‘X’, -- unknown
‘0’, -- forcing 0
‘1’, -- forcing 1
‘Z’, -- high impedance
‘W’, -- weak unknown
‘L’, -- weak 0
‘H’, -- weak 1
‘-’ -- don’t care
);
Example
signal x1,x2,Cin,Cout,Sel : std_logic;
signal C : std_logic_vector (1 to 4);
signal X,Y,S : std_logic_vector (3 downto 0);
std_logic objects are often used in logic expressions.
std_logic_vector objects can be used as binary numbers in arithmetic circuits by including in the code the following statement use ieee.std_logic_signed.all; `` or ``use ieee.std_logic_unsigned.all;
VHDL is strongly typed
- VHDL is a strongly type-checked language. Even for objects that intuitively seem compatible, like bit and std_logic, one cannot be assigned to another.
- use std_logic and std_logic_vector types (Recommendation)
Operators¶


1. Logic operators
E.g. sig <= “11001” and “10011’; sig gets value “10001”
Operators on the same line have equal precedence and must be parenthesized when necessary.

X5 <= (X1 and X2) or (X3 and X4 );
2. Concatenation &
E.g. sig2 <= “001” & sig (3 downto 1); sig2 gets value “001000”


Use of conversion functions
signal s1, s2, s3: std_logic_vector(7 downto 0);
Signal b1, b2: bit_vector(7 downto 0);
The following statements are wrong because of data type mismatch
s1 <= b1; -- bit_vector assigned to std_logic_vector
b2 <= s1 and s2; -- std_logic_vector assigned to bit_vector
s3 <= b1 or s2; -- or is undefined between bit_vector and std_logic_vector
We can use the conversion function to correct these problems
s1 <= to_stdlogicvector(b1);
b2 <= to_bitvector(s1 and s2);
s3 <= to_stdlogicvector(b1) or s2; -- or
s3 <= to_stdlogicvector(b1 or to_bitvector(s2));
Lexical elements¶
- The lexical elements are the basic syntactical units in a VHDL program.
- comments,
- identifiers,
- reserved words,
- number, characters and strings.
Comments¶
- A comment starts with two dashes, –, followed by the comment text.
- The comments are for documentation purpose only.
-- **********************************************
-- example of entity
-- **********************************************
entity example is
--……
end entity example;
Identifier¶
Identifiers are used as names for signals, variables, constants, as well as entities, architectures and so on.
A basic identifier is a sequence of characters that may be
- upper or lower case letters and digits 0 - 9
- underscore (“_”) character
VHDL language is NOT case sensitive.
The first character must be a letter and the last character must NOT be “_”
Two successive underscores “__” are NOT allowed.
- Select, ALU_in, Mem_data, Two_dash_ok (true)
- 12Select, _start, out_, Not__Allow, dot#3 (false)
Preserved words¶
Some words are reserved in VHDL to form the basic language constructs.
abs, access, after, alias, all, and, architecture, array, assert, attribute, begin, block, body, buffer, bus, case, component, configuration, constant, disconnect, downto, else, elsif, end, entity, exit, file, for, function, generate, generic, guarded, if, impure, in, inertial, inout, is, label, library, linkage, literal, loop, map, mod, nand, new, next, nor, not, null, of, on, open, or, others, out, package, port, postponed, procedure, process, pure, range, record, register, reject, rem, report, return, rol, ror, select, severity, shared, signal, sla, sll, sra, srl, subtype, then, to, transport, type, unaffected units, until, use, variable, wait, when, while, with, xnor, xor
Numbers, characters and strings¶
A Number in VHDL can be
integer, such as 0, 1234, and 98E7
real, such as 0., 1.23456, or 9.87E6
represented in other number bases:
- 45 = 2#101101# = 16#2D#
A character in VHDL is enclosed in single quotation marks,
- such as ‘A’, ‘Z’, ‘3’.
- 1 and ‘1’ are different.
A string in VHDL is a sequence of characters enclosed in double quotation marks:
- such as “Hello”, “10000111”.
- 2#10110010# and “10110010” are different
Concurrent statement¶
Table of Contents
The operation of digital system is inherently concurrent.
Within VHDL signals are assigned values using signal assignment statements.
sum <= (x xor y) after 5 ns
Multiple signal assignment statements are executed concurrently in simulated time and are referred to as concurrent signal assignment statements (CSAs).
There are several forms of CSA statements:
- Simple CSA
- Conditional signal assignment
- Selected Signal assignment
Simple CSA¶
architecture concurrent_behavior of half_adder is
begin
sum <= ( x xor y) after 5 ns;
carry <= (x and y) after 5 ns;
end architecture concurrent_behavior;
- General form:
target <= expression;
- expression is logical, comparative or arithmetic operations.
- General form:
- The execution of the statements is determined by the flow of signal, rather than textual order.
Examples
Half_adder


library IEEE;
use IEEE.std_logic_1164.all;
entity half_adder is
port (x, y : in std_logic;
sum, carry : out std_logic);
end entity half_adder;
architecture concurrent_behavior of half_adder is
begin
sum <= ( x xor y) after 5 ns;
carry <= (x and y) after 5 ns;
end architecture concurrent_behavior;
Examples
Full_adder



library IEEE;
use IEEE.std_logic_1164.all;
entity full_adder is
port (A, B, Cin : in std_logic;
Sum, Cout: out std_logic);
end entity full_adder;
architecture dataflow of full_adder is
signal s1, s2, s3 : std_logic;
constant gate_delay : time := 10 ns;
begin
L1: s1 <= (A xor B) after gate_delay;
L2: s2 <= (Cin and s1) after gate_delay;
L3: s3 <= (A and B) after gate_delay;
L4: sum <= (s1 xor Cin) after gate_delay;
L5: cout <= (s2 or s3) after gate_delay;
end architecture dataflow;
L1: s1 <= (A xor B) after gate_delay;
L2: s2 <= (Cin and s1) after gate_delay;
L3: s3 <= (A and B) after gate_delay;
L4: sum <= (s1 xor Cin) after gate_delay;
L5: cout <= (s2 or s3) after gate_delay;
Conditional signal assignment¶
- Simple CSAs is convenient for describing gate-level circuits whose behavior can be expressed with Boolean equations.
- It is useful to model circuits at higher levels of abstraction such as multiplexors and decoders.
Examples
4-to-1, 8-bit multiplexor

library IEEE;
use IEEE.std_logic_1164.all;
entity mux4 is
port (In0, In1, In2, In3 : in std_logic_vector (7 downto 0);
S: in std_logic_vector(1 downto 0);
Z : out std_logic_vector (7 downto 0) );
end entity mux4;
architecture con_arch1 of mux4 is
begin
Z <=In0 when S = “00” else
In1 when S = “01” else
In2 when S = “10” else
In3;
end architecture con_arch1;
architecture con_arch2 of mux4 is
begin
Z <= In0 when S = “00” else
In1 when S = “01” else
In2 when S = “10” else
In3 when S = “11” else
“XXXXXXXX”;
end architecture con_arch2;
- The conditional signal assignment itself is a concurrent signal assignment.
- It has one target, but can have more than one expression.
- When this CSA is executed, the expressions in the right hand side are evaluated in the order that they appear.
- The order of the expressions with their respective conditions inside the statement is important.
- Even there are several lines of text, this corresponds to only one signal assignment statement.
Examples
4-to-2 priority encoder

Assume that S(3) has the highest priority
library IEEE;
use IEEE.std_logic_1164.all;
entity pr_encoder is
port (S: in std_logic_vector(3 downto 0);
Z : out std_logic_vector (1 downto 0) );
end entity pr_encoder;
architecture con_behavioral of pr_encoder is
begin
Z <=“11” when S(3) = ‘1’ else
“10” when S(2) = ‘1’ else
“01” when S(1) = ‘1’ else
“00” when S(0) = ‘1’ else
“00”;
end architecture con_behavioral;
Selected signal assignment¶
- It is similar to the conditional signal assignment statement.
- The value of a target signal is determined by the value of a select expression.
Examples
the same 4-1 multiplexer.
architecture sel_behavioral of mux4 is
begin
with S select
Z <= In0 when “00”,
In1 when “01”,
In2 when “10”,
In3 when others;
end architecture sel_behavioral;

Examples
4-to-2 priority encoder based on a selected signal assignment statement


architecture sel_arch of pr_encoder is
begin
with S select
Z <= “11” when “1000” | “1001” | “1010” | “1011” |
“1100” | “1101” | “1110” | “1111”,
“10” when “0100” | “0101” | “0110” | “0111”,
“01” when “0010” | “0011”,
“00” when others;
end architecture behavioral

architecture sel_arch of pr_encoder is
begin
with S select
Z <= “11” when “1---”,
“10” when “01--”,
“01” when “001-”,
“00” when others;
end architecture behavioral
- The choices for the select expression are not evaluated in sequence.
- All choices are evaluated, but one and only one must be true.
- All of the choices that the programmer specifies must cover all the possible values of the select expression.
- When an event occurs on a signal used in the select expression, or any of the signals used in one of the choices, the statement is executed.
Understanding delays¶
Accurate representation of the behavior of digital circuits requires accurate modeling of delays through the various components.
Three types of delay models
- Inertial delay model
- Transport delay model
- Delta delay
The inertial delay model¶
- Digital circuits takes a finite amount of time for the output of a gate to respond to a change on the input.
- This implies that the change on the input has to persist for a certain period of time to ensure that the output will response.
- If it does not persist long enough the input events will not be propagated to the output.
- This propagation delay model is referred to as the inertial delay model.

Out1 <= Input or ‘0’ after 8 ns;
Out2 <= Input or ‘0’ after 2 ns;
- Any pulse in the input with a width of less than the propagation delay through the gate is said to be rejected.
- often used for component delays
- Default in VHDL program
The transport delay model¶
Transport delay models the delays in hardware that do not exhibit any inertial delay. This delay represents pure propagation delay; that is, any changes on an input are transported to the output, no matter how small of the width, after the specified delay. Keyword transport is used in a signal assignment statement for transport delay model.

Out1 <= transport (Input or ‘0’) after 8 ns;
Out2 <= transport (Input or ‘0’) after 2 ns;
- Pulses are propagated, irrespective of width
- good for interconnect delays.
Delta Delays¶
- If we do not specify a delay for the occurrence of an event on a signal, for example
sum <= (x xor y);
a delta delay is assumed by the simulator - Delta delay is an infinitesimally small delay.
- In a signal assignment, the value is not assigned to the signal directly but after a delta delay at the earliest.
- Delta delays are simply used to enforce dependencies between events and thereby ensure correct simulation.
Examples
combinational

library IEEE;
use IEEE.std_logic_1164.all;
entity combinational is
port (In1, In2 : in std_logic;
z : out std_logic);
end entity combinational;
architecture behavior of combinational is
signal s1, s2, s3, s4 : std_logic := 0;
begin
s1 <= not In1;
s2 <= not In2;
s3 <= not (s1 and In2);
s4 <= not (s2 and In1);
z <= not (s3 and s4);
end architecture behavior;

Sequential statement¶
Table of Contents
- Sequential statements are specified inside a process.
- Processes represent fundamental method by which concurrent activities are modeled.
The process construct¶

- A process is a large concurrent statement that itself contains a series of sequential statements.
- The body of the process is treated by VHDL as a single concurrent statement and is executed at the same time as all other concurrent statements in the simulation.
Process with a sensitivity list¶
The sensitivity list is a list of signal to which the process responds.
signal a, b, c, y: std_logic; -- in architecture declaration
…
process (a, b, c) -- in architecture body
begin
y <= a and b and c; -- infer a combinational circuit
end process;
signal a, b, c, y: std_logic;
…
process (a) -- a process with incomplete sensitivity list
-- not infer a combinational circuit
begin
y <= a and b and c;
end process;
Process with a wait statement¶
A process with wait statements has one or more wait statement but no sensitivity list.
- wait on signals;
- wait until boolean_expression;
- wait for time_expression;

process
begin
y <= a and b and c;
wait on a, b, c;
end process;

Sequential statements¶
sequential signal assignment statement¶
Signal-object <= expression [after delay-value];
- Outside a process – concurrent signal assignment statement
- Within a process – sequential signal assignment, executed in sequence with respect to the other sequential statement which appear within that process.
- When a signal assignment statement is executed, the value of expression is computed immediately, and this computed value is scheduled to be assigned to the signal after the specified delay.
- Inside a process, a signal can be assigned multiple times. If all assignments are with 𝛿-delay, only the last assignment takes effect.
signal a, b, c, d, y: std_logic;
…
process(a, b, c, d)
begin
y <= a or c;
y <= a and b;
y <= c and d;
end process;
signal a, b, c, d, y: std_logic;
…
process(a, b, c, d)
begin
y <= c and d;
end process;
- Although this segment is easy to understand, multiple assignment may introduce subtle mistakes in a more complex code and make synthesis very difficult.
- Unless there is a compelling reason, it is a good idea to avoid assign a signal multiple times in a process. The only exception is the assignment of a default value in the if and case statement.
- The result will be very different if the multiple assignments are the concurrent signal assignment statements
signal a, b, c, d, y: std_logic;
…
-- the statements are not inside a process
y <= a or c;
y <= a and b;
y <= c and d;
- The above code is syntactically correct.
- However, the design is incorrect because of the potential output conflict.
variable assignment statement¶
- Variables can be declared and used inside a process statement.
- Variable assignment statement:
variable-object := expression;
- Variable assignment is immediate.

Signal a, b, y : std_logic;
……
process (a, b) is
variable temp : std_logic;
begin
temp := ‘0’;
temp := temp or a;
temp := temp or b;
y <= temp;
end process;
if statement¶
- An if statement selects a sequence of statements for execution based on the value of a condition.
- General form of an if statement

Examples
4-to-1 multiplexer based on an if statement

architecture if_arch of mux4 is
begin
process(In0, In1, In2, In3, S)
begin
if (S = “00”) then
Z <= In0;
elsif (S = “01”) then
Z <= In1;
elsif (S = “10”) then
Z <= In2;
else Z <= In3;
end if;
end process;
end if_arch;
Examples
4-to-2 priority encoder based on an if statement

architecture if_arch of pr_encoder is
begin
process(S)
begin
if (S(3) = ‘1’) then
Z <= “11”;
elsif (S(2) = ‘1’) then
Z <= “10”;
elsif (S(1) = ‘1’) then
Z <= “01”;
else Z <= “00”;
end if;
end process;
end if_arch;
Comparison to a conditional assignment statement¶
- An if statement is somewhat like a concurrent conditional signal assignment statement.
sig <= value_exp1 when boolean_exp1 else
value_exp2 when boolean_exp2 else
value_exp3 when boolean_exp3 else
…
value_expn;
Process(…)
begin
if boolean_exp1 then sig <= value_exp1;
elsif boolean_exp2 then sig <= value_exp2;
elsif boolean_exp3 then sig <= value_exp3;
…
else sig <= value_expn;
end if;
end process;
- The above two statements are equivalent.
- In general, equivalent only if each branch of the if statement consists of a single assignment of the same single signal.
- An if statement allows for arbitrary nesting of if statement.
process (CTRL1, CTRL2)
begin
if CTRL1 = ‘1’ then
if CTRL2 = ‘0’ then
MUX_OUT <= “0010”;
else
MUX_OUT <= “0001”;
end if;
else
if CTRL2 = ‘0’ then
MUX_OUT <= “1000”;
else
MUX_OUT <= “0100”
end if;
end if;
end process;
Incomplete if branch¶
- In VHDL, only the then branch is mandatory and the other branches can be omitted.

case statement¶
- A case is a multiway branch based on the value ofstatement a control expression
- General form of a case statement

Examples
4-to-1 multiplexer based on a case statement

architecture case_arch of mux4 is
begin
process(In0, In1, In2, In3, S)
begin
case S is
when “00” =>
Z <= In0;
when “01” =>
Z <= In1;
when “10” =>
Z <= In2;
when others
Z <= In3;
end case;
end process;
end case_arch;
Examples
4-to-2 priority encoder based on a case statement

architecture case_arch of pr_encoder is
begin
process(S)
begin
case S is
when “1000” | “1001” | “1010” | “1011” |
“1100” | “1101” | “1110” | “1111” =>
Z <= “11”;
when “0100” | “0101” | “0110” | “0111” =>
Z <= “10”;
when “0010” | “0011” =>
Z <= “01”;
when others
Z <= “00”;
end case;
end process;
end case_arch;
Examples
A two-process half-adder model
null statement¶
The statement null;
is a sequential statement that does not cause any action to take place;
More on process¶
Upon initialization all processes are executed once, or suspended on some form of the wait statement reached.
Thereafter, processes are executed in a data-driven manner: activated
- by events on signals in the sensitivity list of the process or
- by waiting for the occurrence of specific event using the wait statement.
Examples
Signal assignment with process
- All of the ports of the entity and the signals declared within an architecture are visible within a process.
- These port and signals can be read or assigned values from within a process; this is how processes can communicate among themselves.
Examples
Communicating processes

Modeling Structure¶
Table of Contents
Describing a system in terms of the interconnections of its components.
Motivation
- represent a digital system in hierarchical structure.
- share components between developers.
Component¶
NAND2 Gate

Examples
Architecture: Structure style
Component declaration: a component instance needs to be bound to an entity
Component instantiation

Examples
Component Entity: AND2 and INV
entity AND2 is
port (L1, L2 : in bit;
L3 : out bit );
end entity AND2;
architecture dataflow of AND2 is
begin
L3 <= L1 and L2;
end architecture dataflow;
entity INV is
port (L1 : in bit;
L2 : out bit );
end entity INV;
architecture dataflow of INV is
begin
L2 <= not L1;
end architecture dataflow;
Component Declaration
- Defines the component’s interface.
- In the declaration region of an architecture
Component Instantiation
- Only the external view of the component is visible.
- Must be preceded by a label.
- Name association and positional association.
Examples
Full Adder: Entity and architecture

Examples
Full Adder: Data flow style architecture
entity Full_Adder is
port (A, B, Cin : in bit;
Sum, Cout : out bit );
end entity Full_Adder;
architecture DATAFLOW of Full_Adder is
signal S: bit;
begin
S <= A xor B;
Sum <= S xor Cin after 5 ns;
Cout <= (A and B) or (S and Cin);
end architecture DATAFLOW;

Examples
Full Adder: Behavioral style architecture
architecture behavioral of full_adder is
signal s1, s2, s3 : std_logic;
constant delay : time := 5 ns;
begin
HA1: process (In1, In2) is
begin
s1 <= (In1 xor In2) after delay;
s3 <= (In1 and In2) after delay; end process HA1;
HA2: process (s1, c_in) is
begin
sum <= (s1 xor c_in) after delay;
s2 <= (s1 and c_in) after delay; end process HA2;
OR1: process (s2, s3) is
begin
c_out <= (s2 or s3) after delay;
end process OR1;
end architecture behavioral;
Examples
Full Adder: structural style architecture

architecture STRUCTURE of Full_Adder is
component HALF_ADDER is
port (L1, L2 : in bit; SUM, CARRY : out bit);
end component HALF_ADDER;
component OR2 is
port (L1, L2 : in bit; O: out bit);
end component OR2;
signal N1, N2, N3 : BIT
begin
-- see next page;
end architecture STRUCTURE;

architecture STRUCTURE of Full_Adder is
begin
HA1: HALF_ADDER port map (L1=>A, L2=>B, SUM=>N1, CARRY=>N2);
HA2: HALF_ADDER port map (L1=>N1, L2=>CIN, SUM=>SUM,
CARRY=>N3);
OR1: OR2 port map (L1=>N3, L2=>N2, O=>COUT);
end architecture STRUCTURE;
Examples
Component Entity: Half_Adder

entity Half_Adder is
port (L1, L2 : in bit;
Sum: out bit;
Carry: out bit );
end entity Half_Adder;
architecture STRUCTURE of Half_Adder is
component XOR2 is
port (I0, I1: in BIT; O: out bit);
end component XOR2;
component AND2 is
port (I0, I1 : in BIT; O: out bit);
end component AND2;
begin
U1: XOR2 port map (I0 => L1,
I1 => L2, O => Sum);
U2: AND2 port map (I0 => L1, I1 => L2,
O => Carry);
end architecture STRUCTURE;
Examples
Component Entity: OR2, AND2, XOR2
entity OR2 is
port (L1, L2: in bit; O: out bit );
end entity OR2;
architecture BHV of OR2 is
begin
O <= L1 or L2 after 10 ns;
end architecture BHV;
entity AND2 is
port (I0, I1: in bit; O: out bit );
end entity AND2;
architecture dataflow of AND2 is
begin
O <= I0 and I1;
end architecture dataflow;
entity XOR2 is
port (I0, I1: in bit; O: out bit );
end entity XOR2;
architecture BHV of XOR2 is
begin
O <= I0 xor I1 after 10 ns;
end architecture BHV;
Structural Decomposition: A design Hierarchy

Structural Decomposition: Design Tree

Configuration¶
When there is more than one architecture for an entity, configuration explicitly specifies which architecture is to be used for the entity during component instantiation.

The process of association of an architecture description with a component in a structure model is referred to as binding an architecture to a component.
Default binding rules:
- The entity with the same name as the component is bound to the component.
- If there are multiple architectures for the entity, the last compiled architecture for the entity is used.
- The entity-architecture description may locate in the same file as that of instantiating the component, or in some other files in the working directory.


Modeling a test bench¶
Motivation
- Test designs prior to construction and use of the circuit.
To test a compiled VHDL design, we can either
- provide stimuli interactively through the command window of a simulator, or
- write a VHDL program (a VHDL test bench).
A test bench
does not have external ports.
contains two part:
- a component representing the circuit under test
- waveform generators which produce waveforms to the input of the component under test.

Functional verification of combinational designs¶
- Determine if a design meets a system’s functional specifications.
- Not concern with any timing delays that results from mapping synthesized logic to a target programmable logic device.
- Allow to find logic errors early in the design flow and prevent wasting time performing synthesis, place and route, and time simulation.
Language and approach to be used
Full range of VHDL language constructs and features can be used for test bench.
Exhaustive verification
- Counting approach treating all inputs as a single vector starting from 0 and subsequently incremented through all its possible binary combinations.
- Functionality approach taking into account the functionality of the design being tested when determining the order for applying input combination
Single process test bench¶
Wait statement (Sequential statement)
- explicitly specify the conditions under which a process may resume execution after being suspended.
- Basic forms of the wait statement
wait for time-expression ;
,wait for 20 ns;
,wait on signal ;
,wait on clk, reset, status;
,wait until condition ;
,wait until A > B;
,wait ;
Assert statement
- VHDL’s assert statement provides a quick and easy way to check expected values and display messages from your test bench. An assert statement has the following general format:
assert condition_expression -- a Boolean value
report text_string -- the text is displayed if the Boolean value is false
severity severity_level; -- severity level can be one of predefined levels: NOTE, WARNING, ERROR, or FAILURE.
Test benches that compute stimulus and expected results¶
tb: process is -- define a process to apply input stimulus and verify outputs.
constant PERIOD: time := 20 ns;
constant n : integer := 2;
begin -- apply every possible input combination
for i in 0 to 2**n - 1 loop
(x_tb, y_tb) <= to_unsigned(i, n);
wait for PERIOD;
assert ( (sum_tb = (x_tb xor y_tb)) and (carry_tb = (x_tb and y_tb)) )
report “Test failed” severity ERROR;
end loop;
wait;
end process;
Loop statement
- A loop statement is used to iterate through a set of sequential statement.
- General form of a loop statement
[ loop-label ] iteration-scheme loop
sequential-statements
end loop [ loop-label ]
Three types of iteration schemes:

- The object i is implicitly declared within the for loop to belong to the integer type whose value are in the range 0 to 2n-1.
- The loop identifier cannot be assigned any value inside the for loop
Exit statement
- The exit statement can be used only inside a loop.
- It causes execution to jump out of the innermost loop or the loop whose label is specified.
- General form of a exit statement
exit [ loop-label ] [ when condition ]
SUM := 1;
L2: loop
J := 0;
L3: loop
J := J+21;
exit when J > 40;
SUM := SUM * 10;
if SUM > 100 then exit L2;
end if;
end loop L3;
end loop L2;
loop
wait on A, B;
exit when A=B;
end loop;
Next statement
- The next statement can be used only inside a loop.
- It results in skipping the remaining statements in the current iteration; execution resumes with the first statement in the next iteration of this loop, if one exists.
- General form of a next statement
next [ loop-label ] [ when condition ]
for J in 10 downto 5 loop
if SUM < TOTAL_SUM then
SUM := SUM + 2;
elsif SUM = TOTAL_SUM then
next;
else null;
end if;
K := K + 1;
end loop;
signed and unsigned data type
- In VHDL and the std_logic_1164 package, the arithmetic operations are defined only over the integer data type.
signal a, b, sum: integer;
…
sum <= a+b;
- Data types signed and unsigned are defined in IEEE numeric_std package. Both data types are an array of element with the std_logic data type. They are interpreted as a signed number or unsigned number.
- std_logic_vector, signed, and unsigned are all defined as an array of elements with the std_logic data type, but they are three independent data types.
- To use the signed and unsigned data type, we must include:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
signal x, y: signed(15 downto 0);
to_unsigned(i, n)
convert the integer i value to an unsigned vector of length n
(x_tb, y_tb) <= to_unsigned(i, n);
- the unsigned vector value returned in this example is assigned to an aggregate made up of the scalar input signals.
- each of these scalar is type std_logic.
- each element of an unsigned vector is also type std_logic.

signal a, b, c, d, e: unsigned (7 downto 0);
…
a <= b + c; d <= b + 1; e <= (5 + a + b) - c;
“011” >= “1000”; -- return FALSE if type is std_logic_vector or unsigned
-- return TRUE if type is signed

std_logic_vector, unsigned and signed are known as closely related data types. Conversion between these types is done by a procedure known as typing casting.

signal u1, u2: unsigned (7 downto 0);
signal v1, v2: std_logic_vector(7 downto 0);
…
u1 <= unsigned(v1);
v2 <= std_logic_vector(u2);
library ieee;
use ieee.std_logic_1164.all
use ieee.numeric_std.all
…
signal s1, s2, s3, s4, s5, s6: std_logic_vector (3 downto 0);
signal u1, u2, u3, u4, u5, u6: unsigned(3 downto 0);
signal sg: signed(3 downto 0);
…
u3 <= u2 + u1; -- ok
u4 <= u2 + 1; -- ok
u5 <= sg; -- not ok
u6 <= 5; -- not ok
u5 <= unsigned(sg); -- ok
u6 <= to_unsigned(5,4); -- ok
u7 <= sg + u1; -- not ok
u7 <= unsigned(sg) + u1; -- ok
s3 <= u3; -- not ok
s4 <= 5; -- not ok
s3 <= std_logic_vector(u3); -- ok
s4 <= std_logic_vector(to_unsigned(5,4)); -- ok
s5 <= s2 + s1; -- not ok
s6 <= s2 + 1; -- not ok
s5 <= std_logic_vector(unsigned(s2) + unsigned(s1)); -- ok
s6 <= std_logic_vector(unsigned(s2) + 1); -- ok
Post-synthesis and timing verifications for combinational designs¶
Post-synthesis verification
- to verify that the synthesizer has successfully translated a design description to gate-level logic.
- the same test bench used for functional verification could be used.
Timing verification
- to verify gate delays and propagation delays of signal paths of the logic mapped to the target programmable logic device.
- If the delay between application of each stimulus and verification of the corresponding UUT outputs was appropriately chosen in the original functional verification test bench, the same test bench could be used for timing verification.
Modeling at the RT level¶
Table of Contents
A register transfer level (RTL) design consists of a set of registers connected by combinational logic.

Combinational circuit¶
- A combinational circuit, by definition, is a circuit whose output, after the initial transient period, is a function of current input.
- It has no internal state and therefore is “memoryless” about the past event (or past inputs).
signal A, B, Cin, Cout : bit;
…
process (A, B, Cin) is
begin
Cout <= (A and B) or ((A xor B) and Cin);
end;
To describe a combinational circuit¶
- The variables or signals in the process must not have initial values.
- A signal or a variable must be assigned a value before being referenced.
- The arithmetic operators (such as +, -, *, etc), relational operators (such as <, >, =, etc), and logic operators (such as and, or, not, etc) can be used in an expression.
Operator sharing¶
One way to reduce the overall size of synthesized hardware is to identify the resources that can be used by different operations. This is know as resource sharing.

sel <= c1 xor c2;
z <= a + b when sel=‘1’ else
a + c;

sel <= c1 xor c2;
d <= b when sel=`1` else c;
z <= a + d;
Performing resource sharing normally introduces some overhead and may penalize performance.
- In the above examples, assume T adder, T mux, T boolean
- For the circuit not sharing the adders: T = max ( T adder, T boolean) + T mux
- For the circuit sharing the adders: T = T adder + T :sub:`boolean + T mux
Shaping the circuit¶
Using VHDL code, it is possible to outline the general shape of the circuit.

signal a: std_logic_vector (7 downto 0);
signal y: std_logic;
…
y <= a(7) xor a(6) xor a(5) xor a(4) xor a(3)
xor a(2) xor a(1) xor a(0);


Examples
Combinational adder-based multiplier

The algorithm includes three tasks: * Multiply the digits of the multiplier (b4, b3, b2, b1 and b0) by the multiplicand A = (a4, a3, a2, a1, a0) one at a time to obtain b4*A, b3*A, b2*A, b1*A and b0*A.
bi * A = (a4*bi, a3*bi, a2*bi, a1*bi, a0*bi)
- Shift bi * A to left by i position.
- Add the shifted bi * A terms to obtain the final product.


More efficient description of an adder-based multiplier
Sequential circuit¶
- A sequential circuit is a circuit that has an internal state, or memory.
- Its output is a function of current input as well as the internal state. Thus the output is affected by current input values as well as past input values.
- A synchronous sequential circuit, in which all memory elements are controlled by a global synchronizing signal, greatly simplifies the design process and is the most important design methodology.
- Flip-flops and latches are two commonly used one-bit memory devices.
Latch¶
A latch is a level-sensitive memory device.

signal S, d, q: bit
……
process (S, d) is
begin
if (S=‘1’) then
q <= d;
end if;
end process;
- In general, latches are synthesized from incompletely specified conditional expressions in a combinational description.
- Latch inferences occur normally with if statements or case statements.
- To avoid having a latch inferred, assign a value to the signal under all conditions.
signal S, d, q: bit
……
process (S, d) is
begin
if (S=‘1’) then q <= d;
else q <= ‘0’;
end if;
end process;
asynchronous reset or preset An asynchronous reset (or preset) will change the output of a latch to 0 (or 1) immediately.

signal S, RST, d, q: bit
……
process (S, RST, d) is
begin
if (RST = ‘1’) then
q <= ‘0’;
elsif (S=‘1’) then
q <= d;
end if;
end process;
Flip-Flops (f/f)¶
- A flip-flop is an edge-triggered memory device.
- To detect the rising edge (or falling edge), or the event occurred for a signal, we can make use of the attribute of a signal.
signal CLK : bit;
……
CLK’event true if CLK changes its value.
CLK’event and CLK = ‘1’ true for the CLK rising edge
CLK’event and CLK = ‘0’ true for the CLK falling edge
- The event attribute on a signal is the most commonly used edge-detecting mechanism. It operates on a signal and returns a Boolean value. The result is true if the signal shows a change in value.
Examples
a simple flip-flop
An edge triggered flip-flop will be generated from a VHDL description if a signal assignment is executed on the rising (or falling) edge of another signal.

entity dff is
port (d, CLK: in bit; q: out bit);
end entity dff;
architecture behavior of dff is
begin
process (CLK) is
begin
if (CLK’event and CLK=‘1’) then
q <= d;
end if;
end process;
end architecture behavior;
- Synchronous sets and resets
Synchronous inputs set (preset) or reset (clear) the output of flip-flops when they are asserted. The assignment will only take effect while the clock edge is active.

signal CLK, d, q, S_RST: bit;
……
process (CLK) is
begin
if (CLK’event and CLK=‘1’) then
if (S_RST = ‘1’) then
q <= ‘0’;
else
q <= d;
end if;
end if;
end process;
- Asynchronous sets and resets
Asynchronous inputs set (preset) or reset (clear) the output of flip-flops whenever they are asserted independent of the clock.

signal CLK , A_RST, d, q: bit;
……
process (CLK, A_RST) is
begin
if (A_RST = ‘1’) then
q <= ‘0’;
elsif (CLK’event and CLK=‘1’) then
q <= d;
end if;
end process;
- A f/f with more than one asynchronous input

VHDL templates for sequential circuits¶
An RTL circuit can be described in two segments:
- A synchronous section updates the register information at the rising edge of the clock.
q_reg <= q_next;
- A combinational section describes combinational logics, for example, update q_next;
- A synchronous section updates the register information at the rising edge of the clock.

Examples
PULSER

Registers¶

-- 4-bit simple register
signal CLK , ASYNC : bit;
singal Din, Dout :
bit_vector (3 down to 0);
……
process (CLK, ASYNC) is
begin
if (ASYNC = ‘1’) then
Dout <= “1100”;
elsif (CLK’event and CLK=‘1’) then
Dout <= Din;
end if;
end process;
Examples
4-bit serial-in and serial-out shift register

signal CLK ,d, q : bit;
……
architecture two_seg of shift_register is
signal r_reg, r_next: bit_vector (3 downto 0);
begin
process (CLK) is
begin
if (CLK’event and CLK=‘1’) then
r_reg <= r_next;
end if;
end process;
r_next <= d & r_reg(3 downto 1);
q <= r_reg(0);
end architecture two_seg;
Synchronous counter¶
Examples
4-bit synchronous counter
Examples
Decimal counter
- A decimal counter circulates the patterns in binary-coded decimal (BCD) format.
- The BCD code use 4 bits to represent a decimal number.

Examples
Three-digit decimal counter using conditional concurrent statements
Examples
Three-digit decimal counter using a nested if statement
Netlist of RTL components¶
A data path usually consists of a netlist of RTL components such as function units, multiplexers, comparators, registers, etc.

Test benches for sequential system¶
- All synchronous system require a system clock signal.
- A reset signal is required. The reset signal is asserted at power on to place the sequential system in its initial state.
Generating a system clock¶
Examples
50% duty cycle clock
clock_gen: process
constant period : time := 100 ns;
begin
clk <= ‘0’;
wait for period/2;
clk <= ‘1’;
wait for period/2;
end process;
Generating the system reset¶
The reset signal typically
- starts in its asserted state at power on,
- remains in that state for a specified period of time, then
- changes to its unasserted state, and
- remains there for as long as power continues to be applied to the system.
The duration of the assertion of the reset signal is specified as
- either a fixed time
reset <= ‘1’, ‘0’ after 160 ns;
- or some multiple of the clock’s period and is synchronized to the system clock
- either a fixed time
reset_process : process
begin
reset <= ‘1’;
for i in 1 to 2 loop
wait until clk = ‘1’;
end loop;
reset <= ‘0’;
wait;
end process;
Synchronizing stimulus generation and monitoring¶

use ieee.numeric_std.all;
signal x : std_logic_vector(3 downto 0); -- vector with element std_logic
signal y : unsigned(3 downto 0); -- vector with element std_logic
signal z : integer range 0 to 15;
--conversion between std_logic_vector, signed, unsigned
x <= y; -- illegal assignment, type conflict
y <= x; -- illegal assignment, type conflict
x <= std_logic_vector(y); -- legal assignment
y <= unsigned(x); -- legal assignment
--conversion between signed, unsigned, integer
z <= to_integer(y); -- legal assignment
z <= to_integer(unsigned(x)); -- legal assignment
y <= to_unsigned(z, 4); -- legal assignment
x <= std_logic_vector(to_unsigned(z, 4)); -- legal assignment
Modeling at the FSMD level¶
Table of Contents
- A digital design is conceptually divided into two parts – a controller and a datapath.

- A sequential circuit which is implemented in a fixed number of possible states is called a finite state machine (FSM).

It contains five elements:
- symbolic state
- input signal
- output signal
- present state
- next state
Two types of FSM:
- Moore machines
- Mealy machines
Moore machine¶
In the Moore modal of sequential circuits, the outputs are the functions of the present state only.

Examples
A state transition diagram of a Moore machine

Mealy machine¶
In the Mealy modal, the outputs are the functions of both the present state and current inputs.

Examples
A state transition diagram of a Mealy machine

An FSM with a datapath (FSMD)¶
A traditional FSM
- cannot represent storage elements (register) except the state registers.
- works well for a design with a few to several hundred states.
An FSM with a datapath (FSMD) is an extension of a traditional FSM.
- storage and signals can be declared.
- Within a state expression, comparison, arithmetic or logic operations on these signals can be performed.
Algorithm state machine (ASM) chart
The behavior of a FSMD can be represented as a flow-chart-like description – algorithm state machine (ASM) chart.
ASM chart is constructed from ASM blocks;
An ASM block consists of three basic elements:
- the state box
- the decision box
- the conditional output box.

Examples
find the greatest common divisor of two eight-bit numbers xi and yi
x = xi;
y= yi;
St1:
If x=y then
ou=x;
Else {
if x> y then x = x-y;
Else y= y-x;
Go to st1;
}

Examples
GCD calculator
Examples
find the greatest common divisor of two eight-bit numbers xi and yi

Rules to Construct ASM Chart:
- For a given input combination, there is one unique exit path from the current AMS block.
- The exit path of an ASM block must always lead to a state box. The state box can be the state box of the current ASM block or a state box of another ASM block.
Common errors in ASM Chart Construction

Examples
FSMD design of a repetitive-addition multiplier
Consider a multiplier with a_in and b_in, and with output r_out. The repetitive-addition algorithm can be formalized in the following pseudo-code:
if (a_in =0 or b_in =0) then{
r = 0;}
else{
a = a_in; n = b_in; r = 0;
r = r + a;
n = n - 1;
if (n = 0) then {goto stop;}
else {goto op;}
}
r_out = r;
Step 1: Defining the input and output signals
Input signals:
- a_in and b_in: input operands. 8-bit signals with std_logic_vector data type and interpreted as unsigned integers
- start: command. The multiplier starts operation when the start signal is activated.
- clk: system clock;
- reset: asynchronous reset signal for system initialization.
Output signals
- r_out: the product. 16-bit signals.
- ready: external status signal. It is asserted when the multiplication circuit is idle and ready to accept new inputs.
Step 2: Converting the algorithm to an ASM chart

Step 3: Constructing the FSMD
Basic data path can be constructed as follows:
- List all possible RT operations in the ASM chart.
- Group RT operations according to their destination registers.
- Derive the circuit for each group RT operation.
- Add the necessary circuits to generate the status signals.
3.1 The circuit require 3 registers, to store signals r, n, and a respectively.
3.2. The RT operations:
- RT operation with the r register:
- r <- r ( in the idle state)
- r <- 0 (in the load and ab0 state)
- r <- r + a ( in the op state)
- RT operation with the r register:
- RT operation with the n register:
- n <- n ( in the idle state)
- n <- b_in (in the load and ab0 state)
- n <- n - 1 ( in the op state)
- RT operation with the n register:
- RT operation with the a register:
- a <- a ( in the idle and op state)
- a <- a_in (in the load and ab0 state)
- RT operation with the a register:

- Step 4: VHDL descriptions of FSMD

Resource sharing via FSMD example of repetitive-addition multiplier
- Many RT operations perform the same or similar function.
- Some function unit can be shared as long as these operations are scheduled in different states.
- the 16-bit adder and 8-bit decrementor are shared in the following example.
Modified ASM chart


sharing on a repetitive-addition multiplier

Parameterized Design¶
Table of Contents
Goal: Design reuse
- Ideally, we want to design some common modules that can be shared by many applications.
- Since every application is different, it is desirable that a module can be customized to some degree to meet the specific need of an application.
- Customization is normally specified by explicit or implicit parameters
Width Parameters
- The widths of data signals normally can be modified to meet different requirement.
- The width parameters of a parameterized design specify the sizes (i.e., number of bits) of the relevant data signal.
Feature Parameters
- Specify the structure or organization of a design.
- Defined on an ad hoc basis.
- To include or exclude certain functionalities (i.e., features) from implementation or to select one particular version of the implementation
Generics¶
The generic construct of VHDL is a mechanism to pass information into an entity and a component.
- They are first declared in entity and component declaration and later assigned a value during component instantiation
entity para_binary_counter is
generic (WIDTH: natural);
port (
clk, reset: in std_logic;
q: out std_logic_vector(WIDTH-1 downto 0)
);
end entity para_binary_counter;
After the declaration, the generic can be used in the associated architecture bodies.
A generic cannot be modified inside the architecture body and thus functions like a constant
- It is sometimes referred to as a generic constant.
architecture arch of para_binary_counter is
signal reg, reg_next : std_logic_vector (WIDTH-1 downto 0);
begin
process (clk, reset) is
begin
if reset = ‘1’ then
reg <= (others =>’0’);
elsif clk’event and clk=‘1’ then
reg <= reg_next;
end if;
end process;
-- next-state logic
reg_next <= reg + 1;
q <= std_logic_vector(reg);
end architecture arch;
- To use the parameterized free-running binary counter in a hierarchical design, a similar component declaration should be included in the architecture declaration.
- The generic can then be assigned a value in the generic mapping section when a component instance is instantiated.
- Example of the use of generics

Parameterized reduced-xor circuit using a generic
Array attribute¶
A VHDL attribute provides information about a named item, such as a data type or a signal.
We have used the ’event attribute, as in clk’event, express the changing edge of the clk signal.
A set of attributes is associated with an object of an array data type. Let s be a signal with an array data type.
- s’left, s’right: the left and right bounds of the index range of s.
- s’low, s’high: the lower and upper bounds of the index range of s.
- s’length: the length of the index range of s.
- s’range: the index range of s.
- s’reverse_range: the reversed index range of s.
The attributes can be applied to the signal defined with std_logic_vector, unsigned and signed:
signal s1: std_logic_vector (31 downto 0);
signal s2: std_logic_vector (8 to 15);

Parameterized reduced-xor circuit using an attribute
The range of the for loop can also be expressed as:
- for i in a’low+1 to a’high loop
- for i in a’right+1 to a’left loop
The last signal assignment
y <= tmp (tmp’left);
Unconstrained Array¶
- Unconstrained array is defined as an array type with specified data type of the index value, but without specified exact bounds of the index value.
- Example:
type std_logic_vector is array (natural range <>) of std_logic
- Similarly, we have unsigned and signed data types.
- If an object is declared with an unconstrained array data type, we must specify its index range when the data type is used, as 15 downto 0 in
signal x: std_logic_vector(15 downto 0);
- A special case: the unconstrained array can be declared without specifying the range in port declaration.
- Example:
- Since no range is specified for d and q, the boundaries of the two signal will not be check in the analysis stage.
Parameterized reduced-xor circuit using an unconstrained array
The code appears to be correct at first glance
- If we map the a signal to an actual signal with the type of std_logic_vector of 8 bits during component instantiation, we may have a to be:
std_logic_vector(7 downto 0);
std_logic_vector(0 to 7);
std_logic_vector(15 downto 8);
std_logic_vector(8 to 15);
- The code does not work properly for the last two formats.
Improved parameterized reduced-xor circuit using an unconstrained array
Comparison¶
The unconstrained array mechanism uses attributes to infer the relevant information from the actual signal.
- More general and flexible than the generic mechanism, but also
- More opportunities for errors.
- Requires comprehensive error-checking code
Generic mechanism is preferred, unless a module is extremely general and widely used.
- More rigid
- It clearly specifies the range, direction and width of each signal and avoids many subtle erroneous conditions.
Generate Statement¶
The generate statements are concurrent statements with embedded internal concurrent statement, which can be interpreted as a circuit part.
Two types of generated statements:
- for generate statement: used to create a circuit by replicating the hardware part
- conditional or if generate statement: used to specify whether or not to create an optional hardware part.
For Generate Statement¶
- Many digital circuits can be implemented as a repetitive composition of basic building blocks, exhibiting a regular structure, such as a one-dimensional cascading chain, a tree-shaped connection or a two-dimensional mesh.
- For generate statement syntax
gen_label: -- mandatory to identify to this -- particular generate statement
for loop_index in loop_range generate
concurrent statements; -- describe a stage of the iterative circuit
end generate;
- The loop_range has to be static. It is normally specified by the width parameters.
Examples
Binary decoder
- A binary n-to- 2 n decoder is circuit that asserts one of the 2 n possible output signal according to an n bit input signal.
- One way to view the binary decoder is to treat each bit of the decoded output as the result of a constant comparator.

Parameterized binary decoder using a for generate statement

Parameterized reduced-xor circuit using a for generate statement
architecture gen_linear_arch of reduced_xor is
signal tmp: std_logic_vector(WIDTH-1 downto 0);
begin
tmp(0) <= a(0);
xor_gen:
for i in 1 to (WIDTH-1) generate
tmp(i) <= a(i) xor tmp(i-1);
end generate;
y <= tmp(WIDTH-1);
end architecture gen_linear_arch;
- In an iterative structure, the boundary stages interface to the external input and output signals, and sometimes their connections are different from the regular blocks.
Conditional Generate Statement¶
- The conditional generate statement is used to specify an optional circuit that can be included or excluded in the final implementation.
- Conditional generate statement syntax
gen_label: -- mandatory
if boolean_exp generate -- boolean_exp must be static
concurrent statements;
end generate;
- There is no else branch in conditional generate statement.
- If we want to include one of the two possible circuits in an implementation, we must use two separate if generate statements.
Reduced-xor circuit revisited
- One common use of the conditional generate statement is to describe the “irregular” stages in a for generate statement.
- For example, two statements
tmp(0) <= a(0); y <= tmp(WIDTH-1);
are used to rename the input and output signals in the for generate statement examples. - To eliminate these statements, we can use conditional generate statements inside the for generate statement.
Parameterized reduced-xor circuit with a conditional generate statement
Examples
Up-or-down free-running binary counter
- An up-or-down binary counter is a counter that can be instantiated in a specific mode.
- Note that the “or” here means that only one mode of operation, either counting up or counting down but not both, can be implemented in the final circuit.

- We use the UP generic as the feature parameter to specify the desired mode.
Up-or-down free-running binary counter
Up-and-down free-running binary counter
Counter with an optional output buffer
- An output buffer can remove glitches from the signal.
- Since the buffer is only needed for certain application, it will be convenient to include the buffer as an optional part of the circuit.

Counter with an optional output buffer
Comparison¶
To create a circuit with a selectable feature:
- use conditional generate statement
- a full-featured circuit with some input control signal connected to constant values to permanently enable the desired feature
- use the configuration construct
Assume we need a 16-bit up counter in a design.
count16up: up_or_down_counter
generic map (WIDTH => 16, UP =>1)
port map (clk => clk, reset => reset, q=>q);
count16up: up_and_down_counter
generic map (WIDTH => 16)
port map (clk => clk, reset => reset, mode => ‘1’, q=>q);
Difference
The up-or-down counter instance
- creates a circuit with only the needed features.
- The selected portion of code is passed to the synthesis stage, i.e., the synthesis software only needs to synthesize the selected portion.
The up-and-down counter instance
- creates a circuit that consists of all features and uses an external control signal to selectively enable a portion of the circuit.
- The entire VHDL code is passed to synthesis stage. The synthesis software eliminates the unused portion through logic optimization.
In general, use of the feature parameters and conditional generate statement is better than the full-featured approach.
The selected hardware creation can also be achieved by configuration where multiple architecture bodies are constructed, each containing a specific feature, e.g., architectures up_arch and down_arch of the same entity updown_counter, for counting up and counting down, respectively.
And the following instantiation can be used to select the counting up circuit.
count16up: work.updown_counter(up_arch)
generic map(WIDTH =>16)
port map (clk => clk, reset => reset, q => q);
Up-or-down counter with two architecture bodies
Conversely, we can merge the logic from several architecture bodies into a single body and use a feature generic and conditional generate conditions to select the desired portion.
There is no rule about when to use a feature parameter and when to use a configuration construct. In general,
- code with a feature parameter is more difficult to develop and comprehend, but on the other hand, if we use a separate architecture body for each distinctive feature, the number of architecture bodies will grow exponentially and becomes difficult to manage.
- when a feature parameter leads to significant modification or addition of the no-feature codes and starts to make the code incomprehensible, it is probably a good idea to use separate architecture bodies and the configuration construct.
For Loop Statement¶
- The for loop statement is a sequential statement and is the only sequential loop construct that can be synthesized.
for index in loop_range loop --loop_range must be static
sequential statements;
end loop;
- The basic way to synthesize a for loop statement is to unroll or flatten the loop. Unrolling a loop means to replace the loop structure by explicitly listing all iterations.
Examples
Binary decoder
The code is very similar to the for generate version
architecture loop_arch of bin_decoder is
begin
process (a)
begin
for i in 0 to (2**WIDTH-1) loop
if i = to_integer(unsigned(a)) then code(i) <= ‘1’;
else code(i) <= ‘0’;
end if;
end loop;
end process;
end architecture gen_arch;
Examples
Reduced-xor circuit
For loop version: For generate version:
Examples
Priority Encoder
- Recall that a signal can be assigned with multiple times inside process and only the last assignment takes effect.
- A priority encoder is a circuit that returns the binary code of the highest-priority request.
- Assume that the input is an array of r(WIDTH-1 downto 0), and r(WIDTH-1) has the highest priority.
Comparison¶
Both the for generate and for loop statements are used to describe replicated structures.
For generate statement:
- can only use concurrent statements.
- start a design with a conceptual diagram of a few stages; the diagram is used to identify the basic building block and connection pattern, and then the code of the loop body is derived.
For loop statement:
- can only use sequential statements.
- the body of the loop statement can be more general and versatile.
- may lead to unnecessarily complex implementation or even an unsynthesizable description.
Pipelined design¶
Table of Contents
- Pipeline is an important technique to increase the performance of a system.
- The basic idea is to overlap the processing of several tasks so that more tasks can be completed in the same amount of time.
Delay and throughput¶
Delay and throughput are the two criteria used to examine the performance of a system
- Delay: the time required to complete one task.
- Throughput: the number of tasks that can be completed per unit time.
Adding pipeline to a combinational circuit can increase the throughput but not reduce the delay.
Overview on pipelined design¶
The pipelining technique can be applied to a task that is processed in stages.
- An example: Pipelined laundry.
- A complete laundry includes the stages of washing, drying and folding, for example.

For non-pipelined process, a new load cannot start until the previous load is completed.
- It takes 240 minutes to complete the four loads.
- The delay of processing one load is 60 minutes.
- The throughput is 1/60 load per minute.

For pipelined process,
- It takes 120 minutes to complete the four loads.
- The delay in processing one load remains 60 minutes.
- The throughput increases to 2/60 load per minute.
- To process k loads, it will take 40+20k minutes.
- The throughput becomes k/(40+20k) load per minute -> 1/20 load per minute when k is large.
Pipelined combinational circuit
- A combinational circuit can be divided into stages so that the processing of different tasks can be overlapped.
- To ensure that the signals in each stage flow in the correct order and prevent any potential race, registers must be added between successive stages.
- The registers ensures that the signals can be passed to the next stage only at predetermined points.

Assume: propagation delay for each stage: T1, T2, T3 and T4. Tmax = max(T1, T2, T3, T4);
Thus, the minimum clock period has to accommodate the longest delay plus the overhead introduced by the buffer register in each stage: Tc = Tmax + Tr;
The effectiveness of the circuit
Propagation delay:
- non-pipelined circuit: T comb = T1+T2+T3+T4
- pipelined circuit: Tpipe = 4Tc = 4Tmax + 4Tr
Throughput:
- non-pipelined circuit: 1/T comb;
- pipelined circuit: k/(3Tc+kTc) -> 1/Tc.
Ideally, for an N-stage circuit
The propagation delay of each stage is identical (i.e., Tmax = Tcomb/N)
The register overhead (Tr) is comparably small
- T pipe = NTc = NTmax = T comb
- Throughput: 1/Tc = 1/Tmax = N/ T comb
Ideally, it is desirable to have more stages in the pipeline. However, when N becomes large,
- the propagation delay of each stage becomes smaller, but Tr remains the same; its effect cannot be ignored.
- In reality, it is difficult to keep dividing the original combinational circuit into smaller and smaller stages.
Adding pipeline to a combinational circuit¶
The candidate circuits for effective pipeline design should include the following characteristics:
- There is enough input data to feed the pipeline circuit.
- The throughput is the main performance criterion.
- The combinational circuit can be divided into stages with similar propagation delay.
- The propagation delay of a stage is much longer than the delay incurred due to the register.
The procedure to convert a combinational circuit to a pipelined design
- Derive the block diagram of the original combinational circuit and arrange it as a cascading chain.
- Identify the major components and estimate the relative propagation delays of these components.
- Divide the chain into stages of similar propagation delays.
- identify the signals that cross the boundary of the chain.
- Insert registers for these signals in the boundary.
Examples
Simple pipelined adder-based multiplier


Non-pipelined multiplier in cascading stages

Non-pipelined circuit:
-- stage 2
pp2 <= pp1 + bp2;
-- stage 3
pp3 <= pp2 + bp3;
pipelined circuit:

-- register
if (reset = ‘1’) then
pp2_reg <= (others => ‘0’);
pp3_reg <= (others => ‘0’);
elsif (clk’event and clk=‘1’) then
pp2_reg <= pp2_next;
pp3_reg <= pp3_next;
end if;
…
-- stage 2
pp2_next <= pp1_reg + bp2;
-- stage 3
pp3_next <= pp2_reg + bp3;
Examples
Pipelined multiplier
More efficient Pipelined multiplier
- Use a smaller (n+1)-bit adder to replace the 2n-bit adder in an n-bit multiplier.
- Reduce the size of the partial-product register
- Reduce the size of the registers that hold the b signal.
Subprograms, packages and libraries¶
Table of Contents
For complex design, VHDL provides mechanics for structuring programs, reusing modules
- Subprograms such as functions and procedures for encapsulating commonly used operations
- Packages and libraries for sharing large bodies of code.
Functions¶
- Functions are used to compute a value based on the values of the input parameters.
- Function declaration:

- Structure of a function
function rising_edge (clock: std_logic) return boolean is
--
-- declarative region: declare variables local to the function
--
begin
-- body
-- sequential statement;
-- sequential statement;
-- --
return (value);
end function rising_edge;
- Calling a function in a VHDL module:

Functions execute in zero simulation time.
- Wait statement are not permitted in functions
entity dff is
port ( D_in, CLK: in std_logic;
D_out: out std_logic);
end entity dff;
architecture behavior of dff is
function rising_edge(signal clock: in std_logic) return boolean is
variable edge : boolean :=FALSE;
begin
edge := (clock=‘1’ and clock’event);
return (edge);
end function rising_edge;
begin
process (CLK) is
begin
if (rising_edge(CLK)) then
D_out <= D_in;
end if;
end process;
end architecture behavior;
A majority function
- It returns ‘1’ if two or more of the 3 input parameters, a, b and c are ‘1’.
- It can be treated as a shorthand for the ab+ac+bc expression
architecture arch of …
-- declaration
function maj(a, b, c: std_logic) return std_logic is
variable result: std_logic;
begin
result := (a and b) or (a and c) or (b and c);
return result;
end function maj;
signal i1, i2, i3, i4, x, y: std_logic;
begin
…
x <= maj(i1, i2, i3) or i4;
y <= i1 when maj(i2, i3, i4)=‘1’ else …
end arch;
Type conversion functions
To make assignment from an object of one type to an object of another type.
- for example: bit_vector and std_logic_vector.
function to_bitvector (svalue: std_logic_vector) return bit_vector is
variable outvalue : bit_vector(svalue’length - 1 downto 0);
begin
for i in svalue’ range loop -- scan all elements of the array
case svalue(i) is
when ‘0’ => outvalue (i) := ‘0’;
when ‘1’ => outvalue (i) := ‘1’;
when others => outvalue (i) := ‘0’;
end case;
end loop;
return outvalue;
end function to_bitvector;
A Function performing log 2 n
function log2c (n: integer) return integer is
variable m, p: integer;
begin
m := 0;
p := 1;
while p < n loop
m := m+1;
p := p*2;
end loop;
return m;
end function log2c;
Summary
- Unlike entity and architecture, functions (and procedures) are not design units and thus cannot be processed independently.
- In synthesis, functions should not be used to specify the design hierarchy, but should be treated as a shorthand for simple, repeatedly used operations.
- A function can be thought of as an extension of the expression and can be “called” whenever an expression is used.
Package¶
- The primary purpose of a package is to collect elements that can be shared (globally) among two or more design units. A package is represented by:

- Package declaration and package body are design units of VHDL.
An example of a package declaration
package SYNTH_PACK is
constant LOW2HIGH : TIME := 20ns;
type ALU_OP is (ADD, SUB, MUL, DIV, EQL);
type MVL is (‘U’, ‘0’, ‘1’, ‘Z’);
component NAND2
port (A, B : in MVL; C : out MVL);
end component;
-- subprogram, type, constant, signal, variable, component …,
-- and use clause can be declared in package declaration
end package SYNTH_PACK;
- If the declarations include items such as functions or procedure declarations, the behavior of the function and procedure are specified in a separate design unit called the package body.
use WORK.SYNTH_PACK.all;
package PROGRAM_PACK is
constant PROP_DELAY : TIME;
function ISZERO(A: MVL) return boolean;
end package PROGRAM_PACK;
- In this case, a package body is required.
- A package body primarily contains the behavior of the subprograms declared in a package declaration. It may also contain other declarations.
** An example of a package body **
package body PROGRAM_PACK is
constant PROP_DELAY : TIME := 15ns;
function ISZERO(A: MVL) return boolean is
begin
if (A=‘0’) return TRUE;
else return FALSE;
end if;
end function ISZERO;
end package body PROGRAM_PACK;
Note
An item declared inside a package body has its scope restricted to be within the package body, and this item cannot be made visible in other design unit. (This is in contrast to items declared in a package declaration).
Design libraries¶
- Each design unit - entity, architecture, configuration, package declaration, package body is analyzed (complied) and placed in a design library for subsequent use.
- To use a design library, the library must be declared by its logical name.
library logical-library-name1, logical-library-name2,…;
- In VHDL, the libraries STD and WORK are implicitly declared.
- Once a library is declared, all of the functions, procedures, and type declaration of a package in that library can be made accessible to a VHDL model through the use clause.
library IEEE
,use IEEE.std_logic_1164.all;
- These clauses apply only to the immediate entity-architecture pair! Visibility must be established for other design units separately!
Task 1: Behavior Simulation of Full Adder (Week 2)¶
Table of Contents
- Objective: Understand the simple concurrent signal assignment statement, the inertial delay model, and the simulation of a design.

Knowledge Points¶
- Data Type
- bit, p51-53
- array, enumeration, p56-57
- std_logic, p58-60
- Operators, p61-65
- Logic Operators: and, or, nand, nor, xor, xnor,
- Adding: +, -, &
- Concurrent Statements
- simple concurrent signal assignment (CSA) statement, p71-74
- Delay Model
- Inertial delay model, p86-88
- Test Bench
- Self study Chapter 5.3, p142-148

L1: s1 <= (A xor B) after gate_delay;
L2: s2 <= (Cin and s1) after gate_delay;
L3: s3 <= (A and B) after gate_delay;
L4: sum <= (s1 xor Cin) after gate_delay;
L5: cout <= (s2 or s3) after gate_delay;

Task 2: Behavior Simulation of Process (Week 3)¶
Table of Contents
- Objective: Understand the difference between the signal assignment and variable assignment in a process, understand the delta delay, and the simulation of a process.

Knowledge Points¶
Task 3: Implement your First Design – 1Hz 3-digit decade Counter (Week 5)¶
Table of Contents
- Objective: Understand the modeling based on the hierarchical structure, the two segment coding style for the design of a sequential circuit, and implement the design on the FPGA board.

Task 4: FSM and FSMD (Week 6)¶
Table of Contents
Objective: Revision of the construction of finite-state machine (FSM); modeling, simulation and synthesis of FSM; Understand the FSM with a Datapath (FSMD) and Algorithm State Machine (ASM) Chart, and modeling, simulation and synthesis of the FSMD.

Knowledge Points¶
- Modeling FSM p213-221
- FSM with a Datapath (FSMD) p222
- Algorithm State Machine (ASM) Chart p223-224
- Modeling FSMD, p225-230
Task 5: Design Multipliers (Week 7)¶
Table of Contents
- Objective: Understand the combinational design and FSMD design, evaluate of the performance and cost of a design, and trade off between performance and cost.
Combinational Design

FSMD Design

Knowledge Points¶
- Combinational Design, p167-169, p175-181
- Array aggregate p178
- Resource Sharing, p170-174
- Cost and Performance: size, delay, power consumption
- FSMD Design (steps), p231-241
- Defining the input and output signals
- Converting the algorithm to an ASM chart
- Constructing the FSMD
- List all possible RT operations in the ASM chart.
- Group RT operations according to their destination registers.
- Derive the circuit for each group RT operation.
- Add the necessary circuits to generate the status signals.
- VHDL descriptions of FSMD
- Resource sharing via FSMD, p242-249

From the Project Summary, you can see the overview of the design. Note in particular the Utilization, in which the number of LUT and FF, both used and in total, are shown in graphic and table forms, as well as Power consumption.


Task 6: Seven-Segment Display (Week 8)¶
- Objective:
- Revisit the knowledge points that we have studied.
- Get to know the operation of a device by reading its manual and/or other material. Specifically in this task, get to know the operation of the seven-segment LED display.
- Start a design from its block diagram.
- Model each block, and
- Model the entire circuit that drives the seven-segment LED display.
Knowledge Points Revisited¶
- Hierarchy design and Structure Style Modeling
- Two segment coding style
- Combinational circuit design
- Decoder:
- Hex to 7-segment decoder,
- 3-to-8 decoder
- Multiplexer
- Sequential circuit design
- Counter
- Frequency divider
New¶
Task 7 Stepper Motor (week 9)¶
- Objective
- Revisit the knowledge points that we have studied.
- Get to know the peripheral modules (Pmod) of Nexys4 DDR
- Get to know the working principle of the step motor
- Design a drive circuit for the step motor
- Implement a drive circuit on the Nexys4 DDR FPGA board

Knowledge Points Revisited¶
- Hierarchy design and Structure Style Modeling
- Two segment coding style
- Combinational circuit design
- Decoder:
- 2-to-4 decoder
- Sequential circuit design
- Counter
- Frequency divider
- Parameterized Design
- Generic constant
- Array attribute
- Unconstrained array

