33
VHDl is a hardware description language. It is used to describe the behavior of an electronic circuit or system. VHDl stands for VHSIC Hardware Description Language. VHSIC stands for Very High Speed Integrated Circuits. It was initially funded by the United States Department of Defense in the 1980s. Its first version was VDHL 87, later upgraded to so-called VHDL 93. VHDL was the original and the first hardware description language to be standardized by IEEE (Institute of Electrical and Electronics Engineers), through the IEEE 1076 standard. An additional standard, IEEE 1164 was later added. Design Flow We start the design by writing the VHDL code, which is saved in a file with the extension .vhd and the name is same as its Entity's name. Then the next step is compilation. Compilation is the conversion of the high-level VHDL language into a netlist at the gate level. The second step is optimization, which is performed on the gate-level net-list for speed or for area. At this stage, the design can be simulated. Finally, a place-and-route (filter) software will generate the physical layout. Fundamental VHDL Units A standalone piece of VHDL code is composed of atleast three fundamental sections: Library declarations: Contains a list of all libraries to be used in the design. Example:ieee, std, work etc. Entity: Specifies the Input/Output pins of the circuit. Visit www.DeepArash.blogspot.com for more tutorials

Vhdl Tutorial

  • Upload
    31d

  • View
    565

  • Download
    3

Embed Size (px)

DESCRIPTION

www.deeparash.blogspot.com

Citation preview

Page 1: Vhdl Tutorial

VHDl is a hardware description language. It is used to describe the behavior of an electronic circuit or system.

VHDl stands for VHSIC Hardware Description Language. VHSIC stands for Very High Speed Integrated Circuits. It was initially funded by the United States Department of Defense in the 1980s. Its first version was VDHL 87, later upgraded to so-called VHDL 93.

VHDL was the original and the first hardware description language to be standardized by IEEE (Institute of Electrical and Electronics Engineers), through the IEEE 1076 standard. An additional standard, IEEE 1164 was later added.

Design Flow

We start the design by writing the VHDL code, which is saved in a file with the extension .vhd and the name is same as its Entity's name. Then the next step is compilation.

Compilation is the conversion of the high-level VHDL language into a netlist at the gate level.

The second step is optimization, which is performed on the gate-level net-list for speed or for area.

At this stage, the design can be simulated.

Finally, a place-and-route (filter) software will generate the physical layout.

Fundamental VHDL Units

A standalone piece of VHDL code is composed of atleast three fundamental sections:

• Library declarations: Contains a list of all libraries to be used in the design. Example:ieee, std, work etc.

• Entity: Specifies the Input/Output pins of the circuit.

Visit www.DeepArash.blogspot.com for more tutorials

Page 2: Vhdl Tutorial

• Architecture: Contains the VHDl code, which describes how the circuit should behave (function).

Library Declarations

To declare a Library ( that is, to make it visible to the design) two lines of code are needed, one containing the name of the library, and other a use clause, as shown in syntax below.

library library_name;

use library_name.package_name.package_parts;

Example:

library ieee;

use ieee.std_logic_1164.all;

Some other library declarations are as follows:

• library std;

use std.standard.all;

• library work;

use work.all;

The ieee library contains several packages, including the following:

• std_logic_1164: Specifies the STD_LOGIC (8 levels) and STD_ULOGIC (9 levels) multi-values logic systems.

• std_logic_arith

• std_logic_signed

• std_logic_unsigned

Entity

An Entity is a list with specifications of all input and output pins(ports) of the circuit. Its suntax is shown below:

entity entity_name is

port(

port_name : signal_mode signal_type;

Page 3: Vhdl Tutorial

port_name : signal_mode signal_type;

....);

end entity_name;

Example:

entity nand_gate is

port(

a, b : in bit ;

x : out bit;

);

end nand_gate;

Architecture

The Architecture is a description of how the circuit should behave(function).

Its syntax is given below:

architecture architecture_name of entity_name is

(declarations)

begin

(code)

end architecture_name;

Example:

architecture myarchi of nand_gate is

begin

x <= a nand b;

