Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to index a std_logic_vector by enumeration

Tags:

vhdl

I have a std_logic_vector like this:

cntrl_signals:out std_logic_vector(4 downto 0);

One way to have indexes to this vector would be to explicitly define a constant for each.

constant CLK_SIG:integer := 0;
constant EN_SIG:integer := 1;
constant FOO_SIG:integer := 2;
constant BAR_SIG:integer := 3;
constant BAZ_SIG:integer := 4;

The idea is to use these to index the vector.

cntrl_signals <= (CLK_SIG=>1,EN_SIG=>1,others=>0);

My question is if there a nice shorthand way of declaring the indexes (like an enum in C)?

like image 648
c0m4 Avatar asked Dec 10 '12 21:12

c0m4


2 Answers

Well you could use enumerations, the best way would be to declare your own vector of std_logic, indexed by the enumeration instead of by integer.

But probably better would be a record instead of a vector :

type Control_Signals is record
   Clk : std_logic,
   En  : std_logic,
   Foo : std_logic,
   Bar : std_logic,
   Baz : std_logic
end record;

EDIT for more information, following comment:

Unimaginative use of std_logic_vector (and VHDL's type system in general) is holding VHDL back...

If this is a top level entity, then std_logic_vector ports allow you to substitute a post-synthesis netlist for your synthesisable design in the top level testbench. Or you may have to comply with antiquated coding style guidelines that insist on std_logic_vector ports.

But in any other circumstance I would declare the record in a package, use that package throughout the design, and make the ports of the record type. The package should include functions to_slv and to_control_sigs for the (rare, if you get it right) occasions when you actually need std_logic_vectors.

The same applies with enumerations:

type Controls is (Clk, En, Foo, Bar, Baz);
type Control_Signals is array(Controls) of std_logic;
My_Bus_Ctrl : Control_Signals := (Clk => '1', En => '1', others => '0');
My_External_SLV_Port <= std_logic_vector(My_Bus_Ctrl);

And of course, enumerations are a bit more powerful than in C; as well as using them as array index types, you can loop over them. Which keeps your loops in line whenever you update the enumeration!

Records or arrays indexed by enumerations both work; I prefer the record as a bit cleaner and more in line with object oriented practice.

In either case it becomes FAR more useful if you use it for entity ports. Declare one record (or array!) for outgoing bus signals (including address and data) and another for incoming signals, because you can't mix directions in a single port... (There are no bidirectional signals in an FPGA these days, so there is no need for a third port)

Now your design is protected against bus structure changes; changing the address width or adding an interrupt signal only changes the record declaration and any actual users; there is no need to add the new signal throughout the hierarchy...

like image 119
user_1818839 Avatar answered Sep 23 '22 17:09

user_1818839


Brian has the best answer, but another bit of info:

You can create an enumeration like this:

type some_type is (clk, en, foo, bar, baz);

if you have a signal or variable of that type, you can use the 'pos attribute to convert it back into a number:

variable v : some_type := foo;

v'pos will return the integer 2

like image 34
Martin Thompson Avatar answered Sep 25 '22 17:09

Martin Thompson