假设我有一个注册reg [15:0] my_reg
,其中包含一个16位签名样本:
如何将样本从签名转换为未签名?
我已阅读this Wikipedia article,并且知道有符号数的2位补码,但如何有效地在Verilog中执行此转换?
(我不知道my_reg
是正还是负,并且它在每个时钟周期都会发生变化=我在每个正时钟边沿都会收到一个新样本。)
最终目标(增加一点上下文)是实现数字FPGA内置自动增益控制(AGC)。
编辑:按照建议我将这两个问题分成两个不同的帖子。查看另一个here
答案 0 :(得分:6)
在Verilog中,reg包含二进制数据,无符号签名只是解释的问题。位值保持不变,减法和加法总是使用二进制补码执行。
例如,我们可以查看4位值,看看如何解释数字:
Binary Unsigned signed
1000 8 -8
1110 14 -2
1111 15 -1
0001 1 1
0010 2 2
0111 7 7
我认为您希望将这些数字校准为正数,-8变为0,0变为8,7变为15.这将通过将1加入MSB位置来完成。在我们的4位示例中:
Binary Signed Addition Unsigned result
1000 -8 +1000 0000 0
1110 -2 +1000 0110 6
1111 -1 +1000 0111 7
0001 1 +1000 1001 9
0010 2 +1000 1010 10
0111 7 +1000 1111 15
有一些密切相关的问题:
1. Verilog: how to take the absolute value。
2. Verilog Construction of Two's Complement Comparator。
如果您的注册确实包含签名信息,那么在语义上您应该将其定义为:
reg signed [15:0] my_reg;
绝对值:
reg signed [15:0] my_reg;
reg [15:0] my_reg_unsigned;
always @* begin
if (my_reg < 16'd0) begin
my_reg_unsigned = -my_reg ;
end
else begin
my_reg_unsigned = my_reg ;
end
end
如果您不需要绝对但只想使用该数字来驱动某些东西,只需将签名连接到无符号即可,即:
always @* begin
my_reg_unsigned = my_reg ;
end
这将复制位值,my_reg_unsigned
可以使用$signed(my_reg_unsigned)