0

我想设计一个 ALU 来对两个 8 位寄存器( A , B )执行一些操作,为了检测进位输出,我将一个 9 位寄存器定义为 temp 并将 A、b 的操作结果放在该寄存器中。
该临时寄存器的 MSb 用作进位。
这是我的代码的一部分:

module ALU(input signed [7:0] A, input [7:0] B, input carry_in, input [2:0] acode, output reg [7:0] R, output zero, output reg carry_out);

  reg [8:0] temp;
  reg [15:0] temp2;

  always @(A, B, acode) begin
    case(is_shift)
      1'b0: begin
        case(acode)
          3'b000: temp = A + B;
          3'b010: temp = A - B;
        endcase
        R = temp[7:0];
        carry_out = temp[8];

给定 A = 11100101 和 B = 11000111,这里是日志:

//addition
A:  11100101 , B:  11000111
acode:  000
R:  10101100
zero:  0, carry_out:  1

//subtraction
A:  11100101 , B:  11000111
acode:  010
R:  00011110
zero:  0, carry_out:  0

在这两种情况下,temp 的第 9 位应该是 1,并且在加法的情况下是正确的,但在减法的情况下,减法是正确的,但是 temp 的第 9 位没有设置为 1。
这里有什么问题?

顺便说一句: 声明一个已签名的寄存器的效果只是移位和扩展,是吗?所以这个问题不是因为 A 被签名而 B 被 unsigned ,对吧?

4

1 回答 1

1

声明为已签署的登记册的效力仅在转移和扩展

不,它会影响所有算术。尽管通常如果您组合任何无符号或部分选择总线,那么它将默认返回无符号算术。

你不能真正让一个输入有符号而一个没有,二进制补码算法根本行不通。您至少必须签署扩展有符号值并将 0 MSB 插入到无符号上,确保将其评估为正值。

你的第一个例子是:

  1110 0101  // -27
  1100 0111  // -57
1 1010 1100  // -84 (-27 -57)

第二个例子(减法)

  1110 0101  // -27
  0011 1001  // +57
1 0001 1110  // 30 (ignoring MSB) -226 Including MSB

但请注意,输出宽 1 位,RTL 不会让您访问进位,而是额外的和,因此输入是符号扩展的。

1 1110 0101  // -27
1 1100 0111  // -57
1 1010 1100  // -84 

1 1110 0101  // -27
0 0011 1001  // +57
0 0001 1110  // 30

请注意,在正确的符号扩展减法中,MSB 为 0

但是对于第二个无符号值的加法,您需要一个 0 来表明它是一个正数,并且您将有 1 位的位增长:

1 1 1110 0101  // -27
0 0 1100 0111  // 199
0 0 1010 1100  // 172 (-27+199)

这里扩展位(不是进位)是 0。不是你预测的 1。

于 2015-03-30T10:43:15.583 回答