--- description: 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. --- <h1 style='border: none'><center>Hardware Description Languages Lab 4</center></h1> <h2 style='border: none'><center>Numeric Package & Behavioral Style Combinational Design</center></h2> <h5><center>The Islamic University of Gaza<br>Engineering Faculty<br>Department of Computer Engineering</center></h5> <h6>Author: Mohammed Nafiz ALMadhoun<span style="float:right">2021/02/26</span></h6> --- 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: ```vhdl= 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. ```vhdl= 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. ```vhdl= 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. ```vhdl= 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 ```vhdl= 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: ```vhdl= if condition then ... elsif condition then ... else ... end if; ``` Notice that you could repeat `elsif` as many as you want. #### Example: ```vhdl= 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. ```vhdl= 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` <center>End Of Lab 4</center>