downto vs. to in VHDL
Asked Answered
D

7

20

I'm not sure I understand the difference between 'downto' vs. 'to' in vhdl.

I've seen some online explanations, but I still don't think I understand. Can anyone lay it out for me?

Delectation answered 4/10, 2011 at 0:3 Comment(0)
A
17

One goes up, one goes down:

-- gives 0, 1, 2, 3:
for i in 0 to 3 loop

-- gives 3, 2, 1, 0:
for i in 3 downto 0 loop
Angrist answered 4/10, 2011 at 0:7 Comment(4)
Is their a difference in bit location? For example: 7 downto 2 vs 2 to 7?Delectation
To answer the above, for anyone coming past in the future, yes, there is a difference. You are controlling endian-ness. (See answer by vipin) or Wiki on endianness en.wikipedia.org/wiki/EndiannessNic
@Nic "endian-ness" as in a computer science term, or as "what I understand of the word, or how an engineer might use it"? Because, big- and little-endian, in computer science, refer to an aspect of an architecture that is exposed to the Istruction Set Architecture (ISA) level and, thus, can make a difference for programs, like FTP. Bit ordering, in the internal, hardware representation of a number, is not exposed at the ISA level.Belaud
For future folks - this is not controlling endianness! Endianness applies at the byte-level and doesn't affect bit ordering. (Think 0xF00D becoming 0x0DF0).Fugitive
S
46

If you take a processor, for Little endian systems we can use "downto" and for Bigendian systems we use "to".

For example,

signal t1 : std_logic_vector(7 downto 0); --7th bit is MSB and 0th bit is LSB here.

and,

signal t2 : std_logic_vector(0 to 7); --0th bit is MSB and 7th bit is LSB here.

You are free to use both types of representations, just have to make sure that other parts of the design are written accordingly.


This post says something different:

"The term big endian (or little endian) designates the byte order in byte oriented processors and doesn't fit for VHDL bit vectors. The technical term is ascending and descending array range. Predefined numerical types like signed and unsigned are restricted to descending ranges by convention."

So, this answer can be confusing...

Swound answered 4/10, 2011 at 17:42 Comment(2)
Helpful AND succinct. Thank you!Delectation
The edit is correct (although the link is now broken). Endianness much more commonly refers to byte ordering, not bit ordering - especially in the context of a "processor" (CPU). Therefore, this answer is somewhere between confusing and incorrect.Ultramontane
A
17

One goes up, one goes down:

-- gives 0, 1, 2, 3:
for i in 0 to 3 loop

-- gives 3, 2, 1, 0:
for i in 3 downto 0 loop
Angrist answered 4/10, 2011 at 0:7 Comment(4)
Is their a difference in bit location? For example: 7 downto 2 vs 2 to 7?Delectation
To answer the above, for anyone coming past in the future, yes, there is a difference. You are controlling endian-ness. (See answer by vipin) or Wiki on endianness en.wikipedia.org/wiki/EndiannessNic
@Nic "endian-ness" as in a computer science term, or as "what I understand of the word, or how an engineer might use it"? Because, big- and little-endian, in computer science, refer to an aspect of an architecture that is exposed to the Istruction Set Architecture (ISA) level and, thus, can make a difference for programs, like FTP. Bit ordering, in the internal, hardware representation of a number, is not exposed at the ISA level.Belaud
For future folks - this is not controlling endianness! Endianness applies at the byte-level and doesn't affect bit ordering. (Think 0xF00D becoming 0x0DF0).Fugitive
B
15

An interesting online reference I found is here, where among others, under the section "Array Assignments," you can read:

Two array objects can be assigned to each other, as long as they are of the same type and same size. It is important to note that the assignment is by position, and not by index number. There is no concept of a most significant bit defined within the language. It is strickly interpreted by the user who uses the array. Here are examples of array assignments:

with the following declaration:

....
SIGNAL z_bus: BIT_VECTOR (3 DOWNTO 0);
SIGNAL a_bus: BIT_VECTOR (1 TO 4);
....

z_bus <= a_bus;

is the same as:

z_bus(3) <= a_bus(1);
z_bus(2) <= a_bus(2);
z_bus(1) <= a_bus(3);
z_bus(0) <= a_bus(4);

