-
Notifications
You must be signed in to change notification settings - Fork 68
/
Copy pathchapter5.tex
569 lines (505 loc) · 39.1 KB
/
chapter5.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
% Free range VHDL
% Authors: Bryan Mealy, Fabrizio Tappero
% Date: January, 2023
% URL: https://github.com/fabriziotappero/Free-Range-VHDL-book
% (C) 2018-2023 B. Mealy, F. Tappero
%
% !TEX root = master.tex
%
\chapter{Standard Models in VHDL Architectures}
As you may remember, the VHDL architecture describes how your VHDL system will behave. The architecture body contains two parts: the declaration section and the begin-end section where a collection of (concurrent) signal assignments appear. We have studied three types of signal assignment so far: concurrent signal assignment, conditional signal assignment and selected signal assignment. We were about to describe another concurrent statement, the process statement, before we got side-tracked. Now, let us quickly introduce a new topic before we jump into the process statement.
There are three different approaches to writing VHDL architectures. These approaches are known as \textbf{data-flow} style, \textbf{structural} style and \textbf{behavioral} style architectures. The standard approach to learning VHDL is to introduce each of these architectural styles individually and design a few circuits using that style. Although this approach is good from the standpoint of keeping things simple while immersed in the learning process, it is also somewhat misleading because more complicated VHDL circuits generally use a mixture of these three styles. Keep this fact in mind in the following discussion of these styles. We will, however, put most of our focus on data-flow and behavioral architectures. Structural modeling is essentially a method to combine an existing set of VHDL models. In other words, structural modeling supports the interconnection of black boxes but does not have the ability to describe the logic functions used to model the circuit operation. For this reason, it is less of a design method and more of an approach for interfacing previously designed modules.
The reason we choose to slip the discussion of the different architectures at this point is that you already have some familiarity with one of the styles. Up to this point, all of our circuits have been implemented using the data-flow style. We are now at the point of talking about the behavioral style of architectures which is primarily centered around another concurrent statement known as the process statement. If it seems confusing, some of the confusion should go away once we start dealing with actual circuits and real VHDL code.
\section{Data-flow Style Architecture}
A data-flow style architecture specifies a circuit as a concurrent representation of the flow of data through the circuit. In the data-flow approach, circuits are described by showing the input and output relationships between the various built-in components of the VHDL language. The built-in components of VHDL include operators such as AND, OR, XOR, etc. The three forms of concurrent statements we have talked about up until now (concurrent signal assignment, conditional signal assignment and selected signal assignment) are all statements that are found in data-flow style architectures. In other words, if you exclusively used concurrent, conditional and selected signal assignment statement in your VHDL models, you have used a data-flow model. If you were to re-examine some of the examples we have done so far, you can in fact sort of see how the data flows through the circuit. To put this in other words, if you have a working knowledge of digital logic, it is fairly straightforward to imagine the underlying circuitry in terms of standard logic gates. These signal assignment statements effectively describe how the data flows from the signals on the right-hand side of the assignment operator (the ``{\footnotesize$<=$}'') to the signal on the left-hand side of the operator.
The data-flow style of architecture has its strong points and weak points. It is good that you can see the flow of data in the circuit by examining the VHDL code. The data-flow models also allow you to make an intelligent guess as to how the actual logic will appear when you decide to synthesize the circuit. Data-flow modeling works fine for small and relatively simple circuits. But as circuits become more complicated, it is often advantageous to switch to behavioral style models.
\section{Behavioral Style Architecture}
In comparison to the data-flow style architecture, the behavioral style architecture provides no details as to how the design is implemented in actual hardware. VHDL code written in a behavioral style does not necessarily reflect how the circuit is implemented when it is synthesized. Instead, the behavioral style models how the circuit outputs will react to the circuit inputs. Whereas in data-flow modeling you somewhat need to have a feel for the underlying logic in the circuit, behavioral models provide you with various tools to describe how the circuit will behave and leave the implementation details up to the synthesis tool. In other words, data-flow modeling describes how the circuit should look in terms of logic gates whereas behavioral modeling describes how the circuit should behave. For these reasons, behavioral modeling is considered higher up on the circuit abstraction level as compared to data-flow models. It is the VHDL synthesizer tool that decides the actual circuit implementation. In one sense, behavioral style modeling is the ultimate ``black box'' approach to designing circuits.
The heart of the behavioral style architecture is the \textit{process statement}. This is the fourth type of concurrent statement that we will work with. As you will see, the process statement is significantly different from the other three concurrent statements in several ways. The major difference lies in the process statement's approach to concurrency, which is the major sticking point when you deal with this new concurrent statement.
\section{Process Statement}
The process statement itself is a concurrent statement identified by its label, its sensitivity list, a declaration area and a begin-end area containing instructions executed sequentially. An example of the process statement is shown in Listing~\ref{process_statement}.
The main point to remember about the process statement is that its body is constituted of sequential statements. The main difference between concurrent signal assignment statements and process statements lies with these sequential statements. But once again, let us stick to the similarities before we dive into the differences. The process label, listed in Listing~\ref{process_statement} is optional but should always be included to promote the self-description of your VHDL code.
\begin{lstlisting}[float, label=process_statement, caption=Syntax for the process statement.]
-- this is my first process
my_label: process(sensitivity_list) is
<item_declaration>
begin
<sequential_statements>
end process my_label;
\end{lstlisting}
Listings~\ref{process_statement_compl_1} and \ref{process_statement_compl_2} show a data-flow architecture and a behavioral style architecture for the same XOR entity. The main difference between the two architectures is the presence of the process statement in the listed code.
Let us remember that the concurrent signal assignment statement in the data-flow description operates as follows. Since it is a concurrent statement, every time there is a change in any of the signals listed on the right-hand side of the signal assignment operator, the signal on the left-hand side of the operator is re-evaluated. For the behavioral architecture description, every time there is a change in signals in the process sensitivity list, all of the sequential statements in the process are re-evaluated. Evaluation of the process statement is controlled by the signals that are placed in the process sensitivity list. These two approaches are effectively the same except the syntax is significantly different.
So here is where it gets strange. Even though both of the architectures listed in \ref{process_statement_compl_1} and \ref{process_statement_compl_2} have the exact same signal assignment statement (\texttt{F $<=$ A XOR B;}), execution of the statement in the behavioral style architecture is controlled by which signals appear in the \textit{process sensitivity list}. The statement appearing in the data-flow model is re-evaluated every time there is a change in signal A or in the signal B. This is a functional difference rather than a cosmetic difference.
\noindent
\begin{minipage}{0.49\linewidth}
\begin{lstlisting}[label=process_statement_compl_1, caption=Data-flow architecture.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity my_xor is
port ( A,B : in std_logic;
F : out std_logic);
end my_xor;
-- architecture
architecture dataflow of my_xor is
begin
F <= A XOR B;
end dataflow;
--
--
--
\end{lstlisting}
\end{minipage}
\begin{minipage}{0.49\linewidth}
\begin{lstlisting}[label=process_statement_compl_2, caption=Behavioral architecture.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity my_xor is
port ( A,B : in std_logic;
F : out std_logic);
end my_xor;
-- architecture
architecture behav of my_xor is
begin
xor_proc: process(A,B) is
begin
F <= A XOR B;
end process xor_proc;
end behav;
\end{lstlisting}
\end{minipage}
The process statement should be considered a way the programmer has at his disposal to execute a series of sequential statements (i.e. in a behavioral manner); never forget that the process statement is itself a concurrent statement; therefore when you place two processes inside the architecture body, their execution will be concurrent.
In Listing~\ref{process_stat_complete}, you can see what a complete process statement looks like. Remember that all variables defined inside the process body will only be visible within the process body itself. Furthermore, notice that the statement at line 24 is placed inside the architecture body but outside the process body; therefore its execution happens concurrently with the process statement.
\begin{lstlisting}[float, numbers=left,label=process_stat_complete, caption=Use of the process statement.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity my_system is
port ( A,B,C : in std_logic;
F,Q : out std_logic);
end my_system;
-- architecture
architecture behav of my_system is
signal A1 : std_logic;
begin
some_proc: process(A,B,C) is
variable x,y : integer;
begin
x:=74;
y:=67;
A1 <= A and B and C;
if x>y then
F <= A1 or B;
end if;
end process some_proc;
-- we are outside the process body
Q <= not A;
end behav;
\end{lstlisting}
\section{Sequential Statements}
Now that we have the process statement at our disposal, we have a way to execute some code in a sequential manner.
Within a process, the execution of the sequential statements is initiated when a change in the signal contained in the process sensitivity list occurs. Generally speaking, execution of statements within the process body continues until the end of the process body is reached. The strangeness evokes a philosophical dilemma: the process statement is a concurrent statement yet it is made of sequential statements. This is actually a tough concept to grasp. After years of contemplation, I am only starting to grasp the reality of this strange contradiction.
The key to understand sequential evaluation of statements occurring in a concurrent statement remains hidden in the interpretation of VHDL code by the synthesizer. And since the ins and outs of this interpretation are not always readily apparent, some implementation details must be taken for granted until the time comes when you really need to fully understand the process. The solution is to keep your process statements as simple as possible. The tendency is to use the process statement as a repository for a bunch of loosely-related sequential statements. Although syntactically correct, the code is not intelligible (understandable) in the context of digital circuit generation. You should strive to keep your process statements simple. Divide up your intended functionality into several process statements that communicate with each other rather than one giant, complicated, bizarre process statement. Remember, process statements are concurrent statements: they all can be executed concurrently. Try to take advantage of this feature in order to simplify your circuit descriptions.
There are three types of sequential statements that we will be discussing. The first one is the \textbf{signal assignment statement}:
the ``{\footnotesize$<=$}''. We will not say too much about the first type though because we have already been dealing with its analogue in the data-flow models. The other two types of statements are the \textbf{if statement} and the \textbf{case statement}. The nice part about all of these statements is that you have worked with them before in algorithmic programming languages. The structure and function of the VHDL \texttt{if} and \texttt{case} statements is strikingly similar. Keep this in mind when you read the descriptions that follow.
\subsection{Signal Assignment Statement}
The sequential style of a signal assignment statement is syntactically equivalent to the concurrent signal assignment statement. Another way to look at it is that if a signal assignment statement appears inside of a process then it is a sequential statement; otherwise, it is a concurrent signal assignment statement. To drive the point home, the signal assignment statement ``{\footnotesize$F <= A~XOR~B;$}'' in the data-flow style architecture of Listing~\ref{process_statement_compl_1} is a concurrent signal assignment statement while the same statement in the behavioral style architecture, Listing~\ref{process_statement_compl_2}, is a sequential signal assignment statement. The functional differences were already covered in the discussion regarding process statements.
\subsection{\texttt{if} Statement}
The \texttt{if} statement is used to create a branch in the execution flow of the sequential statements. Depending on the conditions listed in the body of the \texttt{if} statement, either the instructions associated with one or none of the branches is executed when the \texttt{if} statement is processed. The general form of the \texttt{if} statement is shown in Listing~\ref{if_stat}.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=if_stat, caption=Syntax of the \texttt{if} statement.]
if (condition) then
<statements>
elsif (condition) then
<statements>
else
<statements>
end if;
\end{lstlisting}
\end{minipage}
The concept of the \texttt{if} statement should be familiar to you in two regards. First, its form and function are similar to the \texttt{if}-genre of statements found in most algorithmic programming languages. The syntax, however, is a bit different. Secondly, the VHDL \texttt{if} statement is the sequential equivalent to the VHDL conditional signal assignment statement. These two statements essentially do the same thing but \textbf{the \texttt{if} statement is a sequential statement found inside a process body while the conditional signal assignment statement is one form of concurrent signal assignment}.
Yet again, there are a couple of interesting things to note about the listed syntax of the \texttt{if} statement.
\begin{my_list}
\item The parentheses placed around the condition expressions are optional. They should be included in most cases to increase the readability of the VHDL source code.
\item Each \texttt{if}-type statement contains an associated \texttt{then} keyword. The final \texttt{else} clause does not have the \texttt{then} keyword associated with it.
\item As written in Listing~\ref{if_stat}, the \texttt{else} clause is a catch-all statement. If none of the previous conditions is evaluated as true, then the sequence of statements associated with the final \texttt{else} clause is executed. The way the \texttt{if} statement is shown in Listing~\ref{if_stat} guarantees that at least one of the listed sequence of statements will be executed.
\item The final \texttt{else} clause is optional. Not including the final \texttt{else} clause presents the possibility that none of the sequence of statements associated with the \texttt{if} statement will be evaluated. This has deep ramifications that we will discuss later.
\end{my_list}
Now let us see some examples that will help us to better understand how to use the \texttt{if} statement.
\begin{leftbar}
\noindent
\textbf{EXAMPLE 9.}
Write some VHDL code using an \texttt{if} statement that implements the following logic function:
$F\_OUT(A,B,C)=A\overline{B}~\!\overline{C}+BC$
\end{leftbar}
\noindent
\textbf{SOLUTION.} Although it is not directly stated in the problem description, the VHDL code for this solution must use a behavioral architecture. This is because the problem states that an \texttt{if} statement should be used. The VHDL code for the solution is shown in Listing~\ref{exe_9}. We have opted to leave out the black-box diagram in this case since the problem is relatively simple and thus does not really demonstrate the power of behavioral modeling.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_9, caption=Solution to Example~9.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity my_ex is
port (A,B,C : in std_logic;
F_OUT : out std_logic);
end my_ex;
-- architecture
architecture silly_example of my_ex is
begin
proc1: process(A,B,C) is
begin
if (A = '1' and B = '0' and C = '0') then
F_OUT <= '1';
elsif (B = '1' and C = '1') then
F_OUT <= '1';
else
F_OUT <= '0';
end if;
end process proc1;
end silly_example;
\end{lstlisting}
\end{minipage}
This is probably not the best way to implement a logic function but it does show an \texttt{if} statement in action. An alternate architecture for the solution of Example~9 is shown in Listing~\ref{exe_9_1}.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_9_1, caption=Alternative solution to Example~9.]
-- architecture
architecture bad_example of my_ex_7 is
begin
proc1: process(A,B,C)
begin
if (A='1' and B='0' and C='0') or (B='1' and C='1') then
F_OUT <= '1';
else
F_OUT <= '0';
end if;
end process proc1;
end bad_example;
\end{lstlisting}
\end{minipage}
One final comment on process statements. Process statements can be preceded with an optional label. A label should always be included with process statements as a form of self-description. This of course means that the label should be meaningful in terms of describing the purpose of the process statement. Providing good label names is somewhat of an art form but keep in mind that it is easier to provide a meaningful name to a process that is not trying to do too much. A more intelligent use of the \texttt{if} statement is demonstrated in the next example.
\begin{leftbar}
\noindent
\begin{minipage}{0.45\linewidth}
\textbf{EXAMPLE 10.}
Write some VHDL code that implements the 8:1 MUX shown below. Use an \texttt{if} statement in your implementation.\\
\end{minipage}
\begin{minipage}{0.5\linewidth}
\begin{flushright}
\begin{tikzpicture}[x=1mm,y=1mm,line width=0.8pt,scale=0.9,framed]
%\draw[help lines] (0,0) grid (50,50);
% BOX
\draw (20,5) rectangle (35,20) node[midway]{$mux\_8t1$};
% INPUTS
\small
\node (b) at (20,22.5) {}; % this is to extend the pink area
\node (a) at (20,2.5) {}; % this is the reference point
\draw [latex-] ($(a)+(0,15)$) -- ++(-10,0) node[above]{Data\_in} node[pos=0.25,above]{8} node[pos=0.4]{/};
\draw [latex-] ($(a)+(0,5)$) -- ++(-10,0) node[above]{SEL} node[pos=0.25,above]{3} node[pos=0.4]{/};
% OUTPUTS
\draw [-latex] ($(a)+(15,10)$) -- ++(10,0) node[above]{F\_CTRL};
\end{tikzpicture}
\end{flushright}
\end{minipage}
\end{leftbar}
\noindent
\textbf{SOLUTION.} The solution to Example~10 is shown in Listing~\ref{exe_10}.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_10, caption=Solution to Example~10.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity mux_8t1 is
port ( Data_in : in std_logic_vector (7 downto 0);
SEL : in std_logic_vector (2 downto 0);
F_CTRL : out std_logic);
end mux_8t1;
-- architecture
architecture mux_8t1_arc of mux_8t1 is
begin
my_mux: process (Data_in,SEL)
begin
if (SEL = "111") then F_CTRL <= Data_in(7);
elsif (SEL = "110") then F_CTRL <= Data_in(6);
elsif (SEL = "101") then F_CTRL <= Data_in(5);
elsif (SEL = "100") then F_CTRL <= Data_in(4);
elsif (SEL = "011") then F_CTRL <= Data_in(3);
elsif (SEL = "010") then F_CTRL <= Data_in(2);
elsif (SEL = "001") then F_CTRL <= Data_in(1);
elsif (SEL = "000") then F_CTRL <= Data_in(0);
else F_CTRL <= '0';
end if;
end process my_mux;
end mux_8t1_arc;
\end{lstlisting}
\end{minipage}
The solution to Example~10 shown in Listing~\ref{exe_10} uses some new syntax. The entity uses bundle signals, but the associated architecture needs to access individual elements of these bundles. The solution is to use the bus index operator to access internal signals of the bus. This is done via the use of a number representing an index placed inside parentheses (for example \texttt{Data\_in(7)}). Bus index operators are used extensively in VHDL and were previously mentioned. The solution to Example~10 shows a more typical use of the operator than was previously mentioned.
One other thing to notice about the solution in Example~10 is that every possible combination of the select variable is accounted for in the code. It would be possible to remove the final \texttt{elsif} statement in the code shown in Listing~\ref{exe_10} and place the associated signal assignment in the \texttt{else} clause. But this is not considered good VHDL practice and should be avoided at all costs. The justification for this is that it will modify the readability of the code but not alter the hardware generated by the code.
\begin{leftbar}
\noindent
\begin{minipage}{0.52\linewidth}
\textbf{EXAMPLE 11.}
Write some VHDL code that implements the 8:1 MUX shown here. Use as many \texttt{if} statements as you deem necessary to implement your design. In the black-box diagram, the \texttt{CE} input is a chip enable. When \texttt{CE = '1'}, the output acts like the MUX of Example~10. When \texttt{CE} is \texttt{'0'}, the output of the MUX is \texttt{'0'}.
\end{minipage}
\begin{minipage}{0.45\linewidth}
\begin{flushright}
\begin{tikzpicture}[x=1mm,y=1mm,line width=0.8pt,scale=0.9,framed]
%\draw[help lines] (0,0) grid (50,50);
% BOX
\draw (20,5) rectangle (35,20) node[midway]{$mux\_8to1$};
% INPUTS
\small
\node (b) at (0,-2) {}; % this is to extend the pink area
\node (b) at (20,22.5) {}; % this is to extend the pink area
\node (a) at (20,2.5) {}; % this is the reference point
\draw [latex-] ($(a)+(0,15)$) -- ++(-10,0) node[above]{Data\_in} node[pos=0.25,above]{8} node[pos=0.4]{/};
\draw [latex-] ($(a)+(0,5)$) -- ++(-10,0) node[above]{SEL} node[pos=0.25,above]{3} node[pos=0.4]{/};
\draw [latex-] ($(a)+(8.5,2.5)$) |- ++(-19,-5) node[above]{CE};
% OUTPUTS
\draw [-latex] ($(a)+(15,10)$) -- ++(10,0) node[above]{F\_CTRL};
\end{tikzpicture}
\end{flushright}
\end{minipage}
\end{leftbar}
\noindent
\textbf{SOLUTION.} The solution to Example~11 is strangely similar to the solution of Example~10. Note that in this solution the \texttt{if} statements can be nested to attain various effects. The solution to Example~11 is shown in Listing~\ref{exe_11}.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_11, caption=Solution to Example~11.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity mux_8to1_ce is
port ( Data_in : in std_logic_vector (7 downto 0);
SEL : in std_logic_vector (2 downto 0);
CE : in std_logic;
F_CTRL : out std_logic);
end mux_8to1_ce;
-- architecture
architecture mux_8to1_ce_arch of mux_8to1_ce is
begin
my_mux: process (Data_in,SEL,CE)
begin
if (CE = '0') then
F_CTRL <= '0';
else
if (SEL = "111") then F_CTRL <= Data_in(7);
elsif (SEL = "110") then F_CTRL <= Data_in(6);
elsif (SEL = "101") then F_CTRL <= Data_in(5);
elsif (SEL = "100") then F_CTRL <= Data_in(4);
elsif (SEL = "011") then F_CTRL <= Data_in(3);
elsif (SEL = "010") then F_CTRL <= Data_in(2);
elsif (SEL = "001") then F_CTRL <= Data_in(1);
elsif (SEL = "000") then F_CTRL <= Data_in(0);
else F_CTRL <= '0';
end if;
end if;
end process my_mux;
end mux_8to1_ce_arch;
\end{lstlisting}
\end{minipage}
\subsection{\texttt{case} Statement}
The \texttt{case} statement is somewhat similar to the \texttt{if} statement in that a sequence of statements is executed if an associated expression is true. The \texttt{case} statement differs from the \texttt{if} statement in that the resulting choice is made depending upon the value of the single control expression. Only one set of sequential statements is executed for each execution of the case statement. The statements executed are determined by the first \texttt{when} branch to evaluate as true. The syntax for the case statement is shown in Listing~\ref{case_stat}.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=case_stat, caption=Syntax for the \textit{case} statement.]
case (expression) is
when choices =>
<sequential statements>
when choices =>
<sequential statements>
when others =>
<sequential statements>
end case;
\end{lstlisting}
\end{minipage}
Once again, the concept of the \texttt{case} statement should be familiar to you in several regards. Firstly, it can generally be viewed as a compact form of the \texttt{if} statement. It is not as functional, however, for the reason described above. Secondly, the case statement is similar in both form and function to the \texttt{case} statement or the \texttt{switch} statement in other algorithmic programming languages. And finally, the VHDL \texttt{case} statement is the sequential equivalent of the VHDL selected signal assignment statement. These two statements essentially have the same capabilities but the case statement is a sequential statement found in a process body while the selected signal assignment statement is one form of concurrent signal assignment. The \texttt{when others} line is not required but should be used as good programming practice.
\begin{leftbar}
\noindent
\textbf{EXAMPLE 12.}
Write some VHDL code that implements the following function using the \texttt{case} statement:
$F\_OUT(A,B,C)=A\overline{B}~\!\overline{C}+BC$
\end{leftbar}
\noindent
\textbf{SOLUTION.} This solution falls into the category of not being the best way to implement a circuit using VHDL. It does, however, illustrate another useful feature in the VHDL. The first part of this solution requires that we list the function as a sum of minterms. This is done by multiplying the non-minterm product term given in the example by 1. In this case, 1 is equivalent to ($A+\overline{A}$). This factoring operation is shown as:
$F\_OUT(A,B,C)=A\overline{B}~\!\overline{C}+BC$
$F\_OUT(A,B,C)=A\overline{B}~\!\overline{C}+BC (A+\overline{A})$
$F\_OUT(A,B,C)=A\overline{B}~\!\overline{C}+ABC+\overline{A}BC$
The solution is shown in Listing~\ref{exe_12}. An interesting feature of this solution is the grouping of the three input signals which allows the use of a \texttt{case} statement in the solution. This approach requires the declaration of an intermediate signal which is appropriately labeled ``ABC''. Once again, this is probably not the most efficient method to implement a function but it does highlight the need to be resourceful and creative when describing the behavior of digital circuits.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_12, caption=Solution to Example~12.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity my_example is
port (A,B,C : in std_logic;
F_OUT : out std_logic);
end my_example;
-- architecture
architecture my_soln_exam of my_example is
signal ABC: std_logic_vector(2 downto 0);
begin
ABC <= A & B & C; -- group signals for case statement
my_proc: process (ABC)
begin
case (ABC) is
when "100" => F_OUT <= '1';
when "011" => F_OUT <= '1';
when "111" => F_OUT <= '1';
when others => F_OUT <= '0';
end case;
end process my_proc;
end my_soln_exam;
\end{lstlisting}
\end{minipage}
Another similar approach to Example~12 is to use the \textit{don't care} feature (represented by the symbol "-") built into VHDL. This allows the logic function to be implemented without having to massage the inputs. As with everything, if you have to modify the problem before you arrive at the solution, you stand a finite chance of creating an error that would not have otherwise been created if you had not taken a more clever approach. A different architecture for the solution of Example~12 is shown in Listing~\ref{exe_12_1}. One possible drawback of using a don't care feature in your VHDL code is that some synthesizers and some simulators do not handle it very well. I would avoid them at all costs and seek a more definitive method of modeling the circuits I am dealing with.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_12_1, caption=Alternative solution to Example~12.]
architecture my_soln_exam2 of my_example is
signal ABC: std_logic_vector(2 downto 0);
begin
ABC <= A & B & C; -- group signals for case statement
my_proc: process (ABC)
begin
case (ABC) is
when "100" => F_OUT <= '1';
when "-11" => F_OUT <= '1';
when others => F_OUT <= '0';
end case;
end process my_proc;
end my_soln_exam2;
\end{lstlisting}
\end{minipage}
One of the main points that should be emphasized in any VHDL program is readability. In the next problem, we will redo Example~11 using a \texttt{case} statement instead of \texttt{if} statements.
\begin{leftbar}
\begin{minipage}{0.5\linewidth}
\noindent
\textbf{EXAMPLE 13.}
Write some VHDL code that implements the 8:1 MUX shown below. Use a case statement in your design. In the black-box diagram shown below, the CE input is a chip enable. When CE = '1', the output acts like the MUX of Example~10. When CE is '0', the output of the MUX is '0'.
\end{minipage}
\begin{minipage}{0.47\linewidth}
\begin{flushright}
\begin{tikzpicture}[x=1mm,y=1mm,line width=0.8pt,scale=0.9,framed]
%\draw[help lines] (0,0) grid (50,50);
% BOX
\draw (20,5) rectangle (35,20) node[midway]{$mux\_8to1$};
% INPUTS
\small
\node (b) at (0,-2) {}; % this is to extend the pink area
\node (b) at (20,22.5) {}; % this is to extend the pink area
\node (a) at (20,2.5) {}; % this is the reference point
\draw [latex-] ($(a)+(0,15)$) -- ++(-10,0) node[above]{Data\_in} node[pos=0.25,above]{8} node[pos=0.4]{/};
\draw [latex-] ($(a)+(0,5)$) -- ++(-10,0) node[above]{SEL} node[pos=0.25,above]{3} node[pos=0.4]{/};
\draw [latex-] ($(a)+(8.5,2.5)$) |- ++(-19,-5) node[above]{CE};
% OUTPUTS
\draw [-latex] ($(a)+(15,10)$) -- ++(10,0) node[above]{F\_CTRL};
\end{tikzpicture}
\end{flushright}
\end{minipage}
\end{leftbar}
\noindent
\textbf{SOLUTION.} This solution to Example~13 is shown in Listing~\ref{exe_13}. The entity declaration is repeated below for your convenience. This solution places the \texttt{case} statement in the body of an \texttt{if} construct. In case you have not noticed it yet, the number of possible solutions to a given problem increases as the circuits you are implementing become more complex.
\noindent
\begin{minipage}{0.99\linewidth}
\begin{lstlisting}[label=exe_13, caption=Solution to Example~13.]
-- library declaration
library IEEE;
use IEEE.std_logic_1164.all;
-- entity
entity mux_8to1_ce is
port ( Data_in : in std_logic_vector (7 downto 0);
SEL : in std_logic_vector (2 downto 0);
CE : in std_logic;
F_CTRL : out std_logic);
end mux_8to1_ce;
-- architecture
architecture my_case_ex of mux_8to1_ce is
begin
my_mux: process (SEL,Data_in,CE)
begin
if (CE = '1') then
case (SEL) is
when "000" => F_CTRL <= Data_in(0);
when "001" => F_CTRL <= Data_in(1);
when "010" => F_CTRL <= Data_in(2);
when "011" => F_CTRL <= Data_in(3);
when "100" => F_CTRL <= Data_in(4);
when "101" => F_CTRL <= Data_in(5);
when "110" => F_CTRL <= Data_in(6);
when "111" => F_CTRL <= Data_in(7);
when others => F_CTRL <= '0';
end case;
else
F_CTRL <= '0';
end if;
end process my_mux;
end my_case_ex;
\end{lstlisting}
\end{minipage}
One very important point in the solution to Example~13 is the fact that a \texttt{case} statement was embedded into an \texttt{if} statement. The technical term for this style of coding is, as you would guess, nesting. Nesting sequential statements is typical in behavioral models and is used often. This is actually one of the features that make behavioral modeling so much more powerful than data-flow modeling. The reality is that conditional and selective signal assignment statements cannot be nested.
\section{Caveats Regarding Sequential Statements}
As you begin to work with sequential statements, you tend to start getting the feeling that you are doing algorithmic programming using a higher-level language. This is due to the fact that sequential statements have a similar look and feel to some of the programming constructs in higher-level languages. The bad part of this tendency is when and if your VHDL coding approach becomes similar to that of the higher-level language. Since this happens very often with people who are learning VHDL, it is appropriate to remind once again that \textbf{VHDL is not programming: VHDL is hardware design}. You are, generally speaking, not implementing algorithms in VHDL, you are describing hardware: this is a totally different paradigm.
It is not uncommon to see many, not so good, pieces of VHDL code that attempt to use a single process statement in order to implement a relatively complex circuit. Although the code appears like it should work in terms of the provided statements, this is an illusion based on the fact that your mind is interpreting the statements in terms of a higher-level language. The reality is that VHDL is somewhat mysterious in that you are trusting the VHDL synthesizer to magically know what you are trying to describe. If you do not understand the ins and outs of VHDL at a low level, your circuit is not going to synthesize properly. Most likely you understand simple VHDL behavioral models. But once the models become complex, your understanding quickly fades away. The solution to this problem is really simple: keep your VHDL models simple, particularly your process statements.
In VHDL, the best approach is to keep your process statements centered around a single function and have several process statements that communicate with each other. The wrong approach is to have one big process statement that does everything for you. The magic of VHDL is that if you provide simple code to the synthesizer, it is more than likely going to provide you with a circuit that works and with an implementation that is simple and eloquent. If you provide the synthesizer with complicated VHDL code, the final circuit may work and may even be efficient in both speed and real estate, but probably not. As opposed to higher-level languages where small amounts of code often translate directly to code of relatively high efficiency, efficiency in VHDL code is obtained by compact and simple partitioning of the VHDL code based on the underlying hardware constructs. In other words, simple VHDL models are better but the simplicity is generally obtained by proper partitioning and description of the model. So try to fight off the urge to impress your friends with the world's shortest VHDL model; your hardware friends will know better.
\section{Summary}
Let us now review some of the important concepts that have been introduced in this chapter.
\begin{my_list}
\item The three main flavors of VHDL modeling styles include data-flow, behavioral and structural models.
\item VHDL behavioral models, by definition, use process statements.
\item VHDL data-flow models by definition use concurrent signal assignment, conditional signal assignment and/or selected signal assignment.
\item The process statement is a concurrent statement. Statements appearing within the process statement are sequential statements.
\item The \texttt{if} statement has a direct analogy to the conditional signal assignment statement used in data-flow modeling.
\item The \texttt{case} statement has a direct analogy to the selected signal assignment statement used in data-flow modeling.
\item Both the \texttt{case} statement and the \texttt{if} statement can be nested. \textbf{Concurrent, conditional and selected signal assignment statements cannot be nested}.
\item The simplest concurrent statement is the concurrent signal assignment statement (e.g. ``{\footnotesize$F <= A;$}''). Its sequential equivalent is the sequential signal assignment statement and it looks identical.
\end{my_list}
\section{Exercises: Behavioral Modeling}
\begin{my_num_list}
\item For the following function, write VHDL behavioral models that implement these functions using both \texttt{case} statements and \texttt{if} statements (two separate models for each function).
a) $F(A,B) =\overline{A}B +A +A\overline{B}$
b) $F(A,B,C,D) =\overline{A}C\overline{D} +\overline{B}C +BC\overline{D}$
c) $F(A,B,C,D) =(\overline{A}+B)\cdot(\overline{B}+C+\overline{D})\cdot(\overline{A}+D)$
d) $F(A,B,C) = \displaystyle\prod(5,1,4,3) $
e) $F(A,B,C,D) = \displaystyle\sum(1,2) $
\item For the circuit below, write the VHDL behavioral model that implements it using both \texttt{case} statements and \texttt{if} statements (two separate models).
\usetikzlibrary{er}
\begin{tikzpicture}[minimum height=9mm]
%\node[draw, not gate US] at (-2.5,0.05) (D) {D};
\node[draw, and gate US] at (0,0.2) (C) {C};
\node[draw, not gate US] at ([xshift=-1.95cm]C.input 2) (D) {D};
\node[draw, or gate US] at (0,1.3) (B) {B};
\node[draw, and gate US] at (0,2.4) (A) {A};
\node[draw, or gate US] at (2.5,1.3) (E) {E};
\draw (D.output) -- (C.input 2);
\draw (A.output) -- +(0.7,0) |- (E.input 1);
\draw (C.output) -- +(0.7,0) |- (E.input 2);
\draw (B.output) -- (E.west);
\draw (E.output) -- ([xshift=0.5cm]E.output) node [right] {E\_out} ;
\draw (A.input 1) -- ([xshift=-3.cm]A.input 1) node [pos=1.1] {A\_1} ;
\draw (A.input 2) -- ([xshift=-3.cm]A.input 2) node [pos=1.1] {A\_2} ;
\draw (B.input 1) -- ([xshift=-3.1cm]B.input 1) node [pos=1.1] {B\_1} ;
\draw (B.input 2) -- ([xshift=-3.1cm]B.input 2) node [pos=1.1] {B\_2} ;
\draw (D.input) -- ([xshift=-1.9cm]D.output) node [left] {D\_1} ;
\node [circle,fill, inner sep=0pt,minimum size=1.2mm] at ([xshift=-6mm]B.input 2) (H) {}; %dot
\draw (C.input 1) -| (H);
%\draw [dashed] (-3.5,-0.5) rectangle (3.5,3.1) node [pos=0.93, auto=left] {my\_circuit} ;
\end{tikzpicture}
\item Model the previous circuit using concurrent, conditional, or selected signal assignment.
\item Provide a VHDL model of an 8-input AND gate using a process statement.
\item Provide a VHDL model of an 8-input OR gate using a process statement.
\item Provide a VHDL model of an 8:1 MUX using a process statement. Include a model that uses \texttt{if} statements and \texttt{case} statements (two separate models).
\item Provide a VHDL model of a 3:8 decoder using a process statement. Include a model that uses \texttt{if} statements and \texttt{case} statements (two separate models). Consider the outputs to be active low.
\end{my_num_list}