I've never gotten into records much. Seems a bit of work if you don't have an actual reason to bundle signals. I guess it is less typing given the many times you have to declare things in VHDL. I used to copy a set of regular expressions in my source files that allow me to generate the different formats for the entity declaration, the component instance and the signals declaration to save on the typing. Maybe I'll try using records next time. The record declaration would need to be in a package to be useful, right?
Yes, the record type needs to be declared in a package, so it's visible to all entities that use it on ports. My designs tend to have a types_pkg package file so I can have types and constants and enumerations of all sorts shared across entities. That's how you make your entity ports have things more useful than simply std_logic and std_logic_vector.
Here's an example of where a record type is useful. The design had a lot of parameters that can be set by user command. The parameters are also stored in nonvolatile memory for recall at power-up or reset. So there's an entity that manages the user setting and getting the parameter values, an entity that manages the non-volatile storage (write and recall) and of course there are the various entities that actually use the parameters.
Obviously the parameters had to each be ports on each entity's port list. The command parser needed to drive as outputs a "new" parameter when the user changed it, along with a strobe telling the non-volatile memory manager to store that new parameter. The parser needed to take in the recalled parameters, too.
When I first started the design, there were only a handful of parameters, so having each on the port list was "manageable." But then as more things needed to be parametrized, the entity port lists got unwieldy. So I just wrapped up all of the parameters into one record. To support the user updating parameters, I created a second record with "new parameter" values and a write strobe for each. A "parameter manager" entity sat in the middle, dealing with new things from the command parser, initial values that are read from non-volatile store at reset, and it output the parameters used by the whole design.
Each entity that needed to consume parameters takes that record as an input. One port on the list, not ... a whole bunch.
The only annoyance is that the synthesis tool complained when a member of the parameter record wasn't used within a given entity.
But it sure made adding new parameters a cinch.