Try   HackMD

Hardware Description Languages Lab 4

Numeric Package & Behavioral Style Combinational Design

The Islamic University of Gaza
Engineering Faculty
Department of Computer Engineering
Author: Mohammed Nafiz ALMadhoun2021/02/26

In the previous labs, we used to write our VHDL code in a dataflow style, which is a direct implementation on the gates level.

In this lab, we are going to write VHDL code using behavioural style, which means that we will write sequential statements in process in abstract level, which will be converted to logic gates.

But first, we will talk about the numeric package.

Numeric Package

In this section, we are going to cover the numeric std package, which contains definitions and operations for numerical values, this will let us create numerical operations easily.

To use the package, you should use it:

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;

Unsigned and Signed

You couldn't read bits as a number without deciding if it's unsigned or signed, in this package, we have both, but note that the signed is a 2's complement number.

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity adder_4bit is port ( a, b : in unsigned (3 downto 0); s : out unsigned (3 downto 0) ); end entity; architecture adder_4bit of adder_4bit is begin s <= a + b; end architecture;

Notice that the unsigned and signed is an array.

Converting between types

You could convert between std_logic_vector, unsigned, and signed using VHDL casting operation.

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity adder_4bit is port ( a, b : in std_logic_vector (3 downto 0); s : out std_logic_vector (3 downto 0) ); end entity; architecture adder_4bit of adder_4bit is begin s <= std_logic_vector(unsigned(a) + unsigned(b)); end architecture;

The casting operation is done by using the name of the type as a function because all these types are related (they all share the same building element std_logic), they will be converted to each other easily.

Converting from/to integers

Integers are numbers in VHDL, they are so different from signed and unsigned, the integers could be used to describe a numerical value for loops and other stuff.

To convert an integer to unsigned, we could use the to_unsigned function, which will take the integer as its first argument, and the width as the second argument.

architecture ... signal test : unsigned (3 downto 0); begin test <= to_unsigned(7, 4); end architecture;

To convert an integer to signed, you could use to_signed.

Converting an unsigned or signed number to an integer could be achieved using the to_integer function, which will take the signal as its first argument.

Writing Process

To write code using behavioural style, you should create a process, the process itself is a concept in VHDL, which got executed concurrently (Nothing got executed, we are writing VHDL!).

Proccess Sensitivty List

The process got resolved when something in its sensitivity list changes, the sensitivity list is a list of singles.

Example

library ieee; use ieee.std_logic_1164.all; entity half_adder is port ( a, b: in std_logic; s, c: out std_logic ); end entity; architecture half_adder of half_adder is begin p1: process (a, b) is begin ... end process; end architecture;

Notice that our sensitivity list is (a, b), so any change in these signals will trigger our process.

Sequential statements

Sequential statements will respect their order, they will be executed one after another, but the whole process will be executed concurrently.

Notice that we are saying executed, but this is a description language, so these are the rules that the synthesizer will assume when converting our statement to logic gates.

IF Statement

As you know an if statement is a conditional statement, which has the following syntax:

if condition then ... elsif condition then ... else ... end if;

Notice that you could repeat elsif as many as you want.

Example:

library ieee; use ieee.std_logic_1164.all; entity half_adder is port ( a, b: in std_logic; s, c: out std_logic ); end entity; architecture half_adder of half_adder is begin p1: process (a, b) is begin if (a = b) then s <= '0'; else s <= '1'; end if; if (a = '1' and b = '1') then c <= '1'; else c <= '0'; end if; end process; end architecture;

Case Statment

The case statement will create a multiplexer in most cases, but notice that we could assign more than one signal in each case.

p1: process (a, b) is begin case std_logic_vector'(a,b) is when "00" => s <= '0'; c <= '0'; when "11" => s <= '0'; c <= '1'; when others => s <= '1'; c <= '0'; end case; end process;

std_logic_vector' will create a vector from single bits.

Note: We will cover loops and more in the next lab!

Lab Tasks

Task 1: ALU

You should create an ALU with the following functionality:

  • 000: a + b
  • 001: a - b
  • 010: -a
  • 011: -b
  • 100: b - a
  • 101: a & b
  • 110: a | b
  • 111: !a

Notice that a and b are 8-bit std_logic_vector, and should be treated as signed with the numerical operations.

Create a testbench that covers at least one case in each operation.

tags: VHDL IUG
End Of Lab 4