FPGA—YOLO

数据加法溢出处理

Verilog 补码加法溢出判断及处理

一、符号位判断

Xf、Yf分别两个数的符号位,Zf为运算结果符号位。

  • 当Xf =Yf =0(两数同为正),而Zf=1(结果为负)时,负溢出;
  • 当出现Xf =Yf =1(两数同为负),而Zf=0(结果为正),正溢出。

二、进位判断

Cs表示符号位的进位,Cp表示最高数值位进位,⊕表示异或。

  • 若 Cs⊕Cp =0 ,无溢出;
  • 若 Cs⊕Cp =1 ,有溢出。

三、变形补码判断

用变形补码进行双符号位运算(正数符为00,负数符号以11)

  • 若运算结果的符号位为”01″,则正溢。
  • 若结果双符号为10,则负溢出。
变形补码的方案为例,代码如下:

always @ (* )
begin
    case(dout[DATA_WIDTH-1:DATA_WIDTH-2])
    	2'b01: dout <= {1'b0,{(DATA_WIDTH-1){1'b1}}};       //正溢
    	2'b10: dout <= {1'b1,{(DATA_WIDTH-1){1'b0}}};     //负溢
    	2'b00,2'b11: dout <= {dout[DATA_WIDTH-1],dout[DATA_WIDTH-3:0]};  //无溢出
    	default: sum <= {dout[DATA_WIDTH-1],dout[DATA_WIDTH-3:0]};
    endcase	      
end

假设您有两个 8 位 2 的补码,a[7:0] 和 b[7:0]。这些数字相加产生 s[7:0]。还要计算是否发生了(有符号的)溢出。
给出输入输出如下:(不区分正负溢出)
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
);

Xf、Yf分别两个数的符号位,Zf为运算结果符号位。
当Xf =Yf =0(两数同为正),而Zf=1(结果为负)时,负溢出;
当出现Xf =Yf =1(两数同为负),而Zf=0(结果为正),正溢出.

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); 
  	assign s=a+b;
    assign overflow=((~a[7])&(~b[7])&s[7])|(a[7]&b[7]&(~s[7]));
            
endmodule
[方法二]
Cs表示符号位的进位,Cp表示最高数值位进位,⊕表示异或。
若 Cs⊕Cp =0 ,无溢出;
若 Cs⊕Cp =1 ,有溢出。

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); 
    wire [7:0] cout;//每一位的进位
    integer i;
    always @(*) begin
        for(i=0;i<8;i++) begin
            if(i==0)
            	{cout[i],s[i]}=a[i]+b[i];
            else
            	{cout[i],s[i]}=a[i]+b[i]+cout[i-1];//需加上前一位的进位
        end
    end
    assign overflow=(cout[7]^cout[6]==1)?1:0;
            
endmodule
[方法三]
用变形补码进行双符号位运算(正数符为00,负数符号以11)
若运算结果的符号位为"01",则正溢;
若结果双符号为10,则负溢出;
若结果的双符号位为00或11,无溢出。

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); 
    wire [8:0] a_2s;
    wire [8:0] b_2s;
    wire [8:0] s_2s;
    assign a_2s={a[7],a};
    assign b_2s={b[7],b};
    assign s_2s=a_2s+b_2s;
    assign s = s_2s[7:0];
    assign overflow = (s_2s[8:7]==2'b01)?1:
        (s_2s[8:7]==2'b10)?1:0;

endmodule

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注