verilog 语法一问
wire [8:0] exp_in_pl1, exp_in_mi1;
assign exp_in_pl1= exp_in+ 1; // 9 bits - includes carry out
assign exp_in_mi1= exp_in- 1; // 9 bits - includes carry out
哪位能给解释一下? 在assign子句中,是怎么变成9bits的。
exp_in的高位补了个0?还是把减1转成加1_1111_1111了?多谢!
不同的综合器和仿真器理解不同,通常的作法是小位宽信号高位补零,对齐后进行加减。
但对于补码数会得到错误结果,所以建议先作符号位扩展,后加减。
问题的本质在于Verilog语言对位宽变换的处理.
assign exp_in_pl1 = exp_in+ 1;
这其中exp_in_pl1是9bit位宽, exp_in是8bit位宽, 1是32bit位宽(为什么呢?).
那么exp_in+ 1运算的结果就是32bit位宽, 然后把低9bits赋给exp_in_pl1, 就是这么简单.
比如exp_in=0, 则exp_in - 1 = -1, 那么exp_in_mi1就等于-1的低9bits.
代码中的数值/数字都会被解释为补码形式, 这很正常, 如果exp_in=0, 那你希望exp_in_mi1应该等于几?
从modelsim的仿真看,你说的是对的!
谢了!解释的很清楚!
能再问一下!一般这么做(扩展位宽)的目的是什么?
原文注释是:// 9 bits - includes carry out
有点困惑!难道是为了处理8`h00和8`hff的情况,所以要加1和减1?
看来对RTL code和电路设计的理解还要大大加强啊.
你对RTL code有困惑, 但是RTL code是用来描述你设计的电路的, 不是为了写代码而写代码. 代码中exp_in_pl1/exp_in_mi1的位宽, 完全取决于你的电路的要求, 代码只是描述电路的工具, 你要理解的是在电路中exp_in_pl1/exp_in_mi1的功能/作用是什么.
如果是算术计算, 那么显然2个8bits相加的结果应该是9bits, 否则可能会溢出(overflow), 这个在课程"计算机原理"或"微机原理"中讲的非常清楚, MPU/CPU都存在一个字长的问题, 但是寄存器再长, 计算都有溢出的可能, 所以有相应的flag或标志位.
如果是用做地址信号, 比如 reg_addr = base_addr + offset; 那么2个8bits相加的结果可以仍然是8bits, 因为地址空间是确定/有限/循环的.
如果是有限域运算, 那么2个8bits相加/相差/相除的结果, 仍然是8bits, 并且没有溢出的情况, 因为有限域是封闭的, 自成一体.
所以你的关注点不应该是代码, 而应该是电路, 是电路决定了代码的形式.
非常感谢!你说的也很对!努力中……
难道会存在一个 中间变量 老记录 exp_in+ 1运算的结果(32bit位宽)吗 ?
至于1是32bit位宽是因为现在的计算机一般以32位为多,故默认就是 32bit位宽
其实可以自己做个试验:
exp_in_pl1[8:0] = exp_in[7:0]+ 1;
$display("exp_in_pl1= |%b|%0b|", exp_in_pl1);
$display("exp_in + 1= |%b|%0b|", (exp_in+1));
$display("exp_in + 1'b1= |%b|%0b|", (exp_in+1'b1));
$display("exp_in + 10'b1 = |%b|%0b|", (exp_in+10'b1));
值都是一样的, 但比较一下打印出来的宽度, 就知道差异了. 实践出真知.
"难道会存在一个 中间变量 老记录 exp_in+ 1运算的结果(32bit位宽)吗?"
中间变量倒不必, 但位宽变换/扩展是计算的基本法则, 这有点类似于C语言中的数据类型转换.
32位确实是受硬件(CPU字长)的影响和限制, 不过还有一个原因是因为Verilog是发源于C, 而C语言中整型/短整型/长整型都有明确的位宽, 整型就是32位.
之前的Verilog1995位宽扩展只到32位, Verilog2001就没有这个限制了. 一般来说呢, a+1'b1 vs. a+1, 前面那种写法要好一点点.
写成 assign exp_in_pl1 = exp_in+ 1'h1;就好理解了
好多了知识呀