数的操作

数的操作

数的表示

数有有符号数和无符号数

表示形式有原码、反码、补码。

无符号数处理相对来说比较简单。

有符号数运算中负数通常用补码表示。

浮点数和定点数相比不常用。定点数的运算电路和普通数据无差别,要注意小数点的位置。有符号数处理需要注意数据的符号位。

8B39A5C117408A97EB6BE249E7FAA6DE

有符号数比较器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function    [DATA_WIDTH-1:0] max_op;
input [DATA_WIDTH-1:0] dat_op0;
input [DATA_WIDTH-1:0] dat_op1;

reg cmp_flag;
if(dat_op0[DATA_WIDTH-1] != dat_op1[DATA_WIDTH-1])begin
cmp_flag = dat_op0;
end
else begin
cmp_flag = (dat_op0[DATA_WIDTH-1])? ((-dat_op0[DATA_WIDTH-1:0]) > (-dat_op1[DATA_WIDTH-1:0])): (dat_op0[DATA_WIDTH-1:0] < dat_op1[DATA_WIDTH-1:0]);
end

max_op[DATA_WIDTH-1:0] = cmp_flag? dat_op1[DATA_WIDTH-1:0]: dat_op0[DATA_WIDTH-1:0];

endfunction

还可以直接定义为signed,工具自动进行符号位扩展。

1
assign max_op[DATA_WIDTH-1:0] = ($signed(dat_op1) >= $signed(dat_op0)? dat_op0[DATA_WIDTH-1:0]: dat_op1[DATA_WIDTH-1:0];

有符号数求绝对值

1
2
3
4
5
function [DATA_WIDTH-1:0] dat_abs;
input [DATA_WIDTH-1:0] dat_in;

assign dat_abs[DATA_WIDTH-1:0] = (dat_in[DATA_WIDTH-1])? (-dat_in): dat_in;
endfunction

有符号数加法器

进行符号位扩展。

1
assign dout[DATA_WIDTH:0] = {add_a[DATA_WIDTH-1], add_a} + {add_b[DATA_WIDTH-1], add_b};

有符号数乘法器

ASIC设计中通常调用DW库中的乘法器IP,有一天我不小心偷看了一眼,发现里面的乘法器直接写的数*号。嘘。

1
2
3
4
5
6
7
8
9
10
11
always @(*)begin
if(tc)begin
dat_a_tmp[A_WIDTH-1:0] = dat_a[A_WIDTH-1]? (-dat_a): dat_a;
dat_b_tmp[B_WIDTH-1:0] = dat_b[B_WIDTH-1]? (-dat_b): dat_b;
product_tmp[PRODUCT_WIDTH-1:0] = dat_a_tmp * dat_b_tmp;
product[PRODUCT_WIDTH-1:0] = (dat_a[A_WIDTH-1] ^ dat_b[B_WIDTH-1])? (-product_tmp): product_tmp;
end
else begin
product[PRODUCT_WIDTH-1:0] = dat_a * dat_b;
end
end

无符号数乘以常数,也直接用*号,例如a * 2‘d3,工具会帮你优化成 a << 2’d1 + a。甚至可能优化得更好。(杠:不要过度依赖工具)。

上面对于无符号数,有符号数应该注意符号位扩展。

1
assign product[A_WIDTH+1:0] = {a[A_WIDTH-1], a[A_WIDTH-1:0],1'd0} + {{2{a[A_WIDTH-1]}}, a[A_WIDTH-1:0]};

还可以直接定义为signed,工具自动进行符号位扩展。

1
2
3
4
5
6
7
8
9
10
11
input   signed  [A_WIDTH - 1:0]     multa;
input signed [B_WIDTH - 1:0] multb;
output signed [C_WIDTH - 1:0] product;

assign product = multa * multb;

input [A_WIDTH - 1:0] multa;
input [B_WIDTH - 1:0] multb;
output signed [C_WIDTH - 1:0] product;

assign product = $signed(multa) * $sigend(multb);

哪种写法好?习惯了就行,最重要的是代码风格统一。不应该混用。

人非圣贤,孰能无过,有错误请指点。将设计电路参数化可重复使用,构建自己的代码库,搭建起你的数字积木,本设计博主放在了GitHub上,可以在订阅号后台回复 “ip_lib”得到GitHub路径进行交流。

NingHeChuan wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!