There are shift operators in VHDL but they should not be used. See rule C_31 in this collection of mostly good coding rules:
I wouldn't classify 'Rule C_31' in the category of 'good' rules.
What is the reason for banning integer and std_ulogic for synthesizeable code?
I think integer with a range can sometimes be motivated.
I don't know why std_logic should be avoided.
std_ulogic can reduce the debugging time by detecting multiple drivers at compile time instead of simulation or synthesis.
I agree, I always use std_ulogic so I don't waste my time debugging what the compiler would catch and it also represents more closely what actual implementation will be (i.e. a singly driven signal). So that puts 'Rule_C29' in the list of rules with which I would not agree.
Perusing their list further...
C_6: It frequently muddies the waters if you insist on only std_logic/std_logic_vector types for entity ports. For the top level entity I agree (but would use ulogic), but for embedded entities I do not agree.
C_13: Not every flip flop needs to be asynchronously reset.
C_18: There is no reason to avoid use of 'buffer' mode.
C_21: Is a pointless rule. Every compliant compiler has always flagged as an error the case where an input is unconnected with no default.
C_25: I've never seen recursive code not work. It certainly doesn't come up often and sometimes the recursive version is a bit more readable, but usually that is a wash and just somebody's preference.
C_28: While their caution regarding initialization is valid, allowing use of only std_logic, std_logic_vector, signed, unsigned types will result in less readable/supportable code. Their rule is overly restrictive for preventing the described problem. Besides, they do allow for enumerated types and they will have the same issue of initializing in sim to something that might not happen in the real part.
C_30: Do not agree. It is quite good to use record types as well as arrays of types. Even rule C_9 seems to allow for record type use, just not at a top level so they are violating rule C_30 when they allow use of a record since that is a user defined type.
C_33: Do not agree, one should use variables where it is appropriate. The only drawback I see to variables and the reason that I minimize their use is that they are not wavable in a simulation after the fact. So while I can log every signal and then add any signal in the entire system to see the total history when needed to debug a problem, you can't do that with variables without restarting the sim. Without restarting, you can see only the current value of the variable, but not the history. However, this is a limitation of the tools, not anything fundamentally wrong with variables.
C_37: Nothing wrong with using procedures in RTL, but appropriate use of procedures in RTL does not come up very often.
C_39: The gymnastics required to put "x <= y and z;" inside a sequential process makes the code harder to understand, not easier.
C_40: This rule is dated. If one uses VHDL-2008, then I do not agree since you can now say 'process(all)'. If you use an earlier language revision I do agree since it is too easy to create a latch by getting the sensitivity list wrong.
C_43: Conflicts with rule C_39 and is another example of when C_39 would not be valid.
C_45: I would say one clock per architecture, not entity. But even there, the dual clock FIFO that crosses the domains needs to go 'somewhere'.
C_47: Do not agree. It depends on the protocol of the interface of the entity. Examples of interfaces that typically require a non-clocked output are the 'waitrequest' of Avalon or 'ack' of Wishbone.
So of the 54 coding rules, I would disagree with 16 of them, but would consider the list to be a fairly decent set of guidelines overall. Also, to be fair, some of these rules may have motivated by bugs with vendor tools used by ALSE...and these rules are 10 years old so even ALSE today might not necessarily agree with everything that was written at that time.
Kevin Jennings