Diferență între revizuiri ale paginii „Applications 3”

De la WikiLabs
Jump to navigationJump to search
 
(Nu s-au afișat 6 versiuni intermediare efectuate de același utilizator)
Linia 1: Linia 1:
Behavioral descriptions, continuous assignment, conditional instructions, use of blocks '''always''' for describing combinational circuits.
+
Many ways to describe a module:
 
+
* ''Behavioral'' description: Uses one or more '''always''' blocks that encloses procedural statements;
Structural descriptions, logic gates, verilog gate primitives.
+
* ''Data-flow'' description: employs parallel continuous assignments ('''assign'''), usually with logic operators;
 
+
* ''Structural'' description: sub-blocks (module instances, gate primitives) connected together;
Exhaustive verification. Loop statements in testbenches.
+
* ''Mixed'' description: combines two or all of the above kinds of description;
  
 
== Exercise 1 ==
 
== Exercise 1 ==
=== half adder - gate-level description ===
 
  
The half-adder is the simplest, 1-bit, adder. It implements the addition of two bits.
+
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"| a
+
! scope="col"| s
! scope="col"| b
+
! scope="col"| y
! scope="col"| c
 
 
|-
 
|-
|0 ||0 || 0 0
+
|0 ||'''in0'''
 
|-
 
|-
|0 ||1 || 0 1
+
|1 ||'''in1'''
|-
 
|1 ||0 || 0 1
 
|-
 
|1 ||1 || 1 0
 
 
|}
 
|}
 +
[[Fișier: Mux2.png]]
 +
  
[[Fișier: app2_sum.png]]
+
=== 2 to 1 multiplexer, data-flow description ===
  
Use data flow description (a simpler kind of behavioral description that uses logic expressions).
+
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
 
|}
 
|}
  
One '''assign''' instruction for each output. Concurrent assignments (in simulation they are evaluated in parallel, mimicking the parallelism of the real circuits)
+
<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 />
 +