end myarchi;

Identifiers

Identifiers are used to name items in a VHDL model. An identifier

Page 4: Vhdl Tutorial

• may only contain alphabetic letters (‘A’ to ‘Z’ and ‘a’ to ‘z’), decimal digits (‘0’ to ‘9’) and the underline

character (‘_’);

• must start with an alphabetic letter;

• may not end with an underline character; and

• may not include two successive underline characters.

Case of letters is not significant. Some examples of valid basic identifiers are

A, X0, counter, Next_Value, generate_read_cycle

Some examples of invalid basic identifiers are

last@value –– contains an illegal character for an identifier

5bit_counter –– starts with a nonalphabetic character

_A0 –– starts with an underline

A0_ –– ends with an underline

clock__pulse –– two successive underlines

Reserved Words Some identifiers, called reserved words or keywords, are reserved for special use in VHDL, so we cannot use them as identifiers for items we define. The full list of reserved words is shown as shown below

Data Types

VHDL has pre-defined and also user-defined data types.

Pre-defined data types can be found in the following packages/libraries:

Page 5: Vhdl Tutorial

• Package standard of library std: Defines BIT, BOOLEAN, INTEGER, and REAL data types.

• Package std_logic_1164 of library ieee: Defines STD_LOGIC and STD_ULOGIC data tepes.

• Package std_logic_arith of library ieee: Defines SIGNED and UNSIGNED data types, plus several data conversion functions, like conv_integer(p), conv_unsigned(p,b), conv_signed(p,b), and conv_std_logic_vector(p,b).

Pre-defined data types are described below:

• BIT (and BIT_VECTOR) : 2-level ('0','1').

Example:

signal x : bit;

-- x is defined as a one-digit signal of type bit.

signal y : bit_vector (3 downto 0);

--y is a 4-bit signal, with the leftmost bit being the MSB.

signal w : bit_vector ( 0 to 7);

-- w is a 8-bit signal, with the rightmost bit being the MSB.

• STD_LOGIC (and STD_LOGIC_VECTOR) : 8-valued logic system introduced in the IEEE 1164 standard.

'X' Forcing unknown

'0' Forcing low

'1' Forcing high

'Z' High impedence

'W' Weak unknown

'L' Weak unknown

'H' Weak high

'-' Don't care

• STD_ULOGIC( and STD_ULOGIC_VECTOR): 9-logic system introduced in the IEEE 1164 standard ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-').

The STD_LOGIC is a subtype of STD_ULOGIC. The latter includes an extra logic value, 'U' which

Page 6: Vhdl Tutorial

stands for unresolved.

Thus, contrary to STD_LOGIC, conflicting logic levels are not automatically resolved here, so output wires should never be connected together directly. However, if two wires are never supposed to be connected together, this system can be used to detect design errors.

• BOOLEAN: True, False.

• INTEGER: 32-bit integer (from -2,147,483,647 to +2,147,483,647).

• NATURAL: Non-negative integers (from 0 to +2,147,483,647).

• REAL: Real numbers ranging from -1.0E38 to +1.0E38. Not synthesizable.

• Physical literals: Used to inform physical quantities, like time, voltage, etc. Useful in simulations. Not synthesizable.

• Character literals: Single ASCII character or a string of such characters. Not synthesizable.

• SIGNED and UNSIGNED: Data types defined in the std_logic_arith package of the ieee library.

User-Defined Data Types

Two categories of user-defined data types are shown below:

• User-defined integer types:

type integer is range -2147483647 to +2147483647;

--This is the pre-defined type integer.

type my_integer is range -12 to 17;

--A user-defined subset of integers.

• User-defined enumerated types:

type my_logic is ('0', '1', 'Z');

--A user-defined subset of std_logic.

type state is (idle, forward, backward, stop);

-- An enumerated data type

type color is (red, green, blue, white);

--Another enumerated data type.

Page 7: Vhdl Tutorial

Subtypes

A Subtype is a type with a constraint. The main reason for using a subtype rather than specifying a new type is that, though operations between data of different types are not allowed, they are allowed between a subtype and its corresponding base type.

