-
Notifications
You must be signed in to change notification settings - Fork 0
/
top-quality-EVAL-SAMPLE.json
422 lines (422 loc) · 263 KB
/
top-quality-EVAL-SAMPLE.json
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
[
{
"textbook-paragraph": "{Finite State Machine Design Examples, Part I} This set of notes uses a series of examples to illustrate design principles for the implementation of finite state machines (FSMs) using digital logic. We begin with an overview of the design process for a digital FSM, from the development of an abstract model through the implementation of functions for the next-state variables and output signals. Our first few examples cover only the concrete aspects: we implement several counters, which illustrate the basic process of translating a concrete and complete state transition diagram into an implementation based on flip-flops and logic gates. We next consider a counter with a number of states that is not a power of two, with which we illustrate the need for FSM initialization. As part of solving the initialization problem, we also introduce a general form of selection logic called a multiplexer. We then consider the design process as a whole through a more general example of a counter with multiple inputs to control its behavior. We work from an abstract model down to an implementation, illustrating how semantic knowledge from the abstract model can be used to simplify the implementation. Finally, we illustrate how the choice of representation for the FSM's internal state affects the complexity of the implementation. Fortunately, designs that are more intuitive and easier for humans to understand also typically make the best designs in terms of other metrics, such as logic complexity. {Steps in the Design Process} Before we begin exploring designs, let's talk briefly about the general approach that we take when designing an FSM. We follow a six-step process:{-8pt} {{}{} {}{}{} {develop an abstract model}{step-abs} {specify I/O behavior}{step-io} {complete the specification}{step-complete} {choose a state representation}{step-repn} {calculate logic expressions}{step-logic} {implement with flip-flops and gates}{step-gates} } {-8pt} In Step {step-abs}, we translate our description in human language into a model with states and desired behavior. At this stage, we simply try to capture the intent of the description and are not particularly thorough nor exact. Step {step-io} begins to formalize the model, starting with its input and output behavior. If we eventually plan to develop an implementation of our FSM as a digital system (which is not the only choice, of course!), all input and output must consist of bits. Often, input and/or output specifications may need to match other digital systems to which we plan to connect our FSM. In fact, { most problems in developing large digital systems today arise because of incompatibilities when composing two or more separately designed pieces} (or { modules}) into an integrated system. Once we know the I/O behavior for our FSM, in Step {step-complete} we start to make any implicit assumptions clear and to make any other decisions necessary to the design. Occasionally, we may choose to leave something undecided in the hope of simplifying the design with ``don't care'' entries in the logic formulation. In Step {step-repn}, we select an internal representation for the bits necessary to encode the state of our FSM. In practice, for small designs, this representation can be selected by a computer in such a way as to optimize the implementation. However, for large designs, such as the LC-3 instruction set architecture that we study later in this class, humans do most of the work by hand. In the later examples in this set of notes, we show how even a small design can leverage meaningful information from the design when selecting the representation, leading to an implementation that is simpler and is easier to build correctly. We also show how one can use abstraction to simplify an implementation. By Step {step-logic}, our design is a complete specification in terms of bits, and we need merely derive logic expressions for the next-state variables and the output signals.",
"GPT-3-Semantic-Search-Generations": {
"question": "What is the design process for a digital FSM?\\n",
"answer": "\nThe design process for a digital FSM includes six steps: developing an abstract model, specifying I/O behavior, completing the specification, choosing a state representation, calculating logic expressions, and implementing with flip-flops and gates."
}
},
{
"textbook-paragraph": "level state, to simplify the implementation.} {Use counters to insert time-based transitions between states (such as timeouts).} {Implement an FSM using logic components such as registers, counters, comparators, and adders as building blocks.} {Explain the basic organization of a computer's microarchitecture as well as the role played by elements of a von Neumann design in the processing of instructions.} {Identify the stages of processing an instruction (such as fetch, decode, getting operands, execution, and writing back results) in a processor control unit state machine diagram.} And, at the highest level, we expect that you will be able to do the following: {}{{}{} {}{}{} {Explain the difference between the Moore and Mealy machine models, as well as why you might find each of them useful when designing an FSM.} {Understand the need for initialization of an FSM, be able to analyze and identify potential problems arising from lack of initialization, and be able to extend an implementation to include initialization to an appropriate state when necessary.} {Understand how the choice of internal state bits for an FSM can affect the complexity of the implementation of next-state and output logic, and be able to select a reasonable state assignment.} {Identify and fix design flaws in simple FSMs by analyzing an existing implementation, comparing it with the specification, and removing any differences by making any necessary changes to the implementation.} { } empty 3rd page {Instruction Set Architecture*} This set of notes discusses tradeoffs and design elements of instruction set architectures (ISAs). { The material is beyond the scope of our class, and is provided purely for your interest.} Those who find these topics interesting may also want to read the ECE391 notes, which describe similar material with a focus on the x86 ISA. As you know, the ISA defines the interface between software and hardware, abstracting the capabilities of a computer's datapath and standardizing the format of instructions to utilize those capabilities. Successful ISAs are rarely discarded, as success implies the existence of large amounts of software built to use the ISA. Rather, they are extended, and their original forms must be supported for decades (consider, for example, the IBM 360 and the Intel x86). Employing sound design principles is thus imperative in an ISA. {Formats and Fields*} The LC-3 ISA employs fixed-length instructions and a load-store architecture, two aspects that help to reduce the design space to a manageable set of choices. In a general ISA design, many other options exist for instruction formats. Recall the idea of separating the bits of an instruction into (possibly non-contiguous) fields. One of the fields must contain an opcode, which specifies the type of operation to be performed by the instruction. In the {LC-3} ISA, most opcodes specify both the type of operation and the types of arguments to the operation. More generally, many addressing modes are possible for each operand, and we can think of the bits that specify the addressing mode as a separate field, known as the { mode} field. As a simple example, the {LC-3's} ADD and AND instructions contain a {1-bit} mode field that specifies whether the second operand of the ADD/AND comes from a register or is an immediate value. Several questions must be answered in order to define the possible instruction formats for an ISA. First, are instructions fixed-length or variable-length? Second, how many addresses are needed for each instruction, and how many of the addresses can be memory addresses? Finally, what forms of addresses are possible for each operand? For example, can one use full memory addresses or only limited offsets relative to a register? The answer to the first question depends on many factors, but several clear advantages exist for both answers. { Fixed-length instructions} are easy to fetch and decode. A",
"GPT-3-Semantic-Search-Generations": {
"question": "What is the need for FSM initialization?\\n",
"answer": "\nAn FSM must be initialized to ensure that it starts in a known state and to avoid undefined behavior. Without initialization, an FSM may produce incorrect results or may not work at all."
}
},
{
"textbook-paragraph": "K-maps, we must start again with new K-maps for the lower-case checker. If instead we have taken the approach of designing logic for the upper and lower bits of the ASCII character, we can reuse most of that logic, since the functions T_4 and T_5 are identical when checking for a lower-case character. Recalling the algebraic form of U(C), we can then write a function L(C) (a lower-case checker) as shown on the left below. {eqnarray*} U&=&C_6 {C_5} {C_4} T_4+C_6 {C_5} C_4 T_5 L&=&C_6 C_5 {C_4} T_4+C_6 C_5 C_4 T_5 &=&C_6 C_5 {C_4} (C_3+C_2+C_1+C_0)+ &&C_6 C_5 C_4 ({C_3}+{C_2} {C_1}+{C_2} {C_0}) {eqnarray*} {file=part2/figs/ascii-cmp-lower.eps,width=3.6in} Finally, if we have used a design based on comparators or adders, the design of a lower-case checker becomes trivial: simply change the numbers that we input to these components, as shown in the figure on the right above for the comparator-based design. The only changes from the upper-case checker design are the inputs to the comparators and the output produced, highlighted with blue text in the figure. {The Multiplexer} Using the more abstract designs for checking ranges of ASCII characters, we can go a step further and create a checker for both upper- and lower-case letters. To do so, we add another input S that allows us to select the function that we want---either the upper-case checker U(C) or the lower-case checker L(C). For this purpose, we make use of a logic block called a { multiplexer}, or { mux}. Multiplexers are an important abstraction for digital logic. In general, a multiplexer allows us to use one digital signal to select which of several others is forwarded to an output. The simplest form of the multiplexer is the 2-to-1 multiplexer shown to the right. The logic diagram illustrates how the mux works. The block has two inputs from the left and one from the top. The top input allows us to choose which of the left inputs is forwarded to the output. When the input S=0, the upper AND gate outputs 0, and the lower AND gate outputs the value of D_0. The OR gate then produces Q=0+D_0=D_0. Similarly, when input S=1, the upper AND gate outputs D_1, and the lower AND gate outputs 0. In this case, the OR gate produces Q=D_1+0=D_1. The symbolic form of the mux is a trapezoid with data inputs on the larger side, an output on the smaller side, and a select input on the angled part of the trapezoid. The labels inside the trapezoid indicate the value of the select input S for which the adjacent data signal, D_1 or D_0, is copied to the output Q. We can generalize multiplexers in two ways. First, we can extend the single select input to a group of select inputs. An {N-bit} select input allows selection from amongst 2^N inputs. A {4-to-1} multiplexer is shown below, for example. The logic diagram on the left shows how the {4-to-1 mux} operates. For any combination of S_1S_0, three of the AND gates produce 0, and the fourth outputs the D input corresponding to the interpretation of S as an unsigned number. Given three zeroes and one D input, the OR gate thus reproduces one of the D's. When S_1S_0=10, for example, the third AND gate copies D_2, and Q=D_2. {{file=part2/figs/mux4-to-1.eps,width=5.60in}} As shown in the middle figure, a {4-to-1} mux can also be built from three {2-to-1} muxes. Finally, the symbolic form of a {4-to-1} mux appears on the right in the figure. The second way in which we can generalize multiplexers is by using several multiplexers of the same type and using the same signals for selection. For example, we might use a single select bit T to choose between any number of paired inputs. Denote input pair by i D_1^i and D_0^i. For each pair, we have an output Q_i. When T=0, Q_i=D_0^i for each value of i. And, when T=1, Q_i=D_1^i for each value of i. Each value of i requires a {2-to-1} mux with its select input driven by the global select signal T. Returning to the example of the upper-",
"GPT-3-Semantic-Search-Generations": {
"question": "What is a multiplexer?\\n",
"answer": "\nA multiplexer is a digital logic block that allows one digital signal to select which of several others is forwarded to an output. The simplest form of the multiplexer is the 2-to-1 multiplexer, which has two inputs from the left and one from the top. The top input allows us to choose which of the left inputs is forwarded to the output."
}
},
{
"textbook-paragraph": "{Finite State Machine Design Examples, Part I} This set of notes uses a series of examples to illustrate design principles for the implementation of finite state machines (FSMs) using digital logic. We begin with an overview of the design process for a digital FSM, from the development of an abstract model through the implementation of functions for the next-state variables and output signals. Our first few examples cover only the concrete aspects: we implement several counters, which illustrate the basic process of translating a concrete and complete state transition diagram into an implementation based on flip-flops and logic gates. We next consider a counter with a number of states that is not a power of two, with which we illustrate the need for FSM initialization. As part of solving the initialization problem, we also introduce a general form of selection logic called a multiplexer. We then consider the design process as a whole through a more general example of a counter with multiple inputs to control its behavior. We work from an abstract model down to an implementation, illustrating how semantic knowledge from the abstract model can be used to simplify the implementation. Finally, we illustrate how the choice of representation for the FSM's internal state affects the complexity of the implementation. Fortunately, designs that are more intuitive and easier for humans to understand also typically make the best designs in terms of other metrics, such as logic complexity. {Steps in the Design Process} Before we begin exploring designs, let's talk briefly about the general approach that we take when designing an FSM. We follow a six-step process:{-8pt} {{}{} {}{}{} {develop an abstract model}{step-abs} {specify I/O behavior}{step-io} {complete the specification}{step-complete} {choose a state representation}{step-repn} {calculate logic expressions}{step-logic} {implement with flip-flops and gates}{step-gates} } {-8pt} In Step {step-abs}, we translate our description in human language into a model with states and desired behavior. At this stage, we simply try to capture the intent of the description and are not particularly thorough nor exact. Step {step-io} begins to formalize the model, starting with its input and output behavior. If we eventually plan to develop an implementation of our FSM as a digital system (which is not the only choice, of course!), all input and output must consist of bits. Often, input and/or output specifications may need to match other digital systems to which we plan to connect our FSM. In fact, { most problems in developing large digital systems today arise because of incompatibilities when composing two or more separately designed pieces} (or { modules}) into an integrated system. Once we know the I/O behavior for our FSM, in Step {step-complete} we start to make any implicit assumptions clear and to make any other decisions necessary to the design. Occasionally, we may choose to leave something undecided in the hope of simplifying the design with ``don't care'' entries in the logic formulation. In Step {step-repn}, we select an internal representation for the bits necessary to encode the state of our FSM. In practice, for small designs, this representation can be selected by a computer in such a way as to optimize the implementation. However, for large designs, such as the LC-3 instruction set architecture that we study later in this class, humans do most of the work by hand. In the later examples in this set of notes, we show how even a small design can leverage meaningful information from the design when selecting the representation, leading to an implementation that is simpler and is easier to build correctly. We also show how one can use abstraction to simplify an implementation. By Step {step-logic}, our design is a complete specification in terms of bits, and we need merely derive logic expressions for the next-state variables and the output signals.",
"GPT-3-Semantic-Search-Generations": {
"question": "What is the design process for a digital FSM?\\n",
"answer": "\nThe design process for a digital FSM typically consists of six steps: (1) developing an abstract model, (2) specifying I/O behavior, (3) completing the specification, (4) choosing a state representation, (5) calculating logic expressions, and (6) implementing with flip-flops and gates."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": "What is a multiplexer?', \"\\n",
"answer": "\nA multiplexer is a device that allows multiple signals to be routed onto a single channel. This is done by selecting one of several input signals and connecting it to the output. Multiplexers are used in a variety of applications, such as telecommunications and computer networking."
}
},
{
"textbook-paragraph": "Notes Set 2.4, for example, we showed a design for a logic slice that compares two bits at a time. In general, we can optimize logic for any number of bits and then apply multiple copies of the resulting logic in space (a generalization of the bit-sliced approach), or in time (a generalization of the serialization approach), or in a combination of the two. Sometimes these tradeoffs may happen at a higher level. As mentioned in Notes Set 2.3, computer software uses the carry out of an adder to perform addition of larger groups of bits (over multiple clock cycles) than is supported by the processor's adder hardware. In computer system design, engineers often design hardware elements that are general enough to support this kind of extension in software. As a concrete example of the possible tradeoffs, consider a serial comparator design based on the {2-bit} slice variant. This approach leads to a serial design with 24 gates and 10 inverters, which is not much larger than our earlier serial design. In terms of gate delays, however, the new design is identical, meaning that we finish a comparison in half the time. More realistic area and timing metrics show slightly more difference between the two designs. These differences can dominate the results if we blindly scale the idea to handle more bits without thinking carefully about the design. Neither many-input gates nor gates driving many outputs work well in practice. {Finite State Machines} A { finite state machine} (or { FSM}) is a model for understanding the behavior of a system by describing the system as occupying one of a finite set of states, moving between these states in response to external inputs, and producing external outputs. In any given state, a particular input may cause the FSM to move to another state; this combination is called a { transition rule}. An FSM comprises five parts: a finite set of states, a set of possible inputs, a set of possible outputs, a set of transition rules, and methods for calculating outputs. When an FSM is implemented as a digital system, all states must be represented as patterns using a fixed number of bits, all inputs must be translated into bits, and all outputs must be translated into bits. For a digital FSM, transition rules must be { complete}; in other words, given any state of the FSM, and any pattern of input bits, a transition must be defined from that state to another state (transitions from a state to itself, called { self-loops}, are acceptable). And, of course, calculation of outputs for a digital FSM reduces to Boolean logic expressions. In this class, we focus on clocked synchronous FSM implementations, in which the FSM's internal state bits are stored in flip-flops. In this section, we introduce the tools used to describe, develop, and analyze implementations of FSMs with digital logic. In the next few weeks, we will show you how an FSM can serve as the central control logic in a computer. At the same time, we will illustrate connections between FSMs and software and will make some connections with other areas of interest in ECE, such as the design and analysis of digital control systems. The table below gives a { list of abstract states} for a typical keyless entry system for a car. In this case, we have merely named the states rather than specifying the bit patterns to be used for each state---for this reason, we refer to them as abstract states. The description of the states in the first column is an optional element often included in the early design stages for an FSM, when identifying the states needed for the design. A list may also include the outputs for each state. Again, in the list below, we have specified these outputs abstractly. By including outputs for each state, we implicitly assume that outputs depend only on the state of the FSM. We discuss this assumption in more detail later in these notes (see ``Machine Models''), but will make the assumption throughout",
"GPT-3-Semantic-Search-Generations": {
"question": " How are next-state variables and output signals implemented in a FSM?\\n",
"answer": "\nA FSM is implemented as a digital system, with all states represented as patterns using a fixed number of bits, all inputs translated into bits, and all outputs translated into bits. Transition rules must be complete, meaning that given any state of the FSM and any pattern of input bits, a transition must be defined from that state to another state. Outputs for a digital FSM are calculated using Boolean logic expressions."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " How does one use abstraction to simplify an implementation?\\n",
"answer": "\nAbstraction is the process of simplifying a complex system by identifying the most important aspects of that system and ignoring the rest. In the context of implementation, abstraction can be used to simplify a design by identifying the most important features of the design and ignoring the rest. This can make the design more manageable and easier to understand."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " Why is it important to make implicit assumptions clear in the design process?\\n",
"answer": "\nThere are a few reasons why it is important to make implicit assumptions clear in the design process. First, if assumptions are not made clear, it can lead to confusion and misunderstanding among the team members working on the design. Second, making assumptions explicit can help to ensure that everyone is on the same page and working towards the same goal. Finally, explicit assumptions can help to prevent errors and mistakes in the design process."
}
},
{
"textbook-paragraph": "Notes Set 2.4, for example, we showed a design for a logic slice that compares two bits at a time. In general, we can optimize logic for any number of bits and then apply multiple copies of the resulting logic in space (a generalization of the bit-sliced approach), or in time (a generalization of the serialization approach), or in a combination of the two. Sometimes these tradeoffs may happen at a higher level. As mentioned in Notes Set 2.3, computer software uses the carry out of an adder to perform addition of larger groups of bits (over multiple clock cycles) than is supported by the processor's adder hardware. In computer system design, engineers often design hardware elements that are general enough to support this kind of extension in software. As a concrete example of the possible tradeoffs, consider a serial comparator design based on the {2-bit} slice variant. This approach leads to a serial design with 24 gates and 10 inverters, which is not much larger than our earlier serial design. In terms of gate delays, however, the new design is identical, meaning that we finish a comparison in half the time. More realistic area and timing metrics show slightly more difference between the two designs. These differences can dominate the results if we blindly scale the idea to handle more bits without thinking carefully about the design. Neither many-input gates nor gates driving many outputs work well in practice. {Finite State Machines} A { finite state machine} (or { FSM}) is a model for understanding the behavior of a system by describing the system as occupying one of a finite set of states, moving between these states in response to external inputs, and producing external outputs. In any given state, a particular input may cause the FSM to move to another state; this combination is called a { transition rule}. An FSM comprises five parts: a finite set of states, a set of possible inputs, a set of possible outputs, a set of transition rules, and methods for calculating outputs. When an FSM is implemented as a digital system, all states must be represented as patterns using a fixed number of bits, all inputs must be translated into bits, and all outputs must be translated into bits. For a digital FSM, transition rules must be { complete}; in other words, given any state of the FSM, and any pattern of input bits, a transition must be defined from that state to another state (transitions from a state to itself, called { self-loops}, are acceptable). And, of course, calculation of outputs for a digital FSM reduces to Boolean logic expressions. In this class, we focus on clocked synchronous FSM implementations, in which the FSM's internal state bits are stored in flip-flops. In this section, we introduce the tools used to describe, develop, and analyze implementations of FSMs with digital logic. In the next few weeks, we will show you how an FSM can serve as the central control logic in a computer. At the same time, we will illustrate connections between FSMs and software and will make some connections with other areas of interest in ECE, such as the design and analysis of digital control systems. The table below gives a { list of abstract states} for a typical keyless entry system for a car. In this case, we have merely named the states rather than specifying the bit patterns to be used for each state---for this reason, we refer to them as abstract states. The description of the states in the first column is an optional element often included in the early design stages for an FSM, when identifying the states needed for the design. A list may also include the outputs for each state. Again, in the list below, we have specified these outputs abstractly. By including outputs for each state, we implicitly assume that outputs depend only on the state of the FSM. We discuss this assumption in more detail later in these notes (see ``Machine Models''), but will make the assumption throughout",
"GPT-3-Semantic-Search-Generations": {
"question": " How does the choice of an FSM's input and output behavior affect the design process?\\n",
"answer": "\nThe choice of an FSM's input and output behavior affects the design process by determining the set of possible states and the set of possible outputs. The set of possible states is determined by the set of possible inputs, and the set of possible outputs is determined by the set of possible outputs."
}
},
{
"textbook-paragraph": "1&0 {eqnarray*} C&=&A_1 B_1+A_1 A_0 B_0+A_0 B_1 B_0 S_1&=& A_1 {B_1} {B_0}+ A_1 {A_0} {B_1}+ {A_1} {A_0} B_1+ {A_1} B_1 {B_0}+ &&{A_1} A_0 {B_1} B_0+ A_1 A_0 B_1 B_0 S_0&=&A_0 {B_0}+{A_0} B_0 {eqnarray*} In theory, {K-maps} extend to an arbitrary number of variables. Certainly Gray codes can be extended. An { {N-bit} Gray code} is a sequence of {N-bit} patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an {(N+1)-bit} Gray code, write the sequence for an {N-bit} Gray code, then add a 0 in front of all patterns. After this sequence, append a second copy of the {N-bit} Gray code in reverse order, then put a 1 in front of all patterns in the second copy. The result is an {(N+1)-bit} Gray code. For example, the following are Gray codes: 1-bit& 0, 1 2-bit& 00, 01, 11, 10 3-bit& 000, 001, 011, 010, 110, 111, 101, 100 4-bit& 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000 Unfortunately, some of the beneficial properties of {K-maps} do not extend beyond two variables in a dimension. { Once you have three variables in one dimension}, as is necessary if a function operates on five or more variables, { not all product terms are contiguous in the grid}. The terms still require a total number of rows and columns equal to a power of two, but they don't all need to be a contiguous group. Furthermore, { some contiguous groups of appropriate size do not correspond to product terms}. So you can still make use of {K-maps} if you have more variables, but their use is a little trickier. {Canonical Forms} What if we want to compare two expressions to determine whether they represent the same logic function? Such a comparison is a test of { logical equivalence}, and is an important part of hardware design. Tools today provide help with this problem, but you should understand the problem. You know that any given function can be expressed in many ways, and that two expressions that look quite different may in fact represent the same function (look back at Equations () to () for an example). But what if we rewrite the function using only prime implicants? Is the result unique? Unfortunately, no. In general, { a sum of products is not unique (nor is a product of sums), even if the sum contains only prime implicants}. For example, consensus terms may or may not be included in our expressions. (They are necessary for reliable design of certain types of systems, as you will learn in a later ECE class.) The green ellipse in the K-map to the right represents the consensus term BC. {eqnarray*} Z &=& A C + B + B C Z &=& A C + B {eqnarray*} Some functions allow several equivalent formulations as sums of prime implicants, even without consensus terms. The K-maps shown to the right, for example, illustrate how one function might be written in either of the following ways: {eqnarray*} Z &=& D + C + A B C + B D Z &=& C + B C + A B D + D {eqnarray*} When we need to compare two things (such as functions), we need to transform them into what in mathematics is known as a { canonical form}, which simply means a form that is defined so as to be unique for each thing of the given type. What can we use for logic functions? You already know two answers! The { canonical sum} of a function (sometimes called the { canonical SOP form}) is the sum of minterms. The { canonical product} of a function (sometimes called the { canonical POS form}) is the product of maxterms. These forms technically only meet the mathematical definition of canonical if we agree on an order for the min/maxterms, but that problem is solvable. However, as you already know, the forms are not particularly convenient to use. In practice, people and tools in the industry use more",
"GPT-3-Semantic-Search-Generations": {
"question": " What is a Gray code?\\n",
"answer": "\nA Gray code is a sequence of N-bit patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an (N+1)-bit Gray code, write the sequence for an N-bit Gray code, then add a 0 in front of all patterns. After this sequence, append a second copy of the N-bit Gray code in reverse order, then put a 1 in front of all patterns in the second copy."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of a Gray code counter?\\n",
"answer": "\nA Gray code counter is a device that is used to count the number of operations in a logic expression. The device works by counting the number of variables in the expression and adding the number of operations. The device is used to optimize logic expressions by reducing the number of operations needed to implement the logic function."
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the transition diagram for a two-bit Gray code counter?\\n",
"answer": "\nThe transition diagram for a two-bit Gray code counter is a loop with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter."
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you develop the implementation for a Gray code counter?', '",
"answer": "\nThe implementation for a Gray code counter is developed by first filling in the K-maps for the next-state values, then deriving algebraic expressions. The next-state logic is then used to develop the implementation."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of a Gray code counter?\\n",
"answer": "\nA Gray code counter is a type of digital counter that is used to count the number of clock pulses. It is named after Frank Gray, who invented the code in 1953. The main advantage of a Gray code counter over other types of counters is that it is less likely to produce errors when counting."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " What are some applications of a Gray code counter?\\n",
"answer": "\nA Gray code counter is used in applications where a digital value must be changed incrementally with the least number of steps. This is because a Gray code counter only changes one bit at a time, which minimizes the number of digital values that must be changed."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What are the inputs and outputs of a Gray code counter?\\n",
"answer": "\nA Gray code counter is a type of digital counter that uses a Gray code to generate its output. The input to a Gray code counter is a digital signal that represents the number of clock pulses that have been applied to the counter. The output of a Gray code counter is a digital signal that represents the number of clock pulses that have been applied to the counter, plus one."
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you design a Gray code counter?']",
"answer": "\nA Gray code counter is designed by first creating a transition diagram that shows the states and outputs of the counter. Next, the next-state logic is developed by creating K-maps for the next-state values and deriving algebraic expressions. Finally, the next-state logic is implemented in a diagram."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " What are some applications of a Gray code counter?\\n",
"answer": "\nA Gray code counter is used in applications where a digital value must be changed incrementally with the least number of steps. This is because a Gray code counter only changes one bit at a time, which minimizes the number of digital values that must be changed."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What are the inputs and outputs of a Gray code counter?\\n",
"answer": "\nA Gray code counter is a type of digital counter that uses a Gray code to generate its output. The input to a Gray code counter is a digital signal that represents the number of clock pulses that have been applied to the counter. The output of a Gray code counter is a digital signal that represents the number of clock pulses that have been applied to the counter, plus one."
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you design a Gray code counter?']",
"answer": "\nA Gray code counter is designed by first creating a transition diagram that shows the states and outputs of the counter. Next, the next-state logic is developed by creating K-maps for the next-state values and deriving algebraic expressions. Finally, the next-state logic is implemented in a diagram."
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you design a Gray code counter?']",
"answer": "\nA Gray code counter is designed by first creating a transition diagram that shows the states and outputs of the counter. Next, the next-state logic is developed by creating K-maps for the next-state values and deriving algebraic expressions. Finally, the next-state logic is implemented in a diagram."
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the fully-specified transition diagram for a three-bit Gray code counter?\\n",
"answer": "\nThe fully-specified transition diagram for a three-bit Gray code counter is as follows:\n\nThe states of the counter form a loop, with the counter moving from one state to the next each cycle.\n\nEach state in the diagram is marked with the internal state value S_2S_1S_0 (before \" / \") and the output Z_2Z_1Z_0 (after \" / \").\n\nBased on the transition diagram, the next-state values S_2^+, S_1^+, and S_0^+ can be filled in as shown."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the equation for the next-state logic of a three-bit Gray code counter?\\n",
"answer": "\nThe next-state logic for a three-bit Gray code counter is as follows:\n\nS_2^+ = S_2 + S_0\nS_1^+ = S_2\nS_0^+ = S_2 S_1"
}
},
{
"textbook-paragraph": "This process is no different than for combinational logic, and should already be fairly familiar to you. Finally, in Step {step-gates}, we translate our logic expressions into gates and use flip-flops (or registers) to hold the internal state bits of the FSM. In later notes, we use more complex building blocks when implementing an FSM, building up abstractions in order to simplify the design process in much the same way that we have shown for combinational logic. {Example: A Two-Bit Gray Code Counter} Let's begin with a two-bit Gray code counter with no inputs. As we mentioned in Notes Set 2.1, a Gray code is a cycle over all bit patterns of a certain length in which consecutive patterns differ in exactly one bit. For simplicity, our first few examples are based on counters and use the internal state of the FSM as the output values. You should already know how to design combinational logic for the outputs if it were necessary. The inputs to a counter, if any, are typically limited to functions such as starting and stopping the counter, controlling the counting direction, and resetting the counter to a particular state. A fully-specified transition diagram for a two-bit Gray code counter appears below. With no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_1S_0 (before the ``/'') and the output Z_1Z_0 (after the ``/''), which are always equal for this counter. Based on the transition diagram, we can fill in the K-maps for the next-state values S_1^+ and S_0^+ as shown to the right of the transition diagram, then derive algebraic expressions in the usual way to obtain S_1^+=S_0 and S_0^+={{S_1}}. We then use the next-state logic to develop the implementation shown on the far right, completing our first counter design. {Example: A Three-Bit Gray Code Counter} Now we'll add a third bit to our counter, but again use a Gray code as the basis for the state sequence. A fully-specified transition diagram for such a counter appears to the right. As before, with no inputs, the states simply form a loop, with the counter moving from one state to the next each cycle. Each state in the diagram is marked with the internal state value S_2S_1S_0 (before ``/'') and the output Z_2Z_1Z_0 (after ``/''). Based on the transition diagram, we can fill in the K-maps for the next-state values S_2^+, S_1^+, and S_0^+ as shown to the right, then derive algebraic expressions. The results are more complex this time. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_0 + S_1 {{S_0}} S_1^+ &=& {{S_2}} S_0 + S_1 {{S_0}} S_0^+ &=& {{S_2}} {{S_1}} + S_2 S_1 {eqnarray*} Notice that the equations for S_2^+ and S_1^+ share a common term, S_1{{S_0}}. This design does not allow much choice in developing good equations for the next-state logic, but some designs may enable you to reduce the design complexity by explicitly identifying and making use of common algebraic terms and sub-expressions for different outputs. In modern design processes, identifying such opportunities is generally performed by a computer program, but it's important to understand how they arise. Note that the common term becomes a single AND gate in the implementation of our counter, as shown to the right. Looking at the counter's implementation diagram, notice that the vertical lines carrying the current state values and their inverses back to the next state logic inputs have been carefully ordered to simplify understanding the diagram. In particular, they are ordered from left to right (on the left side of the figure) as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2. When designing any logic diagram, be sure to make use of a reasonable order so as to make it easy for someone (including yourself!) to read and check the correctness of the logic. {Example: A Color Sequencer} Early graphics systems",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the implementation diagram for a three-bit Gray code counter?\\n",
"answer": "\nThe implementation diagram for a three-bit Gray code counter is a logic diagram that shows the inputs, outputs, and next-state logic for the counter. The diagram is ordered from left to right as {{S_0}}S_0{{S_1}}S_1{{S_2}}S_2, which makes it easy to read and check for correctness."
}
},
{
"textbook-paragraph": "used a three-bit red-green-blue (RGB) encoding for colors. The color mapping for such a system is shown to the right. Imagine that you are charged with creating a counter to drive a light through a sequence of colors. The light takes an RGB input as just described, and the desired pattern is {off (black) yellow violet green blue} You immediately recognize that you merely need a counter with five states. How many flip-flops will we need? At least three, since _2 (5)=3. Given that we need three flip-flops, and that the colors we need to produce as {c|l} RGB& color 000& black 001& blue 010& green 011& cyan 100& red 101& violet 110& yellow 111& white outputs are all unique bit patterns, we can again choose to use the counter's internal state directly as our output values. A fully-specified transition diagram for our color sequencer appears to the right. The states again form a loop, and are marked with the internal state value S_2S_1S_0 and the output RGB. As before, we can use the transition diagram to fill in K-maps for the next-state values S_2^+, S_1^+, and S_0^+, as shown to the right. For each of the three states not included in our transition diagram, we have inserted x's into the K-maps to indicate ``don't care.'' As you know, we can treat each x as either a 0 or a 1, whichever produces better results (where ``better'' usually means simpler equations). The terms that we have chosen for our algebraic equations are illustrated in the K-maps. The x's within the ellipses become 1s in the implementation, and the x's outside of the ellipses become 0s. For our next-state logic, we obtain: {eqnarray*} S_2^+ &=& S_2 S_1 + {{S_1}} {{S_0}} S_1^+ &=& S_2 S_0 + {{S_1}} {{S_0}} S_0^+ &=& S_1 {eqnarray*} Again our equations for S_2^+ and S_1^+ share a common term, which becomes a single AND gate in the implementation shown to the right. {Identifying an Initial State} Let's say that you go the lab and build the implementation above, hook it up to the light, and turn it on. Does it work? Sometimes. Sometimes it works perfectly, but sometimes the light glows cyan or red briefly first. At other times, the light is an unchanging white. What could be going wrong? Let's try to understand. We begin by deriving K-maps for the implementation, as shown to the right. In these K-maps, each of the x's in our design has been replaced by either a 0 or a 1. These entries are highlighted with green italics. {file=part3/figs/colS2-bad.eps,width=1.00in} {file=part3/figs/colS1-bad.eps,width=1.00in} {file=part3/figs/colS0-bad.eps,width=1.00in} Now let's imagine what might happen if somehow our FSM got into the S_2S_1S_0=111 state. In such a state, the light would appear white, since RGB=S_2S_1S_0=111. What happens in the next cycle? Plugging into the equations or looking into the K-maps gives (of course) the same answer: the next state is the S_2^+S_1^+S_0^+=111 state. In other words, the light stays white indefinitely! As an exercise, you should check what happens if the light is red or cyan. We can extend the transition diagram that we developed for our design with the extra states possible in the implementation, as shown below. As with the five states in the design, the extra states are named with the color of light that they produce. {{file=part3/figs/colors-full.eps,width=5.8in}} Notice that the FSM does not move out of the WHITE state (ever). You may at this point wonder whether more careful decisions in selecting our next-state expressions might address this issue. To some extent, yes. For example, if we replace the S_2S_1 term in the equation for S_2^+ with S_2{{S_0}}, a decision allowed by the ``don't care'' boxes in the K-map for our design, the resulting transition diagram does not suffer from the problem that we've found. However, even if we do change our implementation slightly, we need to address another aspect of the problem: how can the FSM",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the color mapping for a three-bit RGB encoding system?\\n\\n",
"answer": "\nThe color mapping for a three-bit RGB encoding system is a system where colors are represented by a combination of red, green, and blue light. The color mapping for such a system is shown to the right. Imagine that you are charged with creating a counter to drive a light through a sequence of colors."
}
},
{
"textbook-paragraph": "have other names for the smaller values: a point for N=0, a line segment for N=1, a square for N=2, and a cube for N=3. The diagrams above and to the right illustrate the cases that are easily drawn on paper. The black dots represent specific input combinations, and the blue edges connect input combinations that differ in exactly one input value (one bit). By viewing a function's domain in this way, we can make a connection between a product of literals and the structure of the domain. Let's use the {3-dimensional} version as an example. We call the variables A, B, and C, and note that the cube has 2^3=8 corners corresponding to the 2^3 possible combinations of A, B, and C. The simplest product of literals in this case is 1, which is the product of 0 literals. Obviously, the product 1 evaluates to 1 for any variable values. We can thus think of it as covering the entire domain of the function. In the case of our example, the product 1 covers the whole cube. In order for the product 1 to be an implicant of a function, the function itself must be the function 1. What about a product consisting of a single literal, such as A or ? The dividing lines in the diagram illustrate the answer: any such product term evaluates to 1 on a face of the cube, which includes 2^2=4 of the corners. If a function evaluates to 1 on any of the six faces of the cube, the corresponding product term (consisting of a single literal) is an implicant of the function. Continuing with products of two literals, we see that any product of two literals, such as A or C, corresponds to an edge of our {3-dimensional} cube. The edge includes 2^1=2 corners. And, if a function evaluates to 1 on any of the 12 edges of the cube, the corresponding product term (consisting of two literals) is an implicant of the function. Finally, any product of three literals, such as B, corresponds to a corner of the cube. But for a function on three variables, these are just the minterms. As you know, if a function evaluates to 1 on any of the 8 corners of the cube, that minterm is an implicant of the function (we used this idea to construct the function to prove logical completeness). How do these connections help us to simplify functions? If we're careful, we can map cubes onto paper in such a way that product terms (the possible implicants of the function) usually form contiguous groups of 1s, allowing us to spot them easily. Let's work upwards starting from one variable to see how this idea works. The end result is called a Karnaugh map. The first drawing shown to the right replicates our view of the {1-dimensional} hypercube, corresponding to the domain of a function on one variable, in this case the variable A. To the right of the hypercube (line segment) are two variants of a Karnaugh map on one variable. The middle variant clearly indicates the column corresponding to the product A (the other column corresponds to ). The right variant simply labels the column with values for A. The three drawings shown to the right illustrate the three possible product terms on one variable. { The functions shown in these Karnaugh maps are arbitrary, except that we have chosen them such that each implicant shown is a prime implicant for the illustrated function.} Let's now look at two-variable functions. We have replicated our drawing of the {2-dimensional} hypercube (square) to the right along with two variants of Karnaugh maps on two variables. With only two variables (A and B), the extension is fairly straightforward, since we can use the second dimension of the paper (vertical) to express the second variable (B). The number of possible products of literals grows rapidly with the number of variables. For two variables, nine are possible, as shown to the right. Notice that all implicants have two properties. First, they occupy contiguous regions of the grid. And, second, their height and width are always powers of two.",
"GPT-3-Semantic-Search-Generations": {
"question": " What is a K-map?\\n",
"answer": "\nA Karnaugh map is a graphical representation of a Boolean function that helps to simplify the function. The map consists of a grid of squares, each of which corresponds to a possible combination of input values. The map is used to find groups of product terms that are implicants of the function."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of an abstract model?\\n",
"answer": "\nAn abstract model is a simplified representation of a system, typically used to aid in understanding the system. In the context of logic optimization, an abstract model can be used to help understand the tradeoffs between different logic expressions."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the difference between a next-state table and a transition diagram?\\n",
"answer": "\nA next-state table lists all of the possible states that the FSM can be in, as well as the inputs and outputs for each state. A transition diagram shows the order in which the states will be visited, based on the inputs and outputs."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of an FSM?\\n",
"answer": "\nAn FSM is a finite state machine, which is a mathematical model of computation used to design both computer programs and digital logic circuits. It is an abstract machine that can be in one of a finite number of states."
}
},
{
"textbook-paragraph": "written ``hi-Z''). In other words, there is effectively no electrical connection between the tri-state buffer and the output OUT. This logical disconnection is achieved by using the outer {file=part3/figs/tri-state.eps,width=3in} {cc|c} EN& IN& OUT 0& x& Z 1& 0& 0 1& 1& 1 (upper and lower) pair of transistors in the logic diagram. When EN=0, both transistors turn off, meaning that regardless of the value of IN, OUT is connected neither to high voltage nor to ground. When EN=1, both transistors turn on, and the tri-state buffer acts as a pair of back-to-back inverters, copying the signal from IN to OUT, as shown in the truth table. What benefit does this logical disconnection provide? So long as only one memory's chip select input is high at any time, the same output line can be shared by more than one memory without the need for additional multiplexers. Memory chips were often combined in this way to produce larger memories. The figure to the right illustrates how larger memories can be constructed using multiple chips. In the case shown, two {2^-bit} memories are used to implement a {2^{k+1}-bit} memory. One of the address bits---in the case shown, the most significant bit---is used to drive a decoder that determines which of the two chips is active (CS=1). The decoder is enabled with the chip select signal for the larger memory, so neither chip is enabled when the external CS is low, as desired. The {file=part3/figs/mem-larger.eps,width=4.75in} rest of the address bits, as well as the external data inputs and write enable signal, are simply delivered to both memories. The external data outputs are also connected to both memories. Ensuring that at most one chip select signal is high at any time guarantees that at most one of the two memory chips drives logic values on the data outputs. Multiple chips can also be used to construct wider memories, as shown to the right. In the case shown, two {2^-bit} memories are used to implement a {2^-bit} memory. Both chips are either active or inactive at the same time, so the external address, write enable, and chip select inputs are routed to both chips. In contrast, the data inputs and outputs are separate: the left chip handles the high N bits of input on writes and produces the high N bits of output on reads, while the right chip handles the low N bits of input and produces the low N bits of output. {file=part3/figs/mem-wider.eps,width=4.05in} Historically, tri-state buffers were also used to reduce the number of pins needed on chips. Pins have long been a scarce resource, and the amount of data that can cross a chip's pins in a second (the product of the number of pins and the data rate per pin) has not grown nearly as rapidly as the number of transistors packed into a fixed area. By combining inputs and outputs, chip designers were able to halve the number of pins needed. For example, data inputs and outputs of memory were often combined into a single set of data wires, with bidirectional signals. When performing a read from a memory chip, the memory chip drove the data pins with the bits being read (tri-state buffers on the memory chip were enabled). When performing a write, other logic such as a processor wrote the value to be stored onto the data pins (tri-state buffers were not enabled). {Dynamic Random Access Memory*} Dynamic random access memory, or DRAM, is used for main memory in computers and for other applications in which size is more important than speed. While slower than SRAM, DRAM is denser (has more bits per chip area). A substantial part of DRAM density is due to transistor count: typical SRAM cells use six transistors (two for each inverter, and two more to connect the inverters to the bit lines), while DRAM cells use only a single transistor. However, memory designers have also made significant advances in further miniaturizing DRAM cells to improve density beyond the benefit available from simple transistor",
"GPT-3-Semantic-Search-Generations": {
"question": " What are the benefits of using an FSM?\\n",
"answer": "\nThere are several benefits of using an FSM. One benefit is that an FSM can be used to implement a wide range of logic functions. Another benefit is that an FSM can be used to construct larger memories from multiple smaller memories. Finally, an FSM can be used to reduce the number of pins needed on a chip."
}
},
{
"textbook-paragraph": "range corresponds to systems in which when a processor's power consumption in a digital system is extremely low relative to the power consumption of the system. For example, the processor in a computer might use less than 1 of the total used by the system including the disk drive, the monitor, the power supply, and so forth. One power consumption value in this range is just as good as any another, and no one cares about the power consumption of the processor in such cases. In the second range, power consumption of the processor makes a difference. Cell phones use most of their energy in radio operation, for example, but if you own a phone with a powerful processor, you may have noticed that you can turn off the phone and drain the battery fairly quickly by playing a game. Designing a processor that uses half as much power lengthens the battery life in such cases. Finally, the third region of power consumption measurements is impossible: if you use so much power, your chip will overheat or even burst into flames. Consumers get unhappy when such things happen. As a first step, you can remove any metrics for which all solutions are effectively equivalent. Until a little less than a decade ago, for example, the power consumption of a desktop processor actually was in the first range that we discussed. Power was simply not a concern to engineers: all designs of interest consumed so little power that no one cared. Unfortunately, at that point, power consumption jumped into the third range rather quickly. Processors hit a wall, and products had to be cancelled. Given that the time spent designing a processor has historically been about five years, a lot of engineering effort was wasted because people had not thought carefully enough about power (since it had never mattered in the past). Today, power is an important metric that engineers must take into account in their designs. However, in some areas, such as desktop and high-end server processors, other metrics (such as performance) may be so important that we always want to operate at the edge of the interesting range. In such cases, we might choose to treat a metric such as power consumption as a { threshold}: stay below 150 Watts for a desktop processor, for example. One still has to make a coordinated effort to ensure that the system as a whole does not exceed the threshold, but reasoning about threshold values, a form of constraint, is easier than trying to think about multiple metrics at once. Some metrics may only allow discrete quantification. For example, one could choose to define compatibility with previous processor generations as binary: either an existing piece of software (or operating system) runs out of the box on your new processor, or it does not. If you want people who own that software to make use of your new processor, you must ensure that the value of this binary metric is 1, which can also be viewed as a threshold. In some cases, two metrics may be strongly { correlated}, meaning that a design that is good for one of the metrics is frequently good for the other metric as well. Chip area and cost, for example, are technically distinct ways to measure a digital design, but we rarely consider them separately. A design that requires a larger chip is probably more complex, and thus takes more engineering time to get right (engineering time costs money). Each silicon wafer costs money to fabricate, and fewer copies of a large design fit on one wafer, so large chips mean more fabrication cost. Physical defects in silicon can cause some chips not to work. A large chip uses more silicon than a small one, and is thus more likely to suffer from defects (and not work). Cost thus goes up again for large chips relative to small ones. Finally, large chips usually require more careful testing to ensure that they work properly (even ignoring the cost of getting the design right, we have to test for the presence of defects), which",
"GPT-3-Semantic-Search-Generations": {
"question": " What are the disadvantages of using an FSM?\\n",
"answer": "\nThere are a few disadvantages of using an FSM. First, if the FSM is not designed carefully, it can be hard to understand and debug. Second, an FSM can use more resources than a simpler design, such as a state machine. Finally, an FSM can be more difficult to change or extend than a simpler design."
}
},
{
"textbook-paragraph": "statement initializes the minimum known value ({ min}) to the value stored at index 0 in the array ({ values[0]}). The second statement is a loop in which the variable { index} takes on values from 1 to 9. For each value, an { if} statement compares the current known minimum with the value stored in the array at index given by the { idx} variable. If the stored value is smaller, the current known value (again, { min}) is updated to reflect the program's having found a smaller value. When the loop finishes all nine iterations, the variable { min} holds the smallest value among the set of 10 integers stored in the { values} array. As a first step towards designing an FSM to implement the code, we transform the code into a flow chart, as shown to the right. The program again begins with initialization, which appears in the second column of the flow chart. The loop in the program translates to the third column of the flow chart, and the { if} statement to the middle comparison and update of { min}. Our goal is now to design an FSM to implement the flow chart. In order to do so, we want to leverage the same kind of abstraction that we used earlier, when extending our keyless entry system with a timer. Although the timer's value was technically also {{file=part3/figs/part3-min-flow-chart.eps,width=3.78in}} part of the FSM's state, we treated it as data and integrated it into our next-state decisions in only a couple of cases. For our minimum value problem, we have two sources of data. First, an external program supplies data in the form of a set of 10 integers. If we assume {32-bit} integers, these data technically form 320 input bits! Second, as with the keyless entry system timer, we have data used internally by our FSM, such as the loop index and the current minimum value. These are technically state bits. For both types of data, we treat them abstractly as values rather than thinking of them individually as bits, allowing us to develop our FSM at a high-level and then to implement it using the components that we have developed earlier in our course. {Choosing Components and Identifying States} Now we are ready to design an FSM that implements the flow chart. What components do we need, other than our state logic? We use registers and counters to implement the variables { idx} and { min} in the program. For the array { values}, we use a {1632-bit} memory.{We technically only need a {1032-bit} memory, but we round up the size of the address space to reflect more realistic memory designs; one can always optimize later.} We need a comparator to implement the test for the { if} statement. We choose to use a serial comparator, which allows us to illustrate again how one logical high-level state can be subdivided into many actual states. To operate the serial comparator, we make use of two shift registers that present the comparator with one bit per cycle on each input, and a counter to keep track of the comparator's progress. How do we identify high-level states from our flow chart? Although the flow chart attempts to break down the program into `simple' steps, one step of a flow chart may sometimes require more than one state in an FSM. Similarly, one FSM state may be able to implement several steps in a flow chart, if those steps can be performed simultaneously. Our design illustrates both possibilities. How we map flow chart elements into FSM states also depends to some degree on what components we use, which is why we began with some discussion of components. In practice, one can go back and forth between the two, adjusting components to better match the high-level states, and adjusting states to better match the desired components. Finally, note that we are only concerned with high-level states, so we do not need to provide details (yet) down to the level of individual clock cycles, but we do want to define high-level states that can be implemented in a fixed number of cycles, or at",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you design an FSM?\\n",
"answer": "\nOne way to design an FSM is to start with a flow chart of the program to be implemented. This flow chart can be used to identify high-level states that can be implemented in a fixed number of clock cycles. Another way to design an FSM is to start with a list of components that are needed to implement the program. This list of components can be used to identify high-level states that can be implemented in a fixed number of clock cycles."
}
},
{
"textbook-paragraph": "statement initializes the minimum known value ({ min}) to the value stored at index 0 in the array ({ values[0]}). The second statement is a loop in which the variable { index} takes on values from 1 to 9. For each value, an { if} statement compares the current known minimum with the value stored in the array at index given by the { idx} variable. If the stored value is smaller, the current known value (again, { min}) is updated to reflect the program's having found a smaller value. When the loop finishes all nine iterations, the variable { min} holds the smallest value among the set of 10 integers stored in the { values} array. As a first step towards designing an FSM to implement the code, we transform the code into a flow chart, as shown to the right. The program again begins with initialization, which appears in the second column of the flow chart. The loop in the program translates to the third column of the flow chart, and the { if} statement to the middle comparison and update of { min}. Our goal is now to design an FSM to implement the flow chart. In order to do so, we want to leverage the same kind of abstraction that we used earlier, when extending our keyless entry system with a timer. Although the timer's value was technically also {{file=part3/figs/part3-min-flow-chart.eps,width=3.78in}} part of the FSM's state, we treated it as data and integrated it into our next-state decisions in only a couple of cases. For our minimum value problem, we have two sources of data. First, an external program supplies data in the form of a set of 10 integers. If we assume {32-bit} integers, these data technically form 320 input bits! Second, as with the keyless entry system timer, we have data used internally by our FSM, such as the loop index and the current minimum value. These are technically state bits. For both types of data, we treat them abstractly as values rather than thinking of them individually as bits, allowing us to develop our FSM at a high-level and then to implement it using the components that we have developed earlier in our course. {Choosing Components and Identifying States} Now we are ready to design an FSM that implements the flow chart. What components do we need, other than our state logic? We use registers and counters to implement the variables { idx} and { min} in the program. For the array { values}, we use a {1632-bit} memory.{We technically only need a {1032-bit} memory, but we round up the size of the address space to reflect more realistic memory designs; one can always optimize later.} We need a comparator to implement the test for the { if} statement. We choose to use a serial comparator, which allows us to illustrate again how one logical high-level state can be subdivided into many actual states. To operate the serial comparator, we make use of two shift registers that present the comparator with one bit per cycle on each input, and a counter to keep track of the comparator's progress. How do we identify high-level states from our flow chart? Although the flow chart attempts to break down the program into `simple' steps, one step of a flow chart may sometimes require more than one state in an FSM. Similarly, one FSM state may be able to implement several steps in a flow chart, if those steps can be performed simultaneously. Our design illustrates both possibilities. How we map flow chart elements into FSM states also depends to some degree on what components we use, which is why we began with some discussion of components. In practice, one can go back and forth between the two, adjusting components to better match the high-level states, and adjusting states to better match the desired components. Finally, note that we are only concerned with high-level states, so we do not need to provide details (yet) down to the level of individual clock cycles, but we do want to define high-level states that can be implemented in a fixed number of cycles, or at",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you implement an FSM?']",
"answer": "\nThe FSM is implemented using registers, counters, and a comparator. The comparator is used to implement the if statement in the program. The registers and counters are used to implement the variables idx and min in the program. The memory is used to implement the array values in the program."
}
},
{
"textbook-paragraph": "1&0 {eqnarray*} C&=&A_1 B_1+A_1 A_0 B_0+A_0 B_1 B_0 S_1&=& A_1 {B_1} {B_0}+ A_1 {A_0} {B_1}+ {A_1} {A_0} B_1+ {A_1} B_1 {B_0}+ &&{A_1} A_0 {B_1} B_0+ A_1 A_0 B_1 B_0 S_0&=&A_0 {B_0}+{A_0} B_0 {eqnarray*} In theory, {K-maps} extend to an arbitrary number of variables. Certainly Gray codes can be extended. An { {N-bit} Gray code} is a sequence of {N-bit} patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an {(N+1)-bit} Gray code, write the sequence for an {N-bit} Gray code, then add a 0 in front of all patterns. After this sequence, append a second copy of the {N-bit} Gray code in reverse order, then put a 1 in front of all patterns in the second copy. The result is an {(N+1)-bit} Gray code. For example, the following are Gray codes: 1-bit& 0, 1 2-bit& 00, 01, 11, 10 3-bit& 000, 001, 011, 010, 110, 111, 101, 100 4-bit& 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000 Unfortunately, some of the beneficial properties of {K-maps} do not extend beyond two variables in a dimension. { Once you have three variables in one dimension}, as is necessary if a function operates on five or more variables, { not all product terms are contiguous in the grid}. The terms still require a total number of rows and columns equal to a power of two, but they don't all need to be a contiguous group. Furthermore, { some contiguous groups of appropriate size do not correspond to product terms}. So you can still make use of {K-maps} if you have more variables, but their use is a little trickier. {Canonical Forms} What if we want to compare two expressions to determine whether they represent the same logic function? Such a comparison is a test of { logical equivalence}, and is an important part of hardware design. Tools today provide help with this problem, but you should understand the problem. You know that any given function can be expressed in many ways, and that two expressions that look quite different may in fact represent the same function (look back at Equations () to () for an example). But what if we rewrite the function using only prime implicants? Is the result unique? Unfortunately, no. In general, { a sum of products is not unique (nor is a product of sums), even if the sum contains only prime implicants}. For example, consensus terms may or may not be included in our expressions. (They are necessary for reliable design of certain types of systems, as you will learn in a later ECE class.) The green ellipse in the K-map to the right represents the consensus term BC. {eqnarray*} Z &=& A C + B + B C Z &=& A C + B {eqnarray*} Some functions allow several equivalent formulations as sums of prime implicants, even without consensus terms. The K-maps shown to the right, for example, illustrate how one function might be written in either of the following ways: {eqnarray*} Z &=& D + C + A B C + B D Z &=& C + B C + A B D + D {eqnarray*} When we need to compare two things (such as functions), we need to transform them into what in mathematics is known as a { canonical form}, which simply means a form that is defined so as to be unique for each thing of the given type. What can we use for logic functions? You already know two answers! The { canonical sum} of a function (sometimes called the { canonical SOP form}) is the sum of minterms. The { canonical product} of a function (sometimes called the { canonical POS form}) is the product of maxterms. These forms technically only meet the mathematical definition of canonical if we agree on an order for the min/maxterms, but that problem is solvable. However, as you already know, the forms are not particularly convenient to use. In practice, people and tools in the industry use more",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the two-bit Gray code?\", '\\n\\n",
"answer": "\nThe two-bit Gray code is a sequence of two-bit patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit."
}
},
{
"textbook-paragraph": "1&0 {eqnarray*} C&=&A_1 B_1+A_1 A_0 B_0+A_0 B_1 B_0 S_1&=& A_1 {B_1} {B_0}+ A_1 {A_0} {B_1}+ {A_1} {A_0} B_1+ {A_1} B_1 {B_0}+ &&{A_1} A_0 {B_1} B_0+ A_1 A_0 B_1 B_0 S_0&=&A_0 {B_0}+{A_0} B_0 {eqnarray*} In theory, {K-maps} extend to an arbitrary number of variables. Certainly Gray codes can be extended. An { {N-bit} Gray code} is a sequence of {N-bit} patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an {(N+1)-bit} Gray code, write the sequence for an {N-bit} Gray code, then add a 0 in front of all patterns. After this sequence, append a second copy of the {N-bit} Gray code in reverse order, then put a 1 in front of all patterns in the second copy. The result is an {(N+1)-bit} Gray code. For example, the following are Gray codes: 1-bit& 0, 1 2-bit& 00, 01, 11, 10 3-bit& 000, 001, 011, 010, 110, 111, 101, 100 4-bit& 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000 Unfortunately, some of the beneficial properties of {K-maps} do not extend beyond two variables in a dimension. { Once you have three variables in one dimension}, as is necessary if a function operates on five or more variables, { not all product terms are contiguous in the grid}. The terms still require a total number of rows and columns equal to a power of two, but they don't all need to be a contiguous group. Furthermore, { some contiguous groups of appropriate size do not correspond to product terms}. So you can still make use of {K-maps} if you have more variables, but their use is a little trickier. {Canonical Forms} What if we want to compare two expressions to determine whether they represent the same logic function? Such a comparison is a test of { logical equivalence}, and is an important part of hardware design. Tools today provide help with this problem, but you should understand the problem. You know that any given function can be expressed in many ways, and that two expressions that look quite different may in fact represent the same function (look back at Equations () to () for an example). But what if we rewrite the function using only prime implicants? Is the result unique? Unfortunately, no. In general, { a sum of products is not unique (nor is a product of sums), even if the sum contains only prime implicants}. For example, consensus terms may or may not be included in our expressions. (They are necessary for reliable design of certain types of systems, as you will learn in a later ECE class.) The green ellipse in the K-map to the right represents the consensus term BC. {eqnarray*} Z &=& A C + B + B C Z &=& A C + B {eqnarray*} Some functions allow several equivalent formulations as sums of prime implicants, even without consensus terms. The K-maps shown to the right, for example, illustrate how one function might be written in either of the following ways: {eqnarray*} Z &=& D + C + A B C + B D Z &=& C + B C + A B D + D {eqnarray*} When we need to compare two things (such as functions), we need to transform them into what in mathematics is known as a { canonical form}, which simply means a form that is defined so as to be unique for each thing of the given type. What can we use for logic functions? You already know two answers! The { canonical sum} of a function (sometimes called the { canonical SOP form}) is the sum of minterms. The { canonical product} of a function (sometimes called the { canonical POS form}) is the product of maxterms. These forms technically only meet the mathematical definition of canonical if we agree on an order for the min/maxterms, but that problem is solvable. However, as you already know, the forms are not particularly convenient to use. In practice, people and tools in the industry use more",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of a Gray code?\\n",
"answer": "\nA Gray code is a sequence of patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an (N+1)-bit Gray code, write the sequence for an N-bit Gray code, then add a 0 in front of all patterns."
}
},
{
"textbook-paragraph": "1&0 {eqnarray*} C&=&A_1 B_1+A_1 A_0 B_0+A_0 B_1 B_0 S_1&=& A_1 {B_1} {B_0}+ A_1 {A_0} {B_1}+ {A_1} {A_0} B_1+ {A_1} B_1 {B_0}+ &&{A_1} A_0 {B_1} B_0+ A_1 A_0 B_1 B_0 S_0&=&A_0 {B_0}+{A_0} B_0 {eqnarray*} In theory, {K-maps} extend to an arbitrary number of variables. Certainly Gray codes can be extended. An { {N-bit} Gray code} is a sequence of {N-bit} patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an {(N+1)-bit} Gray code, write the sequence for an {N-bit} Gray code, then add a 0 in front of all patterns. After this sequence, append a second copy of the {N-bit} Gray code in reverse order, then put a 1 in front of all patterns in the second copy. The result is an {(N+1)-bit} Gray code. For example, the following are Gray codes: 1-bit& 0, 1 2-bit& 00, 01, 11, 10 3-bit& 000, 001, 011, 010, 110, 111, 101, 100 4-bit& 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000 Unfortunately, some of the beneficial properties of {K-maps} do not extend beyond two variables in a dimension. { Once you have three variables in one dimension}, as is necessary if a function operates on five or more variables, { not all product terms are contiguous in the grid}. The terms still require a total number of rows and columns equal to a power of two, but they don't all need to be a contiguous group. Furthermore, { some contiguous groups of appropriate size do not correspond to product terms}. So you can still make use of {K-maps} if you have more variables, but their use is a little trickier. {Canonical Forms} What if we want to compare two expressions to determine whether they represent the same logic function? Such a comparison is a test of { logical equivalence}, and is an important part of hardware design. Tools today provide help with this problem, but you should understand the problem. You know that any given function can be expressed in many ways, and that two expressions that look quite different may in fact represent the same function (look back at Equations () to () for an example). But what if we rewrite the function using only prime implicants? Is the result unique? Unfortunately, no. In general, { a sum of products is not unique (nor is a product of sums), even if the sum contains only prime implicants}. For example, consensus terms may or may not be included in our expressions. (They are necessary for reliable design of certain types of systems, as you will learn in a later ECE class.) The green ellipse in the K-map to the right represents the consensus term BC. {eqnarray*} Z &=& A C + B + B C Z &=& A C + B {eqnarray*} Some functions allow several equivalent formulations as sums of prime implicants, even without consensus terms. The K-maps shown to the right, for example, illustrate how one function might be written in either of the following ways: {eqnarray*} Z &=& D + C + A B C + B D Z &=& C + B C + A B D + D {eqnarray*} When we need to compare two things (such as functions), we need to transform them into what in mathematics is known as a { canonical form}, which simply means a form that is defined so as to be unique for each thing of the given type. What can we use for logic functions? You already know two answers! The { canonical sum} of a function (sometimes called the { canonical SOP form}) is the sum of minterms. The { canonical product} of a function (sometimes called the { canonical POS form}) is the product of maxterms. These forms technically only meet the mathematical definition of canonical if we agree on an order for the min/maxterms, but that problem is solvable. However, as you already know, the forms are not particularly convenient to use. In practice, people and tools in the industry use more",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of a Gray code?\\n",
"answer": "\nA Gray code is a sequence of patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an (N+1)-bit Gray code, write the sequence for an N-bit Gray code, then add a 0 in front of all patterns."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What do the states represent in the transition diagram?\\n",
"answer": "\nThe states in the transition diagram represent the different colors of the stoplight. The first two states are red, followed by yellow, and then green. The last two states are again red."
}
},
{
"textbook-paragraph": "these outputs is given in the table to the right. {c|c} L& light color 0x& red 10& yellow 11& green Let's think about the basic operation of the controller. For safety reasons, the controller must ensure that the lights on one or both roads are red at all times. Similarly, if a road has a green light, the controller should show a yellow light before showing a red light to give drivers some warning and allow them to slow down. Finally, for fairness, the controller should alternate green lights between the two roads. Now take a look at the logic diagram below. The state of the FSM has been split into two pieces: a {3-bit} register S and a {6-bit} timer. The timer is simply a binary counter that counts downward and produces an output of Z=1 when it reaches 0. Notice that the register S only takes a new value when the timer reaches 0, and that the Z signal from the timer also forces a new value to be loaded into the timer in the next cycle. We can thus think of transitions in the FSM on a cycle by cycle basis as consisting of two types. The first type simply counts downward for a number of cycles while holding the register S constant, while the second changes the value of S and sets the timer in order to maintain the new value of S for some number of cycles. 3.45 Let's look at the next-state logic for S, which feeds into the IN inputs on the {3-bit} register (S_2^+=IN_2 and so forth). Notice that none of the inputs to the FSM directly affect these values. The states of S thus act like a counter. By examining the connections, we can derive equations for the next state and draw a transition diagram, as shown to the right. As the figure shows, there are six states in the loop defined by the next-state logic, with the two remaining states converging into the loop after a single cycle. Let's now examine the outputs for each state in order to understand how the stoplight sequencing works. We derive equations for the outputs that control the lights, as shown to the right, then calculate values and colors for each state, as shown to the far right. For completeness, the table includes the states outside of the desired loop. The lights are all red in both of these states, which is necessary for safety. {eqnarray*} S_2^+ &=& {S_2} + S_0 S_1^+ &=& {S_2} S_1 S_0^+ &=& {S_2} {eqnarray*} {eqnarray*} L_1^ &=& S_2 S_1 L_0^ &=& S_0 L_1^ &=& S_2 {S_1} L_0^ &=& S_0 {eqnarray*} {c|cc|cc} &&& EW& NS &&& light& light S& L^& L^& color& color 000& 00& 00& red& red 111& 11& 01& green& red 110& 10& 00& yellow& red 010& 00& 00& red& red 101& 01& 11& red& green 100& 00& 10& red& yellow 001& 01& 01& red& red 011& 01& 01& red& red Now let's think about how the timer works. As we already noted, the timer value is set whenever S enters a new state, but it can also be set under other conditions---in particular, by the signal F calculated at the bottom of the FSM logic diagram. For now, assume that F=0. In this case, the timer is set only when the state S changes, and we can find the duration of each state by analyzing the muxes. The bottom mux selects A when S_2=0, and selects the output of the top mux when S_2=1. The top mux selects B when S_0=1, and selects C when S_0=0. Combining these results, we can calculate the duration of the next states of S when F=0, as shown in the table to the right. We can then combine the next state duration with our previous calculation of the state sequencing (also the order in the table) to obtain the durations of each state, also shown in the rightmost column of the table. {c|cc|cc} & EW& NS& next& current & light& light& state& state S& color& color& duration& duration 000& red& red& A& C 111& green& red& B& A 110& yellow& red& C& B 010& red& red& A& C 101& red& green& B& A 100& red& yellow& C& B 001& red& red& A& --- 011& red& red& A& --- What does F do? Analyzing the gates that",
"GPT-3-Semantic-Search-Generations": {
"question": " What does the uninterrupted counting cycle represent?\\n",
"answer": "\nThe uninterrupted counting cycle represents the duration of each state in the FSM. This is used to calculate the duration of each state in the FSM when F=0."
}
},
{
"textbook-paragraph": "to implement a procedure and a call of that procedure. {file=part4/figs/lec23-2.eps,width=1.25in} [t] { [t] int =add3 (int n1, int n2, int n3) { >return (n1 + n2 + n3); } printf (``d'', add3 (10, 20, 30)); by convention: = n1 is in R0 >n2 is in R1 >n3 is in R2 >return value is in R6 [t] add3: = WWWW= WWWWW= add3:>ADD>R0,R0,R1 >ADD>R6,R0,R2 >RETN > >PUSH>R1>; save the value in R1 >LDI>R0,#10>; marshal arguments >LDI>R1,#20 >LDI>R2,#30 >CALL>add3 >MOV>R1,R6>; return value becomes 2nd argument >LDI>R0,``d''>; load a pointer to the string >CALL>printf >POP>R1>; restore R1 The add3 procedure takes three integers as arguments, adds them together, and returns the sum. The procedure is called with the constants 10, 20, and 30, and the result is printed. By the calling convention, when the call is made, R0 must contain the value 10, R1 the value 20, and R2 the value 30. We assume that the caller wants to preserve the value of R1, but does not care about R3 or R5. In the assembly language version on the right, R1 is first saved to the stack, then the arguments are marshaled into position, and finally the call is made. The procedure itself needs no local storage and does not change any callee-saved registers, thus must simply add the numbers together and place the result in R6. After add3 returns, its return value is moved from R6 to R1 in preparation for the call to printf. After loading a pointer to the format string into R0, the second call is made, and R1 is restored, completing the translation. { System calls} are almost identical to procedure calls. As with procedure calls, a calling convention is used: before invoking a system call, arguments are marshaled into the appropriate registers or locations in the stack; after a system call returns, any result appears in a pre-specified register. The calling convention used for system calls need not be the same as that used for procedure calls. Rather than a call instruction, system calls are usually initiated with a { trap} instruction, and system calls are also known as traps. With many architectures, a system call places the processor in privileged or kernel mode, and the instructions that implement the call are considered to be part of the operating system. The term system call arises from this fact. {Interrupts and Exceptions*} Unexpected processor interruptions arise both from interactions between a processor and external devices and from errors or unexpected behavior in the program being executed. The term { interrupt} is reserved for asynchronous interruptions generated by other devices, including disk drives, printers, network cards, video cards, keyboards, mice, and any number of other possibilities. { Exceptions} occur when a processor encounters an unexpected opcode or operand. An undefined instruction, for example, gives rise to an exception, as does an attempt to divide by zero. Exceptions usually cause the current program to terminate, although many operating systems will allow the program to catch the exception and to handle it more intelligently. The table below summarizes the characteristics of the two types and compares them to system calls. { {|l|l|l|c|c|} {|c|}& {c|}{generated by}& {c|}& asynchronous& unexpected interrupt& external device& packet arrived at network card& yes& yes exception& invalid opcode or operand& divide by zero& no& yes trap/system call& deliberate, via trap instruction& print character to console& no& no } Interrupts occur asynchronously with respect to the program. Most designs only recognize interrupts between instructions. In other words, the presence of interrupts is checked only after completing an instruction rather than in every cycle. In pipelined designs, however, instructions execute simultaneously, and the decision as to which instructions occur ``before'' an interrupt and which occur ``after'' must be made by the processor. Exceptions are not asynchronous in the sense that they occur",
"GPT-3-Semantic-Search-Generations": {
"question": "What is the output behavior?\\n ",
"answer": "\nThe output behavior is that the add3 procedure takes three integers as arguments, adds them together, and returns the sum. The procedure is called with the constants 10, 20, and 30, and the result is printed. By the calling convention, when the call is made, R0 must contain the value 10, R1 the value 20, and R2 the value 30."
}
},
{
"textbook-paragraph": "1&0 {eqnarray*} C&=&A_1 B_1+A_1 A_0 B_0+A_0 B_1 B_0 S_1&=& A_1 {B_1} {B_0}+ A_1 {A_0} {B_1}+ {A_1} {A_0} B_1+ {A_1} B_1 {B_0}+ &&{A_1} A_0 {B_1} B_0+ A_1 A_0 B_1 B_0 S_0&=&A_0 {B_0}+{A_0} B_0 {eqnarray*} In theory, {K-maps} extend to an arbitrary number of variables. Certainly Gray codes can be extended. An { {N-bit} Gray code} is a sequence of {N-bit} patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit. You can construct a Gray code recursively as follows: for an {(N+1)-bit} Gray code, write the sequence for an {N-bit} Gray code, then add a 0 in front of all patterns. After this sequence, append a second copy of the {N-bit} Gray code in reverse order, then put a 1 in front of all patterns in the second copy. The result is an {(N+1)-bit} Gray code. For example, the following are Gray codes: 1-bit& 0, 1 2-bit& 00, 01, 11, 10 3-bit& 000, 001, 011, 010, 110, 111, 101, 100 4-bit& 0000, 0001, 0011, 0010, 0110, 0111, 0101, 0100, 1100, 1101, 1111, 1110, 1010, 1011, 1001, 1000 Unfortunately, some of the beneficial properties of {K-maps} do not extend beyond two variables in a dimension. { Once you have three variables in one dimension}, as is necessary if a function operates on five or more variables, { not all product terms are contiguous in the grid}. The terms still require a total number of rows and columns equal to a power of two, but they don't all need to be a contiguous group. Furthermore, { some contiguous groups of appropriate size do not correspond to product terms}. So you can still make use of {K-maps} if you have more variables, but their use is a little trickier. {Canonical Forms} What if we want to compare two expressions to determine whether they represent the same logic function? Such a comparison is a test of { logical equivalence}, and is an important part of hardware design. Tools today provide help with this problem, but you should understand the problem. You know that any given function can be expressed in many ways, and that two expressions that look quite different may in fact represent the same function (look back at Equations () to () for an example). But what if we rewrite the function using only prime implicants? Is the result unique? Unfortunately, no. In general, { a sum of products is not unique (nor is a product of sums), even if the sum contains only prime implicants}. For example, consensus terms may or may not be included in our expressions. (They are necessary for reliable design of certain types of systems, as you will learn in a later ECE class.) The green ellipse in the K-map to the right represents the consensus term BC. {eqnarray*} Z &=& A C + B + B C Z &=& A C + B {eqnarray*} Some functions allow several equivalent formulations as sums of prime implicants, even without consensus terms. The K-maps shown to the right, for example, illustrate how one function might be written in either of the following ways: {eqnarray*} Z &=& D + C + A B C + B D Z &=& C + B C + A B D + D {eqnarray*} When we need to compare two things (such as functions), we need to transform them into what in mathematics is known as a { canonical form}, which simply means a form that is defined so as to be unique for each thing of the given type. What can we use for logic functions? You already know two answers! The { canonical sum} of a function (sometimes called the { canonical SOP form}) is the sum of minterms. The { canonical product} of a function (sometimes called the { canonical POS form}) is the product of maxterms. These forms technically only meet the mathematical definition of canonical if we agree on an order for the min/maxterms, but that problem is solvable. However, as you already know, the forms are not particularly convenient to use. In practice, people and tools in the industry use more",
"GPT-3-Semantic-Search-Generations": {
"question": "What is the purpose of using a Gray code?\\n ",
"answer": "\nThe purpose of using a Gray code is to create a sequence of patterns that includes all possible patterns such that any two adjacent patterns differ in only one bit. The code is actually a cycle: the first and last patterns also differ in only one bit."
}
},
{
"textbook-paragraph": "implementation of a specification implies decisions} about these details, so decisions should only be left unspecified if any of the possible answers is indeed acceptable. As a concrete example, let's design logic to control an ice cream dispenser. The dispenser has two flavors, lychee and mango, but also allows us to create a blend of the two flavors. For each of the two flavors, our logic must output two bits to control the amount of ice cream that comes out of the dispenser. The two-bit C_L[1:0] output of our logic must specify the number of half-servings of lychee ice cream as a binary number, and the two-bit C_M[1:0] output must specify the number of half-servings of mango ice cream. Thus, for either flavor, 00 indicates none of that flavor, 01 indicates one-half of a serving, and 10 indicates a full serving. Inputs to our logic will consist of three buttons: an L button to request a serving of lychee ice cream, a B button to request a blend---half a serving of each flavor, and an M button to request a serving of mango ice cream. Each button produces a 1 when pressed and a 0 when not pressed. Let's start with the assumption that the user only presses one button at a time. In this case, we can treat input combinations in which more than one button is pressed as ``don't care'' values in the truth tables for the outputs. K-maps for all four output bits appear below. The x's indicate ``don't care'' values. When we calculate the logic function for an output, each ``don't care'' value can be treated as either 0 or 1, whichever is more convenient in terms of creating the logic. In the case of C_M[1], for example, we can treat the three x's in the ellipse as 1s, treat the x outside of the ellipse as a 0, and simply use M (the implicant represented by the ellipse) for C_M[1]. The other three output bits are left as an exercise, although the result appears momentarily. The implementation at right takes full advantage of the ``don't care'' parts of our specification. In this case, we require no logic at all; we need merely connect the inputs to the correct outputs. Let's verify the operation. We have four cases to consider. First, if none of the buttons are pushed (LBM=000), we get no ice cream, as desired (C_M=00 and C_L=00). Second, if we request lychee ice cream (LBM=100), the outputs are C_L=10 and C_M=00, so we get a full serving of lychee and no mango. Third, if we request a blend (LBM=010), the outputs are C_L=01 and C_M=01, giving us half a serving of each flavor. Finally, if we request mango ice cream (LBM=001), we get no lychee but a full serving of mango. The K-maps for this implementation appear below. Each of the ``don't care'' x's from the original design has been replaced with either a 0 or a 1 and highlighted with shading and green italics. Any implementation produces either 0 or 1 for every output bit for every possible input combination. {{file=part2/figs/CLhigh-basic.eps,width=1.00in}{file=part2/figs/CLlow-basic.eps,width=1.00in}{file=part2/figs/CMhigh-basic.eps,width=1.00in}{file=part2/figs/CMlow-basic.eps,width=1.00in}} As you can see, leveraging ``don't care'' output bits can sometimes significantly simplify our logic. In the case of this example, we were able to completely eliminate any need for gates! Unfortunately, the resulting implementation may sometimes produce unexpected results. Based on the implementation, what happens if a user presses more than one button? The ice cream cup overflows! Let's see why. Consider the case LBM=101, in which we've pressed both the lychee and mango buttons. Here C_L=10 and C_M=10, so our dispenser releases a full serving of each flavor, or two servings total. Pressing other combinations may have other repercussions as well. Consider pressing lychee and blend (LBM=110). The outputs are then C_L=11 and C_M=01. Hopefully the dispenser simply gives us one and a half servings of lychee and a half serving of mango.",
"GPT-3-Semantic-Search-Generations": {
"question": " What should happen if the user presses the ``go'' button while in state { COUNT A}?\\n",
"answer": "\nIf the user presses the \"go\" button while in state {COUNT A}, then the outputs are C_L=11 and C_M=01. This means that the user will get one and a half servings of lychee and a half serving of mango."
}
},
{
"textbook-paragraph": "ever get into the unexpected states? What is the initial state of the three flip-flops in our implementation? { The initial state may not even be 0s and 1s unless we have an explicit mechanism for initialization.} Initialization can work in two ways. The first approach makes use of the flip-flop design. As you know, a flip-flop is built from a pair of latches, and we can make use of the internal reset lines on these latches to force each flip-flop into the 0 state (or the 1 state) using an additional input. Alternatively, we can add some extra logic to our design. Consider adding a few AND gates and a input (active low), as shown in the dashed box in the figure to the right. In this case, when we assert by setting it to 0, the FSM moves to state 000 in the next cycle, putting it into the BLACK state. The approach taken here is for clarity; one can optimize the design, if desired. For example, we could simply connect as an extra input into the three AND gates on the left rather than adding new ones, with the same effect. We may sometimes want a more powerful initialization mechanism---one that allows us to force the FSM into any specific state in the next cycle. In such a case, we can add multiplexers to each of our flip-flop inputs, allowing us to use the INIT input to choose between normal operation (INIT=0) of the FSM and forcing the FSM into the next state given by I_2I_1I_0 (when INIT=1). {Developing an Abstract Model} We are now ready to discuss the design process for an FSM from start to finish. For this first abstract FSM example, we build upon something that we have already seen: a two-bit Gray code counter. We now want a counter that allows us to start and stop the {c|ccc} state& no input& halt button& go button counting& counting& halted& halted& halted& & counting count. What is the mechanism for stopping and starting? To begin our design, we could sketch out an abstract next-state table such as the one shown to the right above. In this form of the table, the first column lists the states, while each of the other columns lists states to which the FSM transitions after a clock cycle for a particular input combination. The table contains two states, counting and halted, and specifies that the design uses two distinct buttons to move between the states. The table further implies that if the counter is halted, the ``halt'' button has no additional effect, and if the counter is counting, the ``go'' button has no additional effect. A counter with a single counting state, of course, does not provide much value. We extend the table with four counting states and four halted states, as shown to the right. This version of the table also introduces more formal state names, for which these notes use all capital letters. The upper four states represent uninterrupted counting, in which the counter cycles through these states indefinitely. A user can stop the counter in any state by pressing the ``halt'' button, causing the counter to retain its current value until the user presses the ``go'' button. Below the state table is an abstract transition diagram, which provides exactly the same information in graphical form. Here circles represent states (as labeled) and arcs represent transitions from one state to another based on an input combination (which is used to label the arc). We have already implicitly made a few choices about our counter design. First, the counter {c|ccc} state& no input& halt button& go button { COUNT A}& { COUNT B}& { HALT A}& { COUNT B}& { COUNT C}& { HALT B}& { COUNT C}& { COUNT D}& { HALT C}& { COUNT D}& { COUNT A}& { HALT D}& { HALT A}& { HALT A}& & { COUNT B} { HALT B}& { HALT B}& & { COUNT C} { HALT C}& { HALT C}& & { COUNT D} { HALT D}& { HALT D}& & { COUNT A} shown retains the current state of the system when ``halt'' is pressed. We could instead reset",
"GPT-3-Semantic-Search-Generations": {
"question": " What should happen if the user presses both buttons while in state { HALT A}?\", \"\\n",
"answer": "\nThere are two possible ways that the user could press both buttons while in state { HALT A}. The first way is that the user could press the \"halt\" button and then the \"go\" button. In this case, the FSM would move to state { HALT A} and then to state { COUNT B}. The second way is that the user could press the \"go\" button and then the \"halt\" button. In this case, the FSM would move to state { COUNT B} and then to state { HALT A}."
}
},
{
"textbook-paragraph": "implementation of a specification implies decisions} about these details, so decisions should only be left unspecified if any of the possible answers is indeed acceptable. As a concrete example, let's design logic to control an ice cream dispenser. The dispenser has two flavors, lychee and mango, but also allows us to create a blend of the two flavors. For each of the two flavors, our logic must output two bits to control the amount of ice cream that comes out of the dispenser. The two-bit C_L[1:0] output of our logic must specify the number of half-servings of lychee ice cream as a binary number, and the two-bit C_M[1:0] output must specify the number of half-servings of mango ice cream. Thus, for either flavor, 00 indicates none of that flavor, 01 indicates one-half of a serving, and 10 indicates a full serving. Inputs to our logic will consist of three buttons: an L button to request a serving of lychee ice cream, a B button to request a blend---half a serving of each flavor, and an M button to request a serving of mango ice cream. Each button produces a 1 when pressed and a 0 when not pressed. Let's start with the assumption that the user only presses one button at a time. In this case, we can treat input combinations in which more than one button is pressed as ``don't care'' values in the truth tables for the outputs. K-maps for all four output bits appear below. The x's indicate ``don't care'' values. When we calculate the logic function for an output, each ``don't care'' value can be treated as either 0 or 1, whichever is more convenient in terms of creating the logic. In the case of C_M[1], for example, we can treat the three x's in the ellipse as 1s, treat the x outside of the ellipse as a 0, and simply use M (the implicant represented by the ellipse) for C_M[1]. The other three output bits are left as an exercise, although the result appears momentarily. The implementation at right takes full advantage of the ``don't care'' parts of our specification. In this case, we require no logic at all; we need merely connect the inputs to the correct outputs. Let's verify the operation. We have four cases to consider. First, if none of the buttons are pushed (LBM=000), we get no ice cream, as desired (C_M=00 and C_L=00). Second, if we request lychee ice cream (LBM=100), the outputs are C_L=10 and C_M=00, so we get a full serving of lychee and no mango. Third, if we request a blend (LBM=010), the outputs are C_L=01 and C_M=01, giving us half a serving of each flavor. Finally, if we request mango ice cream (LBM=001), we get no lychee but a full serving of mango. The K-maps for this implementation appear below. Each of the ``don't care'' x's from the original design has been replaced with either a 0 or a 1 and highlighted with shading and green italics. Any implementation produces either 0 or 1 for every output bit for every possible input combination. {{file=part2/figs/CLhigh-basic.eps,width=1.00in}{file=part2/figs/CLlow-basic.eps,width=1.00in}{file=part2/figs/CMhigh-basic.eps,width=1.00in}{file=part2/figs/CMlow-basic.eps,width=1.00in}} As you can see, leveraging ``don't care'' output bits can sometimes significantly simplify our logic. In the case of this example, we were able to completely eliminate any need for gates! Unfortunately, the resulting implementation may sometimes produce unexpected results. Based on the implementation, what happens if a user presses more than one button? The ice cream cup overflows! Let's see why. Consider the case LBM=101, in which we've pressed both the lychee and mango buttons. Here C_L=10 and C_M=10, so our dispenser releases a full serving of each flavor, or two servings total. Pressing other combinations may have other repercussions as well. Consider pressing lychee and blend (LBM=110). The outputs are then C_L=11 and C_M=01. Hopefully the dispenser simply gives us one and a half servings of lychee and a half serving of mango.",
"GPT-3-Semantic-Search-Generations": {
"question": " How do you determine what should happen if a user presses both buttons (HG=11)?\\n",
"answer": "\nIf a user presses both buttons (HG=11), the ice cream cup overflows. This is because the outputs are C_L=11 and C_M=10, so our dispenser releases a full serving of each flavor, or two servings total."
}
},
{
"textbook-paragraph": "implementation of a specification implies decisions} about these details, so decisions should only be left unspecified if any of the possible answers is indeed acceptable. As a concrete example, let's design logic to control an ice cream dispenser. The dispenser has two flavors, lychee and mango, but also allows us to create a blend of the two flavors. For each of the two flavors, our logic must output two bits to control the amount of ice cream that comes out of the dispenser. The two-bit C_L[1:0] output of our logic must specify the number of half-servings of lychee ice cream as a binary number, and the two-bit C_M[1:0] output must specify the number of half-servings of mango ice cream. Thus, for either flavor, 00 indicates none of that flavor, 01 indicates one-half of a serving, and 10 indicates a full serving. Inputs to our logic will consist of three buttons: an L button to request a serving of lychee ice cream, a B button to request a blend---half a serving of each flavor, and an M button to request a serving of mango ice cream. Each button produces a 1 when pressed and a 0 when not pressed. Let's start with the assumption that the user only presses one button at a time. In this case, we can treat input combinations in which more than one button is pressed as ``don't care'' values in the truth tables for the outputs. K-maps for all four output bits appear below. The x's indicate ``don't care'' values. When we calculate the logic function for an output, each ``don't care'' value can be treated as either 0 or 1, whichever is more convenient in terms of creating the logic. In the case of C_M[1], for example, we can treat the three x's in the ellipse as 1s, treat the x outside of the ellipse as a 0, and simply use M (the implicant represented by the ellipse) for C_M[1]. The other three output bits are left as an exercise, although the result appears momentarily. The implementation at right takes full advantage of the ``don't care'' parts of our specification. In this case, we require no logic at all; we need merely connect the inputs to the correct outputs. Let's verify the operation. We have four cases to consider. First, if none of the buttons are pushed (LBM=000), we get no ice cream, as desired (C_M=00 and C_L=00). Second, if we request lychee ice cream (LBM=100), the outputs are C_L=10 and C_M=00, so we get a full serving of lychee and no mango. Third, if we request a blend (LBM=010), the outputs are C_L=01 and C_M=01, giving us half a serving of each flavor. Finally, if we request mango ice cream (LBM=001), we get no lychee but a full serving of mango. The K-maps for this implementation appear below. Each of the ``don't care'' x's from the original design has been replaced with either a 0 or a 1 and highlighted with shading and green italics. Any implementation produces either 0 or 1 for every output bit for every possible input combination. {{file=part2/figs/CLhigh-basic.eps,width=1.00in}{file=part2/figs/CLlow-basic.eps,width=1.00in}{file=part2/figs/CMhigh-basic.eps,width=1.00in}{file=part2/figs/CMlow-basic.eps,width=1.00in}} As you can see, leveraging ``don't care'' output bits can sometimes significantly simplify our logic. In the case of this example, we were able to completely eliminate any need for gates! Unfortunately, the resulting implementation may sometimes produce unexpected results. Based on the implementation, what happens if a user presses more than one button? The ice cream cup overflows! Let's see why. Consider the case LBM=101, in which we've pressed both the lychee and mango buttons. Here C_L=10 and C_M=10, so our dispenser releases a full serving of each flavor, or two servings total. Pressing other combinations may have other repercussions as well. Consider pressing lychee and blend (LBM=110). The outputs are then C_L=11 and C_M=01. Hopefully the dispenser simply gives us one and a half servings of lychee and a half serving of mango.",
"GPT-3-Semantic-Search-Generations": {
"question": " What if the ``halt'' button is pressed (HG=10), or both buttons are pressed (HG=11)?\\n",
"answer": "\nIf the \"halt\" button is pressed (HG=10), the logic outputs C_L=00 and C_M=00, so the dispenser gives no ice cream. If both buttons are pressed (HG=11), the outputs are C_L=11 and C_M=11, so the dispenser gives two servings of each flavor, or four servings total."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " Why is it important to consider all possible input conditions from all possible states?\\n",
"answer": "\nOne important reason to consider all possible input conditions from all possible states is that it can help ensure that a design is correct. For example, if a design only ever receives input values that are within a certain range, it is possible that the design is not actually correct for all input values. Considering all possible input conditions can help catch errors like this.\n\nAnother reason to consider all possible input conditions is that it can help optimize a design. For example, if a design only ever receives input values that are within a certain range, it is possible to simplify the design or make it more efficient. Considering all possible input conditions can help identify opportunities for optimization."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " How can a transition diagram help with this process?\\n",
"answer": "\nA transition diagram can help with this process by helping to identify the most important metrics and by helping to balance the design effectively according to those metrics."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " How can the state table form make the missing parts of the specification even more obvious?\\n",
"answer": "\nThe state table form of a specification can make the missing parts of the specification more obvious by showing the different states that the system can be in and the transitions between those states. This can help to identify what parts of the specification are missing and what needs to be added in order to complete the specification."
}
},
{
"textbook-paragraph": "implementation of a specification implies decisions} about these details, so decisions should only be left unspecified if any of the possible answers is indeed acceptable. As a concrete example, let's design logic to control an ice cream dispenser. The dispenser has two flavors, lychee and mango, but also allows us to create a blend of the two flavors. For each of the two flavors, our logic must output two bits to control the amount of ice cream that comes out of the dispenser. The two-bit C_L[1:0] output of our logic must specify the number of half-servings of lychee ice cream as a binary number, and the two-bit C_M[1:0] output must specify the number of half-servings of mango ice cream. Thus, for either flavor, 00 indicates none of that flavor, 01 indicates one-half of a serving, and 10 indicates a full serving. Inputs to our logic will consist of three buttons: an L button to request a serving of lychee ice cream, a B button to request a blend---half a serving of each flavor, and an M button to request a serving of mango ice cream. Each button produces a 1 when pressed and a 0 when not pressed. Let's start with the assumption that the user only presses one button at a time. In this case, we can treat input combinations in which more than one button is pressed as ``don't care'' values in the truth tables for the outputs. K-maps for all four output bits appear below. The x's indicate ``don't care'' values. When we calculate the logic function for an output, each ``don't care'' value can be treated as either 0 or 1, whichever is more convenient in terms of creating the logic. In the case of C_M[1], for example, we can treat the three x's in the ellipse as 1s, treat the x outside of the ellipse as a 0, and simply use M (the implicant represented by the ellipse) for C_M[1]. The other three output bits are left as an exercise, although the result appears momentarily. The implementation at right takes full advantage of the ``don't care'' parts of our specification. In this case, we require no logic at all; we need merely connect the inputs to the correct outputs. Let's verify the operation. We have four cases to consider. First, if none of the buttons are pushed (LBM=000), we get no ice cream, as desired (C_M=00 and C_L=00). Second, if we request lychee ice cream (LBM=100), the outputs are C_L=10 and C_M=00, so we get a full serving of lychee and no mango. Third, if we request a blend (LBM=010), the outputs are C_L=01 and C_M=01, giving us half a serving of each flavor. Finally, if we request mango ice cream (LBM=001), we get no lychee but a full serving of mango. The K-maps for this implementation appear below. Each of the ``don't care'' x's from the original design has been replaced with either a 0 or a 1 and highlighted with shading and green italics. Any implementation produces either 0 or 1 for every output bit for every possible input combination. {{file=part2/figs/CLhigh-basic.eps,width=1.00in}{file=part2/figs/CLlow-basic.eps,width=1.00in}{file=part2/figs/CMhigh-basic.eps,width=1.00in}{file=part2/figs/CMlow-basic.eps,width=1.00in}} As you can see, leveraging ``don't care'' output bits can sometimes significantly simplify our logic. In the case of this example, we were able to completely eliminate any need for gates! Unfortunately, the resulting implementation may sometimes produce unexpected results. Based on the implementation, what happens if a user presses more than one button? The ice cream cup overflows! Let's see why. Consider the case LBM=101, in which we've pressed both the lychee and mango buttons. Here C_L=10 and C_M=10, so our dispenser releases a full serving of each flavor, or two servings total. Pressing other combinations may have other repercussions as well. Consider pressing lychee and blend (LBM=110). The outputs are then C_L=11 and C_M=01. Hopefully the dispenser simply gives us one and a half servings of lychee and a half serving of mango.",
"GPT-3-Semantic-Search-Generations": {
"question": " What should happen if a user presses the ``go'' button (HG=01)?\\n",
"answer": "\nIf a user presses the \"go\" button (HG=01), the machine should dispense one and a half servings of lychee and a half serving of mango."
}
},
{
"textbook-paragraph": "transitions specified so far are that when we press ``go'' (HG=01), the counter moves to the { COUNT B} state, and that the counter remains halted in state { HALT A} if no buttons are pressed (HG=00). What if the ``halt'' button is pressed (HG=10), or both buttons are pressed (HG=11)? For consistency, we decide that ``halt'' overrides ``go,'' but does nothing special if it alone is pressed while the counter is halted. Thus, input patterns HG=10 and HG=11 also take state { HALT A} back to itself. Here the arc could be labeled HG=00,10,11 or, equivalently, HG=00,1x or HG=x0,11. To complete our design, we apply the same decisions that we made for the { COUNT A} state to all of the other counting states, and the decisions that we made for the { HALT A} state to all of the other halted states. If we had chosen not to specify an answer, an implementation could produce different behavior from the different counting and/or halted states, which might confuse a user. The resulting design appears to the right. {Choosing a State Representation} Now we need to select a representation for the states. Since our counter has eight states, we need at least three (_2 (8)=3) state bits S_2S_1S_0 to keep track of the current state. As we show later, { the choice of representation for an FSM's states can dramatically affect the design complexity}. For a design as simple as our counter, you could just let a computer implement all possible representations (there aren't more than 840, if we consider simple symmetries) and select one according to whatever metrics are interesting. For bigger designs, however, the number of possibilities quickly becomes impossible to explore completely. Fortunately, { use of abstraction in selecting a representation also tends to produce better designs} for a wide variety of metrics (such as design complexity, area, power consumption, and performance). The right strategy is thus often to start by selecting a representation that makes sense to a human, even if it requires more bits than are strictly necessary. The resulting implementation will be easier to design and to debug than an implementation in which only the global behavior has any meaning. Let's return to our specific example, the counter. We can use one bit, S_2, to record whether or not our counter is counting (S_2=0) or halted (S_2=1). The other two bits can then record the counter state in terms of the desired output. Choosing this representation implies that only wires will be necessary to compute outputs Z_1 and Z_0 from the internal state: Z_1=S_1 and Z_0=S_0. The resulting design, in which states are now labeled with both internal state and outputs (S_2S_1S_0/Z_1Z_0) appears to the right. In this version, we have changed the arc labeling to use logical expressions, which can sometimes help us to think about the implementation. The equivalent state listing and state table appear below. We have ordered the rows of the state table in Gray code order to simplify transcription of K-maps. & S_2S_1S_0& { COUNT A}& 000& counting, output Z_1Z_0=00 { COUNT B}& 001& counting, output Z_1Z_0=01 { COUNT C}& 011& counting, output Z_1Z_0=11 { COUNT D}& 010& counting, output Z_1Z_0=10 { HALT A}& 100& halted, output Z_1Z_0=00 { HALT B}& 101& halted, output Z_1Z_0=01 { HALT C}& 111& halted, output Z_1Z_0=11 { HALT D}& 110& halted, output Z_1Z_0=10 {rc|cccc} &&{HG} &S_2S_1S_0& 00& 01& 11& 10 { COUNT A}&000& 001& 001& 100& 100 { COUNT B}&001& 011& 011& 101& 101 { COUNT C}&011& 010& 010& 111& 111 { COUNT D}&010& 000& 000& 110& 110 { HALT D}&110& 110& 000& 110& 110 { HALT C}&111& 111& 010& 111& 111 { HALT B}&101& 101& 011& 101& 101 { HALT A}&100& 100& 001& 100& 100 Having chosen a representation, we can go ahead and implement our design in the usual way. As shown to the right, K-maps for the next-state logic are complicated, since we have five variables and must consider implicants that are not contiguous in",
"GPT-3-Semantic-Search-Generations": {
"question": " How does the choice of state representation affect design complexity?\\n",
"answer": "\nThe choice of state representation affects design complexity in a few ways. First, it can affect the number of bits needed to represent the states. Second, it can affect the number of possible states that can be represented. Third, it can affect the number of transitions that need to be considered when designing the state machine."
}
},
{
"textbook-paragraph": "transitions specified so far are that when we press ``go'' (HG=01), the counter moves to the { COUNT B} state, and that the counter remains halted in state { HALT A} if no buttons are pressed (HG=00). What if the ``halt'' button is pressed (HG=10), or both buttons are pressed (HG=11)? For consistency, we decide that ``halt'' overrides ``go,'' but does nothing special if it alone is pressed while the counter is halted. Thus, input patterns HG=10 and HG=11 also take state { HALT A} back to itself. Here the arc could be labeled HG=00,10,11 or, equivalently, HG=00,1x or HG=x0,11. To complete our design, we apply the same decisions that we made for the { COUNT A} state to all of the other counting states, and the decisions that we made for the { HALT A} state to all of the other halted states. If we had chosen not to specify an answer, an implementation could produce different behavior from the different counting and/or halted states, which might confuse a user. The resulting design appears to the right. {Choosing a State Representation} Now we need to select a representation for the states. Since our counter has eight states, we need at least three (_2 (8)=3) state bits S_2S_1S_0 to keep track of the current state. As we show later, { the choice of representation for an FSM's states can dramatically affect the design complexity}. For a design as simple as our counter, you could just let a computer implement all possible representations (there aren't more than 840, if we consider simple symmetries) and select one according to whatever metrics are interesting. For bigger designs, however, the number of possibilities quickly becomes impossible to explore completely. Fortunately, { use of abstraction in selecting a representation also tends to produce better designs} for a wide variety of metrics (such as design complexity, area, power consumption, and performance). The right strategy is thus often to start by selecting a representation that makes sense to a human, even if it requires more bits than are strictly necessary. The resulting implementation will be easier to design and to debug than an implementation in which only the global behavior has any meaning. Let's return to our specific example, the counter. We can use one bit, S_2, to record whether or not our counter is counting (S_2=0) or halted (S_2=1). The other two bits can then record the counter state in terms of the desired output. Choosing this representation implies that only wires will be necessary to compute outputs Z_1 and Z_0 from the internal state: Z_1=S_1 and Z_0=S_0. The resulting design, in which states are now labeled with both internal state and outputs (S_2S_1S_0/Z_1Z_0) appears to the right. In this version, we have changed the arc labeling to use logical expressions, which can sometimes help us to think about the implementation. The equivalent state listing and state table appear below. We have ordered the rows of the state table in Gray code order to simplify transcription of K-maps. & S_2S_1S_0& { COUNT A}& 000& counting, output Z_1Z_0=00 { COUNT B}& 001& counting, output Z_1Z_0=01 { COUNT C}& 011& counting, output Z_1Z_0=11 { COUNT D}& 010& counting, output Z_1Z_0=10 { HALT A}& 100& halted, output Z_1Z_0=00 { HALT B}& 101& halted, output Z_1Z_0=01 { HALT C}& 111& halted, output Z_1Z_0=11 { HALT D}& 110& halted, output Z_1Z_0=10 {rc|cccc} &&{HG} &S_2S_1S_0& 00& 01& 11& 10 { COUNT A}&000& 001& 001& 100& 100 { COUNT B}&001& 011& 011& 101& 101 { COUNT C}&011& 010& 010& 111& 111 { COUNT D}&010& 000& 000& 110& 110 { HALT D}&110& 110& 000& 110& 110 { HALT C}&111& 111& 010& 111& 111 { HALT B}&101& 101& 011& 101& 101 { HALT A}&100& 100& 001& 100& 100 Having chosen a representation, we can go ahead and implement our design in the usual way. As shown to the right, K-maps for the next-state logic are complicated, since we have five variables and must consider implicants that are not contiguous in",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the right strategy for selecting a state representation?\\n",
"answer": "\nThe right strategy is to start by selecting a representation that makes sense to a human, even if it requires more bits than are strictly necessary. The resulting implementation will be easier to design and to debug than an implementation in which only the global behavior has any meaning."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " Why is it often best to start by selecting a representation that makes sense to a human?\\n",
"answer": "\nOne reason it is often best to start by selecting a representation that makes sense to a human is that it can be easier to understand and work with. Additionally, starting with a representation that makes sense to a human can help ensure that the final product is also easy to understand and use."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " How can the use of abstraction in selecting a state representation lead to a better design?', '\\n",
"answer": "\nAbstraction in selecting a state representation can lead to a better design by allowing the engineer to focus on the important aspects of the problem and ignoring the details that are not important. This can help to simplify the problem and make it easier to find a solution."
}
},
{
"textbook-paragraph": "Notes Set 2.4, for example, we showed a design for a logic slice that compares two bits at a time. In general, we can optimize logic for any number of bits and then apply multiple copies of the resulting logic in space (a generalization of the bit-sliced approach), or in time (a generalization of the serialization approach), or in a combination of the two. Sometimes these tradeoffs may happen at a higher level. As mentioned in Notes Set 2.3, computer software uses the carry out of an adder to perform addition of larger groups of bits (over multiple clock cycles) than is supported by the processor's adder hardware. In computer system design, engineers often design hardware elements that are general enough to support this kind of extension in software. As a concrete example of the possible tradeoffs, consider a serial comparator design based on the {2-bit} slice variant. This approach leads to a serial design with 24 gates and 10 inverters, which is not much larger than our earlier serial design. In terms of gate delays, however, the new design is identical, meaning that we finish a comparison in half the time. More realistic area and timing metrics show slightly more difference between the two designs. These differences can dominate the results if we blindly scale the idea to handle more bits without thinking carefully about the design. Neither many-input gates nor gates driving many outputs work well in practice. {Finite State Machines} A { finite state machine} (or { FSM}) is a model for understanding the behavior of a system by describing the system as occupying one of a finite set of states, moving between these states in response to external inputs, and producing external outputs. In any given state, a particular input may cause the FSM to move to another state; this combination is called a { transition rule}. An FSM comprises five parts: a finite set of states, a set of possible inputs, a set of possible outputs, a set of transition rules, and methods for calculating outputs. When an FSM is implemented as a digital system, all states must be represented as patterns using a fixed number of bits, all inputs must be translated into bits, and all outputs must be translated into bits. For a digital FSM, transition rules must be { complete}; in other words, given any state of the FSM, and any pattern of input bits, a transition must be defined from that state to another state (transitions from a state to itself, called { self-loops}, are acceptable). And, of course, calculation of outputs for a digital FSM reduces to Boolean logic expressions. In this class, we focus on clocked synchronous FSM implementations, in which the FSM's internal state bits are stored in flip-flops. In this section, we introduce the tools used to describe, develop, and analyze implementations of FSMs with digital logic. In the next few weeks, we will show you how an FSM can serve as the central control logic in a computer. At the same time, we will illustrate connections between FSMs and software and will make some connections with other areas of interest in ECE, such as the design and analysis of digital control systems. The table below gives a { list of abstract states} for a typical keyless entry system for a car. In this case, we have merely named the states rather than specifying the bit patterns to be used for each state---for this reason, we refer to them as abstract states. The description of the states in the first column is an optional element often included in the early design stages for an FSM, when identifying the states needed for the design. A list may also include the outputs for each state. Again, in the list below, we have specified these outputs abstractly. By including outputs for each state, we implicitly assume that outputs depend only on the state of the FSM. We discuss this assumption in more detail later in these notes (see ``Machine Models''), but will make the assumption throughout",
"GPT-3-Semantic-Search-Generations": {
"question": " How does the number of state bits affect the design complexity?\\n",
"answer": "\nThe number of state bits affects the design complexity because it determines the number of possible states that the FSM can be in. A larger number of state bits means that there are more possible states and the design must be able to handle all of them."
}
},
{
"textbook-paragraph": "transitions specified so far are that when we press ``go'' (HG=01), the counter moves to the { COUNT B} state, and that the counter remains halted in state { HALT A} if no buttons are pressed (HG=00). What if the ``halt'' button is pressed (HG=10), or both buttons are pressed (HG=11)? For consistency, we decide that ``halt'' overrides ``go,'' but does nothing special if it alone is pressed while the counter is halted. Thus, input patterns HG=10 and HG=11 also take state { HALT A} back to itself. Here the arc could be labeled HG=00,10,11 or, equivalently, HG=00,1x or HG=x0,11. To complete our design, we apply the same decisions that we made for the { COUNT A} state to all of the other counting states, and the decisions that we made for the { HALT A} state to all of the other halted states. If we had chosen not to specify an answer, an implementation could produce different behavior from the different counting and/or halted states, which might confuse a user. The resulting design appears to the right. {Choosing a State Representation} Now we need to select a representation for the states. Since our counter has eight states, we need at least three (_2 (8)=3) state bits S_2S_1S_0 to keep track of the current state. As we show later, { the choice of representation for an FSM's states can dramatically affect the design complexity}. For a design as simple as our counter, you could just let a computer implement all possible representations (there aren't more than 840, if we consider simple symmetries) and select one according to whatever metrics are interesting. For bigger designs, however, the number of possibilities quickly becomes impossible to explore completely. Fortunately, { use of abstraction in selecting a representation also tends to produce better designs} for a wide variety of metrics (such as design complexity, area, power consumption, and performance). The right strategy is thus often to start by selecting a representation that makes sense to a human, even if it requires more bits than are strictly necessary. The resulting implementation will be easier to design and to debug than an implementation in which only the global behavior has any meaning. Let's return to our specific example, the counter. We can use one bit, S_2, to record whether or not our counter is counting (S_2=0) or halted (S_2=1). The other two bits can then record the counter state in terms of the desired output. Choosing this representation implies that only wires will be necessary to compute outputs Z_1 and Z_0 from the internal state: Z_1=S_1 and Z_0=S_0. The resulting design, in which states are now labeled with both internal state and outputs (S_2S_1S_0/Z_1Z_0) appears to the right. In this version, we have changed the arc labeling to use logical expressions, which can sometimes help us to think about the implementation. The equivalent state listing and state table appear below. We have ordered the rows of the state table in Gray code order to simplify transcription of K-maps. & S_2S_1S_0& { COUNT A}& 000& counting, output Z_1Z_0=00 { COUNT B}& 001& counting, output Z_1Z_0=01 { COUNT C}& 011& counting, output Z_1Z_0=11 { COUNT D}& 010& counting, output Z_1Z_0=10 { HALT A}& 100& halted, output Z_1Z_0=00 { HALT B}& 101& halted, output Z_1Z_0=01 { HALT C}& 111& halted, output Z_1Z_0=11 { HALT D}& 110& halted, output Z_1Z_0=10 {rc|cccc} &&{HG} &S_2S_1S_0& 00& 01& 11& 10 { COUNT A}&000& 001& 001& 100& 100 { COUNT B}&001& 011& 011& 101& 101 { COUNT C}&011& 010& 010& 111& 111 { COUNT D}&010& 000& 000& 110& 110 { HALT D}&110& 110& 000& 110& 110 { HALT C}&111& 111& 010& 111& 111 { HALT B}&101& 101& 011& 101& 101 { HALT A}&100& 100& 001& 100& 100 Having chosen a representation, we can go ahead and implement our design in the usual way. As shown to the right, K-maps for the next-state logic are complicated, since we have five variables and must consider implicants that are not contiguous in",
"GPT-3-Semantic-Search-Generations": {
"question": " Why is it important to use abstraction when selecting a state representation?\\n",
"answer": "\nAbstraction is important when selecting a state representation because it allows the designer to select a representation that makes sense to a human, even if it requires more bits than are strictly necessary. The resulting implementation will be easier to design and to debug than an implementation in which only the global behavior has any meaning."
}
},
{
"textbook-paragraph": "Notes Set 2.4, for example, we showed a design for a logic slice that compares two bits at a time. In general, we can optimize logic for any number of bits and then apply multiple copies of the resulting logic in space (a generalization of the bit-sliced approach), or in time (a generalization of the serialization approach), or in a combination of the two. Sometimes these tradeoffs may happen at a higher level. As mentioned in Notes Set 2.3, computer software uses the carry out of an adder to perform addition of larger groups of bits (over multiple clock cycles) than is supported by the processor's adder hardware. In computer system design, engineers often design hardware elements that are general enough to support this kind of extension in software. As a concrete example of the possible tradeoffs, consider a serial comparator design based on the {2-bit} slice variant. This approach leads to a serial design with 24 gates and 10 inverters, which is not much larger than our earlier serial design. In terms of gate delays, however, the new design is identical, meaning that we finish a comparison in half the time. More realistic area and timing metrics show slightly more difference between the two designs. These differences can dominate the results if we blindly scale the idea to handle more bits without thinking carefully about the design. Neither many-input gates nor gates driving many outputs work well in practice. {Finite State Machines} A { finite state machine} (or { FSM}) is a model for understanding the behavior of a system by describing the system as occupying one of a finite set of states, moving between these states in response to external inputs, and producing external outputs. In any given state, a particular input may cause the FSM to move to another state; this combination is called a { transition rule}. An FSM comprises five parts: a finite set of states, a set of possible inputs, a set of possible outputs, a set of transition rules, and methods for calculating outputs. When an FSM is implemented as a digital system, all states must be represented as patterns using a fixed number of bits, all inputs must be translated into bits, and all outputs must be translated into bits. For a digital FSM, transition rules must be { complete}; in other words, given any state of the FSM, and any pattern of input bits, a transition must be defined from that state to another state (transitions from a state to itself, called { self-loops}, are acceptable). And, of course, calculation of outputs for a digital FSM reduces to Boolean logic expressions. In this class, we focus on clocked synchronous FSM implementations, in which the FSM's internal state bits are stored in flip-flops. In this section, we introduce the tools used to describe, develop, and analyze implementations of FSMs with digital logic. In the next few weeks, we will show you how an FSM can serve as the central control logic in a computer. At the same time, we will illustrate connections between FSMs and software and will make some connections with other areas of interest in ECE, such as the design and analysis of digital control systems. The table below gives a { list of abstract states} for a typical keyless entry system for a car. In this case, we have merely named the states rather than specifying the bit patterns to be used for each state---for this reason, we refer to them as abstract states. The description of the states in the first column is an optional element often included in the early design stages for an FSM, when identifying the states needed for the design. A list may also include the outputs for each state. Again, in the list below, we have specified these outputs abstractly. By including outputs for each state, we implicitly assume that outputs depend only on the state of the FSM. We discuss this assumption in more detail later in these notes (see ``Machine Models''), but will make the assumption throughout",
"GPT-3-Semantic-Search-Generations": {
"question": " How does the choice of state representation affect the design of the FSM?\\n",
"answer": "\nDifferent state representations can lead to different FSM designs. For example, if states are represented as patterns using a fixed number of bits, all inputs must be translated into bits, and all outputs must be translated into bits. If an FSM is implemented as a digital system, all states must be represented as patterns using a fixed number of bits, all inputs must be translated into bits, and all outputs must be translated into bits."
}
},
{
"textbook-paragraph": "compact approaches when comparing functions, but those solutions are a subject for a later class (such as ECE 462). {Two-Level Logic} { Two-level logic} is a popular way of expressing logic functions. The two levels refer simply to the number of functions through which an input passes to reach an output, and both the SOP and POS forms are examples of two-level logic. In this section, we illustrate one of the reasons for this popularity and show you how to graphically manipulate expressions, which can sometimes help when trying to understand gate diagrams. We begin with one of DeMorgan's laws, which we can illustrate both algebraically and graphically: C = B+A = {file=part2/figs/demorgan-nand.eps,width=0.95in} Let's say that we have a function expressed in SOP form, such as Z=ABC+DE+FGHJ. The diagram on the left below shows the function constructed from three AND gates and an OR gate. Using DeMorgan's law, we can replace the OR gate with a NAND with inverted inputs. But the bubbles that correspond to inversion do not need to sit at the input to the gate. We can invert at any point along the wire, so we slide each bubble down the wire to the output of the first column of AND gates. { Be careful: if the wire splits, which does not happen in our example, you have to replicate the inverter onto the other output paths as you slide past the split point!} The end result is shown on the right: we have not changed the function, but now we use only NAND gates. Since CMOS technology only supports NAND and NOR directly, using two-level logic makes it simple to map our expression into CMOS gates. {file=part2/figs/SOP-equiv.eps,width=6.5in} You may want to make use of DeMorgan's other law, illustrated graphically to the right, to perform the same transformation on a POS expression. What do you get? {file=part2/figs/demorgan-nor.eps,width=0.95in} {Multi-Metric Optimization} As engineers, almost every real problem that you encounter will admit multiple metrics for evaluating possible designs. Becoming a good engineer thus requires not only that you be able to solve problems creatively so as to improve the quality of your solutions, but also that you are aware of how people might evaluate those solutions and are able both to identify the most important metrics and to balance your design effectively according to them. In this section, we introduce some general ideas and methods that may be of use to you in this regard. { We will not test you on the concepts in this section.} When you start thinking about a new problem, your first step should be to think carefully about metrics of possible interest. Some important metrics may not be easy to quantify. For example, compatibility of a design with other products already owned by a customer has frequently defined the success or failure of computer hardware and software solutions. But how can you compute the compability of your approach as a number? Humans---including engineers---are not good at comparing multiple metrics simultaneously. Thus, once you have a set of metrics that you feel is complete, your next step is to get rid of as many as you can. Towards this end, you may identify metrics that have no practical impact in current technology, set threshold values for other metrics to simplify reasoning about them, eliminate redundant metrics, calculate linear sums to reduce the count of metrics, and, finally, make use of the notion of Pareto optimality. All of these ideas are described in the rest of this section. Let's start by considering metrics that we can quantify as real numbers. For a given metric, we can divide possible measurement values into three ranges. In the first range, all measurement values are equivalently useful. In the second range, possible values are ordered and interesting with respect to one another. Values in the third range are all impossible to use in practice. Using power consumption as our example, the first",
"GPT-3-Semantic-Search-Generations": {
"question": " How does the use of abstraction in selecting a representation impact the design metrics?']",
"answer": "\nAbstraction in selecting a representation can impact the design metrics by reducing the number of metrics that need to be considered. This can simplify the process of designing a solution and make it easier to find an optimal solution."
}
},
{
"textbook-paragraph": "the K-maps. The S_2^+ logic is easy enough: we only need two terms, as shown. Notice that we have used color and line style to distinguish different implicants in the K-maps. Furthermore, the symmetry of the design produces symmetry in the S_1^+ and S_0^+ formula, so we have used the same color and line style for analogous terms in these two K-maps. For S_1^+, we need four terms. The green ellipses in the HG=01 column are part of the same term, as are the two halves of the dashed blue circle. In S_0^+, we still need four terms, but three of them are split into two pieces in the K-map. As you can see, the utility of the K-map is starting to break down with five variables. {Abstracting Design Symmetries} Rather than implementing the design as two-level logic, let's try to take advantage of our design's symmetry to further simplify the logic (we reduce gate count at the expense of longer, slower paths). Looking back to the last transition diagram, in which the arcs were labeled with logical expressions, let's calculate an expression for when the counter should retain its current value in the next cycle. We call this variable HOLD. In the counting states, when S_2=0, the counter stops (moves into a halted state without changing value) when H is true. In the halted states, when S_2=1, the counter stops (stays in a halted state) when H+ is true. We can thus write {eqnarray*} HOLD &=& {S_2} H + S_2 ( H + ) HOLD &=& {S_2} H + S_2 H + S_2 HOLD &=& H + S_2 {eqnarray*} In other words, the counter should hold its current value (stop counting) if we press the ``halt'' button or if the counter was already halted and we didn't press the ``go'' button. As desired, the current value of the counter (S_1S_0) has no impact on this decision. You may have noticed that the expression we derived for HOLD also matches S_2^+, the next-state value of S_2 in the K-map on the previous page. Now let's re-write our state transition table in terms of HOLD. The left version uses state names for clarity; the right uses state values to help us transcribe K-maps. { {rc|cc} &&{HOLD} &S_2S_1S_0& 0& 1 { COUNT A}&000& { COUNT B}& { HALT A} { COUNT B}&001& { COUNT C}& { HALT B} { COUNT C}&011& { COUNT D}& { HALT C} { COUNT D}&010& { COUNT A}& { HALT D} { HALT A}&100& { COUNT B}& { HALT A} { HALT B}&101& { COUNT C}& { HALT B} { HALT C}&111& { COUNT D}& { HALT C} { HALT D}&110& { COUNT A}& { HALT D} {rc|cc} &&{HOLD} &S_2S_1S_0& 0& 1 { COUNT A}&000& 001& 100 { COUNT B}&001& 011& 101 { COUNT C}&011& 010& 111 { COUNT D}&010& 000& 110 { HALT A}&100& 001& 100 { HALT B}&101& 011& 101 { HALT C}&111& 010& 111 { HALT D}&110& 000& 110 The K-maps based on the HOLD abstraction are shown to the right. As you can see, the necessary logic has been simplified substantially, requiring only two terms each for both S_1^+ and S_0^+. Writing the next-state logic algebraically, we obtain {eqnarray*} S_2^+ &=& HOLD S_1^+ &=& S_0 + HOLD S_1 S_0^+ &=& {{S_1}} + HOLD S_0 {eqnarray*} Notice the similarity between the equations for S_1^+S_0^+ and the equations for a {2-to-1} mux: when HOLD=1, the counter retains its state, and when HOLD=0, it counts. An implementation appears below. By using semantic meaning in our choice of representation---in particular the use of S_2 to record whether the counter is currently halted (S_2=1) or counting (S_2=0)---we have enabled ourselves to separate out the logic for deciding whether to advance the counter fairly cleanly from the logic for advancing the counter itself. Only the HOLD bit in the diagram is used to determine whether or not the counter should advance in the current cycle. Let's check that the implementation matches our original design. Start by verifying that the HOLD variable is calculated correctly, HOLD=H+S_2, then look back at the K-map for S_2^+ in the low-level design to verify that the expression we used does indeed match. Next, check the mux",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the value of HOLD when the counter is in the COUNT A state and S_2=0?\\n",
"answer": "\nHOLD is 1 when the counter is in the COUNT A state and S_2=0. This is because the counter is already halted and we didn't press the \"go\" button."
}
},
{
"textbook-paragraph": "the K-maps. The S_2^+ logic is easy enough: we only need two terms, as shown. Notice that we have used color and line style to distinguish different implicants in the K-maps. Furthermore, the symmetry of the design produces symmetry in the S_1^+ and S_0^+ formula, so we have used the same color and line style for analogous terms in these two K-maps. For S_1^+, we need four terms. The green ellipses in the HG=01 column are part of the same term, as are the two halves of the dashed blue circle. In S_0^+, we still need four terms, but three of them are split into two pieces in the K-map. As you can see, the utility of the K-map is starting to break down with five variables. {Abstracting Design Symmetries} Rather than implementing the design as two-level logic, let's try to take advantage of our design's symmetry to further simplify the logic (we reduce gate count at the expense of longer, slower paths). Looking back to the last transition diagram, in which the arcs were labeled with logical expressions, let's calculate an expression for when the counter should retain its current value in the next cycle. We call this variable HOLD. In the counting states, when S_2=0, the counter stops (moves into a halted state without changing value) when H is true. In the halted states, when S_2=1, the counter stops (stays in a halted state) when H+ is true. We can thus write {eqnarray*} HOLD &=& {S_2} H + S_2 ( H + ) HOLD &=& {S_2} H + S_2 H + S_2 HOLD &=& H + S_2 {eqnarray*} In other words, the counter should hold its current value (stop counting) if we press the ``halt'' button or if the counter was already halted and we didn't press the ``go'' button. As desired, the current value of the counter (S_1S_0) has no impact on this decision. You may have noticed that the expression we derived for HOLD also matches S_2^+, the next-state value of S_2 in the K-map on the previous page. Now let's re-write our state transition table in terms of HOLD. The left version uses state names for clarity; the right uses state values to help us transcribe K-maps. { {rc|cc} &&{HOLD} &S_2S_1S_0& 0& 1 { COUNT A}&000& { COUNT B}& { HALT A} { COUNT B}&001& { COUNT C}& { HALT B} { COUNT C}&011& { COUNT D}& { HALT C} { COUNT D}&010& { COUNT A}& { HALT D} { HALT A}&100& { COUNT B}& { HALT A} { HALT B}&101& { COUNT C}& { HALT B} { HALT C}&111& { COUNT D}& { HALT C} { HALT D}&110& { COUNT A}& { HALT D} {rc|cc} &&{HOLD} &S_2S_1S_0& 0& 1 { COUNT A}&000& 001& 100 { COUNT B}&001& 011& 101 { COUNT C}&011& 010& 111 { COUNT D}&010& 000& 110 { HALT A}&100& 001& 100 { HALT B}&101& 011& 101 { HALT C}&111& 010& 111 { HALT D}&110& 000& 110 The K-maps based on the HOLD abstraction are shown to the right. As you can see, the necessary logic has been simplified substantially, requiring only two terms each for both S_1^+ and S_0^+. Writing the next-state logic algebraically, we obtain {eqnarray*} S_2^+ &=& HOLD S_1^+ &=& S_0 + HOLD S_1 S_0^+ &=& {{S_1}} + HOLD S_0 {eqnarray*} Notice the similarity between the equations for S_1^+S_0^+ and the equations for a {2-to-1} mux: when HOLD=1, the counter retains its state, and when HOLD=0, it counts. An implementation appears below. By using semantic meaning in our choice of representation---in particular the use of S_2 to record whether the counter is currently halted (S_2=1) or counting (S_2=0)---we have enabled ourselves to separate out the logic for deciding whether to advance the counter fairly cleanly from the logic for advancing the counter itself. Only the HOLD bit in the diagram is used to determine whether or not the counter should advance in the current cycle. Let's check that the implementation matches our original design. Start by verifying that the HOLD variable is calculated correctly, HOLD=H+S_2, then look back at the K-map for S_2^+ in the low-level design to verify that the expression we used does indeed match. Next, check the mux",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the value of HOLD when the counter is in the HALT A state and S_2=1?\\n",
"answer": "\nHOLD = H + S_2\n\nWhen the counter is in the HALT A state and S_2=1, HOLD = 1. This is because the counter should stop (move into a halted state without changing value) when H is true, and in the halted states, when S_2=1, the counter stops (stays in a halted state) when H+ is true."
}
},
{
"textbook-paragraph": "unit. We define S as the number represented by the bit pattern produced by the add unit. When overflow occurs, S=C, but we always have (S=C) 2^N. { Theorem:} Addition of two {N-bit} 2's complement numbers A and B overflows if and only if one of the following conditions holds: {A<0 and B<0 and S} {A and B and S<0} { Proof:} We once again start with the ``if'' direction. That is, if condition 1 or condition 2 holds, we have an overflow. The proofs are straightforward. Given condition 1, we can add the two inequalities A<0 and B<0 to obtain C=A+B<0. But S, so clearly S=C, thus overflow has occurred. Similarly, if condition 2 holds, we can add the inequalities A and B to obtain C=A+B. Here we have S<0, so again S=C, and we have an overflow. We must now prove the ``only if'' direction, showing that any overflow implies either condition 1 or condition 2. By the { contrapositive}{If we have a statement of the form (p implies q), its contrapositive is the statement (not q implies not p). Both statements have the same truth value. In this case, we can turn our Lemma around as stated.} of our Lemma, we know that if an overflow occurs, either both operands are negative, or they are both positive. Let's start with the case in which both operands are negative, so A<0 and B<0, and thus the real sum C<0 as well. Given that A and B are represented as {N-bit} 2's complement, they must fall in the representable range, so we can write {eqnarray*} -2^{N-1} & A & < 0 -2^{N-1} & B & < 0 {eqnarray*} We add these two inequalities and replace A+B with C to obtain {eqnarray*} -2^N & C & < 0 {eqnarray*} Given that an overflow has occurred, C must fall outside of the representable range. Given that C<0, it cannot be larger than the largest possible number representable using {N-bit} 2's complement, so we can write {eqnarray*} -2^N & C & < -2^{N-1} {eqnarray*} We now add 2^N to each part to obtain {eqnarray*} 0 & C + 2^N & < 2^{N-1} {eqnarray*} This range of integers falls within the representable range for {N-bit} 2's complement, so we can replace the middle expression with S (equal to C modulo 2^N) to find that {eqnarray*} 0 & S & < 2^{N-1} {eqnarray*} Thus, if we have an overflow and both A<0 and B<0, the resulting sum S, and condition 1 holds. The proof for the case in which we observe an overflow when both operands are non-negative (A and B) is similar, and leads to condition 2. We again begin with inequalities for A and B: {eqnarray*} 0 & A & < 2^{N-1} 0 & B & < 2^{N-1} {eqnarray*} We add these two inequalities and replace A+B with C to obtain {eqnarray*} 0 & C < & 2^N {eqnarray*} Given that an overflow has occurred, C must fall outside of the representable range. Given that C{}0, it cannot be smaller than the smallest possible number representable using {N-bit} 2's complement, so we can write {eqnarray*} 2^{N-1} & C & < 2^N {eqnarray*} We now subtract 2^N to each part to obtain {eqnarray*} -2^{N-1} & C - 2^N & < 0 {eqnarray*} This range of integers falls within the representable range for {N-bit} 2's complement, so we can replace the middle expression with S (equal to C modulo 2^N) to find that {eqnarray*} -2^{N-1} & S & < 0 {eqnarray*} Thus, if we have an overflow and both A and B, the resulting sum S<0, and condition 2 holds. Thus overflow implies either condition 1 or condition 2, completing our proof.",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the value of S_2 when the counter is in the COUNT A state and HOLD=0?\\n",
"answer": "\nThe value of S_2 when the counter is in the COUNT A state and HOLD=0 is undefined. This is because, as the passage states, overflow occurs when either both operands are negative or both operands are positive. If both operands are negative, then the resulting sum S is equal to C. However, if both operands are positive, then the resulting sum S is less than C. Thus, it is impossible to determine the value of S_2 without knowing the values of both operands."
}
},
{
"textbook-paragraph": "if a chip finishes its work, the chip can turn itself off, saving energy. How do such high-level metrics relate to the problem at hand? Only indirectly in practice. There are too many factors involved to make direct calculations of cost, power, or performance at the level of logic expressions. Finding an { optimal} solution---the best formulation of a specific logic function for a given metric---is often impossible using the computational resources and algorithms available to us. Instead, tools typically use heuristic approaches to find solutions that strike a balance between these metrics. A { heuristic} approach is one that is believed to yield fairly good solutions to a problem, but does not necessarily find an optimal solution. A human engineer can typically impose { constraints}, such as limits on the chip area or limits on the minimum performance, in order to guide the process. Human engineers may also restructure the implementation of a larger design, such as a design to perform floating-point arithmetic, so as to change the logic functions used in the design. { Today, manipulation of logic expressions for the purposes of optimization is performed almost entirely by computers.} Humans must supply the logic functions of interest, and must program the acceptable transformations between equivalent forms, but computers do the grunt work of comparing alternative formulations and deciding which one is best to use in context. Although we believe that hand optimization of Boolean expressions is no longer an important skill for our graduates, we do think that you should be exposed to the ideas and metrics historically used for such optimization. The rationale for retaining this exposure is threefold. First, we believe that you still need to be able to perform basic logic reformulations (slowly is acceptable) and logical equivalence checking (answering the question, ``Do two expressions represent the same function?''). Second, the complexity of the problem is a good way to introduce you to real engineering. Finally, the contextual information will help you to develop a better understanding of finite state machines and higher-level abstractions that form the core of digital systems and are still defined directly by humans today. Towards that end, we conclude this introduction by discussing two metrics that engineers traditionally used to optimize logic expressions. These metrics are now embedded in { computer-aided design} ({ CAD}) tools and tuned to specific underlying technologies, but the reasons for their use are still interesting. The first metric of interest is a heuristic for the area needed for a design. The measurement is simple: count the number of variable occurrences in an expression. Simply go through and add up how many variables you see. Using our example function C, Equation () gives a count of 6, Equation () gives a count of 8, and Equation () gives a count of 24. Smaller numbers represent better expressions, so Equation () is the best choice by this metric. Why is this metric interesting? Recall how gates are built from transistors. An {N-input} gate requires roughly 2N transistors, so if you count up the number of variables in the expression, you get an estimate of the number of transistors needed, which is in turn an estimate for the area required for the design. A variation on variable counting is to add the number of operations, since each gate also takes space for wiring (within as well as between gates). Note that we ignore the number of inputs to the operations, so a {2-input} AND counts as 1, but a {10-input} AND also counts as 1. We do not usually count complementing variables as an operation for this metric because the complements of variables are sometimes available at no extra cost in gates or wires. If we add the number of operations in our example, we get a count of 10 for Equation ()---two ANDs, two ORs, and 6 variables, a count of 12 for Equation ()---three",
"GPT-3-Semantic-Search-Generations": {
"question": " What is the purpose of the HOLD variable?\\n",
"answer": "\nThe HOLD variable is used to save energy. When a chip finishes its work, it can turn itself off, saving energy. This variable allows the chip to turn itself off when it is finished, saving energy."
}
}
]