////////////////////////////////////////////////////////////////////////////////
///
/// Solution to LSU EE 3755 Fall 2001 Midterm
///

// Exam: http://www.ece.lsu.edu/ee3755/2001f/mt.pdf
// Complete Exam Solution: http://www.ece.lsu.edu/ee3755/2001f/mt_sol.pdf

// Solutions to problems requiring Verilog code.

/// Problem 1

module cla_32(sum,a,b);
input [31:0] a, b;
output [32:0] sum;

wire [31:0]   g, p, carry;

// Code for other carry signals omitted.
//

assign       carry[5] = g[0] & p[1] & p[2] & p[3] & p[4] |
g[1] & p[2] & p[3] & p[4]        |
g[2] & p[3] & p[4]               |
g[3] & p[4]                      |
g[4];

cla_slice s0(sum[0],g[0],p[0],a[0],b[0],carry[0]);
cla_slice s1(sum[1],g[1],p[1],a[1],b[1],carry[1]);
cla_slice s2(sum[2],g[2],p[2],a[2],b[2],carry[2]);
// Code for other cla_slices omitted.
cla_slice s5(sum[5],g[5],p[5],a[5],b[5],carry[5]);
// Code for other cla_slices omitted.

endmodule

/// Problem 2

input [31:0] a, b;
input        s;
output [31:0] sum;
output        overflow;

reg [31:0]    sum;
reg           overflow;

always @( a or b or s ) begin

sum = a + b;

if( s )
overflow = a[31] == b[31] && a[31] != sum[31];
else
overflow = a[31] && b[31] || ( a[31] || b[31] ) && ! sum[31];

end

endmodule

/// Problem 3

module longest_run(lrun,bit,reset,clk);
output [31:0] lrun;
input         bit, reset, clk;

reg [31:0]    this_run, lrun;

always @( posedge clk ) begin

if( reset ) begin lrun = 0; this_run = 0; end

if( bit == 1 ) begin

this_run = this_run + 1;

end else begin

this_run = 0;

end

if( this_run > lrun ) lrun = this_run;

end

endmodule

// Demo for problem 2.

module tlr();

wire [31:0] lrun;
reg         bit, clk, reset;

longest_run lr(lrun,bit,reset,clk);

always begin clk = 0; #5 clk = 1; #5; end

integer i;
reg [31:0] v, r;

initial begin

#0;

v = 32'b0101_1101_0110;
r = 32'b0010_0000_0001;

for(i=0; i<13; i=i+1) begin

bit = v[i];
reset = r[i];
@( negedge clk );

end

\$stop;

end

endmodule

/// Problem 4

// Code used in exam.
// Solution coming soon.

module syn(x,r,a,b,m,neg);
input [31:0] a, b;
input        m, neg;
output [31:0] x, r;

reg [31:0]    x, r, bn;

always @( a or b or m or neg ) begin

if( neg ) bn = -b; else bn = b;

x = a + bn;

if( m ) r = x + b;

end

endmodule