sleeman said:
A couple of things pop into mind off the bat (And please excuse the
obvious syntax fragmentation and probable typos in advance

:
(option 1)
Execute the code in the simulator: write a separate process for
simulation only (hidden by a synthesis translate off pragma, or inside
an IF..GENERATE block). Inside this process, write the same code as
above but print out your mapping explicitly:
process
for i in to (BUS_WIDTH -1) loop
report "aligned(" & integer'image(i) & ") <= data(" &
integer'image((i/DES_FACT) + ((i mod DES_FACT)*NUM_CHAN))
& ");"
end loop;
wait;
end process;
Of course, this only tells you your simulator is right, it doesn't
tell you that synth matches your sims.
(option 2)
In synthesis, write a 64 bit bitmask, initialized to zero. Inside the
generation loop, set each destination bit as you go through the loop,
then check that the entire vector is all ones after the loop is done.
This should be an invariant, so should synthesie out trivially, but if
your logic is wrong you'll double-point to the same bit twice so
you'll leave some bits empty (pigeon-hole principle).
The key idea is that your transform is strictly a *permutation* so
that you guarantee all 64 bits will be covered exactly once.
bitmask : std_ulogic_vector(0 to BUS_WiDTH-1) := (others => '0');
SERDES_Scramble :
for i in 0 to (BUS_WIDTH -1) generate
begin
aligned_data(i) <= data((i/DES_FACT) + ((i mod DES_FACT)
*NUM_CHAN));
bitmask((i/DES_FACT) + ((i mod DES_FACT)*NUM_CHAN)) <= '1';
end generate SERDES_Scramble;
process(clk)
begin
assert (bitmask = (others => '1')) report "oops" severity FAILURE;
end process;
..or equivalently drive a port on the module with the same error
condition. You should be able to get the synthesizer to do this work
for you.
Just a few random thoughts, hope they help.
- Kenn
And to make it even more robust, note that you actually have three free
variables in your code fragment: BUS_WIDTH, DES_FACT, and NUM_CHAN, but
only two real degrees of freedom (DES_FACT and NUM_CHAN). (Thy're
presumably GENERICS in VHDL but variables in the mathematical
sense). Your code implcitly relies on the fact that
BUS_WIDTH=DES_FACT*NUM_CHAN
However, you don't assert or verify it. If you want a robust
paramaterizable solution you should assert this.
How to verify it "stictly: though is another story... that implies that
you have a strict spec. If your strict spec is in terms of an equation,
then you just trace the equation back to VHDL.
Another way to look at it (although not formal in any sense) is to ask
yourself if there's another intuitive way to frame the problem so that
it's consistent with your goal, then see if the two solutions
match. (The concept of safety through redundancy!)
Whn you draw out your manual mapping above, it's evident that you're
just permuting address bits, so that the LHS has index vector iv
iv(B-1 downto 0),
while on the RHS you're permuting these to form the address
iv(B-C-1 downto 0) & iv((B-1) downto (B-C))
Where for brevity,
BUS_WIDTH = 2**B; B = 6 here
NUM_CHAN = 2 ** C; C = 2 here
iv := to_unsigned(i, B)
It's clear that by examining the indices that the RHS has the
appropriate length in bits:
(B-C) + (C) = B
Then you could either rewrite your code, or just assert this to be so:
for i in 0 to (BUS_WIDTH -1) generate
begin
aligned_data(i) <= data((i/DES_FACT) + ((i mod DES_FACT)*NUM_CHAN));
process
variable iv : unisgned := to_unsigned(i, B)
begin
assert (to_integer(iv) = i) report "LHS oops" severity FAILURE;
assert (to_integer(iv(B-C-1 downto 0) & iv(B-1 downto B-C))
= ((i/DES_FACT) + ((i mod DES_FACT)*NUM_CHAN)))
report "RHS oops" severity FAILURE;
end process;
end generate SERDES_Scramble;
Arguably, this is very complex on the surface; this has more to do with
the fact that it's ugly to express this in VHDL, and little to do with
the intent.
As a general principle, if you spend enought time on the problem to get
at least two methods working, in all their ugly detail, you're probably
in good shape!
Of course, the transformation I just described assumes that DES_FACT and
NUM_CHAN are powers of two, and may have misbehaviour when either is
zero, so you want to assert that... ad nauseum.
HTH,
- Kenn