Verilog中的signed运算

1.纯signed运算

module signed_op(
	input					clk_i,
	input					rst_n,
	input	signed			cin,
	input	signed [3:0]	dataa_i,
	input	signed [3:0]	datab_i,
	output	signed [4:0]	sum_o
);	

assign sum_o = dataa_i + datab_i + cin;

endmodule

Verilog中的signed运算_第1张图片

  • 最后四行都是Decimal格式显示。
  • cin为signed时,高就是减一,低电平无影响。
  • 纯signed运算没有异常。

2.signed与unsigned混合运算

module signed_op(
	input					clk_i,
	input					rst_n,
	input					cin,
	input	signed [3:0]	dataa_i,
	input	signed [3:0]	datab_i,
	output	signed [4:0]	sum_o
);	

assign sum_o = dataa_i + datab_i + cin;

endmodule

在这里插入图片描述

  • 最后四行都是Decimal格式显示。
  • signed与unsigned混合运算时,会将所有数据认为是unsigned进行运算也就是将加数和进位都以0拓展至sum的5bit位宽。比如本身是signed表述的4’b1111=-7D,但是由于混合运算,以0拓展,变成了5’b01111=15D。
  • 若把显示格式全部设置为unsigned,结果显示正确,这样验证了上述说法。

Verilog中的signed运算_第2张图片

  • 如何能够保证两者混合运算仍能输出有符号的正确结果呢? 将signed数据以符号位进行人为的拓位。
module signed_op(
	input					clk_i,
	input					rst_n,
	input					cin,
	input	signed [3:0]	dataa_i,
	input	signed [3:0]	datab_i,
	output	signed [4:0]	sum_o
);	

assign sum_o = {dataa_i[3],dataa_i} + {datab_i[3],datab_i} + cin;

endmodule

在这里插入图片描述

  • 最后四行都是Decimal格式显示。
  • 添加了符号位拓展,比如本身是signed表述的4’b1111=-7D,由于存在混合运算,引入人为的以1拓展,变成了5’b11111=-7D。如此一来保证了运算正确。
  • cin是unsigned模式,与signed不同,高电平表述+1,低电平无影响。
  • 把上面拓位的assign语句改为下面的形式也可以实现正确的signed运算,但是 $signed类型转换不可综合。(只可以用于仿真)
assign sum_o = dataa_i + datab_i + $signed(cin);

在这里插入图片描述

3.不同位宽signed与unsigned混合运算

module signed_op(
	input					clk_i,
	input					rst_n,
	input					cin,
	input	signed	 [7:0]	dataa_i,
	input	signed	 [5:0]	datab_i,
	output	signed [8:0]	sum_o
);	

assign sum_o = dataa_i + datab_i + cin;

endmodule

在这里插入图片描述

  • 最后3行都是unsigned格式显示。再向上三行是Decimal。

  • 由于cin是无符号的,所以整个运算都按照无符号来进行了。

  • 如何进行不等位宽的混合运算呢?首先明确:verilog在进行计算的时候是按照补码来进行的。-6D原码:10_0110B,补码11_1010B。这种情况同样需要进行拓位,拓位是以多个符号位进行补全。比如拓展成8bit的-6D,就是1111_1010B。易错的是按照上面的思维定势,只拿1bit符号位放到最高,其余补0,这是不对的。

module signed_op(
	input					clk_i,
	input					rst_n,
	input					cin,
	input	signed	 [7:0]	dataa_i,
	input	signed	 [5:0]	datab_i,
	output	signed [8:0]	sum_o
);	

wire signed [8:0] datab_w = {{3{datab_i[5]}},datab_i};
wire signed [8:0] dataa_w = {dataa_i[7],dataa_i};

assign sum_o = dataa_w + datab_w + cin;

endmodule

在这里插入图片描述

  • 加数类型混合的情况,也是类似的:
module signed_op(
	input					clk_i,
	input					rst_n,
	input					cin,
	input			 [7:0]	dataa_i,
	input	signed	 [5:0]	datab_i,
	output	signed [8:0]	sum_o
);	

wire signed [8:0] datab_w = {{3{datab_i[5]}},datab_i};

assign sum_o = dataa_i + datab_w + cin;

endmodule

在这里插入图片描述

  • data_b、sum_o是Decimal,cin和data_a是unsigned。

你可能感兴趣的:(HDL语法)