Observations:

1) Any difference of "downto" and "to" appears when we want to use a bit-vector not just to represent an array of bits, where each bit has an independent behavior, but to represent an integer number. Then, there is a difference in bit significance, because of the way numbers are processed by circuits like adders, multipliers, etc.

In this arguably special case, assuming 0 < x < y, it is a usual convention that when using x to y, x is the most significant bit (MSB) and y the least significant bit (LSB). Conversely, when using y downto x, y is the MSB and x the LSB. You can say the difference, for bit-vectors representing integers, comes from the fact the index of the MSB comes first, whether you use "to" or "downto" (though the first index is smaller than the second when using "to" and larger when using "downto").

2) You must note that y downto x meaning y is the MSB and, conversely, x to y meaning x is the MSB are known conventions, usually utilized in Intellectual Property (IP) cores you can find implemented and even for free. It is, also, the convention used by IEEE VHDL libraries, I think, when converting between bit-vectors and integers. But, there is nothing even difficult about structural modeling of, e.g., a 32-bit adder that uses input bit-vectors of the form y downto x and use y as the LSB, or uses input bit-vectors of the form x to y where x is used as the LSB...

Nevertheless, it is reasonable to use the notation x downto 0 for a non-negative integer, because bit positions correspond to the power of 2 multiplied by the digit to add up to the number value. This seems to have been extended also in most other practice involving integers.