Example:

type color is (red, green, blue, white);

subtype my_color is color range red to blue;

--Since color = (red, green, blue, white)

-- my_color = (red, green, blue)

Arrays

Arrays are collections of objects of the same type. They can be one-dimensional (1D), two-dimensional (2D), or one-dimensional-by-one-dimensional (1Dx1D).

Syntax is as given below:

type type_name is array (specification) of data_type;

Example:

type row is array ( 7 downto 0 ) of std_logic; --1D array

type matrix is array ( 0 to 3 ) of row; --1Dx1D array

type matrix is array ( 0 to 3 ) of std_logic_vector( 7 downto 0); --1Dx1D signal

type matrix2D is array ( 0 to 3, 7 downto 0 ) of std_logic; -- 2D array

Operators

VHDL has following kind of operators:

• Assignment operators

• Logical operators

• Arithmetic operators

• Relational operators

• Shift operators

Page 8: Vhdl Tutorial

• Concatenation operators

Assignment operators: These are used to assign values to signals, variables, and constants. They are:

<= Used to assign a value to signal.

:= Used to assign a value to a variable, constant or generic.

=> Used to assign values to individual vector elements or with 'others'.

Logical operators: Used to perform logical operations. The data must be of of type bit, bit_vector, std_logic, std_logic_vector, std_ulogic, std_ulogic_vector. The logical operators are NOT, AND, OR, NAND, NOR, XOR, XNOR.

Note: The NOT operator has precedence over the others.

Arithmetic Operators: Used to perform arithmetic operations. The data type can be integer, signed, unsigned or real,also can be std_logic_vector. Arithmetic operators are addition (+), subtraction (-), multiplication (*), division (/), exponentiation (**), modulus (MOD), remainder (REM), absolute value (ABS).

Comparison Operators: Used for making comparisons. These are:

= Equal to

/= Not equal to

< Less than

> Greater than

<= Less than or equal to

>= Greater than or equal to

Shift Operators: Used for shifting data. Their syntax is as given under:

<left operand> < shift operation> <right operand>. The left operand must be of type bit_vector, while the right operand must be an integer (+ or - in front of it is accepted). The shift operators are:

• sll Shift left logic --positions on the right are filled with '0's

• srl Shift right logic --positions on the left are filled with '0's

• sla Shift left arithmetic --positions on the right are filled with rightmost bit

• sra Shift right arithmetic --positions on the left are filled with leftmost bit

• rol Rotate left -- positions are rotated to the left (cyclically)

Page 9: Vhdl Tutorial

• ror Rotate right --positions are rotated to the right (cyclically)

Attributes

Attributes are used to return various types of information about a signal, variable or type. Attributes

consist of a quote mark (‘) followed by the name of the attribute.

Data Attributes:

The pre-defined, synthesizable data attributes are the following:

• d'low : Returns lower array index

• d'high : Returns upper array index

• d'left : Returns leftmost array index

• d'right : Returns rightmost array index

• d'length : Returns vector size

• d'range : Returns vector range

• d'reverse_range : Returns vector range in reverse order

Example: Consider the following signal:

signal d : std-logic_vector (7 downto 0);

so we have d'low=0, d'high= 7, d'left=7, d'right=0, d'length=8, d'range=( 7 downto 0),

Page 10: Vhdl Tutorial

d'reverse_range=(0 to 7).

Signal Attributes:

VHDL provides a number of attributes for signals to find information about their history of transactions

and events. Given a signal s, VHDL defines the following attributes:

• s'event : Returns true when an event occurs on s

• s'stable : Returns true if no event has occurred on s

• s'active : Returns true if s='1'

• s'quiet<time> : Returns true of no event has occurred during the time specified

• s'last_event : Returns the time elapsed since last event

• s'last_active : Returns the time elapsed since the last s='1'

• s'last_value : Returns the value of s before the last event

User-Defined Attributes:

The syntax is given as follows:

Attribute declaration:

attribute attribute_name: attribute_type;

Attribute specification:

attribute attribute_name of target_name: class is value;

