Verilog带符号数运算

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Verilog带符号数运算

摘要:介绍了Verilog带符号数的不同运算。因为Reg和Wire数据默认情况下是无符号的,而在数据处理的情况下,Verilog既要对带符号数据进行各种运算,也要对无符号数和带符号数进行运算,所以简单使用Verilog提供的运算符是不够的。因此研究不同类型数据运算的通用方法是必要的。

关键词:Verilog;带符号数;补码;算术运算

中图分类号:TN911?34 文献标识码:A 文章编号:1004?373X(2015)03?0160?03

Operation of numbers with symbols by Verilog

HUI Wei?jun,SHEN Zhao?jun

(Yancheng Institute of Technology,Yancheng 224051,China)

Abstract:Different operations of data with symbols by Verilog are introduced. Reg and Wire data in the case of default is unsigned,but in the case of data processing,a variety of operations of data with symbols are performed by Verilog,and the unsigned and signed with numbers need to be processed. However,it is not enough to use the operation symbols provided by Verilog. It is necessary to research the general

method for various types of data operation.

Keywords:Verilog;number with symbol;twos complement;arithmetic operation

0 引言

Verilog语言是目前流行的一种硬件描述语言。它的最大的优点是简单、规范,语法规则与C语言十分相似。然而,作为一种描述语言,Verilog不具备C语言丰富的数据类型和数据处理能力。Verilog 95中能处理带符号数数据类型是整型,而整型的默认位宽是32位,且位宽不能改变,因而限制了整型数的使用。为了解决这个问题,Verilog 2001版本增加了对带符号数处理的支持,虽然如此,Verilog对数据处理仍然有很多问题。本文以Verilog 2001为版本,重点讨论带符号数的算术运算,并给出Verilog程序和仿真结果,同时,本文也讨论了带符号数的其他运算情况。

1 加、减运算

Verilog 2001处理带符号数加减运算很简单,只要在定义数组是使用关键字signed即可:

module add_signed(a,b,sum);

input signed [7:0] a,b;

output signed [7:0] sum;

assign sum=a+b;

endmodule

仿真结果如图1所示。

图1 加法仿真结果

Verilog处理带符号数和无符号数运算时候,默认是把带符号数转换为无符号数。因此,对于带进位加法或者带借位减法运算,如果不加处理就会发生错误:

module addc(a,b,c,sum);

input signed [7:0] a,b;

input c;

output signed [8:0] sum;

assign sum=a+b+c;

endmodule

仿真如图2所示,可知结果是错误的,原因是a和b高位扩展加零。改进的方法是把带符号数进行符号扩展:assign sum={a[7],a}+{b[7],b}+c;

图2 带符号数和无符号数加法仿真错误结果

图3所示仿真表明结果是正确的。也可以用系统函数把无符号数转换为带符号数参加运算:

assign sum=a+b+$signed(c);

所得仿真结果将会相同。不同的是,系统函数$signed 不能综合,具有$signed的代码只能用于仿真。

图3 带符号数和无符号数加法仿真正确结果

2 乘法运算

两个带符号数乘法运算的处理与加法运算相似,只需在定义端口的时候使用关键字signed即可:

module mult(a,b,prod);

input signed [7:0] a;

input signed [7:0] b;

output signed [15:0] prod;

assign prod = a * b;

endmodule

如图4所示的仿真表面结果是正确的。当然,实现一个带符号数和无符号数的乘法的时候,默认是把带符号数高位全部扩展为零,因而,用乘法运算符实现的乘法结果将会是错误的,如图5所示。module mult(a,b,prod);

input signed [7:0] a;

input [7:0] b;

output signed [15:0] prod;

assign prod = a*b;

endmodule

图5 带符号数与无符号数乘法仿真错误结果

解决方法是可以用函数$signed把上述代码中的无符号

数b转换为带符号数,此时代码就不可综合。实现通用的两个数乘法的算法,基本的思路是用移位加的方式实现。其算法基础是认为补码是一个权重码,位宽为n的向量存放补码,其MSB的权为[-2n-1,]其他位的权为[2i,]i的取值范围为0≤i≤n-2。当两个位宽为n的数相乘时,从右向左,逐位考察乘数索引为i的位的值,若为1,将被乘数左移i位,作为部分和加到结果中。若乘数最高为位1,因为权为[-2n-1,]所以被乘数要先取反加一,然后再左移n-1位。两个位宽为n的数相乘,最终的结果,是由n个移位的部分和相加得到。

module mult8(a,b,prod);

input signed [7:0] a;

input [7:0] b;

output signed [15:0] prod;

wire [15:0] prod_int0;

wire [15:0] prod_int1;

wire [15:0] prod_int2;

wire [15:0] prod_int3;

wire [15:0] prod_int4;

wire [15:0] prod_int5;

wire [15:0] prod_int6;

wire [15:0] prod_int7;

wire [7:0] inv_add1;

相关文档
最新文档