Implementing one-bit flags in a 32Bit ALU using Verilog

Scruffy Nerfherder picture Scruffy Nerfherder · Dec 6, 2015 · Viewed 10.2k times · Source

I am working on an assignment and am a little lost and don't really know how to get started. I need to implement the following flags in a 32Bit ALU:

• Z ("Zero"): Set to 1 ("True") if the result of the operation is zero

• N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number

• O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.

Additionally, a comparison function that compares input a to input b and then set one of three flags:

• LT if input a is less than input b

• GT if input a is greater than input b

• EQ if input a is equal to input b

I need to modify this ALU to include the three flags and comparison outputs then change the test bench to test for all of these modifications.

This was all the information I received for this assignment and there is no textbook or any other resources really. It's an online class, and I cannot get a response from my instructor. So I am a little confused as to how to get started. I am still a total newbie when it comes to digital logic so please bear with me. I just need some help understanding how these flags and comparison works. If any one can explain this a little better to me as far as how they work and what they do, and possibly how I would implement them into the ALU and testbench, I would really appreciate it.

I don't expect anyone to do my assignment, I really just need help understanding it.

ALU

module alu32 (a, b, out, sel);      
    input [31:0] a, b;    
    input [3:0] sel;   
    output [31:0] out,
    reg [31:0] out;  

    //Code starts here 
    always @(a, b, sel)   
    begin     
        case (sel)       
            //Arithmetic Functions       
            0  : out <= a + b;       
            1  : out <= a - b;       
            2  : out <= b - a;       
            3  : out <= a * b;       
            4  : out <= a / b;       
            5  : out <= b % a;       
            //Bit-wise Logic Functions       
            6  : out <= ~a; //Not       
            7  : out <= a & b; //And       
            8  : out <= a | b; //Or       
            9  : out <= a ^ b; //XOR       
            10 : out <= a ^~ b; //XNOR       
            //Logic Functions       
            11 : out <= !a;       
            12 : out <= a && b;       
            13 : out <= a || b;       
            default: out <= a + b;     
        endcase
    end  
endmodule 

ALU Testbench

module alu32_tb();  
    reg [31:0] a, b; 
    reg [3:0] sel; 
    wire [31:0] out; 

initial begin

$monitor("sel=%d a=%d b=%d out=%d", sel,a,b,out);   
    //Fundamental tests - all a+b   
    #0 sel=4'd0; a = 8'd0; b = 8'd0;    
    #1 sel=4'd0; a = 8'd0; b = 8'd25;   
    #1 sel=4'd0; a = 8'd37; b = 8'd0;   
    #1 sel=4'd0; a = 8'd45; b = 8'd75;  
    //Arithmetic   
    #1 sel=4'd1; a = 8'd120; b = 8'd25; //a-b   
    #1 sel=4'd2; a = 8'd30; b = 8'd120; //b-a   
    #1 sel=4'd3; a = 8'd75; b = 8'd3; //a*b   
    #1 sel=4'd4; a = 8'd75; b = 8'd3; //a/b   
    #1 sel=4'd5; a = 8'd74; b = 8'd3; //a%b  
    //Bit-wise Logic Functions   
    #1 sel=4'd6; a = 8'd31; //Not   
    #1 sel=4'd7; a = 8'd31; b = 8'd31; //And   
    #1 sel=4'd8; a = 8'd30; b = 8'd1; //Or   
    #1 sel=4'd9; a = 8'd30; b = 8'd1; //XOR   
    #1 sel=4'd10; a = 8'd30; b = 8'd1; //XNOR  
    //Logic Functions   
    #1 sel=4'd11; a = 8'd25; //Not   
    #1 sel=4'd12; a = 8'd30; b = 8'd0; //And   
    #1 sel=4'd13; a = 8'd0; b = 8'd30; //Or      
    #1 $finish; 
end  

alu32 myalu (.a(a), .b(b), .out(out), .sel(sel));  
endmodule  

Answer

sharvil111 picture sharvil111 · Dec 6, 2015

You can add these flag outputs to the design. Like the following. Simply connect them in testbench.

// In design:
output zero;
output overflow;
output negative;

// In testbench:
wire zero,overflow,negative;
alu32 myalu (.a(a), .b(b), .out(out), .sel(sel), .zero(zero), .overflow(overflow),.negative(negative));  

For logic part, you can do it with continuous assignments. You may need to add some logic for using these flags only during certain values of sel.

Z ("Zero"): Set to 1 ("True") if the result of the operation is zero

So, we can have condition like all the bits of out must be zero. This can be done in many other ways.

// Bit wise OR-ing on out
assign zero = ~(|out);

O ("Overflow"): Set to 1 ("True") to indicate that the operation overflowed the bus width.

According to this description and the code shown, you simply want carry flag here.That is, a signed extension of addition operation. Refer to this page on WikiPedia for overflow condition.

But, Overflow condition is not the same as the carry bit. Overflow represents data loss while carry represents a bit used for calculation in next stage.

So, doing something like following may be useful:

// Extend the result for capturing carry bit
// Simply use this bit if you want result > bus width
{carry,out} <= a+b;
// overflow in signed arithmetic:
assign overflow = ({carry,out[31]} == 2'b01);

N ("Negative"): Set to 1 ("True") if the first bit of the result is 1, which indicates a negative number

Again this is simply the MSB of the out register. But, the underflow condition is entirely a different thing.

// Depending on sel, subtraction must be performed here
assign negative = (out[31] == 1 && (sel == 1 || sel == 2));

Also, simple condition like assign lt = (a<b) ? 1 : 0; and others can detect the input LT, GT and EQ conditions.

Refer the answer here for the overflow/underflow flag understanding. Overflow-Carry link may also be useful.

Refer Carryout-Overflow, ALU in Verilog and ALU PDF for further information about ALU implementation.