TABLE OF CONTENT
|
|
|
| |
| |
| |
| |
| |
|
|
|
|
CENTRAL ELECTRONICS ENGINEERING RESEARCH INSTITUTE PILANI (RAJASTHAN)
CEERI PROFILE
Central Electronics Engineering Research Institute, popularly known as CEERI, is a constitute establishment of the Council of Scientific and Industrial Research (CSIR), New Delhi. The first Indian Prime Minister Pt. Jawaharlal Nehru laid the foundation stone of the institute on 21st September 1953. The actual R and D work started towards the end of the 1958. The institute has since then blossomed into a center for development of technology and for advanced research in electronics. Over the years the institute has developed a number of products and processes and has established facilities to meet the emerging needs of electronics industry.
CEERI pilani is a pioneer research institute in the country. Since it’s inception it has been working for the growth of electronics in the country and has establish the required infrastructure and well experienced men power for undertaking R and D in the following three major areas:
There are over 12 groups working on the various fields, on the frontiers of knowledge in these thrust areas:
ELECTRONICS SYSTEM AREA for industrial, agriculture and transportation applications.
SEMICONDUCTOR DEVICES AREA for power devices, microelectronics devices, millimeter devices and hybrid microcircuits.
MICROWAVE TUBES AREA for defense and communication.
ELECTRONICS SYSTEM AREA
SEMICONDUCTOR DEVICES AREA
MICROWAVE TUBES AREA
The main thrust of the R and D efforts traditionally carried out by CEERI has been directed towards the collaborative or grant-in-aid research projects. These projects are funded by Government Departments and Government funded user agencies and to a lesser extent, towards in-house development projects resulting in technological know-how, which can be transferred to Indian industries. With dwindling support for capital resources needed for state-of-the-art research, it has now become much more difficult to find the support for developmental activities, which can lead to competitive products or process of interest to industry.
In this way CEERI has under one roof, an advanced comprehensive program of development for power semiconductor devices as well as specific integrated circuits and electronics systems for various applications.
CEERI achievements have contributed significantly towards important substitution and self-reliance. Advanced training programs, seminars, symposia, workshops etc. are being organized by CEERI, pilani regularly. CEERI has also put a lot of emphasis in the development of and efficient software packages.
VLSI DESIGN OVERVIEW
DESIGN OVERVIEW
VLSI design involves translating the given specifications into geometrical patterns that are used in fabrication chips.
This translation task is very complex and cannot be accomplished in one step. It is accomplished through a succession of translation steps of manageable complexity. Each translation step translates more abstract (less detailed) design description into less abstract (more detailed) design representation.
Abstractions are the means of representing various views of the design with varying amounts of details.
More Abstract Level
Check
(Consistency)
Synthesis Analysis
Less Abstract Level
Figure-Design Translations
Different Design Representation levels are called different abstraction levels. The different abstraction levels for representing the behavioral, structural and physical aspects of a design are shown along the corresponding three axes in the Gajski’s Y-Chart.
The Gajski’s Y-Chart graphically represents the three domains and the popular abstraction level used in each of the domains.
DESIGN FLOW USING HDL
Specification + Constraints
Behavioral Description in VHDL
Code Organization Choice
Architecture Choice
RT-Level Description in VHDL
Gate level Net list
Gate-level Net list
Placement & Routing Choice
Physical Design
STEPS IN VLSI DESIGN
Specification Capture
The specification needs to be comprehended and captured through suitable level of abstraction, for example behavioral.
Architecture Design
It includes decomposition of the overall specification (functional + timing) into the specifications (functional + timing) of the constituent blocks and their intercommunications.
Exploration of the architectural alternatives (architectural space) including the possibility of parallelism and pipelining.
It also includes rough estimation of speed/throughput, area and power of each architecture alternatives to decide on an architectural course to be taken i.e. selection of an optimal architecture best suited for the application.
Register- Transfer Level Design
Further refinement of the design is done at Register- Transfer Level (RTL)/ data flow level description.
For a complex processing specification, rarely one can put enough on a chip that would realize the full processing in one step.
PROCESSING ELEMENT
STORAGE
Control Control
Figure- Sequential Control
Therefore, all complex processing is invariable realized via a sequence of simpler processing steps repeatedly using this limited processing hardware and storing the intermediate results that are used in subsequent processing steps i.e. all the complex processing is realized through the use of sequential hardware.
The design issue thus boils down the optimal choice of processing circuitry (one or more processing elements) to be incorporated on the chip, the storage elements, the intercommunication path between the storage elements (both on-chip and off chip) and the processing elements, and the associated sequenci9ng circuitry to the sequencing of processing steps and the actual processing done at each step.
In general, the more complex the processing on the chip, the fewer the processing steps and storage required to achieve full processing.
A Finite State Machine (FSM) for control plus a data path for computation (FSM + D) is a popular abstraction model.
Architecture Exploration and RTL Description
Architecture Exploration involves choosing the number and type of processing elements and implementing/realizing the behavior of the chip using these processing elements.
High- level synthesis tool (transformation of behavioral description to RTL description while exploring different architectures) has begun to help the designers in selected application areas (such as application specific digital signal processing elements).
Logic Level Design
Each of the processing elements, the storage elements and the control part is translated into detailed logic gate level description or the blocks of the logic functions.
Transistor Level Design
A logic function can be realized with the help of transistor circuits of various kinds (with different topologies).
Stick Level Design
Transistor level diagrams are not directly translated into layouts. Stick diagram captures the layer information and topology of the layers that are to be used in the layout.
Physical Design and Layout
Stick diagrams are converted to detailed geometric design (layout) with the appropriate widths, length, separations, overlaps between the layers etc. in view of the design rules and electrical considerations.
Design rules represent the constraints on geometrical patterns on different layers imposed by the considerations of reliable manufacturability of the circuit in a given manufacturing setup (foundry).
Introduction to VHDL
VHDL is a hardware description language for modeling digital systems. In many respects, it is similar to a regular computer programming language such as C++. For example, it has constructs for variable assignments, conditional statements, loops, and functions, just to name a few. In a computer programming language, a compiler is used to translate the high-level source code to machine code.
In VHDL, however, a synthesizer is used to translate the source code to a description of the actual hardware circuit that implements the code. From this description, which we call a net list, the actual physical digital device that realizes the source code can be made automatically. Accurate functional and timing simulation of the code is also possible to test the correctness of the circuit.
Using VHDL to model a digital system can be done at different levels of abstraction, ranging from the structural or gate level to the behavioral or algorithmic level. At the structural level, we specify the components needed in the circuit and how these components are connected together.
To write VHDL code at this level, you must manually design the circuit first. This is analogous to writing programs in machine language.
To use the power of VHDL, our goal is to work at the behavioral level. At this level, we define the circuit using an algorithm written with high-level statements and constructs. The synthesizer automatically translates this high-level code to the net list or circuit that implements the algorithm.
Comments are preceded by two consecutive hyphens ( -- ) and are terminated at the end of the line.
Example:
-- This is a comment
VHDL identifier syntax:
There are three kinds of data objects: signals, variables, and constants. The data object SIGNAL represents logic signals on a wire in the circuit. A signal does not have memory, thus, if the source of the signal is removed, the signal will not have a value.
A VARIABLE object remembers its content and is used for computations in a behavioral model.
A CONSTANT object must be initialized with a value when declared and this value cannot be changed.
Example:
SIGNAL x: BIT;
VARIABLE y: INTEGER;
CONSTANT one: STD_LOGIC_VECTOR(3 DOWNTO 0) := "0001";
BIT and BIT_VECTOR
The BIT and BIT_VECTOR types are predefined in VHDL. Objects of these types can have the values ‘0’ or ‘1’.
The BIT_VECTOR type is simply a vector of type BIT.
Example:
SIGNAL x: BIT;
SIGNAL y: BIT_VECTOR(7 DOWNTO 0);
x <= '1';
y <= "0010";
STD_LOGIC and STD_LOGIC_VECTOR
The STD_LOGIC and STD_LOGIC_VECTOR types provide more values than the BIT type for modeling a real circuit more accurately. Objects of these types can have the following values:
‘0’ −normal 0.
‘1’ −normal 1.
‘Z’ −high impedance.
‘−’ −don’t care.
‘L’ −weak 0.
‘H’ −weak 1.
‘U’ −uninitialized.
‘X’ −unknown.
‘W’ −weak unknown.
The STD_LOGIC and STD_LOGIC_VECTOR types are not predefined and so the two library statements just be included in order to use these types:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
If objects of type STD_LOGIC_VECTOR are to be used as binary numbers in arithmetic manipulations, then either one of the following two USE statements must also be included:
USE ieee.std_logic_signed.ALL; for signed number arithmetic or
USE ieee.std_logic_unsigned.all; for unsigned number arithmetic.
Example:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
SIGNAL x: STD_LOGIC;
SIGNAL y: STD_LOGIC_VECTOR(7 DOWNTO 0);
x <= 'Z';
y <= "001-";
INTEGER
The predefined INTEGER type defines binary number objects for use with arithmetic operators. By default, an INTEGER signal uses 32 bits to represent a signed number. Integers using fewer bits can also be declared with the RANGE keyword.
Example:
SIGNAL x: INTEGER;
SIGNAL y: INTEGER RANGE –64 to 64;
BOOLEAN
The predefined BOOLEAN type defines objects having the two values TRUE and FALSE.
Example:
SIGNAL x: BOOLEAN;
Enumeration TYPE
An enumeration type allows the user to specify the values that the data object can have.
Syntax:
TYPE identifier IS (value1, value2, … );
Example:
TYPE state_type IS (S1, S2, S3);
SIGNAL state: state_type;
state <= S1;
ARRAY
The ARRAY type groups single data objects of the same type together into a one or multi- dimensional array.
Syntax:
TYPE identifier IS ARRAY (range) OF type;
Example:
TYPE byte IS ARRAY(7 DOWNTO 0) OF BIT;
TYPE memory_type IS ARRAY(1 TO 128) OF byte;
SIGNAL memory: memory_type;
memory(3) <= "00101101";
SUBTYPE
A SUBTYPE is a subset of a type, that is, a type with a range constraint.
Syntax:
SUBTYPE identifier IS type RANGE range;
Example:
SUBTYPE integer4 IS INTEGER RANGE –8 TO 7;
SUBTYPE cell IS STD_LOGIC_VECTOR(3 DOWNTO 0);
TYPE memArray IS ARRAY(0 TO 15) OF cell;
The VHDL Built-in operators are listed below.
Describing a design:
In VHDL an entity is used to describe a hardware module.
An entity can be described using,
1. Entity declaration.
2. Architecture.
3. Configuration
4. Package declaration.
5. Package body.
Entity declaration:
An ENTITY declaration declares the external or user interface of the module similar to the declaration of a function. It specifies the name of the entity and its interface. The interface consists of the signals to be passed into the entity or out from it.
Syntax:
entity entity_name is
Port declaration
end entity_name;
Example:
ENTITY ABC IS PORT (M: IN BIT; D: IN BIT; V: IN BIT; S: OUT BIT);
END ABC;
An entity declaration should starts with ‘entity’ and ends with ‘end’ keywords.
Ports are interfaces through which an entity can communicate with its environment. Each port must have a name, direction and a type. An entity may have no port declaration also. The direction will be input, output or inout
In | Port can be read |
Out | Port can be written |
Inout | Port can be read and written |
Buffer | Port can be read and written, it can have only one source. |
Architecture:
It describes the internal description of design or it tells what is there inside design. Each entity has atleast one architecture and an entity can have many architecture. Architecture can be described using structural, dataflow, behavioral or mixed style. Architecture can be used to describe a design at different levels of abstraction like gate level, register transfer level (RTL) or behavior level.
The syntax for the architecture varies depending on the model (dataflow, behavioral, or structural) you use.
Syntax for dataflow model::
ARCHITECTURE architecture-name OF entity-name IS
signal-declarations;
BEGIN
concurrent-statements;
END architecture-name;
The concurrent-statements are executed concurrently.
Example:
ARCHITECTURE Siren_Dataflow OF Siren IS
SIGNAL term_1: BIT;
BEGIN
term_1 <= D OR V;
S <= term_1 AND M;
END Siren_Dataflow;
Syntax for behavioral model:
ARCHITECTURE architecture-name OF entity-name IS
signal-declarations;
function-definitions;
procedure-definitions;
BEGIN
PROCESS-blocks;
concurrent-statements;
END architecture-name;
Statements within the process-block are executed sequentially. However, the process-block itself is a concurrent statement.
Example:
ARCHITECTURE Siren_Behavioral OF Siren IS
SIGNAL term_1: BIT;
BEGIN
PROCESS (D, V, M)
BEGIN
term_1 <= D OR V;
S <= term_1 AND M;
END PROCESS;
END Siren_Behavioral;
ARCHITECTURE architecture-name OF entity-name IS
component-declarations;
signal-declarations;
BEGIN
instance-name: PORT MAP-statements;
concurrent-statements;
END architecture-name;
For each component declaration used, there must be a corresponding entity and architecture for that component.
The PORT MAP statements are concurrent statements.
Example:
ARCHITECTURE Siren_Structural OF Siren IS
COMPONENT myOR PORT ( in1, in2: IN BIT; out1: OUT BIT);
END COMPONENT;
SIGNAL term1: BIT;
BEGIN
U0: myOR PORT MAP (D, V, term1);
S <= term1 AND M;
END Siren_Structural;
Here we should specify the entity name for which we are writing the architecture body. The architecture statements should be inside the begin and end keyword. Architecture declarative part may contain variables, constants, or component declaration.
Configuration:
If an entity contains many architectures and any one of the possible architecture binding with its entity is done using configuration. It is used to bind the architecture body to its entity and a component with an entity.
Syntax:
configuration configuration_name of entity_name is
block_configuration;
end configuration_name.
for block_name component_binding;
end for;
block_name is the name of the architecture body. Component binding binds the components of the block to entities. This can be written as,
for component_labels:component_name
block_configuration;
end for;
Package declaration:
Package declaration is used to declare components, types, constants, functions and so on.
Syntax:
package package_name is
Declarations;
end package_name;
Example:
LIBRARY work;
USE work.my_package.ALL;
ENTITY test_package IS PORT ( x: IN bit4; z: OUT bit4);
END test_package;
ARCHITECTURE Behavioral OF test_package IS
BEGIN
mysignal <= x;
z <= Shiftright(mysignal);
END Behavioral;
Package body:
A package body is used to declare the definitions and procedures that are declared in corresponding package. Values can be assigned to constants declared in package in package body.
Syntax:
package body package_name is
Function_procedure definitions;
end package_name;
ARCHITECHTURE BODY
The internal working of an entity can be defined using different modeling styles inside architecture body. They are
1. Dataflow modeling.
2. Behavioral modeling.
3. Structural modeling.
Fig. - Structure of an Entity
Dataflow modeling:
In this style of modeling, the internal working of an entity can be implemented using concurrent signal assignment.
Let’s take half adder example which is having one XOR gate and a AND gate.
Library IEEE; use IEEE.STD_LOGIC_1164.all; entity ha_en is port ( A,B:in bit; S,C:out bit); end ha_en; architecture ha_ar of ha_en is begin S<=A xor B; C<=A and B; end ha_ar; |
Here STD_LOGIC_1164 is an IEEE standard which defines a nine-value logic type, called STD_ULOGIC. use is a keyword, which imports all the declarations from this package. The architecture body consists of concurrent signal assignments, which describes the functionality of the design. Whenever there is a change in RHS, the expression is evaluated and the value is assigned to LHS.
Behavioral modeling:
In this style of modeling, the internal working of an entity can be implemented using set of statements.
The PROCESS block contains statements that are executed sequentially. However, the PROCESS statement itself is a concurrent statement. Multiple process blocks in an architecture will be executed simultaneously. These process blocks can be combined together with other concurrent statements.
Syntax:
process-name: PROCESS (sensitivity-list)
variable-declarations;
BEGIN
sequential-statements;
END PROCESS process-name;
The sensitivity-list is a comma-separated list of signals in which the process is sensitive to. In other words, whenever a signal in the list changes value, the process will be executed, that is, all the statements in the sequential order listed. After the last statement has been executed, the process will be suspended until the next time that a signal in the sensitivity list changes value before it is again executed.
Example:
PROCESS (D, V, M)
BEGIN
term_1 <= D OR V;
S <= term_1 AND M;
END PROCESS;
Assigns a value to a signal. This statement is just like its concurrent counterpart except that it is executed sequentially, that is, only when execution reaches it.
Syntax:
signal <= expression;
Example:
y <= '1';
z <= y AND (NOT x);
Assigns a value or the result of evaluating an expression to a variable. The value is always assigned to the variable instantaneously whenever this statement is executed.
Variables are only declared within a process block.
Syntax:
signal := expression;
Example:y := '1';
yn := NOT y;
When a process has a sensitivity list, the process always suspends after executing the last statement. An alternative to using a sensitivity list to suspend a process is to use a WAIT statement, which must also be the first statement in a process1.
Syntax2:
WAIT UNTIL condition;
Example:-- suspend until a rising clock edge
WAIT UNTIL clock’EVENT AND clock = '1';
Inside the process the execution of statements will be sequential and if one entity is having two processes the execution of these processes will be concurrent. At the end it waits for another event to occur.
library IEEE; use IEEE.STD_LOGIC_1164.all; entity ha_beha_en is port( A : in BIT; B : in BIT; S : out BIT; C : out BIT ); end ha_beha_en; architecture ha_beha_ar of ha_beha_en is begin process_beh:process(A,B) begin S<= A xor B; C<=A and B; end process process_beh; end ha_beha_ar; |
Here whenever there is a change in the value of a or b the process statements are executed.
Structural modeling:
The structural model allows the manual connection of several components together using signals. All components used must first be defined with their respective ENTITY and ARCHITECTURE sections, which can be in the same file or they can be in separate files.
In the topmost module, each component used in the netlist is first declared using the COMPONENT statement. The declared components are then instantiated with the actual components in the circuit using the PORT MAP statement.
SIGNALs are then used to connect the components together according to the netlist.
Declares the name and the interface of a component that is used in the circuit description. For each component declaration used, there must be a corresponding entity and architecture for that component. The declaration name and the interface must match exactly the name and interface that is specified in the entity section for that component.
Syntax:
COMPONENT component-name IS
PORT (list-of-port-names-and-types);
END COMPONENT;
Example:
COMPONENT half_adder IS PORT (
xi, yi, cin: IN BIT;
cout, si: OUT BIT);
END COMPONENT;
The PORT MAP statement instantiates a declared component with an actual component in the circuit by specifying how the connections to this instance of the component are to be made.
Syntax:
label: component-name PORT MAP (association-list);
The association-list can be specified using either the positional or named method.
Example (positional association):
SIGNAL x0, x1, y0, y1, c0, c1, c2, s0, s1: BIT;
U1: half_adder PORT MAP (x0, y0, c0, c1, s0);
U2: half_adder PORT MAP (x1, y1, c1, c2, s1);
Example (named association):
SIGNAL x0, x1, y0, y1, c0, c1, c2, s0, s1: BIT;
U1: half_adder PORT MAP (cout=>c1, si=>s0, cin=>c0, xi=>x0, yi=>y0);
U2: half_adder PORT MAP (cin=>c1, xi=>x1, yi=>y1, cout=>c2, si=>s1);
The GENERATE statement works like a macro expansion. It provides a simple way to duplicate similar components.
Syntax:
label: FOR identifier IN start [TO | DOWNTO] stop GENERATE
port-map-statements;
END GENERATE label;
Example:-- using a FOR-GENERATE statement to generate four instances of the full adder
-- component for a 4-bit adder
ENTITY Adder4 IS PORT (
Cin: IN BIT;
A, B: IN BIT_VECTOR(3 DOWNTO 0);
Cout: OUT BIT;
SUM: OUT BIT_VECTOR(3 DOWNTO 0));
END Adder4;
ARCHITECTURE Structural OF Adder4 IS
COMPONENT FA PORT (
ci, xi, yi: IN BIT;
co, si: OUT BIT);
END COMPONENT;
SIGNAL Carryv: BIT_VECTOR(4 DOWNTO 0);
BEGIN
Carryv(0) <= Cin;
Adder: FOR k IN 3 DOWNTO 0 GENERATE
FullAdder: FA PORT MAP (Carryv(k), A(k), B(k), Carryv(k+1), SUM(k));
END GENERATE Adder;
Cout <= Carryv(4);
END Structural;
Let’s try to understand this by taking the example of full adder using 2 half adder and 1 OR gate.
library IEEE; use IEEE.STD_LOGIC_1164.all; entity fa_en is port(A,B,Cin:in bit; SUM, CARRY:out bit); end fa_en; architecture fa_ar of fa_en is component ha_en port(A,B:in bit;S,C:out bit); end component; signal C1,C2,S1:bit; begin HA1:ha_en port map(A,B,S1,C1); HA2:ha_en port map(S1,Cin,SUM,C2); CARRY <= C1 or C2; end fa_ar; |
The program we have written for half adder in dataflow modeling is instantiated as shown above. ha_en is the name of the entity in dataflow modeling. C1, C2, S1 are the signals used for internal connections of the component which are declared using the keyword signal. Port map is used to connect different components as well as connect components to ports of the entity.
Component instantiation.
Component_label: component_name port map (signal_list);
Signal_list is the architecture signals which we are connecting to component ports. This can be done in different ways. What we declared above is positional binding. One more type is the named binding. The above can be written as:
HA1:ha_en port map(A => A,B => B, S => S1 ,C => C1 );
HA2:ha_en port map(A => S1,B => Cin, S=> SUM, C => C2);
Test bench:
The correctness of the above program can be checked by writing the test bench.
The test bench is used for generating stimulus for the entity under test. Let’s write a simple test bench for full adder.
library IEEE; use IEEE.STD_LOGIC_1164.all; entity tb_en is end tb_en; architecture tb_ar of tb_en is signal a_i,b_i,c_i,sum_i,carry_i:bit; begin eut: entity work.fa_en(fa_ar) port map(A=>a_i,B=>b_i,Cin=>c_i,SUM=>sum_i,CARRY=>carry_i); stimulus: process begin a_i<='1';b_i<='1';c_i<='1'; wait for 10ns; a_i<='0';b_i<='1';c_i<='1'; wait for 10ns; a_i<='1';b_i<='0';c_i<='0'; wait for 10ns; if now=30ns then wait; end if; end process stimulus; end tb_ar; |
INTRODUCTION TO SYNTHESIS
VHDL is a hardware description language that cannot only describe hardware at the gate level and the Register Transfer Level (RTL), but also at the behavior level using abstract data types. This makes translating a design described in VHDL to logic gates a nontrivial process.
Synthesis is the process of constructing a gate level net list from a model of circuit described in VHDL. Figure shows such a process. A synthesis program may alternately generate RTL net list, which is comprised of Register Transfer Level blocks such as flip flops, arithmetic logic units, multiplexers interconnected by wires. In such a case a second program called the RTL module builder is necessary. The purpose of this builder is to build, or acquire from a library of predefined components, each of the required RTL blocks in the user specified target technology
VHDL Model
SYNTHESIS
RTL module Builder
Area & Timing
Target constraints
Technology
Unoptimized
Logic Optimizer
Gate level net list
Optimized gate level net list
Figure- Synthesis Flow
Having produced a gate level net list, a logic optimizer reads in this net list, and optimizes the circuit for the user specified area and timing constraints. These area and timing constraints, may also be the module builder for the appropriate selection or generation of RTL blocks. A mapping mechanism or a construction mechanism has to be provided that translates the VHDL elements into their corresponding hardware elements.
VHDL is actually made for the use of simulation, so all of the VHDL constructs are not synthesizable. Only a subset of all the constructs is synthesizable. So, it becomes necessary that the designer write the code so that it should be synthesizable and should not have unnecessary latches and logic.
VHDL: A LOGIC SYNTHESIS APPROACH
Logic Synthesis
Specification + Constraints
Behavioral Description in VHDL
Behavioral Synthesis
RT-Level Description in VHDL
Logic Synthesis
Gate-level Net list
Mapped to Xilinx FPGA Device
Figure- VHDL Design Flow
DESIGN UNITS:
There are five kinds of design units provided in VHDL;
SIMULATION CYCLE:
Simulation is the means for optimization and verification of correctness of complex designs. It allows exploration of alternative designs and decreases the difficulty in debugging hardware.
START
SIMULATION
UPDATE EXECUTE
SIGNALS PROCESS
END SIMULATION
Figure- Simulation Cycle
Combinational circuit Design
Combinational circuits are the class of digital circuits where the outputs of the circuit are dependent only on the current inputs. They do not remember the history of past inputs and, therefore, do not require any memory elements.
Sequential circuits on the other hand are circuits in which their outputs are dependent on not only the current inputs but also on past inputs. Because of their dependency on past inputs, sequential circuits must contain memory elements in order to remember the past input values.
A “large” digital circuit, however, may contain both combinational circuits and sequential circuits. However, regardless of whether it is a combinational circuit or a sequential circuit, it is nevertheless a digital circuit, and so they use the same basic building blocks – the AND, OR and NOT gates. What makes them different is in the way the gates are connected.
Combinational components are combinational circuits. Standard combinational components are used in the construction of the datapath. Even though the next-state logic and output logic circuits in the control unit are combinational circuits, they are not considered as standard combinational components available in libraries since they are designed uniquely for a particular control unit to solve a specific problem.
Standard combinational components include but not limited to adder/subtractor, ALU, multiplexer, tri-state buffer, decoder, encoder, comparator, shifter/rotator, and multiplier.
ADDER
Full ADDER
To construct an adder for adding two binary numbers, X = xn-1 … x0 and Y = yn-1 … y0, we need to first consider the addition of a single bit slice xi with yi, together with the carry-in bit ci from the previous bit position. The result from this addition is a sum bit si and a carry-out bit ci+1 for the next bit position. Hence, si = xi + yi + ci, and ci+1 = 1 if there is a carry from the addition to the next bit. The circuit for the addition of this single bit slice is known as a full adder (FA) and its truth table is shown in Figure 4.2 (a). The equations for si and ci+1 are derived as follows:
Fig. - Half Adder (Truth Table, Symbol, Equations, Circuit)
So here is the 'half adder' implemented in VHDL:
library ieee;use ieee.std_logic_1164.all;
--here is the entity
entity halfadd isport (a, b : in std_logic;sum, c : out std_logic);end halfadd;
architecture comp of halfadd is
begin
--a concurrent statement implementing the and gate
c <= a and b;
--a concurrent statement implementing the xor gate
sum <= a xor b;
end comp;
Fig. - Full Adder (Truth Table, Equations, Circuit)
These statements are 'concurrent', which means they are executed at the same time and with no precedence.
Here is an implementation of the full adder using component instantiation through a port map:
library ieee;
use ieee.std_logic_1164.all;
entity fulladd is
port (ina, inb, inc : in std_logic; sumout, outc : out std_logic);
end fulladd;
architecture top of fulladd is
component halfadd
port (a, b : in std_logic; sum, c : out std_logic);
end component;
signal s1, s2, s3 : std_logic;
begin
--a structural instantiation of two half adders
h1: halfadd port map( a => ina, b => inb,sum => s1, c => s3);
h2: halfadd port map( a => s1, b => inc,sum => sumout, c => s2);
outc <= s2 or s3;
end top;
The full adder is for adding two operands that are only one bit wide. To add two operands that are, say eight bits wide we connect eight full adders together in series. The resulting circuit, shown in Figure 4..4, is called a ripple carry adder for adding two eight-bit operands.
Since the FA adds the three bits xi, yi and ci together, we need to set c0 to be 0 in order to perform the addition correctly. Moreover, cout is set to a 1 when there is an overflow for an unsigned addition.
The structural VHDL code for the 4-bit ripple-carry adder is shown . Since we need to duplicate the full adder component four times, we can either use the PORT MAP statement four times or by using the FORGENERATE statement as shown in the code to automatically generate the four components. The statement FOR k IN 3 DOWNTO 0 GENERATE determines how many times to repeat the PORT MAP statement and the values used for k.
Fig. - Full adder: (a) truth table; (b) circuit; (c) logic symbol.
VHDLcode for a 4-bit ripple-carry adder using a FOR-GENERATE statement.
ENTITY FA IS PORT (
ci, xi, yi: IN BIT;
co, si: OUT BIT);
END FA;
ARCHITECTURE Dataflow OF FA IS
BEGIN
co <= (xi AND yi) OR (ci AND (xi XOR yi));
si <= xi XOR yi XOR ci;
END Dataflow;
ENTITY Adder4 IS PORT (
Cin: IN BIT;
A, B: IN BIT_VECTOR(3 DOWNTO 0);
Cout: OUT BIT;
SUM: OUT BIT_VECTOR(3 DOWNTO 0));
END Adder4;
ARCHITECTURE Structural OF Adder4 IS
COMPONENT FA PORT (
ci, xi, yi: IN BIT;
co, si: OUT BIT);
END COMPONENT;
SIGNAL Carryv: BIT_VECTOR(4 DOWNTO 0);
BEGIN
Carryv(0) <= Cin;
Adder: FOR k IN 3 DOWNTO 0 GENERATE
FullAdder: FA PORT MAP (Carryv(k), A(k), B(k), Carryv(k+1), SUM(k));
END GENERATE Adder;
Cout <= Carryv(4);
END Structural;
A decoder, also known as a demultiplexer, asserts one out of n output lines depending on the value of an m-bit binary input data. In general, an m-to-n decoder has m input lines, Am-1, …, A0, and n output lines, Yn-1, …, Y0, where n = 2m. In addition, it has an enable line E for enabling the decoder. When the decoder is disabled with E set to 0, all the output lines are de-asserted. When the decoder is enabled, then the output line whose index is equal to the value of the input binary data is asserted. For example, for a 3-to-8 decoder, if the input address is 101, then the output line Y5 is asserted (set to 1 for active high) while the rest of the output lines are de-asserted (set to 0 for active high).
A decoder is used in a system having multiple components and we want only one component to be selected or enabled at any one time. For example, in a large memory system with multiple memory chips, only one memory chip is enabled at a time. One output line from the decoder is connected to the enable input on each memory chip.
An address presented to the decoder will thus enable that corresponding memory chip. The truth table, circuit and logic symbol for a 3-to-8 decoder are shown in Figure 4.7.
A larger size decoder can be implemented using several smaller decoders. For example, Figure 4.8 uses seven 1- to-2 decoders to implement a 3-to-8 decoder. The correct operation of this circuit is left as an exercise for the reader.The behavioral VHDL code for the 3-to-8 decoder is shown
.
Fig. - A 3-to-decoder: (a) truth table; (b) circuit; (c) logic symbol.
-- A 3-to-8 decoder
LIBRARY ieee;
USE IEEE.std_logic_1164.all;
ENTITY Decoder IS PORT(
E: IN std_logic; -- enable
A: IN std_logic_vector(2 DOWNTO 0); -- 3 bit address
Y: OUT std_logic_vector(7 DOWNTO 0)); -- data bus output
END Decoder;
ARCHITECTURE Behavioral OF Decoder IS
BEGIN
PROCESS (E, A)
BEGIN
IF (E = '0') THEN -- disabled
Y <= (OTHERS => '0'); -- 8-bit vector of 0
ELSE
CASE A IS -- enabled
WHEN "000" => Y <= "00000001";
WHEN "001" => Y <= "00000010";
WHEN "010" => Y <= "00000100";
WHEN "011" => Y <= "00001000";
WHEN "100" => Y <= "00010000";
WHEN "101" => Y <= "00100000";
WHEN "110" => Y <= "01000000";
WHEN "111" => Y <= "10000000";
WHEN OTHERS => NULL;
END CASE;
END IF;
END PROCESS;
END Behavioral;
MULTIPLEXER
The multiplexer, or mux for short, allows the selection of one input signal among n signals, where n > 1 and is a power of two. Select lines connected to the multiplexer determine which input signal is selected and passed to the output of the multiplexer. In general, an n-to-1 multiplexer has n data input lines, s select lines where s = log2 n, i.e. 2s = n, and one output line. For a 2-to-1 multiplexer, there is one select line s to select between the two inputs, d0 and d1. When s = 0, the input line d0 is selected, and the data present on d0 is passed to the output y. When s = 1, the input line d1 is selected and the data on d1 is passed to y.
The truth table, circuit and logic symbol for a 2-to-1 mux are shown in Figure 6. In the truth table, y takes on the value of d0 for the first four rows when s = 0. For the last four rows in the table when s = 1, y takes on the value of d1. The minimized circuit of Figure 4.9 (b) is derived as follows:
y = s'd1'd0 + s'd1d0 + sd1d0' + sd1d0
= s'd0(d1' + d1) + sd1(d0' + d0)
= s'd0 + sd1
(b)
Fig.- A 2-to-1 multiplexer: (a) truth table; (b) circuit; (c) logic symbol.
The VHDL code for an 8-bit wide 4-to-1 multiplexer is shown. Two different implementations of the same multiplexer are shown. The first implementation, written at the behavioral level, uses a process statement. The second implementation, written at the dataflow level, uses a concurrent selected signal assignment statement.
VHDL code for an 8-bit wide 4-to-1 multiplexer.
-- A 4-to-1 8-bit wide multiplexer
LIBRARY ieee;
USE IEEE.std_logic_1164.all;
ENTITY Multiplexer IS
PORT(S: IN std_logic_vector(1 DOWNTO 0); -- select lines
D0, D1, D2, D3: IN std_logic_vector(7 DOWNTO 0); -- data bus input
Y: OUT std_logic_vector(7 DOWNTO 0)); -- data bus output
END Multiplexer;
-- Behavioral level code
ARCHITECTURE Behavioral OF Multiplexer IS
BEGIN
PROCESS (S,D0,D1,D2,D3)
BEGIN
CASE S IS
WHEN "00" => Y <= D0;
WHEN "01" => Y <= D1;
WHEN "10" => Y <= D2;
WHEN "11" => Y <= D3;
WHEN OTHERS => Y <= (OTHERS => 'U'); -- 8-bit vector of U
END CASE;
END PROCESS;
END Behavioral;
-- Dataflow level code
ARCHITECTURE Dataflow OF Multiplexer IS
BEGIN
WITH S SELECT Y <=
D0 WHEN "00",
D1 WHEN "01",
D2 WHEN "10",
D3 WHEN "11",
(OTHERS => 'U') WHEN OTHERS; -- 8-bit vector of U
END Dataflow;
Sequential Circuit Design
Combinational logic refers to circuits whose output is strictly depended on the present value of the inputs. As soon as inputs are changed, the information about the previous inputs is lost, that is, combinational logics circuits have no memory. In many applications, information regarding input values at a certain instant of time is required at some future time. Although every digital system is likely to have combinational circuits, most systems encountered in practice also include memory elements, which require that the system be described in terms of sequential logic. Circuits whose outputs depends not only on the present input value but also the past input value are known as sequential logic circuits. The mathematical model of a sequential circuit is usually referred to as a sequential machine.
A general block diagram of a sequential circuit is shown below in Figure
Fig. - Block Diagram of Sequential Circuit.
The diagram consists of combinational circuit to which memory elements are connected to form a feedback path. The memory elements are devices capable of storing binary information within them. The combinational part of the circuit receives two sets of input signals: one is primary (coming from the circuit environment) and secondary (coming from memory elements). The particular combination of secondary input variables at a given time is called the present state of the circuit. The secondary input variables are also known as the state variables.
The block diagram shows that the external outputs in a sequential circuit are a function not only of external inputs but also of the present state of the memory elements. The next state of the memory elements is also a function of external inputs and the present state. Thus a sequential circuit is specified by a time sequence of inputs, outputs, and internal states.
Sequential Circuit Components
VHDL does not have any explicit object for defining a memory element. Instead, the semantics of the language provides for signals to be interpreted as a memory element. In other words, memory element is declared depending on how these signals are assigned.
If Enable is 1 then Q gets the value of D, otherwise Q gets a 0. In this code, Q is assigned a value for all possible outcomes of the test in the IF statement. With this construct, a combinational circuit is produced.
Sample VHDL description of a combinational circuit.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY no_memory_element IS PORT ( D, Enable: IN std_logic; Q: OUT std_logic);
END no_memory_element;
ARCHITECTURE Behavior OF no_memory_element IS
BEGIN
PROCESS(D, Enable)
BEGIN
IF Enable = '1' THEN
Q <= D;
ELSE
Q <= '0';
END IF;
END PROCESS;
END Behavior;
If we remove the ELSE and the statement in the else part as shown in next code, then we have a situation where no value is assigned to Q if Enable is not 1. The key point here is that the VHDL semantics stipulate that in cases where the code does not specify a value of a signal, the signal should retain its current value. In other words, the signal must remember its current value, and in order to do so, a memory element is implied.
The VHDL code for a D latch with enable. If Enable is 1 then Q gets the value of D. However, if Enable is not 1, the code does not specify what Q should be, therefore, Q retains its current value by using a memory element. This code produces a latch and not a flip-flop because Q follows D as long as Enable is 1, and not only at the active edge of the Enable signal. The process sensitivity list includes both D and Enable because either one of these signals can cause a change in the value of the Q output.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY D_latch_with_enable IS PORT ( D, Enable: IN std_logic; Q: OUT std_logic);
END D_latch_with_enable;
ARCHITECTURE Behavior OF D_latch_with_enable IS
BEGIN
PROCESS(D, Enable)
BEGIN
IF Enable = '1' THEN
Q <= D;
END IF;
END PROCESS;
END Behavior;
The behavioral VHDL code for a positive-edge-triggered D flip-flop. The only difference here is that Q follows D only at the rising edge of the clock, and it is specified here by the condition “Clock' EVENT AND Clock = '1'.” The ' EVENT attribute refers to any changes in the qualifying Clock signal.
So when this happens and the resulting Clock value is a 1, we have in effect, a condition for a positive or rising clock edge. Again, the code does not specify what is assigned to Q when the condition in the IF statement is false so it implies a memory element. Note also that the process sensitivity list contains only the clock signal because it is the only signal that can cause a change in the Q output.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY D_flipflop IS PORT ( D, Clock: IN std_logic; Q: OUT std_logic);
END D_flipflop;
ARCHITECTURE Behavior OF D_flipflop IS
BEGIN
PROCESS(Clock) D flip-flop
BEGIN
IF Clock’EVENT AND Clock = '1' THEN
Q <= D;
END IF;
END PROCESS;
END Behavior;
Another way to describe a flip-flop is to use the WAIT statement instead of the IF statement as shown . When execution reaches the WAIT statement, it stops until the condition in the statement is true before proceeding. The WAIT statement, when used in a process block for synthesis, must be the first statement in the process. Note also that the process sensitivity list is omitted because the WAIT statement implies that the sensitivity list contains only the clock signal.
Structural VHDL code for a positive-edge-triggered D flip-flop.
-- define the structural operation of the D flip-flop
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY positive_edge_triggered_D_flipflop IS PORT (
D, Clock: IN std_logic;
Q, QN: BUFFER std_logic);
END positive_edge_triggered_D_flipflop;
ARCHITECTURE StructuralDFF OF positive_edge_triggered_D_flipflop IS
SIGNAL N1, N2, N3, N4: std_logic;
COMPONENT SRlatch PORT (
SN, RN: IN std_logic;
Q, QN: BUFFER std_logic);
END COMPONENT;
COMPONENT NAND_2 PORT (
I0, I1: IN std_logic;
O: OUT std_logic);
END COMPONENT;
COMPONENT NAND_3 PORT (
I0, I1, I2: IN std_logic;
O: OUT std_logic);
END COMPONENT;
BEGIN
U1: SRlatch PORT MAP (N4, Clock, N1, N2); -- set latch
U2: SRlatch PORT MAP (N2, N3, Q, QN); -- output latch
U3: NAND_3 PORT MAP (N2, Clock, N4, N3); -- reset latch
U4: NAND_2 PORT MAP (N3, D, N4); -- reset latch
END StructuralDFF;
Fig.- Simulation trace for the positive-edge-triggered D flip-flop.
Registers
When we want to store a byte of data, we need to combine eight flip-flops together, and have them work as a unit. A register is just a circuit with two or more D flip-flops connected together in such a way that they all work exactly the same way, and are synchronized by the same clock and enable signals. The only difference is that each flip-flop in the group is used to store a different bit of the data.
Figure (a) shows a 4-bit register with parallel load and asynchronous clear. Four D flip-flops with active high enable and asynchronous clear are used. Notice in the circuit that the control inputs Clk, E, and Clear for all the flip-flops are respectively connected in common so that when a particular input is asserted, all the flip-flops will behave in exactly the same way. The 4-bit input data is connected to D0 through D3, while Q0 through Q3 serve as the 4-bit output data for the register. When the active high load signal Load is asserted, i.e. Load = 1, the data presented on the D lines is stored into the register (the four flip-flops) at the next rising edge of the clock signal.
When Load is de-asserted, the content of the register remains unchanged. The register can be asynchronously cleared, i.e., setting all the Qi's to 0, by asserting the Clear line. The content of the register is always available on the Q lines, so no control line is required for reading the data from the register. Figure (b) and (c) show the operation table and the logic symbol respectively for this 4-bit register.
A sample simulation trace for the register is shown in Figure. At time 100ns, even though Load is asserted, the register is not written with the D input value 5, because Clear is asserted. Between times 200ns and 400ns, Load is de-asserted, so even though Clear is de-asserted, the register is still not loaded with the input value 5. At time 400ns, Load is asserted but the input data is not loaded into the register immediately as can be seen by Q being a 0. The loading occurs at the next rising edge of the clock at 500ns when Q changes to 5. At time 600ns, Clear is asserted, and so Q is reset to 0 immediately without having to wait until the next rising clock edge at 700ns.
(a)
(c)
(b)
Fig.- A 4-bit serial-to-parallel shift register: (a) circuit; (b) operation table; (c) logic symbol.
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY D_flipflop IS
PORT(D, Clock, E : IN STD_LOGIC; Q : OUT STD_LOGIC);
END D_flipflop;
ARCHITECTURE Behavior OF D_flipflop IS
BEGIN
PROCESS(Clock)
BEGIN
IF Clock'EVENT AND Clock = '1' THEN
IF E = '1' THEN
Q <= D;
END IF;
END IF;
END PROCESS;
END Behavior;
-- 4-bit shift register
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY ShiftReg IS
PORT(Serialin, Clock, Shift : IN STD_LOGIC; Q : OUT STD_LOGIC_VECTOR(3 downto 0));
END ShiftReg;
ARCHITECTURE Structural OF ShiftReg IS
SIGNAL N0, N1, N2, N3 : STD_LOGIC;
COMPONENT D_flipflop PORT (D, Clock, E : IN STD_LOGIC; Q : OUT STD_LOGIC);
END COMPONENT;
BEGIN
U1: D_flipflop PORT MAP (Serialin, Clock, Shift, N3);
U2: D_flipflop PORT MAP (N3, Clock, Shift, N2);
U3: D_flipflop PORT MAP (N2, Clock, Shift, N1);
U4: D_flipflop PORT MAP (N1, Clock, Shift, N0);
Q(3) <= N3;
Q(2) <= N2;
Q(1) <= N1;
Q(0) <= N0;
END Structural;
Fig. - Sample simulation trace for the 4-bit serial-in-parallel-out shift register
REFERENCES & BIBLIOGRAPHY
[1] Enoch O.Hwang –Microprocessor Design Principal and Practices with VHDL
[2] J. Bhasker – VHDL Primer, Pearson Education Asia
[3] M.Morris Mano - Digital Design, Pearson Education Asia
Websites
[1] http://www.xilinx.com/support/library.htm - Xilinx Documentation and Library.