加减乘,在fpga设计中,使用verilog hdl语言来描述,简单的很,直接就是+、-、*,没有任何疑问,但是计算过程中的信号的位宽,却值得认真揣摩。
数学运算,必然涉及到有符号数与无符号数的区别,因此在写hdl代码时,必须明确参与运算的信号是否是有符号数。建议:参与运算的符号要么都是有符号数,要么都是无符号数,不建议使用有符号数与无符号数进行数学运算,如果在参与运算的两个信号一个是有符号数,而另外一个是无符号数的话,建议把无符号数扩展一位,将其转换成有符号数来进行处理。
无符号数扩展成有符号数的方法(以verilog为例):
input [7:0] data;
wire [8:0] data_r;
assign data_r = {data[7],data};
加法运算中的位宽处理:
input [7:0] data_a;
input [7:0] data_b;
output [8:0] data_x;
wire [8:0] data_x;
assign data_x = data_a + data_b;
如上面的代码,在做加法运算的时候,建议:
1、加法运算符两边的信号,位宽一致;
2、加法运算符两边的信号,要么都是有符号数,要么都是无符号数;
2、考虑到加法可能产生进位,输出信号比输入信号多1bit即可。
乘法运算中的位宽处理:
1. 两个无符号数相乘
input [7:0] data_a;
input [4:0] data_b;
output [12:0] data_x;
wire [12:0] data_x;
assign data_x = data_a * data_b;
两个无符号数相乘,输出信号位宽直接定义成两个输入信号位宽之和即可。
2. 两个有符号数相乘
reg signed [7:0] data_a;
reg signed [4:0] data_b;
output [12:0] data_x;
wire signed [11:0] data_x;
assign data_x = data_a * data_b;
两个有符号数相乘,考虑到符号位可以合并成一位,输出信号位宽定义成两个输入信号位宽之和-1即可。
3. 平方运算
如果输入信号是无符号数,则输出信号位宽等于输入信号位宽2倍;
如果输入信号是有符号数,则输出信号位宽等于输入信号位宽2倍-2
上述这些都是些基本概念,自己总结一下,备忘。。。