EE 361 Homework 9

Due: Mar. 20 Fri.

Problem A. (6 pts) This is a Verilog HDL assignment. Verilog HDL is a hardware description language. It has the same function as a state diagram or an ASM chart because it is used to describe digital circuits. Verilog HDL is similar to a programming language, and is similar to C in syntax. But it is not the same. C describes a process that is to be executed by a computer. A Verilog HDL program describes a hardware circuit which can be simulated and implemented using real circuits.

For this assignment, you will design a counter circuit. You will use the Veriwell simulator which can be found on the Macintosh computers in Holmes 483. You can also download your own Veriwell simulator (see our EE 361 Homepage for the link). The simulator can be used to write, edit, and simulate your programs.

This assignment is organized as follows

  1. Description of the counter, how it's made up of a register circuit and an ALU circuit.
  2. Verilog HDL implementation of the register circuit: Version 1.
  3. Verilog HDL implementation of the register circuit: Versions 2 and 3.
  4. Testing of register circuit, Version 3. There is also a task which you do not turn in, but highly recommended that you do.
  5. Verilog HDL implementation of ALU. There is also a task which you do not turn in, but highly recommended that you do.
  6. Final task that you turn in, which is to put together a Verilog HDL implementation of the counter along with a tester.

1. Decription of Counter Circuit

The counter is a 2-bit up/down counter with

The output (q1,q0) is equal to the state of the counter, i.e., (q1,q0) is the current count. The counter is positive edge triggered, and has four possible functions: count-up, count-down, hold, and clear. Counting-up means that the state will increment by one. Counting-down means that the state will decrement by one. The function table for the counter is

      s1 s0    function
      -----------------
       0  0    hold
       0  1    count-up
       1  0    count-down
       1  1    clear

There are many ways to implement the counter. We could use a register (e.g., 2 D flip flops) and a ROM, or we could use a register, 2-input NANDs, and voltage inverters. For this example, we will use components such as multiplexers, adders/subtracters, and a register. More specifically, the counter will have the following block diagram

            +-------------+
            |    +------+ |
            V    V      | |
         +-----------+  | |
 s1,s0 ->|    ALU    |  | |
         +-----------+  | |
            |    |      | |
            V    V      | |
         +-----------+  | |
  clk -->| 2-bit Reg |  | |
         +-----------+  | |
            |    |      | |
            |    +------+ |
            +-------------+

where the ALU has the multiplexers and adders/subtractors.

2. Verilog HDL Implementation of Register: Version 1

Let's write some verilog HDL for the 2-bit register. The register is a set of two D flip flops. At every positive clock edge, the flip flops load at their inputs. The inputs will be labeled d1, d0 as shown below.
            d1   d0 
            |    |      
            V    V     
         +-----------+  
  clk -->| 2-bit Reg |  
         +-----------+  
            |    |      
            q1   q0 

The following is Verilog HDL code that implements the register


//   
//  Two-bit Register
//  

module reg2(q1, q0, d1, d0, clk);

input    d1, d0, clk;     //  Declaration of the input/output ports
output   q1, q0;

reg      Q1, Q0;          //  Q1, Q0 are variables that will be used
			  //  to store the state.

initial  Q1 = 0;	  //  This initializes the state (Q1,Q0) to (0,0).
initial  Q0 = 0;          //  Otherwise, the state will be initialized to "xx"

always @(posedge clk) 	  //  The state is updated at the positive clock
	Q1 = d1;	  //  edge
always @(posedge clk) 	  
	Q0 = d0;	  

assign	q1 = Q1;	  //  The output ports are connected to the regs.
assign  q0 = Q0;

endmodule

Let's figure out what's going on with the code starting from the top.

The lines

