Let us take an example of Half adder
VHDL Description: entity half_add is port (I1, I2 : in bit; O1, O2 : out bit); -- Since we are using type bit, no need for attaching a -- Library. -- If we use std_logic, we should attach the IEEE -- Library. end half_add; architecture behave_ex of half_add is begin process (I1, I2) begin O1 <= I1 xor I2 after 10 ns; -- statement 1 O2 <= I1 and I2 after 10 ns; -- statement 2 -- The above two statements are signal-assignment -- statements with 10 nanoseconds delays. -- --Other behavioral (sequential) statements can be added -- here end process; end behave_ex;
Verilog Description: module half_add (I1, I2, O1, O2); input I1, I2; output O1, O2; reg O1, O2; / Since O1 and O2 are outputs and they are written inside “always,” they should be declared as reg / always @(I1, I2) begin #10 O1 = I1 ^ I2; // statement 1. #10 O2 = I1 & I2; // statement 2. end endmodule |
The use of variables inside processes is a common practice in VHDL behavioral description. Consider the following two signal-assignment statements inside a process, where S1, S2, and t1 are signals: Signl : process(t1) begin st1 : S1 <= t1; st2 : S2 <= not S1; end process; In VHDL, a statement can be labeled, and the label should be followed by a colon. In the above code, Signl, st1, and st2 are labels. Alternately, variable-assignment statements can be used instead of the above signal- assignment statement as follows: Varb : process(t1) variable temp1, temp2 : bit; -- This is a variable -- declaration statement begin st3 : temp1 := t1; -- This is a variable assignment -- statement st4 : temp2 := not temp1; -- This is a variable -- assignment statement st5 : S1 <= temp1; st6 : S2 <= temp2; end process;
VHDL Code for Behavioral Description of D-Latch Using Variable-Assignment Statements: entity DLTCH_var is port (d, E : in bit; Q, Qb : out bit); -- Since we are using type bit, no need for attaching a -- Library. If std_logic is used, IEEE library should be --attached end DLTCH_var; architecture DLCH_VAR of DLTCH_var is begin VAR : process (d, E) variable temp1, temp2 : bit; begin if E = ‘1’ then temp1 := d; -- This is a variable assignment statement. temp2 := not temp1; -- This is a variable assignment -- statement. end if; Qb <= temp2; -- Value of temp2 is passed to Qb Q <= temp1; -- Value of temp1 is passed to Q end process VAR; end DLCH_VAR;
|
There are several statements associated with behavioral descriptions. These statements have to appear inside process in VHDL. IF Statement:
IF is a sequential statement that appears inside process in VHDL. It has several formats, some of which are as follows:
VHDL IF-Else Formats:
if (Boolean Expression) then statement 1; statement 2; statement 3; ....... else statement a; statement b; statement c; ....... end if; The execution of IF statement is controlled by the Boolean expression. If the Boolean expression is true, then statements 1, 2, and 3 are executed. If the expression is false, statements a, b, and c are executed. Boolean expression and execution of if: VHDL: if (clk = ‘1’) then temp := s1; else temp := s2; end if;
In above example if clk is high (1), the value of s1 is assigned to the variable temp. Otherwise, s2 is assigned to the variable temp. Execution of if as a latch VHDL if clk = ‘1’ then temp := s1; end if; If clk is high, the value of s1 is assigned to temp. If clk is not high, temp retains its current value, thus simulating a latch. Execution of if as else-if: VHDL: if (Boolean Expression1) then statement1; statement2;... elsif (Boolean expression2) then statement i; statement ii;... else statement a; statement b;... end if;
Implementing else-if: VHDL if signal1 =‘1’ then temp := s1; elsif signal2 = ‘1’ then temp := s2; else temp := s3; end if; |
VHDL Description: library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity MUX_if is port (A, B, SEL, Gbar : in std_logic; Y : out std_logic); end MUX_if; architecture MUX_bh of MUX_if is begin process (A, B, SEL, Gbar) -- A, B, SEL, and Gbar are the sensitivity list of the process. variable temp : std_logic; -- Above statement is declaring temp as a variable; it -- will be calculated as if it is the output of the -- multiplexer. begin if Gbar = ‘0’ then if SEL = ‘1’ then temp := B; else temp := A; end if; --Now assign the variable temp to the output Y <= temp; else Y <= ‘Z’; end if; end process; end MUX_bh;
|
The case statement is a sequential control statement. It has the following format:
VHDL Case Format:
case (control-expression) is when test value or expression1 => statements1; when test value or expression2 => statements2; when test value or expression3 => statements3; when others => statements4; end case;
If, for example, test value1 is true (i.e., it is equal to the value of the control expression), statements1 is executed. The case statement must include all possible conditions (values) of the control-expression. The statement when others can be used to guarantee that all conditions are covered.
The Case Statement
VHDL: case sel is when “00” => temp := I1; when “01” => temp := I2; when “10” => temp := I3; when others => temp := I4; end case;
In above Example, the control is sel. If sel = 00, then temp = I1, if sel = 01, then temp = I2, if sel = 10, then temp = I3, if sel = 11 (others or default), then temp = I4. All four test values have the same priority; it means that if sel = 10, for example, then the third (VHDL) statement (temp := I3) is executed directly without checking the first and second expressions (00 and 01). |
Edge-triggered flip-flops are sequential circuits. Flip-flops are triggered by the edge of the clock, in contrast to latches where the level of the clock (enable) is the trigger. Positive (negative) edge-triggered flip-flops sample the input only at the positive (negative) edges of the clock; any change in the input that does not occur at the edges is not sampled by the output.
State diagram
VHDL: library ieee; use ieee.std_logic_1164.all; entity JK_FF is port(JK : in bit_vector (1 downto 0); clk : in std_logic; q, qb : out bit); end JK_FF; architecture JK_BEH of JK_FF is begin P1 : process (clk) variable temp1, temp2 : bit; begin if rising_edge (clk) then case JK is when “01” => temp1 := ‘0’; when “10” => temp1 := ‘1’; when “00” => temp1 := temp1; when “11” => temp1 := not temp1; end case; q <= temp1; temp2 := not temp1; qb <= temp2; end if; end process P1; end JK_BEH; |
Clk | Input clr | Current state | Next State |
| H | xxx | 000 |
| L | 000 | 001 |
| L | 001 | 010 |
| L | 010 | 011 |
| L | 011 | 100 |
| L | 100 | 101 |
| L | 101 | 110 |
| L | 110 | 111 |
| L | 111 | 000 |
L | X |
| hold |
VHDL Description library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity CT_CASE is port (clk, clr : in std_logic; q : buffer std_logic_vector (2 downto 0)); end CT_CASE; architecture ctr_case of CT_CASE is begin ctr : process(clk) variable temp : std_logic_vector (2 downto 0) := “101”; --101 is the initial value, so the counter starts from -- 110 begin if rising_edge (clk) then if clr = ‘0’ then case temp is when “000” => temp := “001”; when “001” => temp := “010”; when “010” => temp := “011”; when “011” => temp := “100”; when “100” => temp := “101”; when “101” => temp := “110”; when “110” => temp := “111”; when “111” => temp := “000”; when others => temp := “000”; end case; else temp := “000”; end if; end if; q <= temp; end process ctr; end ctr_case; |
VHDL: wait for 10 ns;
The wait statement can be implemented to generate clocks, as it is usually common in bench marks.
Implementation of the wait-for Statement to Generate Clocks
VHDL:
Library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity waittestVHDL is port ( a,b,c : out std_logic); end waittestVHDL; architecture Behavioral of waittestVHDL is begin p1 :process variable a1: std_logic := ‘0’; begin a <= a1; wait for 10 ns; a1 := not a1; end process; p2 :process variable b1: std_logic := ‘0’; begin b <= b1; wait for 20 ns; b1 := not b1; end process; p3 :process variable c1: std_logic := ‘0’; begin c <= c1; wait for 40 ns; c1 := not c1; end process; END;
|
The HDL general format for a For-Loop is:
for <lower index value> <upper index value> <step> statements1; statement2; statement3; …. end loop
If the value of index is between lower and upper, all statements written inside the body of the loop are executed. For each cycle, the index is modified at the end loop according to the step. If the value of index is not between the lower and upper values, the loop is terminated.
VHDL For-Loop:
for i in 0 to 2 loop if temp(i) = ‘1’ then result := result + 2**i; end if; end loop; statement1; statement2; ....
The index is i, the lower value is 0, the upper value is 2, and the step is 1. All statements between the for statement and end loop are executed until the index i goes out of range. At the very beginning of the loop, i takes the value of 0.
|
In VHDL, next and exit are two sequential statements associated with loop; exit causes the program to exit the loop, and next causes the program to jump to the end of the loop, skipping all statements written between next and end loop. The index is incremented, and if its value is still within the loop’s range, the loop is repeated. Otherwise, the program exits the loop. VHDL NEXT-EXIT: for i in 0 to 2 loop ...... ..... next When z = ’1’; statements1; end loop; statements2;
In the above example, at the very beginning of the loop’s execution, i takes the value 0; at the statement next When z = ’1’, the program checks the value of z. If z = 1, then statements1 is skipped and i is incremented to 1. The loop is then repeated with i = 1. If z is not equal to 1, then statements1 is executed, i is incremented to 1, and the loop is repeated.
|
VHDL Description
library IEEE; use IEEE.STD_LOGIC_1164.ALL; --The above library statements can be omitted; --however no error if it is not omitted. --The basic VHDL has type “natural.” entity factr is port(N : in natural; z : out natural); end factr; architecture factorl of factr is begin process (N) variable y, i : natural; begin y := 1; i := 0; while (i < N) loop i := i + 1; y := y i; end loop; z <= y; end process; end factorl; |
To write the code for the counter, binary-integer conversion is used
VHDL Description:
library ieee; use ieee.std_logic_1164.all; entity CNTR_Hold is port (clk, hold : in std_logic; q : buffer std_logic_vector (3 downto 0)); end CNTR_Hold; architecture CNTR_Hld of CNTR_Hold is begin ct : process (clk) variable temp : std_logic_vector (3 downto 0) := “0000”; -- temp is initialized to 0 so count starts at 0 variable result : integer := 0; begin if rising_edge (clk) then result := 0; -- change binary to integer lop1 : for i in 0 to 3 loop if temp(i) = ‘1’ then result := result + 2i; end if; end loop; -- increment result to describe a counter result := result + 1; -- change integer to binary lop2 : for i in 0 to 3 loop -- exit the loop if hold = 1 exit when hold = ‘1’; -- “when” is a predefined word if (result MOD 2 = 1) then temp (i) := ‘1’; else temp (i) := ‘0’; end if; --Successive division by 2 result := result/2; end loop; q <= temp; end if; end process ct; end CNTR_Hld;
|