-3

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
4

2 回答 2

2

你的代码很好。只需要一些修改。ALUOut必须是[N:0],因为在添加的情况下您需要一个进位位。此外,在减法的情况下必须需要借位。

参考 SystemVerilog LRM 1800-2012 Section 11.6 Expression bit lengths ,

SystemVerilog 使用操作数的位长度来确定在计算表达式时要使用多少位。

因此,ALUOut[N-1:0] = ALUinA[N-1:0] + ALUinB[N-1:0];严格评估 的表达式N,而ALUOut = ALUinA + ALUinB;将根据 的大小进行评估ALUOut。在这里,您看不到差异,因为您的所有操作数都是N位宽,但是当ALUOut增加N+1到位(包括进位)时,就会产生差异。

例如,

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

应执行到a = 15 b = 1 carry = 0 sum = 0while,使用注释的分配语句执行到a = 15 b = 1 carry = 1 sum = 0

有关详细信息,请参阅LRM 1800-2012第 11.6 节。此外,关于 ALU 设计的这个这个链接也很有用。

于 2015-11-04T12:56:28.853 回答
1

在 2 的补码-B中是~B+1~位反转)。因此A - B == A + (-B) == A + ~B + 1. 但是你在做 RTL,所以你不需要写 2 的补码进行减法,因为它是默认的。A - B并将A + ~B + 1合成相同。

A[N-1:0] + B[N-1:0]始终是无符号操作。A + B如果 A 和 B 声明为input signed [N-1:0] A, B,则可以是有符号操作,否则它是无符号操作。

其他注意事项:

你的标题有问题。许多模拟器、合成器和其他 Verilog 工具都可以接受您所拥有的,但这并不符合 IEEE 标准。有两种标题样式,ANSI 和非 ANSI。我推荐 ANSI,除非需要遵循 IEEE1364-1995 版本的标准。

ANSI 样式(IEEE Std 1364-2001 及以上):

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

非 ANSI 样式(IEEE Std 1364-1995 及以上):

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)语法合法。然而,由于 IEEE1364-2001 组合逻辑被重新编写为always @*always @(*)@*并且@(*)是同义词,用户偏好)。使用 Verilog (IEEE1364) 的继承者 SystemVerilog (IEEE1800),always_comb推荐always @*用于组合逻辑和always_latch电平敏感锁存逻辑。

于 2015-11-04T17:38:25.030 回答