EE313 VHDL Part II - United States Naval Academy · 2018-01-10 · EE313 - VHDL Part II...

13
1 EE313 - VHDL Part II Representing Values in VHDL Developing code requires entering data of many types. Whether you are initializing signals or typing in operands for comparison statements, it is important that the data is entered correctly so that the compiler understands your intent and you are saved the headaches of finding both syntax and semantic errors. Below we illustrate how certain types of data should be entered into your VHDL code. Decimal (Base-10) Values Integers are represented in the usual way. For example, the integer fifty seven is represented by 57 and the integer negative five is represented by -5. VHDL also allows the use exponential notation. For example, the number 7000 can be represented as 7E3. You might be asking yourself if you could type that number 7e3 so that you don’t have to press the SHIFT key. The answer is yes since VHDL is not case sensitive. BITS/CHARACTERS A bit or character is surrounded by single quotes. Examples include '0', '1', '$', and 'X'. BIT_VECTORS/STRINGS A BIT_VECTORS is a collection of bits that are related. A STRING is a collection of characters that are related. An example of how these would be defined in the ENTITY declaration is shown in (1) and (2). ledg : OUT BIT_VECTOR(7 DOWNTO 0); (1) name : OUT STRING(1 TO 4); (2) Here the symbol ledg is a BIT_VECTOR that represents the 6 green leds LEDG7 through LEDG0 from the DE2 board. If you wanted to assign a the binary number 00011010 to these 8 bits, you would use the following VHDL statement. ledg<="00011010"; (3) If you removed the double quotation marks, you would get a VHDL type mismatch error because the compiler would think you are trying to assign the decimal value eleven thousand ten to the BIT_VECTOR. When changing a single BIT of a BIT_VECTOR, you treat it for what it is, a single BIT. For example, to change only the BIT at index location 3 you would write ledg(3)<='0'; (4) STRINGS are treated similarly to BIT_VECTORS. Hexadecimal Quantities To represent a hexadecimal quantity, place the number in double quotes and precede it with an X. Using hexadecimal can be used as a shortcut for typing in long BIT_VECTORS. The example shown in (3) above would be written as shown in (4). ledg<=x"1A"; (4)

Transcript of EE313 VHDL Part II - United States Naval Academy · 2018-01-10 · EE313 - VHDL Part II...

1

EE313 - VHDL Part II

Representing Values in VHDL

Developing code requires entering data of many types. Whether you are initializing signals or typing in

operands for comparison statements, it is important that the data is entered correctly so that the compiler

understands your intent and you are saved the headaches of finding both syntax and semantic errors. Below we

illustrate how certain types of data should be entered into your VHDL code.

Decimal (Base-10) Values Integers are represented in the usual way. For example, the integer fifty seven is represented by 57 and the

integer negative five is represented by -5.

VHDL also allows the use exponential notation. For example, the number 7000 can be represented as 7E3.

You might be asking yourself if you could type that number 7e3 so that you don’t have to press the SHIFT key.

The answer is yes since VHDL is not case sensitive.

BITS/CHARACTERS A bit or character is surrounded by single quotes. Examples include '0', '1', '$', and 'X'.

BIT_VECTORS/STRINGS A BIT_VECTORS is a collection of bits that are related. A STRING is a collection of characters that are

related. An example of how these would be defined in the ENTITY declaration is shown in (1) and (2).

ledg : OUT BIT_VECTOR(7 DOWNTO 0); (1)

name : OUT STRING(1 TO 4); (2)

Here the symbol ledg is a BIT_VECTOR that represents the 6 green leds LEDG7 through LEDG0 from the

DE2 board. If you wanted to assign a the binary number 00011010 to these 8 bits, you would use the following

VHDL statement.

ledg<="00011010"; (3)

If you removed the double quotation marks, you would get a VHDL type mismatch error because the compiler

would think you are trying to assign the decimal value eleven thousand ten to the BIT_VECTOR.

When changing a single BIT of a BIT_VECTOR, you treat it for what it is, a single BIT. For example, to

change only the BIT at index location 3 you would write

ledg(3)<='0'; (4)

STRINGS are treated similarly to BIT_VECTORS.

Hexadecimal Quantities To represent a hexadecimal quantity, place the number in double quotes and precede it with an X. Using

hexadecimal can be used as a shortcut for typing in long BIT_VECTORS. The example shown in (3) above

would be written as shown in (4).

ledg<=x"1A"; (4)

2

VHDL Standard Data Types

When we want to use a SIGNAL (an input/output or internal value of a circuit) or when we want to use a

variable, we have to tell the compiler what the SIGNAL or variable is. Consider the circuit below, which shows

an input X to an ADDER.

X

Is X a single bit?

Or is X a group of two bits (to be applied as the control signals for a 2-4 multiplexer)?

Or is X a group of four bits (to be applied as the input to a 4-16 decoder)?

Or is X best viewed as a Boolean expression that results in a True/False question (e.g., is smoke emanating?)

The point: We must tell the compiler what X is supposed to be. Specifically, we must tell the compiler X’s

type. The allows the compiler to determine what operators are allowed and how to execute the operations.

Recall from VHDL Part I that a SIGNAL is defined using one of the two following syntaxes

SIGNAL portname: portmode type; -- Used in the ENTITY declaration

SIGNAL signalname: type -- Used in the ARCHITECTURE declaration

where:

portname and signalname are user selected names meeting the standard Naming Rules

type is the data type including the size for vector data types

portmode is IN, OUT, INOUT, BUFFER, or LINKAGE.

Note that the keyword SIGNAL may be omitted in the PORT section of the ENTITY declaration.

The pre-defined operators for some of the more common VHDL types are shown in Table 1 followed by a

number of examples illustrating how the various data types might be defined and used.

3

Op

erato

r C

lass

Op

erato

rs

BO

OL

EA

N

BIT

BIT

_V

EC

TO

R

ST

D_

LO

GIC

ST

D_

LO

GIC

_V

EC

TO

R

CH

AR

AC

TE

R

ST

RIN

G

SE

VE

RIT

Y_

LE

VE

L

INT

EG

ER

RE

AL

TIM

E

Logical AND, OR, NAND,

NOR, XOR, XNOR X X X X X

Other NOT X X X X X X

Relational =, /=, <, <=, >, >= X X X X X X X X X X

Shift SLL, SRL, SLA,

SRA, ROL, ROR X

Adding +, - X X X

Adding & X

Sign +, - X X X

Multiplying *, / X X X

Multiplying MOD, REM X

Other ** X X

Other ABS X X X

Table 1 – Type Operators

Example ENTITY Definitions PORT(

a, b : IN BIT;

x, y : OUT BIT;

key : IN BIT_VECTOR(3 DOWNTO 0);

ledg : OUT BIT_VECTOR(7 DOWNTO 0);

ledr : BUFFER BIT_VECTOR(0 TO 17);

name: OUT STRING(1 TO 4)

);

END example;

4

Example ARCHITECTURE Definitions and signal uses.

ARCHITECTURE arc OF example IS

SIGNAL c: BIT;

SIGNAL d1: STD_LOGIC_VECTOR(7 DOWNTO 0);

SIGNAL d2: STD_LOGIC_VECTOR(0 TO 7);

SIGNAL z: BOOLEAN;

SIGNAL initial: CHARACTER;

-- The RANGE of an INTEGER determines the number of bits used

-- to store the value of the integer.

SIGNAL my4bitint: INTEGER RANGE 0 to 15; -- Uses 4 bits

SIGNAL my8bitint: INTEGER RANGE 0 to 255; -- Uses 8 bits

SIGNAL myreal: REAL;

SIGNAL mytime: TIME;

BEGIN

x<=NOT a;

y<='1'; -- Assign 1 to bit x

ledg(3 downto 0)<=key; -- Assign inputs key(3 to 0) to ledg(3 to 0)

ledr(0)<=key(3); -- Assign inputs key(3 to 0) to ledr(0 to 3)

ledr(1)<=key(2);

ledr(2)<=key(1);

ledr(3)<=key(0);

ledr(4 to 7)<="1001"; -- Assign 1001 to ledr(4 to 7)

name<="USNA";

my4bitint<=3;

my8bitint<=2;

d1<="00100011";

-- Roll ledr bits 0 to 3 RIGHT 3 times and store in

-- ledr bits 10 to 13. Note that this does not work

-- if ledr is type OUT vice BUFFER.

ledr(10 to 13)<=ledr(0 to 3) ROR my4bitint;

-- Roll key bits 3 to 0 RIGHT 2 times and store in ledg

-- bits 7 to 4. Note that the direction that the variable

-- is defined effects how the shift functions will work.

ledg(7 downto 4)<=key ROR my8bitint;

END arc;

5

Concurrent Code

VHDL is inherently concurrent. This means that the lines of code can be viewed as all being executed at the

same time. If we want VHDL to NOT execute all lines at the same time—i.e., if we want VHDL to execute

