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?
Thanks
2 Answers 2
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.
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.
-
\$\begingroup\$ I've said it once, and I'll say it again... (depending on your tolerance of "correctness") there is something wrong with using
std_logic_vector
as a counter - and that is that std_logic_arith goes against VHDL's fundamental approach of strong typing, and goes against VHDL's fundamental approach of strong typing. If you want Verilog it's over there \$\endgroup\$Martin Thompson– Martin Thompson2014年01月31日 15:11:01 +00:00Commented Jan 31, 2014 at 15:11