Diferență între revizuiri ale paginii „Applications 3”
(Nu s-au afișat 11 versiuni intermediare efectuate de același utilizator) | |||
Linia 1: | Linia 1: | ||
− | Behavioral | + | Many ways to describe a module: |
− | + | * ''Behavioral'' description: Uses one or more '''always''' blocks that encloses procedural statements; | |
− | Structural | + | * ''Data-flow'' description: employs parallel continuous assignments ('''assign'''), usually with logic operators; |
− | + | * ''Structural'' description: sub-blocks (module instances, gate primitives) connected together; | |
− | + | * ''Mixed'' description: combines two or all of the above kinds of description; | |
== Exercise 1 == | == Exercise 1 == | ||
− | |||
− | + | Mux 2:1 (two to one multiplexer) is the simplest selection logic circuit. It selects between two inputs, in0 and in1, according to the value of the selection input, s: | |
{| class="wikitable" style="text-align: center; | {| class="wikitable" style="text-align: center; | ||
− | ! scope="col"| | + | ! scope="col"| s |
− | ! scope="col"| | + | ! scope="col"| y |
− | |||
|- | |- | ||
− | |0 || | + | |0 ||'''in0''' |
|- | |- | ||
− | + | |1 ||'''in1''' | |
− | |||
− | |||
− | |||
− | |1 || | ||
|} | |} | ||
+ | [[Fișier: Mux2.png]] | ||
+ | |||
− | + | === 2 to 1 multiplexer, data-flow description === | |
− | Use | + | Use one or more continuous assignments. A ''continuous assignment'' is a single assignment statement attached to an '''assign''' keyword. A continuous assignment updates the value of the RHS variable whenever any variable from the RHS expression changes. The RHS expressions is a logic expression, an expression that employs logic operators. |
Logic expressions employ only logic operators. | Logic expressions employ only logic operators. | ||
Linia 32: | Linia 28: | ||
! scope="col"| operator | ! scope="col"| operator | ||
! scope="col"| function | ! scope="col"| function | ||
+ | ! scope="col"| example | ||
|- | |- | ||
− | |~ ||not | + | |~ ||not||~a |
|- | |- | ||
− | |& ||and | + | |& ||and|| a & b |
|- | |- | ||
− | | | ||or | + | | | ||or|| a | b |
|- | |- | ||
− | |^ ||xor | + | |^ ||xor|| a ^ b |
|} | |} | ||
− | + | <syntaxhighlight lang="Verilog"> | |
+ | module mux2( | ||
+ | input s, | ||
+ | input [1:0] in, | ||
+ | output y | ||
+ | ); | ||
+ | |||
+ | // dataflow description | ||
+ | assign y = (s & in[1]) | (~s & in[0]); | ||
+ | |||
+ | endmodule | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Note:''' The variable whose value is updated through a continuous assignment should be declared of type '''wire'''. | ||
+ | |||
+ | |||
+ | === 2 to 1 multiplexer, behavioral description === | ||
+ | |||
+ | Uses one or more '''always''' blocks. The template of an '''always''' block is: | ||
+ | |||
+ | '''always @('''''sensitivity list''''') begin'''<br /> | ||
+ | ''block of statements''<br /> | ||
+ | '''end''' | ||
+ | |||
+ | For combinational circuits the safest way to declare the sensitivity list is to use the wildcard ('''*'''). | ||
+ | It stands for all variables that appear inside RHS expressions of the '''always''' block. | ||
+ | The statements employed may be assignments, conditional assignments and procedural statements ('''if''', '''case'''). | ||
+ | The '''always''' block of statements is executed whenever any of the variables from the sensitivity list changes its value. The statements are executed in the exact order in which they appear inside the '''always''' block. | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
− | + | module mux2( | |
− | + | input s, | |
+ | input [1:0] in, | ||
+ | output y | ||
+ | ); | ||
+ | |||
+ | // behavioral description with if-else | ||
+ | always @(*) begin | ||
+ | if(s) | ||
+ | y = in[1]; | ||
+ | else | ||
+ | y = in[0]; | ||
+ | end | ||
+ | |||
+ | endmodule | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Bit selection operator ('''[ ]''') is used to select a bit (or a couple of consecutive bits) from a multibit variable. | + | '''Note:''' Any variable that gets its value through assignments inside an '''always''' block must be declared of type '''reg'''. |
− | + | If the variable is also an output of the module, the output is declared as <syntaxhighlight lang="Verilog" inline>output reg</syntaxhighlight>. | |
− | + | ||
+ | '''Note:''' Bit selection operator ('''[ ]''') is used to select a bit (or a couple of consecutive bits) from a multibit variable. '''in[0]''' is bit 0 from the input vector '''in'''. | ||
+ | |||
+ | |||
+ | === 2 to 1 multiplexer, alternative behavioral description === | ||
+ | |||
+ | The same module may be described using different procedural statements. Some descriptions may be higher-level than others. Usually, the higher the level of description, the shorter is the code. | ||
+ | |||
+ | The codes below show three alternative behavioral descriptions for the above multiplexer: | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | // behavioral description with case | ||
+ | always @(*) begin | ||
+ | case(s) | ||
+ | 0: y = in[0]; | ||
+ | 1: y = in[1]; | ||
+ | endcase | ||
+ | end | ||
+ | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
− | + | // behavioral description with conditional assignment | |
− | + | always @(*) begin | |
− | + | y = s ? in[1] : in[0]; | |
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | = | + | <syntaxhighlight lang="Verilog"> |
− | + | // behavioral description with vector selection | |
+ | always @(*) begin | ||
+ | y = in[s]; | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Note:''' The last two alternatives may be also employed in continuous assignments, because they are single statements. For example vector selection may be used inside an '''assign''' instead of an '''always''': <syntaxhighlight lang="Verilog" inline>assign y = in[s];</syntaxhighlight>. | ||
− | |||
− | + | === 2 to 1 multiplexer, structural description: gate-level === | |
− | Verilog gate primitives | + | The ''gate-level description'' is a structural description that uses only logic gates. Verilog language offers predefined logic gates that may be instantiated in structural descriptions. The verilog gate primitives are '''not''', '''and''', '''nand''', '''or''', '''nor''', '''xor''', and '''xnor'''. |
Except for the '''not''' gate, all other primitive gates may have 2, 3 or more inputs. | Except for the '''not''' gate, all other primitive gates may have 2, 3 or more inputs. | ||
Linia 85: | Linia 138: | ||
<syntaxhighlight lang="Verilog" inline>nand g2(dout, d1, d2);</syntaxhighlight> is a '''nand''' gate with dout at output and two wires, d1 and d2, connected to its inputs. | <syntaxhighlight lang="Verilog" inline>nand g2(dout, d1, d2);</syntaxhighlight> is a '''nand''' gate with dout at output and two wires, d1 and d2, connected to its inputs. | ||
− | <syntaxhighlight lang="Verilog" inline>nand g3(dout, d1, d2, d3, d4);</syntaxhighlight> is a '''nand''' gate with dout at output and | + | <syntaxhighlight lang="Verilog" inline>nand g3(dout, d1, d2, d3, d4);</syntaxhighlight> is a '''nand''' gate with dout at output and four inputs, connected to d1, d2, d3 and d4. |
− | [[Fișier: | + | [[Fișier: Mux2a.png]] |
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | module mux2( | ||
+ | input s, | ||
+ | input [1:0] in, | ||
+ | output y | ||
+ | ); | ||
+ | |||
+ | wire s_n; | ||
+ | wire w1; | ||
+ | wire w0; | ||
− | + | // gate-level structural description | |
+ | not (s_n, s); | ||
+ | and (w1, in[1], s); | ||
+ | and (w0, in[0], s_n); | ||
+ | or (y, w1, w0); | ||
− | + | endmodule | |
− | |||
− | |||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | Implement the | + | === 2 to 1 multiplexer, FPGA implementation === |
+ | |||
+ | Implement one of the previous multiplexer descriptions using 2 buttons (BTN0 and BTN1 ) for the inputs in0 and in1, one switch (SW0) for selection, and one LED (LED0) for the multiplexer output (y): | ||
+ | |||
+ | [[Fișier: Dic_lab3_mux_fpga.png]] | ||
− | == Exercise | + | The constraints file sets the connections between the mux ports and the FPGA pins. |
− | + | ||
+ | <syntaxhighlight> | ||
+ | ##Switches | ||
+ | set_property -dict { PACKAGE_PIN V2 IOSTANDARD LVCMOS33 } [get_ports { s }]; #SW 0 | ||
+ | |||
+ | ##Buttons | ||
+ | set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { in[0] }]; #BTN 0 | ||
+ | set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { in[1] }]; #BTN 1 | ||
+ | |||
+ | ##LEDs | ||
+ | set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { y }]; #LED 0 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | == Exercise 2 == | ||
− | + | Write a testbench for the 2:1 multiplexer, using verilog statements to generate all input combinations. There are 3 input bits: one selection bit, and two input bits to select from. Therefore there are possible 8 input combinations. An exhaustive verification should check the output for all those 8 input combinations: | |
− | {| class="wikitable" | + | {| class="wikitable" |
− | ! | + | |- |
− | + | ! s !! in[1] !! in[0] | |
+ | |- | ||
+ | | 0|| 0|| 0 | ||
+ | |- | ||
+ | | 0 || 0|| 1 | ||
+ | |- | ||
+ | | 0|| 1|| 0 | ||
+ | |- | ||
+ | | 0|| 1|| 1 | ||
+ | |- | ||
+ | | 1|| 0|| 0 | ||
+ | |- | ||
+ | | 1|| 0|| 1 | ||
|- | |- | ||
− | | | + | | 1|| 1|| 0 |
|- | |- | ||
− | |1 || | + | | 1|| 1|| 1 |
|} | |} | ||
− | |||
− | ''' | + | A convenient way is to generate those 8 combinations in the order in which they appear in the truth table, starting with '''0 0 0''', continuing with '''0 0 1''', '''0 1 0''', a.s.o. |
− | + | There are many ways to generate such a combination of values for the dut input variables: | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
+ | === simple assignments === | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
− | + | initial begin | |
− | + | {s, a, b} = 3'b000; | |
− | + | #1 {s, a, b} = 3'b001; | |
− | + | #1 {s, a, b} = 3'b010; | |
− | + | #1 {s, a, b} = 3'b011; | |
+ | #1 {s, a, b} = 3'b100; | ||
+ | #1 {s, a, b} = 3'b101; | ||
+ | #1 {s, a, b} = 3'b110; | ||
+ | #1 {s, a, b} = 3'b111; | ||
+ | #1 $stop; | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | === for statement | + | === for statement === |
− | + | Its template is: | |
'''for('''''initial_assignment''''';''' ''expression''''';''' ''step_assignment''''')''' ''block of statements''; | '''for('''''initial_assignment''''';''' ''expression''''';''' ''step_assignment''''')''' ''block of statements''; | ||
Linia 145: | Linia 237: | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
+ | integer index; | ||
initial begin | initial begin | ||
{s, a, b} = 0; | {s, a, b} = 0; | ||
Linia 150: | Linia 243: | ||
#1 {s, a, b} = {s, a, b} + 1; | #1 {s, a, b} = {s, a, b} + 1; | ||
end | end | ||
+ | #1 $stop; | ||
+ | end | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | === repeat statement === | ||
+ | |||
+ | Its syntax is '''repeat''' (''number of times'') ''block of statements'' | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | initial begin | ||
+ | {s, a, b} = 0; | ||
+ | repeat (8) #1 {s, a, b} = {s, a, b} + 1; | ||
+ | #1 $stop; | ||
end | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | + | == Exercise 3 == | |
+ | |||
+ | The half-adder is the simplest, 1-bit, adder. It implements the addition of two bits. | ||
+ | |||
+ | {| class="wikitable" style="text-align: center; | ||
+ | ! scope="col"| a | ||
+ | ! scope="col"| b | ||
+ | ! scope="col"| s | ||
+ | |- | ||
+ | |0 ||0 || 0 0 | ||
+ | |- | ||
+ | |0 ||1 || 0 1 | ||
+ | |- | ||
+ | |1 ||0 || 0 1 | ||
+ | |- | ||
+ | |1 ||1 || 1 0 | ||
+ | |} | ||
+ | |||
+ | [[Fișier: Dic_lab2_adder.png]] | ||
+ | |||
+ | This table may be read either as the addition table, with '''s''' considered as a base-2 number value, or it may be read as a truth table, if '''s''' is viewed as a pair of two logic values. Each bit of '''s''' may be computed as a logic function with two arguments. | ||
+ | |||
+ | |||
+ | === half adder, data-flow description === | ||
+ | |||
+ | Use data flow description with '''assign''' statement for each output. They are concurrent assignments: in simulation they are evaluated in parallel, mimicking the parallelism of the real circuits. | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | // data-flow description | ||
+ | assign s[0] = a ^ b; | ||
+ | assign s[1] = a & b; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Note:''' Despite '''s''' being declared as one variable, its bits are separately updated by concurrent assignments. | ||
+ | |||
+ | |||
+ | === half adder, structural description === | ||
− | + | [[Fișier: half_adder.png]] | |
− | + | Using gate primitives, a possible structural description of the half-adder may be: | |
− | + | <syntaxhighlight lang="Verilog"> | |
+ | // gate-level description | ||
+ | xor g1(s[0], a, b); | ||
+ | and g2(s[1], a, b); | ||
+ | </syntaxhighlight> | ||
− | |||
− | == Exercise | + | == Exercise 4 == |
− | === 4 to 1 multiplexer | + | === 4 to 1 multiplexer, behavioral description === |
[[Fișier: mux4.png]] | [[Fișier: mux4.png]] | ||
Linia 182: | Linia 326: | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
− | case(s) | + | always @(*) begin |
− | + | case(s) | |
− | + | 0: y = in[0]; | |
− | + | 1: y = in[1]; | |
− | + | 2: y = in[2]; | |
− | endcase | + | 3: y = in[3]; |
+ | endcase | ||
+ | end | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | == Exercise | + | '''s''' is a two-bit variable, therefore it may take values from the integer set {0, 1, 2, 3}. |
− | === 4 to 1 multiplexer | + | |
+ | '''Note:''' The '''case''' statement employed for a combinational logic circuit description SHOULD update the variable it controls for any possible value of the ''selectVariable''. | ||
+ | |||
+ | '''Note:''' As in Exercise 1, a much more compact description is possible with bit selection, <syntaxhighlight lang="Verilog" inline>assign y = in[s];</syntaxhighlight>. | ||
+ | |||
+ | == Exercise 5 == | ||
+ | === 4 to 1 multiplexer, structural description === | ||
− | [[Fișier: | + | [[Fișier: mux4b.png]] |
− | + | Design the 4 to 1 multiplexer using three instances of the 2 to 1 multiplexer (from Exercise 1). | |
Be careful to distinctly name each instance and each internal wire! | Be careful to distinctly name each instance and each internal wire! |
Versiunea curentă din 13 martie 2023 10:00
Many ways to describe a module:
- Behavioral description: Uses one or more always blocks that encloses procedural statements;
- Data-flow description: employs parallel continuous assignments (assign), usually with logic operators;
- Structural description: sub-blocks (module instances, gate primitives) connected together;
- Mixed description: combines two or all of the above kinds of description;
Exercise 1
Mux 2:1 (two to one multiplexer) is the simplest selection logic circuit. It selects between two inputs, in0 and in1, according to the value of the selection input, s:
s | y |
---|---|
0 | in0 |
1 | in1 |
2 to 1 multiplexer, data-flow description
Use one or more continuous assignments. A continuous assignment is a single assignment statement attached to an assign keyword. A continuous assignment updates the value of the RHS variable whenever any variable from the RHS expression changes. The RHS expressions is a logic expression, an expression that employs logic operators. Logic expressions employ only logic operators.
operator | function | example |
---|---|---|
~ | not | ~a |
& | and | a & b |
| | or | a | b |
^ | xor | a ^ b |
module mux2(
input s,
input [1:0] in,
output y
);
// dataflow description
assign y = (s & in[1]) | (~s & in[0]);
endmodule
Note: The variable whose value is updated through a continuous assignment should be declared of type wire.
2 to 1 multiplexer, behavioral description
Uses one or more always blocks. The template of an always block is:
always @(sensitivity list) begin
block of statements
end
For combinational circuits the safest way to declare the sensitivity list is to use the wildcard (*). It stands for all variables that appear inside RHS expressions of the always block. The statements employed may be assignments, conditional assignments and procedural statements (if, case). The always block of statements is executed whenever any of the variables from the sensitivity list changes its value. The statements are executed in the exact order in which they appear inside the always block.
module mux2(
input s,
input [1:0] in,
output y
);
// behavioral description with if-else
always @(*) begin
if(s)
y = in[1];
else
y = in[0];
end
endmodule
Note: Any variable that gets its value through assignments inside an always block must be declared of type reg.
If the variable is also an output of the module, the output is declared as output reg
.
Note: Bit selection operator ([ ]) is used to select a bit (or a couple of consecutive bits) from a multibit variable. in[0] is bit 0 from the input vector in.
2 to 1 multiplexer, alternative behavioral description
The same module may be described using different procedural statements. Some descriptions may be higher-level than others. Usually, the higher the level of description, the shorter is the code.
The codes below show three alternative behavioral descriptions for the above multiplexer:
// behavioral description with case
always @(*) begin
case(s)
0: y = in[0];
1: y = in[1];
endcase
end
// behavioral description with conditional assignment
always @(*) begin
y = s ? in[1] : in[0];
end
// behavioral description with vector selection
always @(*) begin
y = in[s];
end
Note: The last two alternatives may be also employed in continuous assignments, because they are single statements. For example vector selection may be used inside an assign instead of an always: assign y = in[s];
.
2 to 1 multiplexer, structural description: gate-level
The gate-level description is a structural description that uses only logic gates. Verilog language offers predefined logic gates that may be instantiated in structural descriptions. The verilog gate primitives are not, and, nand, or, nor, xor, and xnor. Except for the not gate, all other primitive gates may have 2, 3 or more inputs.
All gate primitives are instantiated using the same template: gatePrimitiveType myGate(outputConnection, inputConnection1, inputConnection2 ...) as in the following examples:
not g1(dout, din);
is a not gate with dout at output and din connected at its input.
nand g2(dout, d1, d2);
is a nand gate with dout at output and two wires, d1 and d2, connected to its inputs.
nand g3(dout, d1, d2, d3, d4);
is a nand gate with dout at output and four inputs, connected to d1, d2, d3 and d4.
module mux2(
input s,
input [1:0] in,
output y
);
wire s_n;
wire w1;
wire w0;
// gate-level structural description
not (s_n, s);
and (w1, in[1], s);
and (w0, in[0], s_n);
or (y, w1, w0);
endmodule
2 to 1 multiplexer, FPGA implementation
Implement one of the previous multiplexer descriptions using 2 buttons (BTN0 and BTN1 ) for the inputs in0 and in1, one switch (SW0) for selection, and one LED (LED0) for the multiplexer output (y):
The constraints file sets the connections between the mux ports and the FPGA pins.
##Switches
set_property -dict { PACKAGE_PIN V2 IOSTANDARD LVCMOS33 } [get_ports { s }]; #SW 0
##Buttons
set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { in[0] }]; #BTN 0
set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { in[1] }]; #BTN 1
##LEDs
set_property -dict { PACKAGE_PIN G1 IOSTANDARD LVCMOS33 } [get_ports { y }]; #LED 0
Exercise 2
Write a testbench for the 2:1 multiplexer, using verilog statements to generate all input combinations. There are 3 input bits: one selection bit, and two input bits to select from. Therefore there are possible 8 input combinations. An exhaustive verification should check the output for all those 8 input combinations:
s | in[1] | in[0] |
---|---|---|
0 | 0 | 0 |
0 | 0 | 1 |
0 | 1 | 0 |
0 | 1 | 1 |
1 | 0 | 0 |
1 | 0 | 1 |
1 | 1 | 0 |
1 | 1 | 1 |
A convenient way is to generate those 8 combinations in the order in which they appear in the truth table, starting with 0 0 0, continuing with 0 0 1, 0 1 0, a.s.o. There are many ways to generate such a combination of values for the dut input variables:
simple assignments
initial begin
{s, a, b} = 3'b000;
#1 {s, a, b} = 3'b001;
#1 {s, a, b} = 3'b010;
#1 {s, a, b} = 3'b011;
#1 {s, a, b} = 3'b100;
#1 {s, a, b} = 3'b101;
#1 {s, a, b} = 3'b110;
#1 {s, a, b} = 3'b111;
#1 $stop;
end
for statement
Its template is:
for(initial_assignment; expression; step_assignment) block of statements;
The foor loop is repeated until the expression evaluates true. The simplest for statement uses an integer index that is incremented at the end of each iteration. The for loop below generates all combinations from 000 to 111 for tree logic variables, s, a and b. The index must be declared as a variable of type integer.
integer index;
initial begin
{s, a, b} = 0;
for(index = 0; index < 8; index = index + 1) begin
#1 {s, a, b} = {s, a, b} + 1;
end
#1 $stop;
end
repeat statement
Its syntax is repeat (number of times) block of statements
initial begin
{s, a, b} = 0;
repeat (8) #1 {s, a, b} = {s, a, b} + 1;
#1 $stop;
end
Exercise 3
The half-adder is the simplest, 1-bit, adder. It implements the addition of two bits.
a | b | s |
---|---|---|
0 | 0 | 0 0 |
0 | 1 | 0 1 |
1 | 0 | 0 1 |
1 | 1 | 1 0 |
This table may be read either as the addition table, with s considered as a base-2 number value, or it may be read as a truth table, if s is viewed as a pair of two logic values. Each bit of s may be computed as a logic function with two arguments.
half adder, data-flow description
Use data flow description with assign statement for each output. They are concurrent assignments: in simulation they are evaluated in parallel, mimicking the parallelism of the real circuits.
// data-flow description
assign s[0] = a ^ b;
assign s[1] = a & b;
Note: Despite s being declared as one variable, its bits are separately updated by concurrent assignments.
half adder, structural description
Using gate primitives, a possible structural description of the half-adder may be:
// gate-level description
xor g1(s[0], a, b);
and g2(s[1], a, b);
Exercise 4
4 to 1 multiplexer, behavioral description
case instruction. Selects between multiple cases. Template
case(selectVariable)
value1 : instruction block 1
value2 : instruction block 2
a.s.o.
endcase
value1, value2 a.s.o. are integer values of the selectVariable
always @(*) begin
case(s)
0: y = in[0];
1: y = in[1];
2: y = in[2];
3: y = in[3];
endcase
end
s is a two-bit variable, therefore it may take values from the integer set {0, 1, 2, 3}.
Note: The case statement employed for a combinational logic circuit description SHOULD update the variable it controls for any possible value of the selectVariable.
Note: As in Exercise 1, a much more compact description is possible with bit selection, assign y = in[s];
.
Exercise 5
4 to 1 multiplexer, structural description
Design the 4 to 1 multiplexer using three instances of the 2 to 1 multiplexer (from Exercise 1).
Be careful to distinctly name each instance and each internal wire!