繁体   English   中英

32 位 ALU 的 Verilog 设计

[英]Verilog Design of a 32-bit ALU

你能帮我做一个 32 位 ALU 并向我解释一些事情吗? 要做:

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)

到目前为止这样做:

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

你的代码很好。 只需要一些修改。 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大小进行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 = 0而使用注释的赋值语句执行到a = 15 b = 1 carry = 1 sum = 0

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

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

A[N-1:0] + B[N-1:0]始终是无符号运算。 如果 A 和 B 被声明为input signed [N-1:0] A, B ,则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 @(*)@*@(*)是同义词,用户偏好)。 对于 SystemVerilog (IEEE1800),Verilog (IEEE1364) 的后继者,对于组合逻辑,推荐always_comb优于always @* ,对于电平敏感的锁存逻辑,推荐always_latch

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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