I am trying to write a systemVerilog testbench for my VHDL designs. The problem is the data types. For instance, in VHDL I have:
punti_retta : out integer range 255 downto 0;
fdata_in : in integer range 127 downto -128;
For the first one, I tried "integer [7:0] punti_retta" in the systemVerilog testbench; however, the tool ignored the range definition and according to the waveform it is wrong.
What and how should I define for these signals in my systemVerilog testbench? Is there any suggestion?
Verilog does not have an integer range in the same way as VHDL.
You can make an equivalent type if your integer range is a power of two like in your example:
punti_retta : out integer range 255 downto 0;
fdata_in : in integer range 127 downto -128;
The first one is an unsigned integer of 8 bits so you can use logic [7:0] punti_regga;.
Instead of logic you can also use wire or reg
The second one is signed integer of 8 bits so you can use logic signed [7:0] fdata_in;.
But VHDL also allows you to use:
my_counter : integer range 0 to 395;
There is no exact equivalent in Verilog. However when that variable is going to be synthesized, the tool must have enough bits so in hardware you get a 9 bit unsigned type. Thus the real hardware can count beyond 395!
The Verilog equivalent is logic [8:0] my_counter ;
SystemVerilog does not have the concept of integer ranges, only bit-widths. You can approximate ranges using $clog2().
bit [$clog2(255)-1:0] punti_retta;
bit signed [7:0] fdata_in;
Since there is no standard for crossing standard boundaries, you're going to have to look at the restrictions your tool puts on mapping port types. You might have to put the types in a common package.
BTW, the bit range in integer [7:0] is ignored or made an error because of a quirk in the first Verilog-XL simulator. Originally, the integer type was unsized and determined by the OS your simulation was executing on. They had planned to use that syntax to specify the integer size, but never got around to implementing it.
Let's say I have a fixed point value in my VHDL - Code which is defined as std_logic_vector. I know that my last 4-bit are the decimals.
When I use the simulator it will of course not see the last 4 bits as decimals, is there any possibility to change it in the simulation, so that the simulation knows that the 3rd bit has the value of 0.5 , the 2nd the value of 0.25 and so on ?
It's possible in Vivado to show the result in the simulator as a fixed point representation.
When you rightclick in the simulator on the signal you want to show in fixed point, click radix --> real settings. There you get the following window and you can select fixed point.
Real settings window
I doubt about that this is possible unfortunately. Specifically for std_logic the types are the following:
'U': Uninitialized. This signal hasn't been set yet.
'X': Unknown Impossible to determine this value/result.
'0': Logic 0
'1': Logic 1
'Z': High Impedance
'W': Weak signal, can't tell if it should be 0 or 1.
'L': Weak signal that should probably go to 0
'H': Weak signal that should probably go to 1
'-': Don't care.
As a result the simulator is recognizing ONLY the above symbols, anything else will result in error, including a floating point number to describe a bit. Here's an example from me trying to put a floating point value to be displayed:
add_force {/test/a[27]} -radix unsigned {0.4 0ns}
ERROR: [Simtcl 6-179] Couldn't add force for the following reason:
Illegal value '0.4': Could not convert value '0.4' to a decimal
number.
I also observed Vivado as tagged so I guess you use the integrated simulator. In my example the closest to a floating point number was the decimal number. There is no built in variable at Vivado to support floating points for display in the simulation. Below you see the radix it supports so you are tightly restricted only to those choices, which all result in error except ASCII but I don't think that's the behavior you want.
Is there any way to use pre-defined types from STD_LOGIC_1164 or STD_NUMERIC to represent an integer ranging from 0 to 2^32-1 ? (considering the default integer type ranges from -2^31-1 to 2^31-1)
I need to implement 32-bit counter and was looking for some way to save code using integer type instead of std_logic_vector.. Any design pattern for this ?
Or, better asked: Whats the best way to declare a 32-bit (unsigned) integer supporting the operations >/<, =, +-/ ?
Tahnks in advance
Edit1: One option I found was to declare a signal as std_logic_vector(31 downto 0), and to perform conversions when doing comparisons or +- operations.. ex: counter <= counter + std_logic_vector(unsigned(value) + 1).. Still haven't found a way to do division though (in case,for example, 1/4 of the value of counter is needed)
Using the Integer types, you cannot (at least, not portably; there may be some VHDL tools that go beyond the minimum and offer a 64-bit integer)
Using IEEE.numeric_std, you can declare an Unsigned with a full 32-bit range (or 53-bit if you wish) and it should do everything you want.need, unless I misunderstand what you are asking.
use ieee.numeric_std.all;
and then use the unsigned data type - this operates as a bit vector with mathematical operations defined for it. You can choose how many bits you'd like. For example:
signal mynum : unsigned(234 downto 0)
I'm creating a full adder with a variable number of bits. I've got a component that is a half-adder which takes in three inputs (the two bits to add, and a carry in bit) and gives 2 outputs (one bit output and a carry out bit).
I need to tie the carry out of one half-adder to the carry in of another. And I need to do this a variable number of times (if I'm adding 4 digit numbers, I'll need 4 half adders. If I'm doing 32 bit numbers, I'll need 32 half adders).
I was going to tie the carry outs of one half-adder to the carry in of another using signals, but I don't know how to create a variable number of signals.
I can instantiate a variable number of half-adders using a for-loop in a process, but since signals are defined outside of processes, I can't use a for loop for it. I don't know how I should tie the half-adders together.
The easiest way to write an adder in VHDL is not to worry about full adders and half adders, but just type:
a <= b + c;
where a,b and c are signed or unsigned
95% of the time, the synthesis tools will do a better job than you would.
I think you want variable-width signals not variable numbers of signals
Your signals need to be std_logic_vector(31 downto 0) for example - and then you wire up the bits of those signals to your half-adders appropriately.
Of course, as those signals are numbers, then don't use std_logic_vector use signed or unsigned (and the ieee.numeric_std lib).
And (as Philippe rightly points out) unless this is a learning exercise, just use the + operator.
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?
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...
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
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!)
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.
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.
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
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.