Array literals in VHDL - arrays

We have defined a vector as
A: in std_logic_vector(7 downto 0);
when assigning a literal to this vector such as
A <= {'1', '0', '0', '1'};
will this expession populate the vector positions of 7,6,5 & 4 or positions of 3,2,1 & 0
The idea is a vector of bits which we can sign extend to an 8 bit integer but it will only currently work if the latter is true.

Invalid syntax here. If you want to keep the various bits as a list you can make the assignment:
A(3 downto 0) <= (3 => '1', 2=> '0', 1=> '0', 0=> '1') ;
Bonus sign extension:
A <= (2=> '0', 1=> '0', 0=> '1', others => '1') ;

I don't think this is legal - at least it isn't in Xilinx ISE.
The right way to do it would be to specify the part of A that you want to assign:
A(3 downto 0) <= "1001";

Why are you using individual bits as a numeric constant? Is there some reason you're not doing something like:
A <= std_logic_vector(to_signed(-7,A'length));
You can get rid of the std_logic_vector cast if you A is a signed type to start with, and you can use unsigned types and conversion functions if you don't want sign extension.

If you want sign extension, use the appropriate type signed.
Then you can convert a proper number (like -1) to a vector of the appropriate width using the to_signed function, for example:
to_signed (-1, a'length)
Advantages to doing this over explicit bit setting are:
simpler code
everyone can read it and understand what you are doing (no comments necessary!)
when a changes length, it all (still) Just Works

Related

How to analyze bytes of a variable's value in C

is it possible to divide for example an integer in n bits?
For example, since an int variable has a size of 32 bits (4 bytes) is it possible to divide the number in 4 "pieces" of 8 bits and put them in 4 other variables that have a size of 8 bits?
I solved using unsigned char *pointer pointing to the variable that I want to analyze bytes, something like this:
int x = 10;
unsigned char *p = (unsigned char *) &x;
//Since my cpu is little endian I'll print bytes from the end
for(int i = sizeof(int) - 1; i >= 0; i--)
//print hexadecimal bytes
printf("%.2x ", p[i]);
Yes, of course it is. But generally we just use bit operations directly on the bits (called bitops) using bitwise operators defined for all discrete integer types.
For instance, if you need to test the 5th least significant bit you can use x &= 1 << 4 to have x just to have the 5th bit set, and all others set to zero. Then you can use if (x) to test if it has been set; C doesn't use a boolean type but assumes that zero is false and any other value means true. If you store 1 << 4 into a constant then you have created a "(bit) mask" for that particular bit.
If you need a value 0 or 1 then you can use a shift the other way and use x = (x >> 4) & 1. This is all covered in most C books, so I'd implore you to read about these bit operations there.
There are many Q/A's here how to split integers into bytes, see e.g. here. In principle you can store those in a char, but if you may require integer operations then you can also split the int into multiple values. One problem with that is that an int is just defined to at least store values from -32768 to 32767. That means that the number of bytes in an int can be 2 bytes or more.
In principle it is also possible to use bit fields but I'd be hesitant to use those. With an int you will at least know that the bits will be stored in the least significant bits.

How to initialize an _Extint() from an hardcoded litteral?

The rust project I m using depends on fixed_hash 0.2.2. And I would need to compare one H160 against a literal (mode exactly know if my_var==0xdac17f958d2ee523a2206206994597c13d831ec7).
Internally, the H160 type is just a pointer to a plain integer encoded like with _Extint(). And as I already need to pass the value to a C module, I m thinking about just making the comparison from there.
The problem is integer litterals in clang are read as 64 bits Integers, so that
const _ExtInt(160) my_const=0xdac17f958d2ee523a2206206994597c13d831ec7;
fails with
<source>:1:28: error: integer literal is too large to be represented in any integer type
So how to assign 0xdac17f958d2ee523a2206206994597c13d831ec7 to my_const in big endian?
Construct it from smaller values and shift.
const _ExtInt(160) my_const =
(unsigned _ExtInt(160))0xdac17f95ull << 128 |
(unsigned _ExtInt(160))0x8d2ee523a2206206ull << 64 |
(unsigned _ExtInt(160))0x994597c13d831ec7ull << 0;

C / Real Time initialize memory with different type of datas

I'm facing an issue :
Today i want declare 300 bytes and initialize them with different datas
for example :
unsigned short memory[] = {
0xFFFF, 0xFFFF, "X6", "M1", 1, 150 , 6, .....
}
I want to do that because i want that my data to be initialize on memory as this :
Value of X and 6 on the same 2 Bytes. if i do 'X', '6' i'll have :
0x0058 and 0x0006 instead of 0x5806..
Can you please light my mind ?
I'm a begginer in real time development.
Thanx for your times.
Naqued
"X6" is a string that consists of 3 bytes. I don't know what your compiler does with it (complain?).
To create an unsigned short initializer with characters, use 'XX' for example, which results in 0x5858. To use values of nibbles that are not characters you can include an escaped value in the character constant.
'X\x06' would give you 0x5806. Note how the second byte uses a hexadecimal escape character within the character constant, written as a backslash (start of escape), followed by 'x' (the base of the number that follows), followed by the byte value 06. Depending on your architecture, you may need to write it as '\x06X'.
If I understand correctly, you want to declare a 2-byte item array, but initialize some elements byte by bytes.
If you want to do that following your example syntax, you could do it with binary operations :
'X' << 8 | 6
Here you are starting with the binary value of char 'X', offsetting it by 8 bits left, thus occupying the leftmost byte of the 2-byte unsigned short. Then you are doing a binary OR with what you want on the right byte to insert it.
So in your case it would be :
unsigned short memory[] = {
0xFFFF, 0xFFFF, 'X' << 8 | 6, 'M' << 8 | 1, 1, 150 , 6, .....
}
Thanks for all your respons.
I found an other way to do it :
{ 0xFFFF, 0xFFFF, (('X' << 8) + '6') }
Here i'm offsetting X on 8bits left and simply add the '6' carac by + .
it do the right things too.
i understand better how work byte offset now.
Thanks to all

Converting C Macro to VHDL

I'm fairly new to VHDL and trying to convert two given C macros to be executed as a single instruction on my FPGA. The macros are:
#define m_in_bits(buf, num) (buf) >> (24 - (num)) // buf is uint32_t
#define m_ext_bits(buf, i) ((buf) < (1<<((i)-1)) ? (buf) + (((-1)<<(i)) + 1) : (buf))
And the C code that uses the macros is:
m_ext_bits(m_in_bits(buffer, size), size);
I'm having issues with getting m_ext_bits to properly compile. Here's my VHDL:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity myEntity is
port(
signal buffer: in std_logic_vector(31 downto 0);
signal result: out std_logic_vector(31 downto 0)
);
end entity myEntity;
architecture myArch of myEntity is
signal size : signed (3 downto 0);
begin
size <= signed(buffer(27 downto 24));
result(15 downto 0) <= std_logic_vector(signed(buffer(23 downto 0)) srl (24 - to_integer(size))
+ signed((-1 sll to_integer(size)) + 1)); -- the offending line
end architecture myArch ;
The long line beginning with result(15 downto 0) <= actually compiles without error (that implements the m_in_bits macro). However, when I add the following line, beginning with the +, errors occur. I tried playing around with casting the std_logic_vector and signed types and the errors change.
type of expression is ambiguous - "SIGNED" or "UNSIGNED" are two possible matches...
can't determine definition of operator ""sll"" -- found 0 possible definitions...
illegal SIGNED in expression...
I think it's a matter of proper casting and using the correct types to fulfill the required operations.
First, buffer is a reserved VHDL word, so change that; using argbuf below.
The expression -1 sll to_integer(size) is not defined in VHDL, since the
integer value -1 is a numerical expression only with no bit representation
specified by VHDL, so shifting is not possible. Neither are operations like
bitwise and, or, etc. on integers. A -1 representation in 24-bit signed type can be created as:
to_signed(-1, 24)
There is a length issue with the assign, since 16-bit signal (result(15 downto
0)) is assigned with 24-bit value (based on right side argbuf(23 downto 0)).
The srl should then compile when the above is addressed.
Code as:
result(15 downto 0) <= std_logic_vector(resize((signed(argbuf(23 downto 0)) srl (24 - to_integer(size)))
+ signed((to_signed(-1, 24) sll to_integer(size)) + 1), 16));
However, the VHDL shift operators, e.g. srl, may give unexpected results, as
described in this page "Arithmetic and logical shifts and rotates are done with
functions in VHDL, not
operators",
so you may consider using the shift functions defined in numeric_std instead,
e.g. shift_right, as a general coding style. Code with functions as:
result(15 downto 0) <= std_logic_vector(resize(shift_right(signed(argbuf(23 downto 0)), 24 - to_integer(size))
+ signed(shift_left(to_signed(-1, 24), to_integer(size)) + 1), 16));

Bits Shift in C- is the i bit on?

I'm trying to understand the following function which decides whether a bit is on:
int isBitISet( char ch, int i )
{
char mask = 1 << i ;
return mask & ch ;
}
First, why do I get a char? for ch=abcdefgh and i=5 the function suppose to return the fifth bit from the right (?) , d. so mask=00000001<<5=00100000, and 00100000 & abcdefgh = 00c00000.
Can you please explain me how come we get char and we can do all these shifts without any casting? how come we didn't get the fifth bit and why the returned value is really the Indication whether the bit is on or not?
Edit: the 'abcdefg' are just a symbols for the bits, I didn't mean to represent a string in a char type.
I used to think of a char as 'a' and not as an actual 8 bits, so probably this is the answer to my first question.
It won't give you the fifth bit. Binary numbers start at 20, so the first bit is actually indexed with 0, not with 1. It will give return you sixth bit instead.
Examples:
ch & (1 << 0); // first bit
ch & (1 << 1); // second bit
ch & ((1 << 3) | (1 << 2)); // third and fourth bit.
Also, a char is only an interpretation of a number. On most machines it has a size of 8 bit, which you can either interpret as a unsigned value (0 to 255) or signed value (-128 to 127). So basically it's an integer with a very limited range, thus you can apply bit shifting without casting.
Also, your function will return an integer value that equals zero if and only if the given bit isn't set. Otherwise it's a non-zero value.
The function may return a char, because the input it works on is also a char only. You certainly can not pass in ch=abcdefgh, because that would be a string of 8 chars.
You can do shifts on chars, because C allows to do it. char is just an 8-bit integer type so there's no need to disallow it.
You are right about the fact, that isBitISet(abcdefgh, 5) returns 00c00000 if the letters a, b, etc. are bits in the binary representation of numbers.
The return value is not the fifth bit from the right, it is the same number as in the input, but with all the bits but the fifth bit zeroed.
You also have to remember that numbering of bits goes from zero, so the fifth bit being c is correct, just as that the zeroth bit is h.
This example uses an integer type to represent a boolean value. This is common in C code prior to C99, as C didn't have the bool type.
If you treat your return value as a boolean value, remember that everything non-zero is true, and zero is false. Hence, the output of isBitISet is true for C if bit i is set, and false otherwise.
You should know by now that in computers, everything starts with 0. That is, bit number 5 is in fact the sixth bit (not the fifth).
Your analysis is actually correct, if you give it abcdefgh and 5, you get 00c00000.
When you do the "and":
return mask & ch;
since mask has type int, ch will also automatically be cast to int (same way as many other operators). That's why you don't need explicit casting.
Finally, the result of this function is in the form 0..0z0..0. If z, the bit you are checking for is 0, this value is 0 which is false as long as an if is concerned. If it is not zero, then it is true for an if.
Do:
return 0 != (mask & ch) ;
if you want a bool (0x00000000 or 0x00000001) return. mask & ch alone will give you the bit you're asking about at correct position.
(others said more than enuff about i=5 being sixth bit)
First of all, this function does not return the i-th bit, but tells you if that bit is on or off.
The usage of char mask is implementation depend here. Simply defines an 8-bit mask since the value on which to apply this mask is a char.
Why would you need a cast when 1 is a char? i is only an value for << operator.
ch=abcdefgh makes no sense as an input. ch is char, so ch can only be one character.
The working is as follows: first you construct a mask to zero all the bits you don't need. So for example if the input is ch = 204 (ch = 11001100) and we want to know if the 6th bit is on, so i = 5. So mask = 1 << 5 = 00100000. Then this mask is applied to the value with an AND operation. This will zero everything except the bit in question: 11001100 & 00100000 = 00000000 = 0. As 0 is false in C, then 6th bit is not set. Another example on same ch input and i = 6: mask = 1 << 6 = 01000000; 11001100 & 01000000 = 01000000 = 64, which is not 0, and thus true, so 7th bit is set.

Resources