where attribute_type is any data type

class is type,signal,function etc

value is '0', 27, "00111001" etc

Example:

attribute number_of_inputs: integer; --declaration

attribute number_of_input of nand3: signal is 3; --specification

...

inputs <= nand3'number_of_pins; -- attribute call,returns 3

Overloading

Overloading is a feature found in various programming languages that allows the creation of

Page 11: Vhdl Tutorial

several methods with the same name which differ from each other in terms of the type of the input and the type of the output of the function.

Example:

procedure READ ( L : inout line; VALUE : out character; GOOD : out boolean ); procedure READ (L : inout line; VALUE : out character ); procedure READ ( L : inout line; VALUE : out integer; GOOD : out boolean ); procedure READ ( L : inout line; VALUE : out integer );

Operator Overloading

The pre-defined "+" operator does not allow addition between data of type bit. We can define our own operators, suing the same name as the pre-defined ones. Example: we could use "+" to indicate a new kind of addition, this time between values of type bit_vector. This technique is called operator overloading. Defining operators to work on new types is called operator overloading. Example:

package P_BIT_ARITH is function "+" (L: bit_vector; R: bit_vector) return bit_vector; -- 1 function "+" (L: integer; R: bit_vector) return bit_vector; -- 2 function "+" (L: bit_vector; R: integer) return bit_vector; -- 3 function "+" (L: bit_vector; R: bit_vector) return integer; -- 4 end P_BIT_ARITH; use work.P_BIT_ARITH.all; entity OVERLOADED is port(A_VEC, B_VEC: in bit_vector(3 downto 0); A_INT, B_INT: in integer range 0 to 15; Q_VEC: out bit_vector(3 downto 0); Q_INT: out integer range 0 to 15); end OVERLOADED; architecture EXAMPLE of OVERLOADED is begin Q_VEC <= A_VEC + B_VEC; -- a Q_VEC <= A_INT + B_VEC; -- b Q_VEC <= A_VEC + B_INT; -- c Q_VEC <= A_INT + B_INT; -- d

Page 12: Vhdl Tutorial

Q_INT <= A_VEC + B_VEC; -- e Q_INT <= A_INT + B_INT; -- f end EXAMPLE;

Generic

Generic is a way of specifying a generic parameter (that is, a static parameter that can be easily modified and adapted to different applications). The purpose is to have more flexibility and reusability in the code.

The syntax is as given under:

generic (parameter_name : parameter_type := parameter_value);

Example:

entity my_entity is

generic ( n: integer := 8 );

port(...);

end entity;

architecture my_architecture of my_entity is

...

end my architecture;

Combinational versus Sequential Logic

By definition, combinational logic is that in which the output of the circuit depends only on the current inputs. It is clear that, in principle, the system requires no memory and can be implemented using conventional logic gates.

In contrast, sequential logic is that in which the output does depend on previous inputs. Therefore, storage elements are required.

Page 13: Vhdl Tutorial

A common mistake is to think that any circuit that possesses storage elements (flipflops) is sequential. A RAM (Random Access Memory) is an example. A RAM can be modeled as shown in figure:

Notice that the storage elements appear in a forward path rather than in a feedback loop. The memory-read operation depends only on the address vector presently applied to the RAM input, with the retrieved value nothing to do with previous memory accesses.

Concurrent versus Sequential Code

VHDL code is inherently concurrent (parallel). Only statements placed inside a process, function or procedure are sequential.

Concurrent code is also called dataflow code.

When Statement

When is one of the fundamental concurrent statements. It appears in two forms: when/else (simple when) and with/select/when (selected when). Its syntax is shown below:

• when/else

assignment when condition else

assignment when condition else

...;

• with/select/when

with identifier select

assignment when value,

assignment when value,

...;

Example:

--with when/else

outp <= "000" when (inp=,0, or reset='1') else

Page 14: Vhdl Tutorial

"001" when ctl='1' else

"010";

--with with/select/when

with control select

output <= "000" when reset,

"111" when set,

unaffected when others;

Example

architecture mux of mux is

