/// LSU EE 4702-1 Spring 2001 Midterm Exam Verilog Code

 /// Code used in exam, for exam, and solutions.

 /// Exam:  http://www.ee.lsu.edu/v/2001/mt.pdf
 /// Solution:  http://www.ee.lsu.edu/v/2001/mt_sol.pdf

///
/// Problem 1
///

module monitor(eq_time, siga, sigb, clk);
   input siga, sigb, clk;
   output eq_time;

   wire [31:0] siga, sigb;
   wire        clk;
   reg [31:0]  eq_time;

   reg [31:0]  next_count;

   always @( siga or sigb ) if( siga != sigb ) next_count = 0;

   always @( posedge clk ) 
     begin
        eq_time = next_count;
        if( siga == sigb ) next_count = next_count + 1;
     end

endmodule

module demo_monitor();

   wire [31:0] et;
   reg [31:0]  a, b;
   reg         clk;
   
   monitor m(et,a,b,clk);

   initial clk = 0;

   always #10 clk = ~clk;

   initial begin

      a = 0;
      b = 1;

      #25;

      a = 1;

      #40;

      b = 2;
      #4;
      b = 1;
      #50;
      a = 3;

      #25;

      b = 7;

      #25;
      a = 7;
      #50;

      $stop;
   end

endmodule

// Timing Diagram:  


///
/// Problem 2a
///

module timing_stuff();

   reg clk, clk3;
   reg clk2a, clk2b, clk2c, clk2d;
   initial begin
      clk = 0; clk2a = 0; clk2b = 0; clk2c = 0; clk2d = 0; clk3 = 0;
      #50 $stop;
   end

   always #5 clk = ~clk;

   always @( posedge clk ) clk2a = ~clk2a;

   always #12 @( posedge clk ) clk2b = ~clk2b;

   always @( posedge clk ) #12 clk2c = ~clk2c;
   
   always @( posedge clk ) clk2d <= #12 ~clk2d;

   always @( posedge clk ) @( posedge clk ) clk3 = ~clk3;

endmodule // timing_stuff

// Solution:  

///
/// Problem 2b
///

module timing();
   integer a, b, c, d;
   
   initial begin
      a = 0;
      b = 10;
      c = 20;
      d <= #0 3;
      
      d = 30;
      d <= #1 300;
      d <= #2 3000;
      #1;
      b = 100;
      c <= 200;
      a <= #5 b + c;
      #1;
      b = 1000;
      c <= 2000;
      #10;

   end 

endmodule 

// Solution:  

///
/// Problem 3a
///

module count_match_1(count,symbol,targ);
   input symbol, targ;   
   output count;  
   reg [31:0] count;
   wire [31:0] symbol,targ;

   always wait( symbol == targ ) count = count + 1;

   // Infinite loop when symbol == targ. (Simulator freezes.)
   // Possible correct code:

   always begin
      wait( symbol == targ ) count = count + 1;
      wait( symbol != targ );
   end

endmodule

module count_match_3(count,symbol,targ);
   input symbol, targ;
   output count;
   reg [31:0] count;
   wire [31:0] symbol,targ;

   always #10 if( symbol == targ ) count = count + 1;

   // Might miss changes in symbol, will overcount if symbol doesn't change.
   // Not easy to fix without changing problem.

endmodule

module count_match_4(count,symbol,targ);
   input symbol, targ;
   output count;
   reg [31:0] count;
   wire [31:0] symbol,targ;

   always @( symbol == targ ) count = count + 1;

   // Counts twice, when symbol becomes equal and when it becomes unequal.

   // Possible fix:

   always @( posedge symbol == targ ) count = count + 1;

endmodule

///
/// Problem 3b
///


module adder1(x,a,b);
   input a, b;
   output x;
   wire [31:0] a, b;
   wire [31:0] x = a + b;
endmodule

module adder2(x,a);
   input a;
   output x;
   parameter b = 0;
   wire [31:0] a;
   wire [31:0] x = a + b;
endmodule

// Line below (define) is part of solution.
`define b 7

module adder3(x,a);
   input a;
   output x;
   wire [31:0] a;
   wire [31:0] x = a + `b;
endmodule

module use_adders(x_1,x_2,x_3,a);
   input a;
   output x_1, x_2, x_3;  // Each output should be a + 7

   // Solution below:

   wire [31:0] x_1, x_2, x_3, a;

   adder1 a1(x_1,a,32'd7);
   adder2 #(7) a2(x_1,a);
   adder3 a3(x_1,a);
   

endmodule

///
/// Problem 3c
///

module prob3c();

   reg [5:0] a, b, c, r;

   initial begin

      a = 6'b101010;
      c = 6'bx1x0x1;

      r = & a;   // 0
      
      r = | a;   // 1

      r = ^ a;   // 1

      r = & c;   // 0
      
      r = | c;   // 1

      r = ^ c;   // x
      
   end

endmodule

///
/// Problem 3d
///

module prob3d();

   reg [5:0] x, y, foo, bar;

   initial begin
      x = 0;
      y = 1;
      
      foo = 7;
      bar = 'bx;

      if( foo > bar ) x = x + 1; else y = y + 1;

      case( foo > bar )
        1: x = x + 1;
        default: y = y + 1;
      endcase

   end

endmodule

///
/// Problem 3e
///

`define incr(a) a=a+1
// ...
module prob3e();
   integer i, j, k, x, y;

   // Sample uses of macro.
   initial begin


      // Increment in for loop must be an assignment.
      for(i=0; i<10; `incr(i)) x = x + y;
      for(j=0; j<10; `incr(j)) begin foo(j); k = k + x; end
   end
   
endmodule

///
/// Problem 4
///

module yet_another_symbol_counter(fives, nines, c);
   input c;
   output fives, nines;
   wire [7:0] c;
   reg [31:0] fives, nines;
   
   initial fork

      begin
         fives = 0;
         nines = 0;
      end

      #50 fork:A
         repeat( 42 ) @( c ) if( c == 5 ) fives = fives + 1;
         #100 disable A;
      join

      #70 fork:B
         forever @( c ) if( c == 9 ) nines = nines + 1;
         #200 disable B;
      join
      
   join

   // fives:  Counts from 50 to 150 cycles, first 42 symbols checked.
   // nines:  Counts from 70 to 270, all signals checked.

endmodule