打印

verilog 中有符号数的差值绝对值

[复制链接]
14719|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
钻研的鱼|  楼主 | 2010-1-7 17:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在项目中经常用到两个有符号数的差值绝对值,一般是用两步,第一步:实现有符号数的差值,第二步取绝对值。有符号数的差值实现很麻烦,因为verilog不直接支持有符号数的计算,请教各位大侠好一点的方法。注意:不要在程序中使用signed类型

相关帖子

沙发
一只小蜗牛| | 2010-1-8 10:52 | 只看该作者
不是很明白你的问题啊。
能否说的详细一点?
对符号数,一部分概念来自verilog本身的定义,来指导编译器如何理解和处理verilog里的符号数,另一部分概念来自逻辑本身,就是“数“在综合后的电路里的传输与存贮,也就是你如何在逻辑上完成数的处理与存贮。这两个不能混在一起。
可否详细说一下,你在verilog中拿到的是什么数,是从port来的输入呢(有一定机制标明是负数还是正数)?还是别人的程序处理的中间数?(那么它必是存在整数寄存器或是十进制的整数。)

使用特权

评论回复
板凳
一只小蜗牛| | 2010-1-8 11:05 | 只看该作者
偏软件背景的人一般喜欢使用verilog语言本身所表达的含义来编程,但经过编译以后,有些电路和自己的期望有时不一致。
偏硬件背景的人一般喜欢使用逻辑电路的思维来设计,这样效果一般比较好,但是有时不够灵活。有时候费劲巴拉的写一大串代码,其实有时一个简单的操作符便可实现同样的电路。
还有一种人,跟着感觉写代码,写完,靠仿真来验证。:lol,这是最忌讳的一种。

使用特权

评论回复
地板
钻研的鱼|  楼主 | 2010-1-8 13:27 | 只看该作者
简化一点,先说有符号数的减法。譬如8bit,最高位是符号位,差值也是符号位,8bit,考虑溢出等!至于数的来源,可以不管他。

使用特权

评论回复
5
一只小蜗牛| | 2010-1-8 14:47 | 只看该作者
本帖最后由 一只小蜗牛 于 2010-1-8 14:53 编辑

1)如果是正数,bit8 = 0, 如果是负数,bit8=1, 是吗?
2)当为负数时,bit6~bit0是原数还是补码。 比如说-1吧,是8‘h81呢,还是8'hff?

使用特权

评论回复
6
钻研的鱼|  楼主 | 2010-1-9 09:29 | 只看该作者
对于第一条,应该是bit7
对于第二条,是补码

使用特权

