Assuming I have a register reg [15:0] my_reg
, which contains a 16-bit signed sample:
How do I convert the sample from signed to unsigned?
I have read this Wikipedia article, and am aware of the 2-bit complement for signed numbers, but how do I perform this conversion in Verilog efficiently?
(I don't know if my_reg
is positive or negatve, and it changes in every clock cycle = I receive a new sample on every positive clock edge).
The ultimate goal (to add a little bit of context) is to implement a digital FPGA built-in automatic gain control (AGC).
EDIT: as suggested I have split the two questions in two different posts. See the other one here
Signed numbers. By default, 'reg' and 'wire' data type are 'unsigned number, whereas 'integer' is signed number. Signed number can be defined for 'reg' and 'wire' by using 'signed' keywords i.e. 'reg signed' and 'wire signed' respectively as shown in Table 3.2.
logic, bit, reg, and packed arrays of those types are all unsigned by default.
Referring to SV LRM 1800-2012 : "... the $signed and $unsigned system functions are available for casting the signedness of expressions.". So, if we have logic signed [7:0] myreg; and myreg=$signed(4'b1100) , then the MSB is considered as signed bit and myreg=-4 .
Yes it is synthesizable. But it builds combinatorial logic (slow).
In Verilog a reg contains binary data, signed unsigned are just a matter of interpretation. The bit values stay the same, subtraction and addition are always performed using two's complement.
For example, we can look at a 4 bit value and see how the numbers can be interpreted:
Binary Unsigned signed
1000 8 -8
1110 14 -2
1111 15 -1
0001 1 1
0010 2 2
0111 7 7
I think you want to calibrate these numbers on to a positive scale, -8 becomes 0, 0 becomes 8, 7 becomes 15. This would be done by adding 1 in to the MSB position. In our 4 bit example:
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
There are some closely related questions:
1. Verilog: how to take the absolute value.
2. Verilog Construction of Two's Complement Comparator.
If your register really does contain signed information then semantically you should define it as :
reg signed [15:0] my_reg;
To absolute the value:
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
If you do not need to absolute it but just want to use that number to drive some thing it is valid to just connect signed to an unsigned, ie:
always @* begin
my_reg_unsigned = my_reg ;
end
This will copy the bit values, my_reg_unsigned
can be interpreted as signed using $signed(my_reg_unsigned)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With