ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2025
Просмотров: 3475
Скачиваний: 2
Sequential Code |
101 |
WHEN "01" => x<=b; y<=c;
WHEN OTHERS => x<="0000"; y<="ZZZZ";
END CASE;
The CASE statement (sequential) is very similar to WHEN (combinational). Here too all permutations must be tested, so the keyword OTHERS is often helpful. Another important keyword is NULL (the counterpart of UNAFFECTED), which should be used when no action is to take place. For example, WHEN OTHERS => NULL;. However, CASE allows multiple assignments for each test condition (as shown in the example above), while WHEN allows only one.
Like in the case of WHEN (section 5.3), here too ‘‘WHEN value’’ can take up three forms:
WHEN value |
-- single value |
||
WHEN |
value1 to value2 |
-- range, for enumerated data types |
|
-- |
only |
||
WHEN |
value1 | value2 |... |
-- |
value1 or value2 or ... |
Example 6.6: DFF with Asynchronous Reset #3
The code below implements the same DFF of example 6.1 (figures 6.1 and 6.2). However, here CASE was used instead of IF only. Notice that a few unnecessary declarations were intentionally included in the code to illustrate their usage.
1 |
---------------------------------------------- |
|
2 |
LIBRARY ieee; |
-- Unnecessary declaration, |
3 |
-- because |
4USE ieee.std_logic_1164.all; -- BIT was used instead of
5 |
-- STD_LOGIC |
6 |
---------------------------------------------- |
7ENTITY dff IS
8PORT (d, clk, rst: IN BIT;
9 |
q: OUT BIT); |
10 |
END dff; |
11 |
---------------------------------------------- |
12 |
ARCHITECTURE dff3 OF dff IS |
13BEGIN
14PROCESS (clk, rst)
15BEGIN
16CASE rst IS
TLFeBOOK
102 |
Chapter 6 |
SSD |
|||||||||||||||||||||||||
C |
a |
||||||||||||||||||||||||
O |
|||||||||||||||||||||||||
U |
f |
b |
|||||||||||||||||||||||
clk |
N |
||||||||||||||||||||||||
T |
digit2 |
g |
|||||||||||||||||||||||
e |
c |
||||||||||||||||||||||||
E |
|||||||||||||||||||||||||
R |
|||||||||||||||||||||||||
digit1 |
d |
x |
|||||||||||||||||||||||
reset |
Input: “xabcdefg” |
Figure 6.7 |
|
2-digit counter of example 6.7. |
17WHEN '1' => q<='0';
18WHEN '0' =>
19IF (clk'EVENT AND clk='1') THEN
20 |
q <= d; |
||
21 |
END IF; |
||
22 |
WHEN OTHERS => NULL; |
-- |
Unnecessary, rst is of type |
23 |
-- |
BIT |
24END CASE;
25END PROCESS;
26END dff3;
27----------------------------------------------
Example 6.7: Two-digit Counter with SSD Output
The code below implements a progressive 2-digit decimal counter (0 ! 99 ! 0), with external asynchronous reset plus binary-coded decimal (BCD) to seven-segment display (SSD) conversion. Diagrams of the circuit and SSD are shown in figure 6.7. The CASE statement (lines 31–56) was employed to determine the output signals that will feed the SSDs. Notice that we have chosen the following connection between the circuit and the SSD: xabcdefg (that is, the MSB feeds the decimal point, while the LSB feeds segment g).
As can be seen, this circuit is a straight extension of that presented in example 6.2, with the di¤erences that now two digits are necessary rather than one, and that the outputs must be connected to SSD displays. The operation of the circuit can be verified in the simulation results of figure 6.8.
TLFeBOOK
Sequential Code |
103 |
Figure 6.8
Simulation results of example 6.7.
1 --------------------------------------------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 --------------------------------------------------
5ENTITY counter IS
6PORT (clk, reset : IN STD_LOGIC;
7 |
digit1, digit2 : OUT STD_LOGIC_VECTOR (6 DOWNTO 0)); |
|
8 |
END counter; |
|
9 |
-------------------------------------------------- |
|
10 ARCHITECTURE |
counter OF counter IS |
|
11BEGIN
12PROCESS(clk, reset)
13VARIABLE temp1: INTEGER RANGE 0 TO 10;
14VARIABLE temp2: INTEGER RANGE 0 TO 10;
15BEGIN
16---- counter: ----------------------
17IF (reset='1') THEN
18temp1 := 0;
19temp2 := 0;
20ELSIF (clk'EVENT AND clk='1') THEN
21temp1 := temp1 + 1;
22IF (temp1=10) THEN
23temp1 := 0;
24temp2 := temp2 + 1;
25IF (temp2=10) THEN
26 |
temp2 := 0; |
TLFeBOOK
104 |
Chapter 6 |
27END IF;
28END IF;
29END IF;
30---- BCD to SSD conversion: --------
31CASE temp1 IS
32 |
WHEN 0 => digit1 <= "1111110"; |
--7E |
|
33 |
WHEN 1 => digit1 <= "0110000"; |
--30 |
|
34 |
WHEN 2 => digit1 <= "1101101"; |
--6D |
|
35 |
WHEN 3 => digit1 <= "1111001"; |
--79 |
|
36 |
WHEN 4 => digit1 <= "0110011"; |
--33 |
|
37 |
WHEN 5 => digit1 <= "1011011"; |
--5B |
|
38 |
WHEN 6 |
=> digit1 <= "1011111"; |
--5F |
39 |
WHEN 7 |
=> digit1 <= "1110000"; |
--70 |
40 |
WHEN 8 |
=> digit1 <= "1111111"; |
--7F |
41 |
WHEN 9 |
=> digit1 <= "1111011"; |
--7B |
42WHEN OTHERS => NULL;
43END CASE;
44CASE temp2 IS
45 |
WHEN 0 => digit2 <= "1111110"; |
--7E |
|
46 |
WHEN 1 => digit2 <= "0110000"; |
--30 |
|
47 |
WHEN 2 => digit2 <= "1101101"; |
--6D |
|
48 |
WHEN 3 => digit2 <= "1111001"; |
--79 |
|
49 |
WHEN 4 => digit2 <= "0110011"; |
--33 |
|
50 |
WHEN 5 => digit2 <= "1011011"; |
--5B |
|
51 |
WHEN 6 |
=> digit2 <= "1011111"; |
--5F |
52 |
WHEN 7 |
=> digit2 <= "1110000"; |
--70 |
53 |
WHEN 8 |
=> digit2 <= "1111111"; |
--7F |
54 |
WHEN 9 |
=> digit2 <= "1111011"; |
--7B |
55WHEN OTHERS => NULL;
56END CASE;
57END PROCESS;
58END counter;
59--------------------------------------------------
Comment: Notice above that the same routine was repeated twice (using CASE statements). We will learn, in Part II, how to write and compile frequently used pieces of code into user-defined libraries, so that such repetitions can be avoided.
TLFeBOOK
Sequential Code |
105 |
6.6LOOP
As the name says, LOOP is useful when a piece of code must be instantiated several times. Like IF, WAIT, and CASE, LOOP is intended exclusively for sequential code, so it too can only be used inside a PROCESS, FUNCTION, or PROCEDURE.
There are several ways of using LOOP, as shown in the syntaxes below.
FOR / LOOP: The loop is repeated a fixed number of times.
[label:] FOR identifier IN range LOOP (sequential statements)
END LOOP [label];
WHILE / LOOP: The loop is repeated until a condition no longer holds.
[label:] WHILE condition LOOP (sequential statements)
END LOOP [label];
EXIT: Used for ending the loop.
[label:] EXIT [label] [WHEN condition];
NEXT: Used for skipping loop steps.
[label:] NEXT [loop_label] [WHEN condition];
Example of FOR / LOOP:
FOR i IN 0 TO 5 LOOP
x(i) <= enable AND w(i+2);
y(0, i) <= w(i);
END LOOP;
In the code above, the loop will be repeated unconditionally until i reaches 5 (that is, six times).
TLFeBOOK
106 |
Chapter 6 |
One important remark regarding FOR / LOOP (similar to that made for GENERATE, in chapter 5) is that both limits of the range must be static. Thus a declaration of the type "FOR i IN 0 TO choice LOOP", where choice is an input (nonstatic) parameter, is generally not synthesizable.
Example of WHILE / LOOP: In this example, LOOP will keep repeating while i < 10.
WHILE (i < 10) LOOP
WAIT UNTIL clk'EVENT AND clk='1';
(other statements)
END LOOP;
Example with EXIT: In the code below, EXIT implies not an escape from the current iteration of the loop, but rather a definite exit (that is, even if i is still within the data range, the LOOP statement will be considered as concluded). In this case, the loop will end as soon as a value di¤erent from ‘0’ is found in the data vector.
FOR i IN data'RANGE LOOP
CASE data(i) IS
WHEN '0' => count:=count+1;
WHEN OTHERS => EXIT;
END CASE;
END LOOP;
Example with NEXT: In the example below, NEXT causes LOOP to skip one iteration when i ¼ skip.
FOR i IN 0 TO 15 LOOP
NEXT WHEN i=skip; |
-- jumps to next iteration |
(...)
END LOOP;
Several complete design examples, illustrating various applications of LOOP, are presented below.
Example 6.8: Carry Ripple Adder
Figure 6.9 shows an 8-bit unsigned carry ripple adder. The top-level diagram shows the inputs and outputs of the circuit: a and b are the input vectors to be added, cin is the carry-in bit, s is the sum vector, and cout is the carry-out bit. The one-level- below-top diagram shows how the carry bits propagate (ripple).
TLFeBOOK
Sequential Code |
107 |
Top level: |
One level below top: |
|||||||||||||||||||||||||||||||||||||
a0 |
b0 |
a1 b1 |
a7 b7 |
|||||||||||||||||||||||||||||||||||
a |
s |
|||||||||||||||||||||||||||||||||||||
b |
||||||||||||||||||||||||||||||||||||||
+ |
c0 |
+ |
+ |
+ |
c8 |
|||||||||||||||||||||||||||||||||
c1 |
c2 |
c7 |
||||||||||||||||||||||||||||||||||||
cin |
cout |
(cin |
(cout) |
|||||||||||||||||||||||||||||||||||
s0 |
s1 |
s7 |
||||||||||||||||||||||||||||||||||||
Figure 6.9 |
||||||||||||||||||||||||||||||||||||||
8-bit carry ripple adder of example 6.8 |
||||||||||||||||||||||||||||||||||||||
Figure 6.10
Simulation results of example 6.8.
Each section of the latter diagram is a full-adder unit (section 1.4). Thus its outputs can be computed by means of:
sj ¼ aj XOR bj XOR cj
cjþ1 ¼ (aj AND bj) OR (aj AND cj) OR (bj AND cj)
Two solutions are presented, being one generic (that is, for any number of bits, based on what we saw in chapter 4) and the other specific for 8-bit numbers. Moreover, we illustrate the use of vectors and FOR/LOOP in the first solution, and of integers and IF in the second. Simulation results from either solution are shown in figure 6.10.
Note: We will see more about adders in chapter 9.
1 ----- Solution 1: Generic, with VECTORS --------
2LIBRARY ieee;
3USE ieee.std_logic_1164.all;
TLFeBOOK
108 |
Chapter 6 |
4 ------------------------------------------------
5ENTITY adder IS
6GENERIC (length : INTEGER := 8);
7PORT ( a, b: IN STD_LOGIC_VECTOR (length-1 DOWNTO 0);
8cin: IN STD_LOGIC;
9s: OUT STD_LOGIC_VECTOR (length-1 DOWNTO 0);
10cout: OUT STD_LOGIC);
11END adder;
12 ------------------------------------------------
13 ARCHITECTURE adder OF adder IS
14BEGIN
15PROCESS (a, b, cin)
16VARIABLE carry : STD_LOGIC_VECTOR (length DOWNTO 0);
17BEGIN
18carry(0) := cin;
19FOR i IN 0 TO length-1 LOOP
20s(i) <= a(i) XOR b(i) XOR carry(i);
21carry(i+1) := (a(i) AND b(i)) OR (a(i) AND
22 |
carry(i)) OR (b(i) AND carry(i)); |
23END LOOP;
24cout <= carry(length);
25END PROCESS;
26END adder;
27 ------------------------------------------------
1 ---- Solution 2: non-generic, with INTEGERS ----
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ------------------------------------------------
5ENTITY adder IS
6PORT ( a, b: IN INTEGER RANGE 0 TO 255;
7c0: IN STD_LOGIC;
8s: OUT INTEGER RANGE 0 TO 255;
9 |
c8: OUT STD_LOGIC); |
10 |
END adder; |
11 |
------------------------------------------------ |
12 |
ARCHITECTURE adder OF adder IS |
13 |
BEGIN |
TLFeBOOK
Sequential Code |
109 |
14PROCESS (a, b, c0)
15VARIABLE temp : INTEGER RANGE 0 TO 511;
16BEGIN
17IF (c0='1') THEN temp:=1;
18ELSE temp:=0;
19END IF;
20temp := a + b + temp;
21IF (temp > 255) THEN
22c8 <= '1';
23 |
temp := temp--- |
256; |
24ELSE c8 <= '0';
25END IF;
26s <= temp;
27END PROCESS;
28END adder;
29 ------------------------------------------------
Example 6.9: Simple Barrel Shifter
Figure 6.11 shows the diagram of a very simple barrel shifter. In this case, the circuit must shift the input vector (of size 8) either 0 or 1 position to the left. When actually shifted (shift ¼ 1), the LSB bit must be filled with ‘0’ (shown in the botton left corner of the diagram). If shift ¼ 0, then outp ¼ inp; if shift ¼ 1, then outp(0) ¼ ‘0’ and outp(i) ¼ inp(i 1), for 1 ai a7.
A complete VHDL code is presented below, which illustrates the use of FOR/ LOOP. Simulation results appear in figure 6.12.
Note: A complete barrel shifter (with shift ¼ 0 to n 1, where n is the size of the input vector) will be seen in chapter 9.
1 ---------------------------------------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------------
5ENTITY barrel IS
6GENERIC (n: INTEGER := 8);
7PORT ( inp: IN STD_LOGIC_VECTOR (n-1 DOWNTO 0);
8shift: IN INTEGER RANGE 0 TO 1;
9 |
outp: OUT STD_LOGIC_VECTOR (n-1 DOWNTO 0)); |
TLFeBOOK