3) Bit order has nothing to do with endianness. Endianness refers to byte ordering (well, byte ordering is a form of bit ordering...). Endianness is an issue exposed at the Instruction Set Architecture (ISA) level, i.e., it is visible to the programmer that may access the same memory address with different operand sizes (e.g., word, byte, double word, etc). Bit ordering in the implementation (as in the question) is never exposed at the ISA level. Only the semantics of relative bit positions are visible to the programmer (e.g., shift left logical can be actually implemented by shifting right a register who's bit significance is reversed in the implementation).

(It is amazing how many answers that mention this have been voted up!)

Belaud answered 18/7, 2014 at 19:28 Comment(7)
Thanks for your suggestion to my answer, but it's actually correct already. Note the answer says "in the direction of the loop" -- we aren't changing from a : IN SLV(7 DOWNTO 1) to a : IN SLV(1 TO 7), in which case a palindrome would indeed not see any difference. But the change is FOR i IN 1 TO 7 vs FOR i IN 7 DOWNTO 1... and then any input with two set bits will see a difference, palindrome or not.Vaules
Also, it's a bit ambiguous, but "endianness" is correctly used to refer to either bit order or byte order.Vaules
@BenVoigt: I disagree. "Endianness" has to do with programming (read/write using different size operands -- in number of bytes) and is not related to bit level implementation. So, it is always about byte order, unless you use it for something that is not related to big/little endian.Belaud
The ordering of bits inside a byte is never exposed at the ISA level, as is the case for byte ordering, where you can have lb (load byte) and lw (load word), or even ldw (load double-word). Thus, relative bit order is only visible at HW implementation time, and does not make any difference to programs like FTP, as "endianness" does.Belaud
Also, unless you are very careful, bit-reversing of (say) a word, does not result to the same as reading its bytes and placing them in reverse order in a word-size register (e.g., 0x55555555 reversing bytes is the same, but reversing bits it is 0xAAAAAAAA). Thus, bit-reversing could conflict with the traditional definition of "endianness," unless you reverse the order of bits also whenever loading/storing a single byte from/to memory (which does not need additional HW). In other words, you can implement "endianness" by bit reversing, but "endianness" (visible to programs) is not bit reversing.Belaud
"Endianness" has to do with the relative order of bytes in memory when addressed in larger quantities (e.g. words). It appears at programming time, because bytes are addressable and also words and d-words, etc. It is implemented in HW mostly among components one of which is memory and not any kind of components. Between other component types, it is more natural for bit order to be important, instead of byte order, as the inputs and outputs of none-memory components have only one size (you cannot address inside them, other than the bits).Belaud
For my comment on your post, you are right; my mistake.Belaud
N
4

In vector types, the left-most bit is the most significant. Hence, for 0 to n range, bit 0 is the msb, for a n downto 0 range bit n is the msb.

This comes in handy when you are combining IP which uses both big-endian and little-endian bit orderings to keep your head straight!

For example, Microblaze is big-endian and uses 0 as its msb. I interfaced one to an external device which was little-endian, so I used 15 downto 0 on the external pins and remapped them to 16 to 31 on the microblaze end in my interface core.

VHDL forces you to be explicit about this, so you can't do le_vec <= be_vec; directly.

Netty answered 7/10, 2011 at 14:57 Comment(0)
V
3

Mostly it just keeps you from mixing up the bit order when you instantiate components. You wouldn't want to store the LSB in X(0) and pass that to a component that expects X(0) to contain the MSB.

Practically speaking, I tend to use DOWNTO for vectors of bits (STD_LOGIC_VECTOR(7 DOWNTO 0) or UNSIGNED(31 DOWNTO 0)) and TO for RAMs (TYPE data_ram IS ARRAY(RANGE NATURAL<>) OF UNSIGNED(15 DOWNTO 0); SIGNAL r : data_ram(0 TO 1023);) and integral counters (SIGNAL counter : NATURAL RANGE 0 TO max_delay;).

To expand on @KerrekSB's answer, consider a priority encoder:

ENTITY prio
    PORT (
        a : IN STD_LOGIC_VECTOR(7 DOWNTO 1);
        y : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
    );
END ENTITY;

ARCHITECTURE seq OF prio IS
BEGIN
    PROCESS (a)
    BEGIN
        y <= "000";
        FOR i IN a'LOW TO a'HIGH LOOP
            IF a(i) = '1' THEN
                y <= STD_LOGIC_VECTOR(TO_UNSIGNED(i, y'LENGTH));
            END IF;
        END LOOP;
    END PROCESS;
END ENTITY;

The direction of the loop (TO or DOWNTO) controls what happens when multiple inputs are asserted (example: a := "0010100"). With TO, the highest numbered input wins (y <= "100"). With DOWNTO, the lowest numbered input wins (y <= "010"). This is because the last assignment in a process takes precedence. But you could also use EXIT FOR to determine the priority.

Vaules answered 4/10, 2011 at 0:10 Comment(1)
@kavadias: Thanks for your suggestion, but it's actually correct already. Note that we aren't changing from a : IN SLV(7 DOWNTO 1) to a : IN SLV(1 TO 7), in which case a palindrome would indeed not see any difference. But the change is FOR i IN 1 TO 7 vs FOR i IN 7 DOWNTO 1... and then any input with two set bits will see a difference, palindrome or not.Vaules
C
1

I was taught that a good rule is to use "downto" for matters where maintaining binary order is important (for instance an 8 bit signal holding a character) and "to" is used when the signal is not necessarily interconnected for instance if each bit in the signal represents an LED that you are turning on and off.

connecting a 4 bit "downto" and a 4 bit "to" looks something like

sig1(3 downto 0)<=sig2(0 to 3)

-------3--------------------0

-------2--------------------1

-------1--------------------2

-------0--------------------3

taking part of the signal instead sig1(2 downto 1) <= sig2(0 to 1)

-------2--------------------0

-------1--------------------1

Calvinism answered 4/10, 2011 at 13:26 Comment(0)
M
0

Though there is nothing wrong with any of the answers above, I have always believed that the provision of both is to support two paradigms.

First is number representation. If I write the number 7249 you immediately interpret it as 7 thousand 2 hundred and forty-nine. Numbers read from left to right where the most significant digit is on the left. This is the 'downto' case.

The second is time representation where we always think of time progressing from left to right. On a clock the numbers increase over time and 2 always follows 1. Here I naturally write the order of bits from left 'to' right in time ascending order regardless of the representation of the bits. In RS232 for instance we start with a start bit followed by 8 data bits (LSB first) then a stop bit. Here the MSB is on the right; the 'to' case.

As said the most important thing is not to mix them arbitrarily. In decoding an RS232 stream we may end up doing just that to turn bits received in time order into bytes which are MSB first but this is very much the exception rather than the rule.

Matelda answered 1/3, 2019 at 15:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.