converting a wire value to an integer in verilog - syntax

I want to convert the data in a wire to an integer. For example:
wire [2:0] w = 3'b101;
I want a method that converts this to '5' and stores it in an integer. How can I do that in a better way than this:
j=1;
for(i=0; i<=2; i=i+1)
begin
a=a+(w[i]*j);
j=j*2;
end
Also, how do I convert it back to binary once I have the value in an integer? This seems a clumsy way. Thank you.

Easy! Conversion is automatic in verilog if you assign to an integer. In verilog, all the data types are just collection on bits.
integer my_int;
always #( w )
my_int = w;

As Marty said : conversion between bit vectors and integers is automatic.
But there are a number of pitfalls. They are obvious if you keep in mind that an integer is a 32 bit signed value.
Don't try to assign e.g. a 40 bit value to an integer.
Default bit vector are unsigned so a 32 bit vector may become negative when it is an integer.
The opposite is also true: a negative integer e.g. -3 will become an 8 vector with value 8'b11111101
I don't know why you want to convert to an integer and back. I just want to point out that arithmetic operations are fully supported on signed and unsigned bit vectors. In fact they are more powerful as there is no 32-bit limit:
reg [127:0] huge_counter;
...
always #(posedge clk)
huge_counter <= huge_counter + 128'h1;
Also using a vector as index is supported:
wire [11:0] address;
reg [ 7:0] memory [0:4095];
...
assign read_data = memory[address];

Related

Efficiently transform float and double values into bytes that preserve the comparison relationship between values

I need a method by which to efficiently translate any float or double value to an array of bytes so that it preserves the comparison relationship to any other value.
Example: V1 and V2 are turned into arrays A1 and A2. If A1[0]<A2[0], then V1 must be smaller than V2. Same for larger. If A1[0]==A2[0] and A1[1]>A2[1] then V1 must be larger than V2. And so on. If all the bytes are the same, then the values V1 and V2 must be equal.
For a four byte integer I, an array that would satisfy the above condition would be [U>>24, (U>>16)&255, (U>>8)&255, U&255], where U is the uint positive value V-int.MinValue.
Since doubles are stored as 8 bytes, I expect something close to 8 bytes.
Do you think such a thing can be achieved? Thanks!
C# solution is preferred.
The standard representation for doubles and floats that is used by most languages, IEEE 754, is already very close to supporting this requirement.
In C#, you can use BitConverter.DoubleToInt64Bits or SingleToInt32Bits to get the underlying bits of a double or float directly as an integer.
In order to make comparisons work out right, you only have to fix up the way negative numbers are handled:
long bits = BitConverter.DoubleToInt64Bits( theDouble );
if (bits < 0L) {
bits ^= Int64.MaxValue;
}
The resulting longs will then have the same numeric order as the corresponding doubles. This works for all values except Nan, which isn't really comparable to anything else. The infinities, +0.0 and -0.0 work fine.
If you want +0.0 and -0.0 to have the same value, you can do this:
long bits = BitConverter.DoubleToInt64Bits( theDouble );
if (bits < 0L) {
bits = (bits^Int64.MaxValue)+1L;
}
Note that if you want to make your byte array, you'll probably want to convert to an unsigned integer. You need to flip the sign bit if you want to preserve the ordering, or just do it like this:
long bits = BitConverter.DoubleToInt64Bits( theDouble );
ulong arraybits;
if (bits >= 0L) {
arraybits = (1UL<<63) + (ulong)bits;
} else {
arraybits = (ulong)~bits;
}

VHDL - Need some advice on division & multiplication

Fellow SO users,
I'm trying to calibrate a resistive humidity sensor that I'm reading values from the ADC. The ADC outputs an 8-bit value. I'm using a Vref value of 5V.
My first step in calibrating is to divide the number by 255 and multiply by the Vref value.
Hence, calibrated value = (output / 255) * Vref.
Now, in VHDL, I've come across some VHDL code to divide two numbers. The one I have divides two unsigned numbers so that shouldn't be a problem. It is over here;
VHDL divide two unsigned numbers
Now, in my VHDL file, I have the 8 bit ADC value (humidity) and I have defined two constants, max_val (11111111 = 255) and Vref (00000101 = 5) both as unsigned.
I'm first converting humidity to an unsigned by using unsigned(humidity) and then passing this value and the max_num value into the division function. With the result, I'm multiplying it by Vref.
Now, my question is;
Is this a good approach? I.e; the way I'm dividing and multiplying.
How do I convert the unsigned value back into a std_logic_vector?
Kind regards.
I think it should divided by 256? Or with 255 i think your result will almost similar (note that max distance is between 255/256 and 255/255: = 0.00390625). Result will be with fixed point number. Multiply by 5: shift right 2 = multiply by 4 then add with this number (A*5 = A*4 + A), your code should like:
A_Multiply_4 <= A&"00";
A_Multiply_5 <= A_Multiply_4 + A;
To convert from unsigned to std_logic_vector (i remember it exist in std_logic_1164):
slv_array <= std_logic_vector(unsigned_number);
If you wanna divide by 255, i think you should divide your num by 256 and add a little number after shift:
1/255 = 1/256 + 1/x
with x = 2 power something. Shifter is the best way.
I tried with 1/3 and have to pleasant with this method.
P/s x = 2^16 and you got diff between 2 case is 5.9838388480392156862745098039216e-8. But i don't think number you want have more than 8 bit after point.