begin

with sel select

y <= a when "00",

b when "01",

c when "10",

d when others;

end mux;

Sequential Code:

Sequential code is also known as behavioral code.

Process

A process is a sequential section of the VHDL code. A process must be installed in the main code, and is executed every time a signal in the sensitivity list changes ( or the condition related to wait is fulfilled). Its syntax is as shown below:

process (sensitivity list)

[variable name type [range] [:= initial_value;]]

begin

(sequential code)

Page 15: Vhdl Tutorial

end process;

Variables are optional. If used, they must be declared in the declarative part of teh process(before the word begin, as shown in the syntax above).

If Statement

The syntax of If is as shown below:

if conditions then assignments;

elsif conditions then assignments;

...

else assignments;

end if;

Example:

if|(x<y) then temp := "11111111";

elsif (x=y and w='0') then temp:="11110000";

else temp:=(others =>'0');

Wait Statement

The syntax for the wait statment is given as follows:

wait until signal_condition;

wait on signal1, signal2,...;

wait for time;

Example:

wait until (clk'event and clk='1');

wait on clk,rst;

wait for 5ns;

Case Statement

The syntax for the Case statement is given as below:

case identifier is

Page 16: Vhdl Tutorial

when value => assignments;

when value => assignmnets;

...

end case;

Example:

Case control is

when "00" => x<=a;

when "01" => x<= b;

when others => x<=c;

end case;

Loop Statement

The syntax for the loop statement is given as below:

• For loop: The loop is repeated a fixed number of times.

for identifier in range loop

(sequential statements)

end loop;

• While loop: The loop is repeated until a fixed condition no longer holds.

while condition loop

(sequential statements)

end loop;

• Exit : Used for ending the loop.

[label:] exit [label] [when condition];

• Next: Used for skipping steps.

[label:] next [loop_label] [when condition];

Example of for loop

Page 17: Vhdl Tutorial

for i in 0 to 5 loop

x(i) <= enable and w(i+2);

y(0, i) <= w(i);

end loop;

Signals and Variables:

VHDL has two ways of passing non-static values around: by means of a signal or by means of a variable. A signal can be declared in a package, entity or architecture (in its declarative part), while a variable can be declared inside a piece of sequential code (in a process, for example).Therefore signal is can be global, but the variable is always local.

The update of a variable is immediate, that is, we can promptly count on its new value in the next line of code, that is not the case with a signal (when used in a process), for its new value is generally only guaranteed to be available after the conclusion of the present run of the process.

The assignment operator for a signal is "<=" while for a variable it is ":=".

Syntax for Signal is as given below:

signal name: type [range] [:= initial_value];

Example: signal control: bit := '0';

Syntax for Variable is as given below:

variable control: bit := '0';

Comparison between Signal and Variable:

Constant

Constant serves to establish default values. Its syntax is as shown below:

constant name : type := value;

Example:

Page 18: Vhdl Tutorial

constant set_bit : bit := '1';

A constant can be declared in a package, entity or architecture.

Package:

Frequently used peices of VHDL code are usually written in the form of components, functions, or procedures. Such codes are then placed inside a package and compiled into the destination library.The importance of this technique is that it allows code partitioning, code sharinng and code reuse.

The syntax for Package is as given below:

package package_name is

(declarations)

end package_name;

[package body package_name is

(function and procedure descriptions)

end package_name;]

Example:

library ieee;

use ieee.std_logic_1164.all;

package my_package is

type state is (st1, st2, st3, st4);

type color is (red, green,blue);

constant vec: std_logic_vector (7 downto 0) := "11111111';

end my_package;

Component

A Component is also another way of partitioning a code and providing code sharing and code reuse. For example, commonly used circuits, like flipflops, multiplexers, adders, basic gates etc can be placed in a library, so any project can make use of them without having to explicitly rewrite such codes.

To use (instantiate) a Component, it must first be declared. The corresponding syntaxes are shown below:

• Component declaration:

Page 19: Vhdl Tutorial

component component_name is

port(

port_name : signal_mode signal_type;

port_name : signal_mode signal_type;

.....);

end component;

• Component instantiation

label: component_name port map(port_list);

Example:

--Component declaration

component inverter is

port(a: in std_logic; b: out std_logic);

end component;

--Component instantiation

u1: inverter port map ( x,y );

Port Map

There are two ways to map the ports of a component during its instantiation: positional mapping and nominal mapping. Example:

Component inverter is

port (a: in std_logic; b: out std_logic);

end component;

...

u1: inverter port map (x,y);

In above, the positional; that is, ports x and y correspond to a and b, respectively. On the other hand, a nominal mapping would be the following:

u1: inverter port map (x=>a, y=>b);

Positional mapping is easier to write, but nominal mapping is less error-prone. Ports can also be left unconnected (using the keyword OPEN)

For example:

Page 20: Vhdl Tutorial

u2: my_circuit port map (x=>a, y=>b, w=>OPEN, z=>d);

Functions and Procedures:

Functions and Procedures are collectively called subprograms.

Function:

A Function is a section of sequential code. Its purpose is to create new functions to deal with commonly encountered problems, like data type conversion, logical operations, arithmetic computations, and new operators and attributes. By writing such code as a function, it can be shared and reused, also propitiating the main code to be shorter and easier to understand.

To construct and use a function, two parts are necessary: the function itself (function body) and a call to the function. Their syntaxes are shown below.

• Function Body

function function_name [<parameter list>] return data_type is

[declarations]

begin

(sequential statements)

end function_name;

• Function Call

A function is called as part of an expression. The expression can obviously appear by itself or associated to a statement (either construct or sequential).

Examples of function calls:

x <= conv_integer(a); --converts a to an integer

y <= maximum(a, b); --returns the largest of a and b

Example of Function:

function bv_to_natural ( bv : in bit_vector ) return natural is

variable result : natural := 0;

begin

for index in bv'range loop

result := result * 2 + bit'pos(bv(index));

end loop;

return result;

Page 21: Vhdl Tutorial

end function bv_to_natural;

Procedure

A Procedure is very similar to a Function and has the same basic purposes. However, a procedure can return more than one value.

Like a Function, two parts are necessary to construct and use a Procedure: procedure body and procedure call.

Syntax of Procedure body is as given below

procedure procedure_name [<parameter list>] is

[declarations]

begin

(sequential statements)

end procedure_name;

A procedure can have any of In, Out or Inout parameters, which can be signals, variables or constants.

Example:

procedure my_procedure ( a: in bit; signal b,c : in bit;

signal x: out bit_vector(7 downto 0);

signal y: inout integer range 0 to 99) is

begin

...

end my_procedure;

Procedure Call

Examples of procedure calls:

compute_min_max(in1, in2, in3, out1, out2);

-- statement by itself

divide (dividend, divisor, quotient, remainder);

--statement by itself

Page 22: Vhdl Tutorial

Example of Procedure:

architecture behavioral of receiver is

… –– type declarations, etc

signal recovered_data : bit;

signal recovered_clock : bit;

procedure receive_packet ( signal rx_data : in bit;

signal rx_clock : in bit;

data_buffer : out packet_array ) is

begin

for index in packet_index_range loop

wait until rx_clock = '1';

data_buffer(index) := rx_data;

end loop;

end procedure receive_packet;

begin

packet_assembler : process is

variable packet : packet_array;

begin

receive_packet ( recovered_data, recovered_clock, packet ); -- Procedure Call

end process packet_assembler;

end architecture behavioral;

Assert

Assert is a non-synthesizable statement whose purpose is to write out massages (on the screen, for example) when problems are found during simulation. Its syntax is as shown below:

assert condition

Page 23: Vhdl Tutorial

[report "message"]

[severity severity_level];

The message is written when the condition is false.

Example:

assert a'length = b'length

report "error: vectors do not have same length!"

severity failure;

Examples:

• Or Gate:

library ieee; use ieee.std_logic_1164.all; -------------------------------------- entity OR_ent is port( x: in std_logic; y: in std_logic; F: out std_logic ); end OR_ent; --------------------------------------- architecture OR_arch of OR_ent is begin process(x, y) begin -- compare to truth table if ((x='0') and (y='0')) then F <= '0'; else F <= '1'; end if; end process; end OR_arch; architecture OR_beh of OR_ent is --Second method begin

Page 24: Vhdl Tutorial

F <= x or y; end OR_beh;

• Nand Gate

library ieee; use ieee.std_logic_1164.all; ------------------------------------------ entity NAND_ent is port( x: in std_logic; y: in std_logic; F: out std_logic ); end NAND_ent; ------------------------------------------ architecture behv1 of NAND_ent is begin process(x, y) begin -- compare to truth table if (x='1' and y='1') then F <= '0'; else F <= '1'; end if; end process; end behv1; ----------------------------------------- architecture behv2 of NAND_ent is –Second method begin F <= x nand y; end behv2;

• Tri State Buffer library ieee; use ieee.std_logic_1164.all; entity tristate_b is port( d_in: in std_logic_vector(7 downto 0); en: in std_logic; d_out: out std_logic_vector(7 downto 0) ); end tristate_b; architecture behavior of tristate_b is begin process(d_in, en) begin if en='1' then

Page 25: Vhdl Tutorial

d_out <= d_in; else d_out <= "ZZZZZZZZ"; end if; end process; end behavior;

• 3:1 Multiplexer library ieee; use ieee.std_logic_1164.all; ------------------------------------------------- entity Mux is port( I3: in std_logic_vector(2 downto 0); I2: in std_logic_vector(2 downto 0); I1: in std_logic_vector(2 downto 0); I0: in std_logic_vector(2 downto 0); S: in std_logic_vector(1 downto 0); O: out std_logic_vector(2 downto 0) ); end Mux; ------------------------------------------------- architecture behv1 of Mux is begin process(I3,I2,I1,I0,S) begin -- use case statement case S is when "00" => O <= I0; when "01" => O <= I1; when "10" => O <= I2; when "11" => O <= I3; when others => O <= "ZZZ"; end case; end process; end behv1; architecture behv2 of Mux is begin -- use when.. else statement O <= I0 when S="00" else I1 when S="01" else I2 when S="10" else I3 when S="11" else "ZZZ"; end behv2;

• 1:3 Demultiplexer

Page 26: Vhdl Tutorial

library ieee; use ieee.std_logic_1164.all; ------------------------------------------------- entity DEMUX is port( I: in std_logic_vector(1 downto 0); O: out std_logic_vector(3 downto 0) ); end DEMUX; ------------------------------------------------- architecture behv of DEMUX is begin -- process statement process (I) begin -- use case statement case I is when "00" => O <= "0001"; when "01" => O <= "0010"; when "10" => O <= "0100"; when "11" => O <= "1000"; when others => O <= "XXXX"; end case; end process; end behv; architecture when_else of DEMUX is begin -- use when..else statement O <= "0001" when I = "00" else "0010" when I = "01" else "0100" when I = "10" else "1000" when I = "11" else "XXXX"; end when_else; Note: An encoder refers to a device that is used to change a signal or data into a code. Whereas a Multiplexer or mux is a device which performs multiplexing or it takes information from more than one channels and outputs into a single channel. Thus multiplexer is basically a kind of encoder where its function is to combine multiple inputs into one output.

Page 27: Vhdl Tutorial

• ADDER

library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -------------------------------------------------------- entity ADDER is generic(n: natural :=2); port( A: in std_logic_vector(n-1 downto 0); B: in std_logic_vector(n-1 downto 0); carry: out std_logic; sum: out std_logic_vector(n-1 downto 0) ); end ADDER; -------------------------------------------------------- architecture behv of ADDER is -- define a temparary signal to store the result signal result: std_logic_vector(n downto 0); begin -- the 3rd bit should be carry result <= ('0' & A)+('0' & B); sum <= result(n-1 downto 0); carry <= result(n); end behv;

• Comparator entity Comparator is generic(n: natural :=2); port( A: in std_logic_vector(n-1 downto 0); B: in std_logic_vector(n-1 downto 0); less: out std_logic; equal: out std_logic;

Page 28: Vhdl Tutorial

greater: out std_logic ); end Comparator; --------------------------------------------------- architecture behv of Comparator is begin process(A,B) begin if (A<B) then less <= '1'; equal <= '0'; greater <= '0'; elsif (A=B) then less <= '0'; equal <= '1'; greater <= '0'; else less <= '0'; equal <= '0'; greater <= '1'; end if; end process; end behv;

• ALU entity ALU is port( A: in std_logic_vector(1 downto 0); B: in std_logic_vector(1 downto 0); Sel: in std_logic_vector(1 downto 0); Res: out std_logic_vector(1 downto 0) ); end ALU; --------------------------------------------------- architecture behv of ALU is begin process(A,B,Sel) begin

Page 29: Vhdl Tutorial

-- use case statement to achieve -- different operations of ALU case Sel is when "00" => Res <= A + B; when "01" => Res <= A + (not B) + 1; when "10" => Res <= A and B; when "11" => Res <= A or B; when others => Res <= "XX"; end case; end process; end behv;

• Multiplier library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -- two 4-bit inputs and one 8-bit outputs entity multiplier is port( num1, num2: in std_logic_vector(1 downto 0); product: out std_logic_vector(3 downto 0) ); end multiplier; architecture behv of multiplier is begin process(num1, num2) variable num1_reg: std_logic_vector(2 downto 0); variable product_reg: std_logic_vector(5 downto 0); begin num1_reg := '0' & num1;

Page 30: Vhdl Tutorial

product_reg := "0000" & num2; -- use variables doing computation -- algorithm is to repeat shifting/adding for i in 1 to 3 loop if product_reg(0)='1' then product_reg(5 downto 3) := product_reg(5 downto 3) + num1_reg(2 downto 0); end if; product_reg(5 downto 0) := '0' & product_reg(5 downto 1); end loop; -- assign the result of computation back to output signal product <= product_reg(3 downto 0); end process; end behv;

• Simple Latch library ieee ; use ieee.std_logic_1164.all; -------------------------------------------- entity D_latch is port( data_in: in std_logic; enable: in std_logic; data_out: out std_logic ); end D_latch; -------------------------------------------- architecture behv of D_latch is begin -- compare this to D flipflop process(data_in, enable) begin if (enable='1') then -- no clock signal here data_out <= data_in; end if; end process;

Page 31: Vhdl Tutorial

end behv

• JK Flip Flop

library ieee; use ieee.std_logic_1164.all; ---------------------------------------------- entity JK_FF is port ( clock: in std_logic; J, K: in std_logic; reset: in std_logic; Q, Qbar: out std_logic ); end JK_FF; ----------------------------------------------- architecture behv of JK_FF is -- define the useful signals here signal state: std_logic; signal input: std_logic_vector(1 downto 0); begin -- combine inputs into vector input <= J & K; p: process(clock, reset) is begin if (reset='1') then state <= '0'; elsif (rising_edge(clock)) then -- compare to the truth table case (input) is when "11" => state <= not state; when "10" => state <= '1'; when "01" => state <= '0';

Page 32: Vhdl Tutorial

when others => null; end case; end if; end process; -- concurrent statements Q <= state; Qbar <= not state; end behv;

• Counter library ieee ; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; ---------------------------------------------------- entity counter is generic(n: natural :=2); port( clock: in std_logic; clear: in std_logic; count: in std_logic; Q: out std_logic_vector(n-1 downto 0) ); end counter; ---------------------------------------------------- architecture behv of counter is signal Pre_Q: std_logic_vector(n-1 downto 0); begin -- behavior describe the counter process(clock, count, clear) begin if clear = '1' then Pre_Q <= Pre_Q - Pre_Q; elsif (clock='1' and clock'event) then if count = '1' then Pre_Q <= Pre_Q + 1;

Page 33: Vhdl Tutorial

end if; end if; end process; -- concurrent assignment statement Q <= Pre_Q; end behv;