&nbsp;&nbsp;''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">
assign c[0] = a ^ b;
+
module mux2(
assign c[1] = a & b;
+
    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 c is declared as a 2 bit output, each of its bits may be separately controlled. The index must be a positive integer in the range set when the variable was declared.
+
If the variable is also an output of the module, the output is declared as <syntaxhighlight lang="Verilog" inline>output reg</syntaxhighlight>.
If myVariable was declared of type <syntaxhighlight lang="Verilog" inline>output [7:0]</syntaxhighlight>, then the integer used for selection must not exceed 7.
+
 
 +
'''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>
  
=== repeat statement in testbenches ===
 
An ''exahaustive test'' is a test that generates all possible combinations of values for the inputs of the dut.
 
Write a testbench for the half-adder that uses a '''repeat''' statement to generate all input combinations, and a concatenation operator that makes possible to update two or more variables at the same time.
 
  
 
<syntaxhighlight lang="Verilog">
 
<syntaxhighlight lang="Verilog">
initial begin
+
// behavioral description with conditional assignment
     {a, b} = 0;
+
always @(*) begin
    repeat (4) #1 {a, b} = {a, b} + 1;
+
     y = s ? in[1] : in[0];  
 
end
 
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Some remarks:
 
* There is no increment operator in verilog.
 
* Adding 1 to 3 on 2 bits turns around to 0.
 
* A delay may precede a statement.
 
  
== Exercise 2 ==
+
<syntaxhighlight lang="Verilog">
=== 1-bit half adder - structural description ===
+
// 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>.
  
Work on the same project as that of Exercise 1. You need only to modify the description of the half-adder module.
 
  
'''Gate-level description''' = a structural description that uses only logic gates.
+
=== 2 to 1 multiplexer, structural description: gate-level ===
  
Verilog gate primitives: '''not''', '''and''', '''nand''', '''or''', '''nor''', '''xor''' and '''xnor'''.
+
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 87: Linia 140:
 
<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.
 
<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: half_adder.png]]
+
[[Fișier: Mux2a.png]]
 +
 
 +
<syntaxhighlight lang="Verilog">
 +
module mux2(
 +
    input s,
 +
    input [1:0] in,
 +
    output y
 +
);
 +
 
 +
wire s_n;
 +
wire w1;
 +
wire w0;
  
Using gate primitives, a possible structural description of the half-adder may be:
+
// gate-level structural description
 +
not (s_n, s);
 +
and (w1, in[1], s);
 +
and (w0, in[0], s_n);
 +
or  (y, w1, w0);
  
<syntaxhighlight lang="Verilog">
+
endmodule
xor g1(c[0], a, b);
 
and g2(c[1], a, b);
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Recompile the design file (from the simulator), and restart simulation.
 
  
Implement the design using 2 switches (SW0 and SW1) as inputs a and b, and two LEDs (LED0 and LED1) to show the result, c.
+
=== 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 3 ==
+
The constraints file sets the connections between the mux ports and the FPGA pins.
=== 2 to 1 multiplexer, behavioral description ===
+
 
 +
<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 ==
  
The simplest selection logic circuit. It selects between two inputs, in0 and in1, based on the value of the selection input, s:
+
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" style="text-align: center;
+
{| class="wikitable"
! scope="col"| s
+
|-
! scope="col"| c
+
! s !! in[1] !! in[0]
 +
|-
 +
| 0|| 0|| 0
 +
|-
 +
| 0 || 0|| 1
 +
|-
 +
| 0|| 1|| 0
 +
|-
 +
| 0|| 1|| 1
 +
|-
 +
| 1|| 0|| 0
 +
|-
 +
| 1|| 0|| 1
 
|-
 
|-
|0 ||'''in0'''
+
| 1|| 1|| 0
 
|-
 
|-
|1 ||'''in1'''
+
| 1|| 1|| 1
 
|}
 
|}
[[Fișier: Mux2.png]]
 
  
'''always''' block. Used for behavioral descriptions. Template:
+
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:
'''always @('''''sensitivity list''''') begin'''<br />
 
&nbsp;&nbsp;''block of instructions''<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 on RHS expressions and in evaluation expressions.
 
  
 +
=== simple assignments ===
 
<syntaxhighlight lang="Verilog">
 
<syntaxhighlight lang="Verilog">
always @(*) begin
+
initial begin
  if(s)
+
      {s, a, b} = 3'b000;
     c = in[1];
+
    #1 {s, a, b} = 3'b001;
  else
+
    #1 {s, a, b} = 3'b010;
     c = in[0];
+
    #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>
  
Any variable that gets 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>.
 
  
=== for statement in testbenches ===
+
=== for statement ===
Write a testbench using a '''for''' statement to generate all input combinations. Its template is:
+
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 4 ==
 
=== 2 to 1 multiplexer - gate-level description ===
 
  
Work on the same project as that of Exercise 3. You need only to modify the description of the 2 to 1 multiplexer module.  
+
== 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 ===
  
Implement the 2 to 1 multiplexer using only verilog gate primitives. For simulation you may reuse the testbench from Exercise 3 (copy its file into the directory of this project and set it as the testbench). Change the type of the multiplexer's instance in the testbench, if it is different from Exercise 3.
+
[[Fișier: half_adder.png]]
  
[[Fișier: Mux2a.png]]
+
Using gate primitives, a possible structural description of the half-adder may be:
  
Recompile the design file (from the simulator), and restart simulation.
+
<syntaxhighlight lang="Verilog">
 +
// gate-level description
 +
xor g1(s[0], a, b);
 +
and g2(s[1], a, b);
 +
</syntaxhighlight>
  
Implement the design 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 (c).
 
  
== Exercise 5 ==
+
== Exercise 4 ==
=== 4 to 1 multiplexer - behavioral description ===
+
=== 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
  0: c = in[0];
+
    case(s)
  1: c = in[1];
+
        0: y = in[0];
  2: c = in[2];
+
        1: y = in[1];
  3: c = in[3];
+
        2: y = in[2];
endcase  
+
        3: y = in[3];
 +
    endcase
 +
end
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Exercise 6 ==
+
'''s''' is a two-bit variable, therefore it may take values from the integer set {0, 1, 2, 3}.
=== 4 to 1 multiplexer - structural description ===
+
 
 +
'''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: mux4b.png]]
 
[[Fișier: mux4b.png]]
  
Implement the 4 to 1 multiplexer using three instances of the 2 to 1 multiplexer (add to the project the file of that module either from Exercise 3, or Exercise 4) and a primitive gate.
+
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

Mux2.png


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.

Mux2a.png

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):

Dic lab3 mux fpga.png

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

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.

// 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

Half adder.png

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

Mux4.png

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

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!