无符号整数除法器:16位除8位
备注:在写testbench时发现reg型变量是有符号的补码形式。使用{$random}%b产生无符号随机数,除数被除数依旧可能取值为负数;然后手动输入大于2^7=128的数作为除数,发现发生溢出,除数被当作负数,这才发现此时reg型变量应该是被当作了有符号数的补码形式。一般认为reg型变量为无符号型变量,有出入,特此记录。
源代码
//unsigned 16bit/8bit
module unsignediv(divee,divor,result,odd);
input [15:0] divee;
input [7:0] divor;
output [15:0]result;
output [15:0]odd;
reg [15:0] result,odd;
reg [15:0] tempa;
reg [7:0] tempb;
reg [31:0] temp_a,temp_b;
integer i;
always @ (divee or divor)
begin
tempa=divee;
tempb=divor;
temp_a={16'h0000,tempa};
temp_b={tempb,16'h0000};
for(i=0;i<16;i=i+1)
begin
temp_a={temp_a[30:0],1'b0};
if(temp_a[31:16]>=tempb)
temp_a=temp_a-temp_b+1'b1;
else temp_a=temp_a;
end
result=temp_a[15:0];
odd=temp_a[31:16];
end
endmodule
测试代码
module unsigned_tb;
reg [15:0] divee;
reg [7:0] divor;
wire [15:0] result,odd;
initial
begin
#10 divee = 12345;
divor = 106;
#100 divee = 2383;
divor = 12;
#100 divee = {$random}%100;
divor = {$random}%10;
#1000 $stop;
end
unsignediv U1(divee,divor,result,odd);
endmodule
仿真结果
仿真过程中发现的reg疑问
(1)当使用随机数
module unsigned_tb;
reg [15:0] divee;
reg [7:0] divor;
wire [15:0] result,odd;
initial
begin
#10 divee = {$random}%10000;
divor = {$random}%256; //{$random}%b表示产生一个0~b-1的随机整数
#100 divee = {$random}%1000;
divor = {$random}%100;
#100 divee = {$random}%100;
divor = {$random}%10;
#1000 $stop;
end
unsignediv U2(divee,divor,result,odd);
endmodule
仿真结果
可以看到,-127这一组计算错误,原因是:即使利用{$random}%b产生正随机数,但当最高位为1时,即数值大小超过128时,按照有符号整数补码的读数规则,为相应负数。而源代码只适用于无符号整数即正整数的除法运算,因此计算错误是在所难免的。通过手动输入具体数值,验证确实是这个原因。
(2)当手动输入
module unsigned_tb;
reg [15:0] divee;
reg [7:0] divor;
wire [15:0] result,odd;
initial
begin
#10 divee = 12345;
divor = 106; //divor=8'b01101010
#100 divee = 12345;
divor = 106+128; //divor=8'd234=8'b11101010
#100 divee = 2383;
divor = 12;
#100 divee = {$random}%100;
divor = {$random}%10;
#1000 $stop;
end
unsignediv U3(divee,divor,result,odd);
endmodule
为了具有对比性,把除数的最高位分别设置为0和1,可以看到结果如下图所示:
仿真结果
8’b11101010 = 8’d234 = -8’d22,计算发生错误。其他例子都是正确的。
结论:
verilog中reg型变量是无符号整数类型,发生此类错误原因暂时不明。不过得到的教训是以后在仿真过程中注意:最好让数据最高位为0,避免发生溢出为负这样的错误。
Ps:如果有看到我这篇小记录且知道原因的小伙伴还请指教指教!!