lines of code sequentially, one after another—we have to specifically inform VHDL of this intent. Concurrent

code is also called dataflow code.

We have seen several examples of concurrent code that implements Boolean or arithmetic equations (mux,

decoder, full adder, etc).

Other fundamental types of statements that can be used in concurrent code are:

Conditional signal assignments using WHEN/ELSE statements.

Selected signal assignments using WITH/SELECT/WHEN statements.

Structured assignments using GENERATE statements.

WHEN/ELSE Statement Syntax:

The conditions in a WHEN/ELSE statement are prioritized. The first output statement listed has the highest

priority and will be executed first, if the condition is true. If the first condition is not true, the second output

statement will be executed next, and so on.

WITH/SELECT/WHEN Statement Syntax:

The selected signal assignment (WITH/SELECT/WHEN) examines the value of the expression and executes

only the assignment statement that matches the WHEN value, and all other statements are skipped.

WHEN OTHERS is required to terminate a WITH/SELECT/WHEN statement. This is used to ensure that all

possible choices of the expression are considered.

Note the use of commas in the syntax for the WITH/SELECT/WHEN statement.

Commas are used in a

WITH/SELECT/WHEN

statement

WHEN OTHERS must be used to

terminate a WITH/SELECT/WHEN

statement

6

WHEN/ELSE Examples Implement a 4-to-1 mux using a WHEN/ELSE statement.

Note that if we use type BIT_VECTOR to combine S1 and S0 into one signal of 2 bits, we can write the VHDL

code as:

BIT_VECTOR type

7

WITH/SELECT/WHEN Examples Implement a 4-to-1 mux using a WITH/SELECT/WHEN statement.

One important keyword, UNAFFECTED, that is often used to indicate no action is to take place for some

conditions. For example, let’s look at VHDL code for a 3-to-1 mux (output is assigned to one of 3 inputs).

8

Comparison Example 1

Implement ̅ ̅ ̅ ̅̅ ̅̅ ̅̅ ̅̅ ̅̅ ̅̅ ̅̅ using the following three methods.

a. Boolean expression.

b WHEN/ELSE statement.

c. WITH/SELECT/WHEN statement.

Boolean Expression Solution

WHEN/ELSE Solution

WITH/SELECT/WHEN Solution

9

GENERATE Statement

GENERATE statement is another important concurrent statement that can be used to reduce number of lines of

code for structured circuits such as iterative systems. By employing GENERATE statement, a section of code

can be repeated for a number of times. GENERATE statement has two modes:

1. Unconditional GENERATE (FOR/GENERATE)

2. Conditional GENERATE (IF/GENERATE).

Syntax for unconditional GENERATE statement (FOR/GENERATE):

Syntax for conditional GENERATE statement (IF/GENERATE):

Notes:

A label is required for a GENERATE statement.

IF/GENERATE is used within a FOR/GENERATE loop.

loop_id is generally of type INTEGER.

GENERATE Example Implement the following circuit using GENERATE statements. Assume that Switches 7 down to 0 are the A

inputs and Switches 17 down to 10 are the B inputs. The output C is displayed on the eight green LEDs. The

inputs A and B should be displayed on the corresponding red LEDs.

A (7 downto 0)

B (7 downto 0)

C (7 downto 0)

10

Unconditional GENERATE Solution

Conditional GENERATE Solution

11

Comparison Example 2 Implement a 2-to-4 decoder using

a. WHEN/ELSE statement.

b. WITH/SELECT/WHEN statement.

c. GENERATE statement.

WHEN/ELSE Solution

WITH/SELECT/WHEN Solution (Uses Same ENTITY Section as WHEN/ELSE Solution)

GENERATE Solution

Note: type INTEGER

12

STD_LOGIC Type

Although declaring a signal to be a BIT or a BIT_VECTOR is intuitive and easy to understand, it is actually

frowned upon! It is common practice to use the STD_LOGIC and STD_LOGIC_VECTOR types in place of

the BIT and BIT_VECTOR types. The reasons why could be debated but the primary benefit is it can have a

value of more than just ‘1’, or ‘0’. Specifically it allows for conditions such as the High Impedance condition

necessary for a buffer and other special case conditions. The values that the STD_LOGIC type may have are

shown in Table 2.

Value Description

U Uninitialized

X Forcing Unknown

0 Forcing 0

1 Forcing 1

Z High Impedance

W Weak Unknown

L Weak 0

H Weak 1

- Don’t Care

Table 2 – STD_LOGIC Values

13

Seemingly Complicated Example An ALU.