评论回复
7
一只小蜗牛| | 2010-1-11 15:36 | 只看该作者
`timescale 1ns/10ps
module gen_diff(
   dataa ,
   datab ,
   datac
);

input  [7:0]  dataa ;
input  [7:0]  datab ;
// datac[7]   is carry out
// datac[6:0] is the data;
output [7:0]  datac ;

integer intc ;
integer intc_signed ;

reg    [7:0] datac ;

always @(*)
begin
   intc_signed = (dataa[7] ? dataa[6:0] -128: dataa[6:0]) - (datab[7] ? datab[6:0]-128 : datab[6:0]);
   intc = (intc_signed <0) ? - intc_signed : intc_signed ;
   datac = intc ;
end

endmodule

这个模块我用ncverilog(a Cadence tools) 仿真
用dc_shell(a synopsys tools)综合的。
RTL 与gate 我都仿过了,功能没问题。
抛砖引玉,希望有更好的设计,让俺也学习一下。
另外希望钻研的鱼,不要老是一味的钻研,希望你能抽点时间提高一下自己的交流能力,大家知识和工作背景都很不一样,为了让你的问题让所有人都能理解,你应该一次就把问题描述清楚,而不是让人问来问去。

使用特权

评论回复
8
钻研的鱼|  楼主 | 2010-1-11 18:59 | 只看该作者
先说符号数的表示:
假设 dataa [7:0] = 8'b1111_1111,就是10进制的-1
        dataa [7:0] = 8'b0111_1111,就是10进制的127
这个表示应该没有歧义吧
    datab、datac也是如此表征。
你中间用了interger变量,这种变量在verilog中是32bit的有符号数,我不建议这样用。
我觉得有符号数的减法要根据dataa和datab的符号位作相应的处理

使用特权

评论回复
9
一只小蜗牛| | 2010-1-12 08:58 | 只看该作者
你没看注释,datac不是这样表征的,datac[7] 是溢出位,datac[6:0]是差的绝对值,是正数,不存在补码的问题。
我能理解你的想法,但是我综合的结果里,并没有出现你所谓的32位,可见综合工具是完全可以给优化的。你没仔细看我在二楼三楼的留言,你建议什么不重要,重要的是综合工具对代码编译后产生的电路是什么。在这方面,做编译工具的公司已经作了很多工作,他已经做了的,你没必要非得自己去从底层实现,这是做硬件出身的后遗症。这个电路无非就是一个组合逻辑,用两个八位数,产生一个八位数。你需要的是一个结果,而不是非得用你自己喜欢的方式,如果是那样,你干脆用MOS管设计好了,更有成就感。
下边是我的综合结果:

module gen_diff ( dataa, datab, datac );
  input [7:0] dataa;
  input [7:0] datab;
  output [7:0] datac;
  wire   n17, n18, n19, n20, n21, n22, n23, n24, n25, n26, n27, n28, n29, n30,
         n31, n32, n33, n34, n35, n36, n37, n38, n39, n40, n41, n42, n43, n44,
         n45, n46, n47, n48, n49, n50, n51, n52, n53, n54, n55, n56, n57, n58,
         n59, n60, n61;

  xo2_lp U20 ( .A(n17), .B(n18), .Y(datac[7]) );
  mx2i_lp U21 ( .D0(n19), .D1(n20), .S(n21), .YN(n18) );
  ao21_lp U22 ( .A(n22), .B(n23), .C(n24), .Y(n17) );
  xn2_lp U23 ( .A(n25), .B(n23), .Y(datac[6]) );
  xn3_lp U24 ( .A(datab[6]), .B(dataa[6]), .C(n26), .Y(n23) );
  nr2_lp U25 ( .A(n22), .B(n24), .Y(n25) );
  nr2b_lp U26 ( .AN(n27), .B(n28), .Y(n22) );
  xo2_lp U27 ( .A(n29), .B(n28), .Y(datac[5]) );
  xo3_lp U28 ( .A(datab[5]), .B(dataa[5]), .C(n30), .Y(n28) );
  nr2_lp U29 ( .A(n27), .B(n24), .Y(n29) );
  nr2b_lp U30 ( .AN(n31), .B(n32), .Y(n27) );
  xo2_lp U31 ( .A(n33), .B(n32), .Y(datac[4]) );
  xo3_lp U32 ( .A(datab[4]), .B(dataa[4]), .C(n34), .Y(n32) );
  nr2_lp U33 ( .A(n31), .B(n24), .Y(n33) );
  nr2b_lp U34 ( .AN(n35), .B(n36), .Y(n31) );
  xo2_lp U35 ( .A(n37), .B(n36), .Y(datac[3]) );
  xo3_lp U36 ( .A(datab[3]), .B(dataa[3]), .C(n38), .Y(n36) );
  nr2_lp U37 ( .A(n35), .B(n24), .Y(n37) );
  nr2b_lp U38 ( .AN(n39), .B(n40), .Y(n35) );
  xo2_lp U39 ( .A(n41), .B(n40), .Y(datac[2]) );
  xo3_lp U40 ( .A(datab[2]), .B(dataa[2]), .C(n42), .Y(n40) );
  nr2_lp U41 ( .A(n39), .B(n24), .Y(n41) );
  nr2_lp U42 ( .A(n43), .B(datac[0]), .Y(n39) );
  xo2_lp U43 ( .A(n44), .B(n43), .Y(datac[1]) );
  xn3_lp U44 ( .A(datab[1]), .B(dataa[1]), .C(n45), .Y(n43) );
  nr2b_lp U45 ( .AN(datac[0]), .B(n24), .Y(n44) );
  mx2_lp U46 ( .D0(n20), .D1(n19), .S(n46), .Y(n24) );
  ao21_lp U47 ( .A(n47), .B(n21), .C(n48), .Y(n46) );
  oa21_lp U48 ( .A(n26), .B(n49), .C(n50), .Y(n21) );
  scg6_lp U49 ( .A(n49), .B(n26), .C(datab[6]), .Y(n50) );
  iv_lp U50 ( .A(dataa[6]), .Y(n49) );
  scg9_lp U51 ( .A(n30), .B(n51), .C(n52), .Y(n26) );
  scg6_lp U52 ( .A(n51), .B(n30), .C(datab[5]), .Y(n52) );
  iv_lp U53 ( .A(dataa[5]), .Y(n51) );
  scg9_lp U54 ( .A(n34), .B(n53), .C(n54), .Y(n30) );
  scg6_lp U55 ( .A(n53), .B(n34), .C(datab[4]), .Y(n54) );
  iv_lp U56 ( .A(dataa[4]), .Y(n53) );
  scg9_lp U57 ( .A(n38), .B(n55), .C(n56), .Y(n34) );
  scg6_lp U58 ( .A(n55), .B(n38), .C(datab[3]), .Y(n56) );
  iv_lp U59 ( .A(dataa[3]), .Y(n55) );
  scg9_lp U60 ( .A(n42), .B(n57), .C(n58), .Y(n38) );
  scg6_lp U61 ( .A(n57), .B(n42), .C(datab[2]), .Y(n58) );
  iv_lp U62 ( .A(dataa[2]), .Y(n57) );
  ao21_lp U63 ( .A(n45), .B(dataa[1]), .C(n59), .Y(n42) );
  scg20_lp U64 ( .A(dataa[1]), .B(n45), .C(datab[1]), .Y(n59) );
  xo2_lp U65 ( .A(dataa[7]), .B(datab[7]), .Y(n19) );
  nr2b_lp U66 ( .AN(n47), .B(n48), .Y(n20) );
  nr2_lp U67 ( .A(n60), .B(datab[7]), .Y(n48) );
  nd2_lp U68 ( .A(datab[7]), .B(n60), .Y(n47) );
  iv_lp U69 ( .A(dataa[7]), .Y(n60) );
  oa21_lp U70 ( .A(datab[0]), .B(n61), .C(n45), .Y(datac[0]) );
  nd2_lp U71 ( .A(datab[0]), .B(n61), .Y(n45) );
  iv_lp U72 ( .A(dataa[0]), .Y(n61) );
endmodule

使用特权

评论回复
10
一只小蜗牛| | 2010-1-12 09:24 | 只看该作者
我说的话可能比较难于入耳,但是我希望没有歧义。我喜欢不同的声音,也愿意接受别人的批判,唯有这样,大家都会在这种辩论中获益。说实话,我不是很懂fpga的现状,但是对于ic的前端设计,这样一个既硬又软的工作中,对工具的学习和理解占了很大的一部分时间,另外一部分便是对电路的学习和理解。有时候你会看到那些软件出身的写算法的人写的RTL是很“恐怖“的,不仅有很多interger,还有很多for循环,这并不影响他们那一群人在ic的设计中是非常高端的群体之一。你如果建议他们不要用循环语句,他们肯定会惊奇的看着你,为什么做硬件的人那么想表现他学过几天门电路呢?!:lol

使用特权

评论回复
11
钻研的鱼|  楼主 | 2010-1-12 14:58 | 只看该作者
我不喜欢辩论,也没时间辩论。我感兴趣的是就事论事,解决问题!
你所说的是代码思维和编码风格,这个仁者见仁,智者见智。
在fpga设计中,我不喜欢用for循环,除非它只是用来编写的方便,而不是真正综合到逻辑网表里。
至于IC设计,高端群体,他们的风格,我不了解,所以我不评论,我只关心在fpga设计领域的习惯,因为我很少看到fpga代码里有这种风格。
在fpga设计领域里,我经常关心底层的实现,这个底层不一定是与非门,而是有一个相对限度。辟如加法,我也不会去了解底层的与非门怎样实现,
但我知道xilinx的加法器是怎样实现的,在长位数加法时怎样估算时钟频率
fpga设计频率的提升与代码习惯很有关系,代码的习惯也与对底层了解多少有关。一个好的系统设计,与对fpga的物理结构了解非常紧密。在这里我就不多说了。

回到问题上,可以更简化一点,就是在在verilog里面有符号数和无符号数的加法有无区别?
假设 a b是8bit的数据,verilog中    c=a+b,   

在不溢出情况下,如果a和b看做无符号数,c也是无符号数,结果是否正确?肯定正确
在不溢出情况下,如果a和b看做有符号数,c也是有符号数,结果是否正确?可能正确,verilog不支持有符号数

使用特权

评论回复
12
一只小蜗牛| | 2010-1-12 16:55 | 只看该作者
首先对于有符号数,verilog中明确定义了它所存储在的数据类型(整数寄存器和十进制形式的整数)。如果a,b都是普通的寄存器类型,c=a+b;肯定是有问题的,有时对,有时错,就等于错!你在对verilog一些基本的定义都没有了解的情况下大谈底层逻辑,我确实有点不适应。你不愿意去学习可综合verilog的语义,也不愿意过多的谈编译器的功效,你只喜欢一个门一个门的搭起来,然后用verilog描述出来,我见过的很多偏硬的人都这样。我本人在进入现在的ic公司的时候,既没有学过verilog,也没学过vhdl,全部是用图形来搭电路,我现在还记得面试我的人当时那惊奇的目光。就事论事,这种问题很容易解决,就一个语句,但是个人好恶却很难解决,即使是长篇大论也不一定有效果。
所谓辩论是指希望有不同的声音和思路,这样大家都有进步,如果每个人都只想解决自己的问题,没有几个人会愿意做那个只解决别人问题的人。时间长了,这种帖子会冷得很,估计不会有什么人回。

使用特权

评论回复
13
钻研的鱼|  楼主 | 2010-1-13 11:58 | 只看该作者
用modelsim做的实验

module adder(
        clk,
        a,
        b,
   c,
        ov
);
input clk;
input [7:0] a;
input [7:0] b;
output reg [7:0] c;
output reg ov;


always @(posedge clk) begin
                {ov,c} <= a + b;
end

endmodule
16进制:a赋值为0x02,b赋值为0xfd,  结果:c的值是0xff,ov为0
   假设a、b看作是无符号数,10进制:a为2,b为253,c的值是255,正确
   假设a、b看作是有符号数,10进制:a为2,b为-3,c的值是-1,正确


16进制:a赋值为0x02,b赋值为0xfe,  结果:c的值是0x00,ov为1
   假设a、b看作是无符号数,10进制:a为2,b为254,最终结果应该是256,由于c只有8bit,所以溢出
   假设a、b看作是有符号数,10进制:a为2,b为-2,最终结果应该是0,也不应该溢出
   
verilog中把reg类型看做无符号数,ov其实是表示进位。可以稍微修改一下,用在有符号的加法中。  

module adder(
        clk,
        a,
        b,
   c,
        ov
);
input clk;
input [7:0] a;
input [7:0] b;
output reg [7:0] c;
output ov;
reg carry;

wire [7:0] sum;
assign sum = a + b;

wire ov_flag;
assign ov_flag = (sum[7] & ~a[7] & ~b[7]) | (~sum[7] & a[7] & b[7]);

always @(posedge clk) begin
   c <= sum;
   ov <= ov_flag;
end
endmodule

如果ov为1,则表示有符号数运算结果不正确,否则,正确!
   
16进制:a赋值为0x02,b赋值为0xfd,  结果:c的值是0xff,ov为0
   a、b看作是有符号数,10进制:a为2,b为-3,c的值是-1,正确


16进制:a赋值为0x02,b赋值为0xfe,  结果:c的值是0x00,ov为0
   a、b看作是有符号数,10进制:a为2,b为-2,最终结果应该是0
   
16进制:a赋值为0x02,b赋值为0xff,  结果:c的值是0x01,ov为0
   a、b看作是有符号数,10进制:a为2,b为-1,最终结果应该是1   
   
16进制:a赋值为0x77,b赋值为0x78,  结果:c的值是0xef,ov为1
   a、b看作是有符号数,10进制:a为119,b为120,最终结果应该是239,但c的最高位是符号位,正数最大值为127,所以溢出,结果不对   

16进制:a赋值为0x81,b赋值为0x82,  结果:c的值是0x03,ov为1
   a、b看作是有符号数,10进制:a为-127,b为-126,最终结果应该是-253,但c的最高位是符号位,负数最大值为-128,所以溢出,结果不对

使用特权

评论回复
14
netvideo| | 2010-2-3 23:46 | 只看该作者
module gen_diff(
   dataa ,
   datab ,
   datac
);

input  [7:0]  dataa ;
input  [7:0]  datab ;
output [7:0]  datac ;

wire [8:0] tmp;
assign tmp=dataa-datab;
assign datac=tmp[8]?(1'b1+~tmp):tmp;
endmodule

使用特权

评论回复
15
草原狼10| | 2013-8-7 17:33 | 只看该作者
学习来的!!!!

使用特权

评论回复
16
GoldSunMonkey| | 2013-8-7 23:39 | 只看该作者
草原狼10 发表于 2013-8-7 17:33
学习来的!!!!

您要是能分享您的心得就更好了

使用特权

评论回复
17
草原狼10| | 2013-8-8 09:02 | 只看该作者
GoldSunMonkey 发表于 2013-8-7 23:39
您要是能分享您的心得就更好了

恩恩

使用特权

评论回复
18
GoldSunMonkey| | 2013-8-8 23:09 | 只看该作者
草原狼10 发表于 2013-8-8 09:02
恩恩

欢迎常来啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

64

主题

967

帖子

4

粉丝