I have some VHDL code that has the following signal definition:

signal hcount  : integer range 0 to 235;

This is used as a counter throughout my system (so I believe it needs to continue as an integer and not be declared as a std_logic_vector for example), but I also need to use its least 3 significant bits to index an eight-bit signal like this (which does not compile):

signal somereg : std_logic_vector(7 downto 0);
somereg(hcount and B"00000111") <= <a bit value>;

What is the most appropriate way to index the "somereg" vector above?



A better way than using std_logic_vector and the non-standard std_logic_arith and std_logic_signed libraries is to use IEEE.numeric_std.all; and make the counter unsigned (or signed in other contexts where you need negative values).

signal hcount  : unsigned(7 downto 0);

And you can perform conversions to and from integer, and bitwise operations:

hcount <= to_unsigned(123,hcount'length);

signal somereg : std_logic_vector(7 downto 0);
somereg(to_integer(hcount(2 downto 0)) <= <a bit value>;

However in the given example, the bitwise operations turn out to be unnecessary: instead of masking bits to extract a 3-bit register address, you could use division and mod operations. Synthesis tools (mostly) aren't stupid : divide and mod by powers of 2 are optimised into the obvious field extractions and don't even generate "and" gates.

signal hcount    : natural range 0 to 235;
signal reg_addr  : natural range 0 to 7;

signal somereg : std_logic_vector(7 downto 0);
reg_addr <= hcount mod 8;
somereg(reg_addr) <= <a bit value>;

One benefit of this (apart from fewer ugly type conversions) is that you still profit from the integer subtype you declared for hcount : incrementing it to 236 will raise an overflow error in simulation, allowing you to catch and correct logic errors early.

  • \$\begingroup\$ +1 for not using the unhappily names std_logic_arith. \$\endgroup\$ – carveone Jan 31 '14 at 12:18

First of all, there's nothing wrong with using std_logic_vector as a counter. I do it all the time. I typically have the following library statements at the top of each module, which give you the necessary arithmetic operators on bit vectors.

library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.std_logic_arith.all;
  use IEEE.std_logic_signed.all;   -- or IEEE.std_logic_unsigned.all

But if you really want to stay with integer, there are standard functions that will convert an integer to other types. In your case, you would use something like

somereg <= std_logic_vector (to_unsigned (hcount, somereg'length));

to_unsigned() is a conversion function that converts the integer into a bit vector, which is why it needs to know the length of the target. Then, std_logic_vector() is a simple type-cast of the bit vector.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.