How do I create numeric_std signed value greater than 2³¹-1?

In the following type and constant declaration, the last value in the array will not actually be 2**35-1, since integers greater than 2**31-1 are not standard VHDL (2002)
library ieee;
use ieee.numeric_std.all;
-- Boilerplate elided...
constant X_SIZE : natural := 40; -- Really, anything greater than 32
type x_array is array(natural range <>) of signed;
constant XS : x_array := (
to_signed(0, X_SIZE),
to_signed(1, X_SIZE),
to_signed(2**35 - 1, X_SIZE) -- Not possible!
);
I can't do to_signed(2, X_SIZE)**35 - 1 because exponentiation is not defined on signed. I'm loathe to type out the full array because it seems clunky and X_SIZE might change in the future. So how do I create the value I want here? Is there a better way than literally typing out 40 0s and 1s?
Depending on the value, there are a few ways to do it.
Using a hexadecimal literal is good for arbitrary numbers and will save a bit of space: x"1FFFFFFFF"
Aggregate assignment gives a way to specify a pattern (eg. for any size, one zero followed by all ones): (X_SIZE-1 downto 35 => '0', others => '1') — be warned though, if you try to combine this with other operators or functions, the compiler will not be able to infer the required size of the vector. You'll need to do something like: (X_SIZE-1 downto 35 => '1', 35 downto 0 => '0'). At this point you might not be saving much space, but depending on what you're doing, it might make your intent much clearer than a literal.
You can also construct a unit in the desired type, and shift it around: shift_left(to_unsigned(1, X_SIZE), 35) - 1.

What is this VHDL code setting max and min to? An explanation of fixed point representation would be helpful

constant MAX : unsigned(18 downto 0) := "100" & x"0000";
constant MIN : unsigned(18 downto 0) := "001" & x"0000";
What is this VHDL code setting max and min to? An explanation of fixed point representation would be helpful.
The & operator concatenates the two bit vectors "100" and x"0000" (e.g. "00" & "11" would be equivalent to "0011").
The X"012345689ABCDEF" syntax means that the following vector should be interpreted as a hex number (e.g. X"0" actually is "0000", X"F" would be "1111" or X"0F" would be "00001111"). This allows you to write a bit vector in a more compact way.
For the interpretation of a bit vector check e.g. http://en.wikipedia.org/wiki/Binary_numeral_system
For representation of hexdecimal numbers check e.g. http://en.wikipedia.org/wiki/Hexadecimal
Edit for clarification: I assume you are using the unsigned type from the numeric_std package. From the header of that package
This package defines numeric types and arithmetic functions
for use with synthesis tools. Two numeric types are defined:
-- > UNSIGNED: represents UNSIGNED number in vector form
-- > SIGNED: represents a SIGNED number in vector form
The base element type is type STD_LOGIC.
The leftmost bit is treated as the most significant bit.
Signed vectors are represented in two's complement form.
So your MAX is set to 2^18 and your MIN to 2^16.

binary number comparison

If I have a 32 bit two's complement number and I want to know what is the easiest way to know of two numbers are equal... what would be the fastest bitwise operator to know this? I know xor'ing both numbers and check if the results are zero works well... any other one's?
how about if a number is greater than 0?? I can check the 31'st bit to see if it's greater or equal to 0..but how about bgtz?
Contrary to your comments, '==' is part of Verilog, and unless my memory is a lot worse than usual tonight, it should synthesize just fine. Just for example, you could write something like:
// warning: untested, incomplete and utterly useless in any case.
// It's been a while since I wrote much Verilog, so my syntax is probably a bit off
// anyway (might well be more like VHDL than it should be).
//
module add_when_equal(clock, a, b, x, y, z);
input clock;
input [31:0] a, b, x, y;
output [31:0] z;
reg [31:0] a, b, x, y, z;
always begin: main
#(posedge clock);
if (a == b)
z <= x + y;
end
endmodule;
Verilog also supports the other comparison operators you'd normally expect (!=, <=, etc.). Synthesizers are fairly "smart", so something like x != 0 will normally synthesize to an N-input OR gate instead of a comparator.
// this should work as comparator for Equality
wire [31:0] Cmp1, Cmp2;
wire Equal;
assign Equal = &{Cmp1 ~^ Cmp2}; // using XNOR
assign Equal = ~|{Cmp1 ^ Cmp2}; // using XOR
if you can xor and then compare the result with zero then you can compare a result with some value and if you can compare something to a value then you can just compare the two values without using an xor and a 32 bit zero.

Resources