数据加法溢出处理
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