微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 小总结一下verilog的位宽与数据转换

小总结一下verilog的位宽与数据转换

时间:10-02 整理:3721RD 点击:
昨天写某verilog的教学实例,又犯了常犯的错误,枉花了不少时间。
总结一下:
如果有以下定义:
wire signed [7:0] a;
wire signed [15:0] b;
wire signed [16:0] sum;
wire signed [23:0] prod;
关于数学运算的位宽:
  • 加乘等数学运算实现的位宽决定于操作数中位宽宽的那个,比如:
a + b ,  a * b 都是按16位实现的,如有溢出概不负责。
  • 如果是运算后立即赋值,而被赋值变量较宽,则按被赋值的变量宽度计算,比如:
sum = a + b; 是按17位实现的。

prod = a * b; 是按24位实现的。
都不会有溢出问题。
  • 但这么写,就悲剧了:
sum = {a + b}; 加法后没有立即赋值而是做了其它运算,这里以位拼接为例的,于是加法是按16位实现的,结果会溢出。
  • 同样,这样写也是悲剧的:
prod = (a * b) >>> 7; 本想要相乘后除以128,结果乘法是按16位实现的,会溢出,我就是错在这里,不是第一次了。
简便的解决办法是: prod = (24'sb1 * a * b) >>> 7; 放心综合器不会傻到多实现一个乘法器……

关于赋值:
  • real常量赋值给整形,是四舍五入的!比如:
a = 100 * 0.267; a最终是等于8'sd27的,所以我们不必画蛇添足写个+0.5或-0.5了。
  • 短有符号数赋值给长数(不管有无符号),是会填充符号位的,保证值的意义尽量不变,比如:
如果先有:a = -8'sd1或者a = 8'd255(注意两者对a来讲是无区别的);
b = a; 或直接写 b = -8'sd1; b最终都是等于-16'sd1的。
注意如果先有:wire [7:0] c = -8'd1;
在写:b = c; 和 b = -8'd1; 情况是不一样的!
在对c赋值时c已然变为8'd255,理解为 8'd0 - 8'd1(因为“-8'd1”代表的“无符号数-1”是不能理解的),前者是无符号数向长有符号数赋值时,自然是填充0,结果b为16'sd255。
而后者,应理解为一个减法运算后立即赋值,所以减法运算是按16位有符号进行的:16'sd0 - 8'd1,结果b为-16'sd1。



    好文章

就是好文章!

关于最后一点,个人的理解是:
a作为有符号数,在进行位数展宽时,按有符号数进行扩展,因此最终的b仍是-1,
c作为无符号数,扩展位宽时,按无符号的来,即高位补0,所以b最终为255.

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top