//   
//  Two-bit Register
//  
are comment lines. The double slash (//) means that everything to the right is a comment. (This is the way comments are done in the programming language C++).

The next line

module reg2(q1, q0, d1, d0, clk);
is a module declaration, which starts with "module" and ends with a semicolon. Here, a hardware module is defined with input and output ports, q1, q0, d1, d0, and clk, which are listed in the parentheses. These ports are the connections into and out of the module. For example, a NAND circuit has two inputs and one output. If the NAND were a module, then these inputs and outputs would correspond to input and output ports.

Note that the module is given the name "reg2". Thus, "reg2" is a name given to the module, just as "7400" is a name given to a chip with four 2-input NANDs. The general format of a module declaration is

module module_name(port_list);
where the port list is optional. Remember this format because if you deviate from it, you will get a syntax error. Also, see page 8 of the Verilog HDL handbook for a description of module structure.

The next set of lines are the port declarations

input    d1, d0, clk;     //  Declaration of the input/output ports
output   q1, q0;

This defines which ports are to be used as inputs and outputs. Notice that each line is terminated by a semicolon. Also note that a comment may be appended after a semicolon.

The next line declares variables

reg      Q1, Q0;          
Here, Q1 and Q0 are declared to be 1-bit registers (also note the semicolon terminating the line, and the comma separating variables). There are two kinds of variables: registers and wires (wires are not shown in this example). Registers are just like variables in C since they can store values. Wires can't store anything, but are used to connect things together (just like real wires). Registers and wires can take on the following values: 0, 1, x (unknown), and z (high impedence).

In the next couple of lines, we initialize the registers

initial  Q1 = 0;	  //  This initializes the state (Q1,Q0) to (0,0).
initial  Q0 = 0;          //  Otherwise, the state will be initialized to "xx"
The "initial" statement is one of two procedural statements, where the other is "always". Procedural statements are used whenever registers are updated. The statement "initial" is used to describe how a register should be set initially (at time 0). In other words, it is used to initialize the value of the register. The statement "always" is used to describe how a register is updated while the module is running. We'll discuss "always" a little bit later.

The lines

initial  Q1 = 0;	  //  This initializes the state (Q1,Q0) to (0,0).
initial  Q0 = 0;          //  Otherwise, the state will be initialized to "xx"
say that Q1 and Q0 should be initialized to 0. The lines are to be executed in parallel. Thus, Q1 and Q0 are cleared to zero simultaneously. It is important to note that all procedure statements are excecuted in parallel. You can think of each procedure statement as being a piece of hardware, and that hardware components run in parallel. This is different from C language where you would expect "Q1 = 0" to be executed before "Q0 = 0".

Another way to do the initialization is use a single initial statement

initial 
	begin
	Q1 = 0;
	Q0 = 0;
	end
Note that the "begin-end" statements denote what is to be executed for the "initial" statement. In this case, everything between begin-end is executed in sequence. Thus, Q1 = 0 is executed before Q0 = 0, so it's more like C.

In general, "initial" statements have the following form.

initial register = expression;
or
initial
	begin
	register1 = expression1;
	register2 = expression2;
	     .
	     .
	     .
	end
where the expressions are mathematical expressions composed of variables (i.e., registers, wires, or ports), parentheses, and the following operators Note that the left hand side of "=" must be a register. A wire won't work.

Okay, let's get back to the "reg2" Verilog HDL code. The next set of lines is

always @(posedge clk) 	  //  The state is updated at the positive clock
	Q1 = d1;	  //  edge
always @(posedge clk) 	  
	Q0 = d0;	  
These are examples of "always" procedure statements. They update the registers Q1 and Q0 with the values d1 and d0, respectively, when there is a positive edge on the clock signal "clk".

To understand these statements, let's start from a simpler version. Consider the statement

always Q1 = d1;
This means that the statement "Q1 = d1" is constantly (or always) being evaluated. So this is like a wire. For the reg2 application, this isn't good because we'd like Q1 to be updated only at positive clock edges. To accomplish this we can introduce an event into the statement (see page 21 of Verilog HDL handbook for a description of events):
always @clk Q1 = d1;
Here the event is "@clk". This means that the statement "Q1 = d1" is executed whenever "clk" changes value. This is closer to what we want but not exactly. The problem is that "clk" will change values at both the positive and negative clock edges, but we don't want a change at the negative edge. To have "Q1 = d1" executed only at the positive clock edge, we use the statement
always @(posedge clk) Q1 = d1;

Note that "always" is a procedure statement just like "initial". So we have the following:

Let's get back to the "reg2" code. The next couple of lines are

assign	q1 = Q1;	  //  The output ports are connected to the regs.
assign  q0 = Q0;
The keyword assign means that these are continuous assignment statements. These are used to update wires and output ports (which act like wires). So these statements are constantly being evaluated, and are being evaluated in parallel.

The general form is

assign wire_or_port = expression;
You cannot use begin-end with a continous assignment. In other words,
assign 
	begin
	  .
  	  .
	end
is BAD. Begin-end can only be used with the procedure statements "always" and "initial". Remember that to update wires/ports use "assign", and to update registers use "initial" and "always".

The final line of the "reg2" code is

endmodule
which terminates the module. We're done with describing the reg2 module.

3.1. Verilog HDL Implementation of Register: Version 2

This version will call another module called Dff, which is an implementation of a D flip flop.
// 
//  Version 2 of reg2
//

module reg2(q1, q0, d1, d0, clk);

input	d1, d0, clk;
output	q1, q0;

Dff	dff1(q1,d1,clk);
Dff	dff0(q0,d0,clk);

endmodule

//  
//  D flip flop module
//

module Dff(q,d,clk)

input 	d, clk;
output 	q;

reg	Q;		//  This is where the state is stored.

initial	Q = 0;

always @(posedge clk) Q = d;  // Update Q on pos. clock edge.

assign  q = Q;		//  Connect Q to the output port of D flip flop.

endmodule

This variation of "reg2" has the two lines

Dff	dff1(q1,d1,clk);
Dff	dff0(q0,d0,clk);

These are similar to function calls in C. However, they're more like macro calls which we'll illustrate a bit later. The general form of these calls are

Module_type  name(list_of_inputs_and_outputs);

The "Module_type" (e.g., the Dff module) has to be defined somewhere. The "name" (e.g., dff1) is some distinct label given to the instance of the module type. The list of inputs and outputs are registers, wires, or ports. Note that position is important. For example, in the case of the Dff module, the first position corresponds to the output of the flip flop, the second position corresponds to the D input, and the third position is the clock input. Thus, if the module were to have its variables renamed as

//  
//  D flip flop module
//
module Dff(frank,clk,Dee)

input 	clk, Dee;
output 	frank;

reg	Q;		//  This is where the state is stored.

initial	Q = 0;

always @(posedge Dee) Q = clk;

assign  frank = Q;

endmodule

then it would still work (here, the Dff module was changed only by replacing "q" with "frank", "d" with "clk", and "clk" with "Dee").

To illustrate what the idea of a "macro" call, think of having the lines

Dff	dff1(q1,d1,clk);
Dff	dff0(q0,d0,clk);

in "reg2" being replaced by lines of code in the Dff module. In other words, the code for "reg2"
module reg2(q1, q0, d1, d0, clk);

input	d1, d0, clk;
output	q1, q0;

Dff	dff1(q1,d1,clk);
Dff	dff0(q0,d0,clk);

endmodule
after the macro expansion would look like
module reg2(q1, q0, d1, d0, clk);

input	d1, d0, clk;
output	q1, q0;

reg	Q.1;		

initial	Q.1 = 0;

always @(posedge clk) Q.1 = d1;

assign  q1 = Q.1;

reg	Q.0;		

initial	Q.0 = 0;

always @(posedge clk) Q.0 = d0;

assign  q0 = Q.0;

endmodule

3.2. Verilog Implementation of Register: Version 3

This implementation uses bit arrays.


//   
//  Version 3 of reg2
//  

module reg2(q, d, clk);

input [1:0] d;		  // Declaration of input/output ports.
input clk;     
output [1:0] q;

reg [1:0]  Q;          	  //  Q1, Q0 are variables that will be used
			  //  to store the state.
initial  Q = 0;	  	  //  This initializes the state (Q1,Q0) to (0,0).

always @(posedge clk) 	  //  The state is updated at the positive clock
	Q = d;	  	  //  edge

assign	q = Q;	  	  //  The output ports are connected to the regs.

endmodule
Here, register "Q" and ports "q" and "d" are 2-bit arrays with indices ranging from 1 to 0. Not that all updates are bitwise updates. Note that to call "reg2", the inputs and outputs have to be 2-bit arrays for "q" and "d". See page 11 of Verilog HDL handbook for more on arrays.

See page 7 on how to define constants. For example, instead of

initial Q = 0;
we could have
initial Q = 2'b00;
which means set Q to a 2-bit binary number 00.

Whew! Let's take a break.

4. Tester for Register (Version 3)

Now that we've got the register figured out, we should proceed with the ALU block, right? Wrong! To be on the safe side we should test the register on Veriwell. This not only tests our design but also tests our knowledge of the Verilog HDL language and the Veriwell simulator.

What happens if we type in module reg2 and let it run on Veriwell? Veriwell will compile the code and check for errors. If there are any, it'll point them out and we can correct them. Now suppose we have them corrected and then run reg2, what can we expect? Nothing because the code is not required to print anything out. In addition, reg2 requires a clock signal -- it doesn't have its own clock.

We need another module which will run reg2 and print out values that we can use to validate reg2. This is our main module. Typically, Verilog HDL programs will have a main module. These modules do not have any ports, since they are not called by any other module. They supply the clock signal, connect modules together, and display important data. This module is like a work bench in lab, where you have voltage supplies, clock generators, and probes.

We'd like our main module to supply a clock signal, input various values into reg2, and display the values in reg2. The following is a main module "test". We'll go through it shortly.

module test;

reg  [1:0] d;		// Inputs to reg2a
wire [1:0] q;		// These wires connect to the output values of reg2.

reg	clock;		// Clock signal is stored in this register.

//
// Clock generator
//

initial clock = 0;	// Initialize clock signal to 0
always #1 clock = ~clock;  // Invert signal every time unit.  Thus,
			//	clock period is 2 time units.
//
// Displaying data in the simulation
//

initial
	begin
	$display("Time   clock   d    q");  // $display is like a printf
					    //   statement
	$monitor("%d %b %b %b",$time,clock,d,q);
					    // $monitor is also like printf
					    //   but it will print when any
					    //   of its variables changes
	end				    //   values.

// 
//  "Driver" for reg2 -- it inputs various types of values.
//

initial
	begin
	d = 0;		//  Initially set the input of reg2 to 00
	#4 d = 1;	//  After a delay of 4 time units, set the
			//     input of reg2 to 01
	#4 d = 2;	//  After another delay of 4 time units, set
			//     the input of reg2 to 10
	#4 d = 3;	//  After yet another delay of 4 time units, set
			//     the input of reg2 to 11.
	#4 $stop;	//  Halts simulation after 4 more time units.
	end
//
//  Datapath
//     Here we assume version 3 of reg2 (bit array version).

reg2	reg2a(q, d, clock);

endmodule

Note that we have some new stuff in this module, so let's go through it starting from the top. The first few lines are

reg  [1:0] d;		// Inputs to reg2a
wire [1:0] q;		// These wires connect to the output values of reg2.

reg	clock;		// Clock signal is stored in this register.
These are related to the second to the last line
reg2	reg2a(q, d, clock);
which induces an instance of "reg2" that is labeled "reg2a". reg2a needs to input a clock, input its parallel load, and output its state q. The register "clock" will be used as the clock input, and the 2-bit register "d" will be used as the load inputs. By varying the values of "d" we can load different values into "reg2a". The 2-bit wire variable "q" is used to connect "reg2a"'s outputs to the "test" module.

The next couple of lines are used to manage the clock


initial clock = 0;	
always #1 clock = ~clock;  

The first statement initializes the clock signal to 0. The second statement toggles the clock every time unit. To better understand this statement, realize that Veriwell simulates the circuit according to some simulated time line. The exact simulated time is in some variable within the simulator. Its value can be accessed through the variable "$time". This simulated time is an integer value and indicates the number of time units that have elapsed. These time units could represent real time such as microseconds or nanoseconds.

The statement


#1 clock = ~clock;  

means that the statement "clock = ~clock" will be executed after 1 time unit delay. Thus, "#1" corresponds to a 1 time unit delay. The general form of a time delay is "#delay" where "delay" is a positive integer constant (DO NOT use variables). This is called Delay Control and is described on page 21 of the Verilog HDL handbook. Hence, the statement

always #1 clock = ~clock;  

will toggle the clock signal after every time unit leading to a period of 2 time units. Another way to accomplish the same clock period is

always 
	begin
	#1 clock = 0; 
	#1 clock = 1;
	end 

Notice that the two statements in the begin-end block are executed in sequence. Since the begin-end block is part of an "always" statement, it's executed over and over again.

Note that the delay is necessary for the simulation to make sense at all. To see this, consider the statement

always clock = ~clock;
Now we have problems. The statement clock = ~clock is constantly updated without any time elapsing, i.e., $time is never updated. Thus, although the simulator is working, it never progresses in simulated time. It's like having time stand still.

The next set of lines of the main module "test" displays the data

initial
	begin
	$display("Time   clock   d    q");  // $display is like a printf
					    //   statement
	$monitor("%d %b %b %b",$time,clock,d,q);
					    // $monitor is also like printf
					    //   but it will print when any
					    //   of its variables changes
	end				    //   values.
The first line
	$display("Time   clock   d    q");  
is just like the printf statement. It can also be used to output variables, for example
	$display("Time=%d  clock=%b   d=%b    q=%b",$time,clock,d,q);  
will print out the value of $time in integer, "clock" in binary, "d" in binary, and "q" in binary. Notice that "%d" and "%b" means that the values should be printed in "decimal" and "binary", respectively. Page 27 of the Verilog HDL handbook has a description of $display. Note the line feed "\n" is not typically specified in a quoted string.

The second line

	$monitor("%d %b %b %b",$time,clock,d,q);
is like $display, but it displays whenever one of its values (except $time) changes. In the example, $monitor will display whenever one of the variables "clock", "d", or "q" changes. Thus, $monitor can display more than once during a simulation. This statement can appear only once in a program. Two or more appearances of $monitor will cause a compile error. This differs from $display which can appear many times in a program. See page 28 of the Verilog HDL handbook for a description of $monitor.

The next few lines

initial
	begin
	d = 0;		//  Initially set the input of reg2 to 00
	#4 d = 1;	//  After a delay of 4 time units, set the
			//     input of reg2 to 01
	#4 d = 2;	//  After another delay of 4 time units, set
			//     the input of reg2 to 10
	#4 d = 3;	//  After yet another delay of 4 time units, set
			//     the input of reg2 to 11.
	#4 $stop;	//  Halts simulation after 4 more time units.
	end
are used to drive the program. The statements in the begin-end block are executed in sequence starting from simulated time 0.

Note that instead of using decimal valued constants, we could use other formats for constants. For example, an alternative to the initial statement above is

initial
	begin
	d = 2'b00;
	#4 d = 2'b01;	
	#4 d = 2'b10;	
	#4 d = 2'b11;	
	#4 $stop;	
	end
Here the constants are given as 2-bit numbers. See page 7 for a description of other formats for constants. Yet another alternative to the initial statement is the following set of initial statements
initial	d = 0;
initial #4 d = 1;
initial #8 d = 2;
initial #12 d = 3;
initial #16 $stop;
Okay, that takes care of the "test" module. Let's do a little review.

Let's take another break.

Optional Task 1 (DO NOT turn in): Now let's enter the test program into Veriwell and see if reg2 works.

Keep working on your program until you get it to work.

Take another break.

5. Verilog HDL Implementation of the ALU

Now we're ready to tackle the ALU. First, let's discuss what the ALU is supposed to do. Recall that the counter has the following function table.

     s1 s0    function
     -----------------
      0  0    hold
      0  1    count-up
      1  0    count-down
      1  1    clear
The ALU is a combinational circuit that supplies the next state (q1+,q0+) to the 2-bit register. The ALU has four inputs (q1,q0,s1,s0), two outputs (q1+,q0+), and the following function table
     s1 s0    function
     -----------------
      0  0    (q1+,q0+) = (q1,q0)
      0  1    (q1+,q0+) = (q1,q0) + 1
      1  0    (q1+,q0+) = (q1,q0) - 1
      1  1    (q1+,q0+) = (0,0)
Next is a Verilog HDL implementation of the alu (read the comments to figure out what's going on):
//  The ALU module

module Alu2(qout, qin, s);

input [1:0]	qin, s;		// Port declarations
output [1:0]	qout;

//	The following wires are used to determine the values of qout when
//	the counter is counting "up", counting "down", "holding",
//	or "clearing".

wire [1:0]  	up, down, hold, clr;	

assign up = qin + 1;
assign down = qin - 1;
assign hold = qin;
assign clr = 0;

//  	A 4:1 multiplexer is used to choose the output value.

Mux4 mux4a(qout, s, hold, up, down, clr);

endmodule

//  4:1 Multiplexer module

module Mux4(y, s, i0, i1, i2, i3);

input [1:0] s, i0, i1, i2, i3;  // y = i0, if s = 0
output [1:0] y;			//   = i1, if s = 1
				//   = i2, if s = 2
				//   = i3, if s = 3

//  The way we'll be implementing the multiplexer is
//  by implementing the following equation:
//
//  y = i0 & (~s[0]) & (~s[1])
//  		|  i1 & (~s[0]) & s[1]
//  		|  i2 & s[0] & (~s[1])
//  		|  i3 & s[0] & s[1]
//
//  But this equation won't work because i0, i1, i2, i3 are 2-bits
//  a piece while s[0] and s[1] are 1 bit a piece.  So we'll make
//  two bit versions of s[0] and s[1], and then implement the equation
//  using bit-wise operations

wire [1:0]  s1, s0;	// Our 2-bit versions of s[1] and s[0].

assign s1[1] = s[1];
assign s1[0] = s[1];
assign s0[1] = s[0];
assign s0[0] = s[0];

assign y = i0 & (~s0) & (~s1)
  		|  i1 & (~s0) & s1
  		|  i2 & s0 & (~s1)
  		|  i3 & s0 & s1;
endmodule
Note that both the Alu2 and Mux4 modules use wire variables. Note that the variables are used to define operations of combinational circuits. For example in Alu2, the lines
assign up = qin + 1;
assign down = qin - 1;
define adder and subtractor operations. Another example in Mux4 is
assign y = i0 & (~s0) & (~s1)
  		|  i1 & (~s0) & s1
  		|  i2 & s0 & (~s1)
  		|  i3 & s0 & s1;
which defines the 4:1 multiplexing operation.

For the heck of it, let's look at another way to implement the ALU. We'll implement it using full adders. Here's a full adder in Verilog HDL

//  Full adder

module FA(cout, sum, a, b, cin);

input 	a, b, cin;	//  These are the bits to be added, where
			//     cin is the carry-in
output  cout, sum;	//  The output is (cout,sum), where cout is
			//     the carry-out bit, and sum is the
			//     sum bit.

assign sum = a ^ b ^ cin;	//  The sum is the exclusive-ors of
				//     the input bits.
assign cout = a & b | a & cin | b & cin;
				//  cout = 1 if at least two of the
				//      input bits are 1.
endmodule
Now we can connect two full adders as follows

    y  -------+---------------+
              | q1            | q0
              |  |            |  |
              V  V            V  V
            +------+        +------+
    cout1 <-|  FA  |<-------|  FA  |<-- cin0
            +------+        +------+
                |               |
                V               V
               q1+             q0+
Notice that this configuration has two control inputs: y and cin0. It has the following function table

         y  cin0  |  q1+ q0+
        ----------+----------
         0   0    |  q1  q0
         0   1    |  (q1 q0) + 1
         1   0    |  (q1 q0) - 1
         1   1    |  q1  q0, because we are basically adding 1 and
				subtracting 1.
The only thing that the configuration doesn't do for us is to output zeros. So we modify it by adding in ANDs (denoted by "&").

    y0 -------+---------------+
              | q1            | q0
              |  |            |  |
              V  V            V  V
            +------+        +------+
    cout1 <-|  FA  |<-------|  FA  |<-- cin0
            +------+        +------+
    y1 ------+--|------------+  |
             |  |            |  |
            +----+          +----+
            |  & |          | &  |
            +----+          +----+
               |               |
              q1+             q0+
It now has the following function table.
      y1 y0 cin0  |  q1+ q0+
      ------------+----------
      0  x   x    |  0   0        (clear)
      1  0   0    |  q1  q0       (hold)
         0   1    |  (q1 q0) + 1  (count-up)
         1   0    |  (q1 q0) - 1  (count-down)
         1   1    |  q1  q0,      (hold)
We need a control circuit that will have as inputs (s1,s0) and output the appropriate values for (y1,y0) and cin0. So it's truth table should be
        s1  s0 |  y1  y0  cin0
       --------+--------------
        0   0  |  1   0   0 (hold)
        0   1  |  1   0   1 (count-up)
        1   0  |  1   1   0 (count-down)
        1   1  |  0   x   x (clear)
The MSOP (minimum sum of product) formulas for the outputs are
     y1  = s1' + s0'
     y0  = s1
     cin0 = s0
This leads to the following Verilog HDL program for alu2
//  Alu2

module Alu2(qout, qin, s);

input  [1:0]    qin, s;  // Port declarations
output [1:0]    qout;

wire   [1:0]    y, cin, cout, faout; // faout will store the sum bits
				     //   of the full adders

//  The control

assign y[1]   = (~s[1]) | (~s[0]);
assign y[0]   = s[1];
assign cin[0] = s[0];

//  The full adder configuration

FA fa1(cout[1], faout[1], qin[1], y[0], cin[1]);
FA fa0(cout[0], faout[0], qin[0], y[0], cin[0]);
assign cin[1] = cout[0];	//  The carry-out of full adder 0
				//    is connected to the carry-in of
				//    full adder 1.
assign qout[1] = faout[1] & y[1]; // The outputs of the full adders
assign qout[0] = faout[0] & y[1]; //   are AND'd with y[1]

endmodule

Optional Task 2 (DO NOT Turn In): Now test either version of alu2 using Veriwell. Note that you need to come up with a main module that will "test" alu2. For example, your main module should try different values for "s" and "qin", to see if "qout" changes so that the counter can count, hold, and clear.

6. Counter Circuit

Real Task (MUST TURN IN). Once you have alu2 working, put the counter together. Again you should test it by having a main module. The main module could have the counter clear, then count-up for some time, then hold for some time, then count-down for some time, and then clear. Have the program labeled "hw9.v" and have a project for it labeled "hw9.prj". The program should show that the counter works by having it count up for some time, hold, count down for some time, and then clear. Turn the program in on a diskette, clearly labeled with your name and "EE 361 Hw9".