I'm struggling to understand the bit order of an aggregate, especially since I've used name association.
The buses are defined as (0 to 3)
and (3 downto 0)
, but since I've used named association, why are the outputs z3..0
and ob3..0
the reverse of each other? Why is outputs_b
the reverse of z_bus
? Why did assigning outputs_b
from the constant array make a difference to the bit ordering as compared to assigning z_bus
from a literal?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Test_TB is
end entity;
architecture V1 of Test_TB is
type TLogicLevel is (L, H, X);
type TOutputs is array(natural range<>) of TLogicLevel;
type TOutputsTable is array(natural range<>) of TOutputs;
constant OUTPUTS_TABLE: TOutputsTable :=
(
(3 => H, 2 => H, 1 => H, 0 => L),
(3 => X, 2 => X, 1 => X, 0 => X) -- Added this because it can't compile an array with a single element.
);
signal outputs_a: TOutputs(0 to 3);
signal outputs_b: TOutputs(3 downto 0);
signal oa0, oa1, oa2, oa3: TLogicLevel;
signal ob0, ob1, ob2, ob3: TLogicLevel;
signal y_bus: TOutputs(0 to 3);
signal z_bus: TOutputs(3 downto 0);
signal y0, y1, y2, y3: TLogicLevel;
signal z0, z1, z2, z3: TLogicLevel;
begin
process
begin
wait for 10 ns;
y_bus <= (3 => H, 2 => H, 1 => H, 0 => L); -- Performs bit-for-bit copy.
z_bus <= (3 => H, 2 => H, 1 => H, 0 => L); -- Performs bit-for-bit copy. NOT REVERSED.
outputs_a <= OUTPUTS_TABLE(0); -- Performs bit-for-bit copy.
outputs_b <= OUTPUTS_TABLE(0); -- Performs bit-reverse copy. IS REVERSED.
wait for 10 ns;
(3 => oa3, 2 => oa2, 1 => oa1, 0 => oa0) <= outputs_a; -- Performs bit-for-bit copy.
(3 => ob3, 2 => ob2, 1 => ob1, 0 => ob0) <= outputs_b; -- Performs bit-reverse copy of a reverse copy, i.e. reverse reverse.
wait for 10 ns;
(3 => y3, 2 => y2, 1 => y1, 0 => y0) <= y_bus; -- Performs bit-for-bit copy.
(3 => z3, 2 => z2, 1 => z1, 0 => z0) <= z_bus; -- Performs bit-reverse copy of non-reverse copy. So z3..0 is the reverse of ob3..0.
wait;
end process;
end architecture;
Your code is behaving as I would expect.
signal y_bus: TOutputs(0 to 3);
signal z_bus: TOutputs(3 downto 0);
...
y_bus <= (3 => H, 2 => H, 1 => H, 0 => L);
z_bus <= (3 => H, 2 => H, 1 => H, 0 => L);
For y_bus
the left hand bit is 0
, which you have set to L
.
For z_bus
the left hand bit is 3
, which you have set to H
. CHECK.
constant OUTPUTS_TABLE: TOutputsTable :=
(
(3 => H, 2 => H, 1 => H, 0 => L),
...
signal outputs_a: TOutputs(0 to 3);
signal outputs_b: TOutputs(3 downto 0);
....
outputs_a <= OUTPUTS_TABLE(0);
outputs_b <= OUTPUTS_TABLE(0);
For OUTPUTS_TABLE(0)
the left hand bit is 0
, which you have set to L
. For outputs_a
the left hand bit is 0
, so you would expect that to be L
. For outputs_b
the left hand bit is 3
, so you would expect that to be L
. CHECK.
signal outputs_a: TOutputs(0 to 3);
signal outputs_b: TOutputs(3 downto 0);
...
(3 => oa3, 2 => oa2, 1 => oa1, 0 => oa0) <= outputs_a;
(3 => ob3, 2 => ob2, 1 => ob1, 0 => ob0) <= outputs_b;
For outputs_a
the left hand bit is 0
, so you would expect oa0
to be L
, because it is that that is one the left hand side. For outputs_b
the left hand bit is 3
, so you would expect ob0
to be L
, because it is that that is one the left hand side. CHECK. But hang on, why are oa0
and ob0
the left hand side? Because that is how the bits in the aggregates (3 => oa3, 2 => oa2, 1 => oa1, 0 => oa0)
and (3 => ob3, 2 => ob2, 1 => ob1, 0 => ob0)
will be numbered, because the index type will be an integer
and integer
types count up.
signal y_bus: TOutputs(0 to 3);
signal z_bus: TOutputs(3 downto 0);
....
y_bus <= (3 => H, 2 => H, 1 => H, 0 => L);
z_bus <= (3 => H, 2 => H, 1 => H, 0 => L);
....
(3 => y3, 2 => y2, 1 => y1, 0 => y0) <= y_bus;
(3 => z3, 2 => z2, 1 => z1, 0 => z0) <= z_bus;
So, as we already know, for y_bus
the left hand bit is 0
, which you have set to L
and for z_bus
the left hand bit is 3
, which you have set to H
. So, you would expect y0
(the left hand bit) to be L
and z0
(the left hand bit) to be H
. CHECK.
My head hurts.