A common RTL transformation is factoring an expression by cases. For example, if v is an integer variable and you know at some point in the computation it can only take on values from 0 to N-1, then you might rewrite
out = f(u,v,w);
for (int i = 0; i < N; i++) A[i] = f(u,i,w); out = A[v];
You need in general an array, not a case statement, because the number of cases usually depends on parameters. The example was applying outside information about which v values are possible. Another kind of outside information would be if you expect v to arrive late. Of course, designers sometimes factor by cases just because they see a cleverly simplifying factorization, and they can’t depend on the tools to see the same trick.
Declaring the range of A is not always as obvious as [0:11]. It would be natural to declare A to be an associative array, with the index type as that of the cases. Then the RTL could just concentrate on iterating over the possible cases and creating the factors, and leave some of the mechanics of A to the tool. This bookkeeping could be especially convenient when there’s not an obvious correspondence between the cases and a range of integers.
Aside: Another use of associative arrays in design could be providing a message board for arbitrating access to some shared resource, with the index being the address of those contending for access. For example, if several places want to write to a shared variable, they could put their requests into a associative array, according to their index (and an arbitrator could communicate the results in another). Otherwise, each has to explicitly write at least write a flag each cycle telling whether or not they are trying to write a value. Again, it’s just some bookkeeping that could make the code a little simpler. However, access to shared resources would be better managed via channels and interface classes.