简体   繁体   中英

Verilog Design of a 32-bit ALU

Can you help me guys do a 32-bit ALU and explain me some things? Wanna do:

0 bitwise AND: out = inA & inB.
1 bitwise OR: out = inA | inB.
2 addition: out = inA + inB.
6 subtraction: out = inA – inB //2's complement
7 Set On Less Than: out = ((inA < inB)?1:0)
12 NOR: out = ~( inA | inB)

Done this so far:

module ALU #(parameter N=32)(ALUOut, Zero, ALUinA, ALUinB, ALUop); 
    output  [N-1:0] ALUOut;
    reg     [N-1:0] ALUOut;
    output  Zero;
    reg     Zero;
    input   [3:0] ALUop;
    input   [N-1:0] ALUinA, ALUinB;

    always @(ALUinA or ALUinB or ALUop)
    begin
        case (ALUop)
           4'b0000: ALUOut  = ALUinA & ALUinB ;   // 0:AND

Your code is good. Just some modifications required. ALUOut must be [N:0] , since you'll require a carry bit in case of addition. Also, borrow bit must be required in case of subtraction.

Referring to SystemVerilog LRM 1800-2012 Section 11.6 Expression bit lengths ,

SystemVerilog uses the bit length of the operands to determine how many bits to use while evaluating an expression.

So, ALUOut[N-1:0] = ALUinA[N-1:0] + ALUinB[N-1:0]; will strictly evaluate an expression of N , while ALUOut = ALUinA + ALUinB; will evaluate depending on size of ALUOut . Here, you can not see the difference, since all youe operands are N bits wide, but when ALUOut is increased to N+1 bits(including carry), then it can create a difference.

For example,

module top();
  bit [3:0] a,b;
  logic [3:0] sum;
  bit carry;

  assign sum[3:0] = a[3:0] + b[3:0];
// assign {carry,sum}= a + b;
  initial
      $monitor("a = %0d b = %0d carry = %0d sum = %0d",a,b,carry,sum);

  initial
    begin
      a = 5; b = 1;
      #5 ; a = 15; b = 1;
    end
endmodule

shall execute to a = 15 b = 1 carry = 0 sum = 0 while, using the commented assign statement executes to a = 15 b = 1 carry = 1 sum = 0

Refer to LRM 1800-2012 , Section 11.6 for further information. Also, this and this links regarding ALU design can be useful.

In 2's complement -B is ~B+1 ( ~ is bit invert). Therefor A - B == A + (-B) == A + ~B + 1 . But your doing RTL, so you don't need to write the 2's complement for subtraction as it is default. A - B and A + ~B + 1 will synthesize the same.

A[N-1:0] + B[N-1:0] is always an unsigned operation. A + B can be a signed operation if A and B are declared as input signed [N-1:0] A, B , otherwise it is an unsigned operation.

Other notes:

There is an issue with your header. Many simulators, synthesizers, and other Verilog tools will accept what you have, but it is not complaint with the IEEE standard. There are two header styles, ANSI and non-ANSI. I recommend ANSI unless required to follow the IEEE1364-1995 version of the standard.

ANSI style (IEEE Std 1364-2001 and above):

module ALU #(parameter N=32)( 
    output reg [N-1:0] ALUOut,
    output reg Zero,
    input   [N-1:0] ALUinA, ALUinB,
    input   [3:0] ALUop );

Non-ANSI style (IEEE Std 1364-1995 and above):

module ALU (ALUOut, Zero, ALUinA, ALUinB, ALUop);
    parameter N=32;
    output  [N-1:0] ALUOut;
    output  Zero;
    input   [3:0] ALUop;
    input   [N-1:0] ALUinA, ALUinB;

    reg     [N-1:0] ALUOut;
    reg     Zero;

always @(ALUinA or ALUinB or ALUop) is syntax legal. However since IEEE1364-2001 combinational logic is recommenced to be written as always @* or always @(*) ( @* and @(*) are synonymous, user preference). With SystemVerilog (IEEE1800), the successor of Verilog (IEEE1364), always_comb is recommend over always @* for combinational logic, and always_latch for level-sensitive latching logic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM