ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.06.2025
Просмотров: 3459
Скачиваний: 2
5Concurrent Code
Having finished laying out the basic foundations of VHDL (chapters 1 to 4), we can now concentrate on the design (code) itself.
VHDL code can be concurrent (parallel) or sequential. The former will be studied in this chapter, while the latter will be seen in chapter 6. This division is very important, for it allows a better understanding of which statements are intended for each kind of code, as well as the consequences of using one or the other.
The concurrent statements in VHDL are WHEN and GENERATE. Besides them, assignments using only operators (AND, NOT, þ, *, sll, etc.) can also be used to construct concurrent code. Finally, a special kind of assignment, called BLOCK, can also be employed in this kind of code.
5.1Concurrent versus Sequential
We start this chapter by reviewing the fundamental di¤erences between combinational logic and sequential logic, and by contrasting them with the di¤erences between concurrent code and sequential code.
Combinational versus Sequential Logic
By definition, combinational logic is that in which the output of the circuit depends solely on the current inputs (figure 5.1(a)). It is then clear that, in principle, the system requires no memory and can be implemented using conventional logic gates.
In contrast, sequential logic is defined as that in which the output does depend on previous inputs (figure 5.1(b)). Therefore, storage elements are required, which are connected to the combinational logic block through a feedback loop, such that now the stored states (created by previous inputs) will also a¤ect the output of the circuit.
A common mistake is to think that any circuit that possesses storage elements (flip-flops) is sequential. A RAM (Random Access Memory) is an example. A RAM can be modeled as in figure 5.2. Notice that the storage elements appear in a forward path rather than in a feedback loop. The memory-read operation depends only on the address vector presently applied to the RAM input, with the retrieved value having nothing to do with previous memory accesses.
Concurrent versus Sequential Code
VHDL code is inherently concurrent (parallel). Only statements placed inside a PROCESS, FUNCTION, or PROCEDURE are sequential. Still, though within these blocks the execution is sequential, the block, as a whole, is concurrent with any other (external) statements. Concurrent code is also called dataflow code.
TLFeBOOK
66
input |
Combinational |
output |
|||
Logic |
|||||
(a)
Figure 5.1
Combinational (a) versus sequential (b) logic.
Chapter 5
input |
Combinational |
output |
||||||
Logic |
||||||||
present |
next |
|||||||
state |
Storage |
state |
||||||
Elements |
||||||||
(b) |
||||||||
input |
Combinational |
output |
||||
Logic |
||||||
Storage
Elements
Figure 5.2
RAM model.
As an example, let us consider a code with three concurrent statements (stat1, stat2, stat3). Then any of the alternatives below will render the same physical circuit:
stat1 stat3 stat1
stat2 C stat2 C stat3 C etc. stat3 stat1 stat2
It is then clear that, since the order does not matter, purely concurrent code can not be used to implement synchronous circuits (the only exception is when a GUARDED BLOCK is used). In other words, in general we can only build combinational logic circuits with concurrent code. To obtain sequential logic circuits, sequential code (chapter 6) must be employed. Indeed, with the latter we can implement both, sequential as well as combinational circuits.
TLFeBOOK
Concurrent Code |
67 |
In this chapter, we will discuss concurrent code, that is, we will study the statements that can only be used outside PROCESSES, FUNCTIONS, or PROCEDURES. They are the WHEN statement and the GENERATE statement. Besides them, assignments using only operators (logical, arithmetic, etc) can obviously also be used to create combinational circuits. Finally, a special kind of statement, called BLOCK, can also be employed.
In summary, in concurrent code the following can be used:
Operators;
The WHEN statement (WHEN/ELSE or WITH/SELECT/WHEN);
The GENERATE statement;
The BLOCK statement.
Each of these cases is described below.
5.2Using Operators
This is the most basic way of creating concurrent code. Operators (AND, OR, þ, . *, sll, sra, etc.) were discussed in section 4.1, being a summary repeated in table 5.1 below.
Operators can be used to implement any combinational circuit. However, as will become apparent later, complex circuits are usually easier to write using sequential code, even if the circuit does not contain sequential logic. In the example that follows, a design using only logical operators is presented.
Table 5.1
Operators.
Operator type |
Operators |
Data types |
Logical |
NOT, AND, NAND, |
BIT, BIT_VECTOR, |
OR, NOR, XOR, XNOR |
STD_LOGIC, STD_LOGIC_VECTOR, |
|
STD_ULOGIC, STD_ULOGIC_VECTOR |
||
Arithmetic |
þ, , *, /, ** |
INTEGER, SIGNED, UNSIGNED |
(mod, rem, abs) |
||
Comparison |
¼, =¼, <, >, <¼, >¼ |
All above |
Shift |
sll, srl, sla, sra, rol, ror |
BIT_VECTOR |
Concatenation |
&, ( , , , ) |
Same as for logical operators, plus SIGNED and |
UNSIGNED |
||
TLFeBOOK
68 |
Chapter 5 |
a
b
MUX y
c
d
s1 s0
Figure 5.3
Multiplexer of example 5.1.
Example 5.1: Multiplexer #1
Figure 5.3 shows a 4-input, one bit per input multiplexer. The output must be equal to the input selected by the selection bits, s1-s0. Its implementation, using only logical operators, can be done as follows:
1 ---------------------------------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------
5ENTITY mux IS
6PORT ( a, b, c, d, s0, s1: IN STD_LOGIC;
7 |
y: OUT STD_LOGIC); |
8 |
END mux; |
9 |
--------------------------------------- |
10 |
ARCHITECTURE pure_logic OF mux IS |
11BEGIN
12y <= (a AND NOT s1 AND NOT s0) OR
13(b AND NOT s1 AND s0) OR
14(c AND s1 AND NOT s0) OR
15(d AND s1 AND s0);
16END pure_logic;
17 ---------------------------------------
Simulation results, confirming the functionality of the circuit, are shown in figure 5.4.
TLFeBOOK
Concurrent Code |
69 |
Figure 5.4
Simulation results of example 5.1.
5.3WHEN (Simple and Selected)
As mentioned above, WHEN is one of the fundamental concurrent statements (along with operators and GENERATE). It appears in two forms: WHEN / ELSE (simple WHEN) and WITH / SELECT / WHEN (selected WHEN). Its syntax is shown below.
WHEN / ELSE:
assignment WHEN condition ELSE assignment WHEN condition ELSE
...;
WITH / SELECT / WHEN:
WITH identifier SELECT assignment WHEN value, assignment WHEN value,
...;
Whenever WITH / SELECT / WHEN is used, all permutations must be tested, so the keyword OTHERS is often useful. Another important keyword is UNAFFECTED, which should be used when no action is to take place.
TLFeBOOK
70 |
Chapter 5 |
Example:
------ With WHEN/ELSE -------------------------
outp <= "000" WHEN (inp='0' OR reset='1') ELSE "001" WHEN ctl='1' ELSE
"010";
---- With WITH/SELECT/WHEN --------------------
WITH control SELECT
output <= "000" WHEN reset, "111" WHEN set,
UNAFFECTED WHEN OTHERS;
-----------------------------------------------
Another important aspect related to the WHEN statement is that the ‘‘WHEN value’’ shown in the syntax above can indeed 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 5.2: Multiplexer #2
This example shows the implementation of the same multiplexer of example 5.1, but with a slightly di¤erent representation for the sel input (figure 5.5). However, in it WHEN was employed instead of logical operators. Two solutions are presented: one using WHEN/ELSE (simple WHEN) and the other with WITH/SELECT/WHEN (selected WHEN). The experimental results are obviously similar to those obtained in example 5.1.
a
b
MUX y
c
d
sel (1:0)
Figure 5.5
Multiplexer of example 5.2.
TLFeBOOK
Concurrent Code |
71 |
1 ------- Solution 1: with WHEN/ELSE --------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 -------------------------------------------
5ENTITY mux IS
6PORT ( a, b, c, d: IN STD_LOGIC;
7sel: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
8 |
y: OUT STD_LOGIC); |
9 |
END mux; |
10 |
------------------------------------------- |
11 |
ARCHITECTURE mux1 OF mux IS |
12BEGIN
13y <= a WHEN sel="00" ELSE
14b WHEN sel="01" ELSE
15c WHEN sel="10" ELSE
16d;
17END mux1;
18 -------------------------------------------
1 --- Solution 2: with WITH/SELECT/WHEN -----
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 -------------------------------------------
5ENTITY mux IS
6PORT ( a, b, c, d: IN STD_LOGIC;
7sel: IN STD_LOGIC_VECTOR (1 DOWNTO 0);
8 |
y: OUT STD_LOGIC); |
9 |
END mux; |
10 |
------------------------------------------- |
11 |
ARCHITECTURE mux2 OF mux IS |
12BEGIN
13WITH sel SELECT
14y <= a WHEN "00", -- notice "," instead of ";"
15b WHEN "01",
16c WHEN "10",
17 |
d WHEN OTHERS; |
-- cannot be "d WHEN "11" " |
18 |
END mux2; |
|
19 |
-------------------------------------------- |
TLFeBOOK
72 |
Chapter 5 |
In the solutions above, sel could have been declared as an INTEGER, in which case the code would be the following:
1 ----------------------------------------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ----------------------------------------------
5ENTITY mux IS
6PORT ( a, b, c, d: IN STD_LOGIC;
7sel: IN INTEGER RANGE 0 TO 3;
8 |
y: OUT STD_LOGIC); |
9END mux;
10 ---- Solution 1: with WHEN/ELSE ---------------
11 ARCHITECTURE mux1 OF mux IS
12BEGIN
13y <= a WHEN sel=0 ELSE
14b WHEN sel=1 ELSE
15c WHEN sel=2 ELSE
16d;
17END mux1;
18-- Solution 2: with WITH/SELECT/WHEN --------
19ARCHITECTURE mux2 OF mux IS
20BEGIN
21WITH sel SELECT
22y <= a WHEN 0,
23b WHEN 1,
24c WHEN 2,
25d WHEN 3; -- here, 3 or OTHERS are equivalent,
26 |
END mux2; |
-- for all options are tested anyway |
27 |
----------------------------------------------- |
Note: Only one ARCHITECTURE can be synthesized at a time. Therefore, whenever we show more than one solution within the same overall code (like above), it is implicit that all solutions but one must be commented out (with ‘‘- -’’), or a synthesis script must be used, in order to synthesize the remaining solution. In simulations, the CONFIGURATION statement can be used to select a specific architecture.
Note: For a generic mux, please refer to problem 5.1.
TLFeBOOK
Concurrent Code |
73 |
ena
input (7:0) |
output (7:0) |
|||
Figure 5.6
Tri-state bu¤er of example 5.3.
Example 5.3: Tri-state Bu¤er
This is another example that illustrates the use of WHEN. The 3-state bu¤er of figure 5.6 must provide output ¼ input when ena (enable) is low, or output ¼ ‘‘ZZZZZZZZ’’ (high impedance) otherwise.
1LIBRARY ieee;
2 USE ieee.std_logic_1164.all;
3 ----------------------------------------------
4ENTITY tri_state IS
5PORT ( ena: IN STD_LOGIC;
6input: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
7 |
output: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)); |
8 |
END tri_state; |
9 |
---------------------------------------------- |
10 |
ARCHITECTURE tri_state OF tri_state IS |
11BEGIN
12output <= input WHEN (ena='0') ELSE
13 |
(OTHERS => 'Z'); |
14 |
END tri_state; |
15 |
---------------------------------------------- |
Simulation results from the circuit synthesized with the code above are shown in figure 5.7. As expected, the output stays in the high-impedance state while ena is high, being a copy of the input when ena is turned low.
Example 5.4: Encoder
The top-level diagram of an n-by-m encoder is shown in figure 5.8. We assume that n is a power of two, so m ¼ log2n. One and only one input bit is expected to be high at a time, whose address must be encoded at the output. Two solutions are presented, one using WHEN / ELSE, and the other with WITH / SELECT / WHEN.
TLFeBOOK
74 |
Chapter 5 |
Figure 5.7
Simulation results of example 5.3.
x(n-1) |
|||||
x(n-2) |
n x m |
||||
… |
(m-1:0) |
||||
ENCODER |
|||||
x(1) |
|||||
x(0) |
|||||
Figure 5.8 |
|||||
Encoder of example 5.4. |
|||||
1 ---- Solution 1: with WHEN/ELSE -------------
2LIBRARY ieee;
3 USE ieee.std_logic_1164.all;
4 ---------------------------------------------
5ENTITY encoder IS
6PORT ( x: IN STD_LOGIC_VECTOR (7 DOWNTO 0);
7 |
y: OUT STD_LOGIC_VECTOR (2 DOWNTO 0)); |
|
8 |
END encoder; |
|
9 |
--------------------------------------------- |
|
10 |
ARCHITECTURE encoder1 OF encoder IS |
|
11 |
BEGIN |
|
12 |
y <= |
"000" WHEN x="00000001" ELSE |
13"001" WHEN x="00000010" ELSE
14"010" WHEN x="00000100" ELSE
15"011" WHEN x="00001000" ELSE
16"100" WHEN x="00010000" ELSE
17"101" WHEN x="00100000" ELSE
18"110" WHEN x="01000000" ELSE
19"111" WHEN x="10000000" ELSE
20"ZZZ";
TLFeBOOK