FriendFX
FriendFX

Reputation: 3079

Can we restrict the index order of an array parameter for a procedure?

Lets say we have a behavioural VHDL procedure for a testbench:

procedure jtag_load_data(data : in std_ulogic_vector) is
begin
  jtag_clock(1, '1', '0');
  jtag_clock(2, '0', '0');
  for i in data'length-1 downto 1 loop
    jtag_clock(1, '0', data(i));
  end loop;
  jtag_clock(2, '1', data(0));
  jtag_clock(1, '0', data(0));
end procedure;

This procedure can either be called with a constant parameter like so

jtag_load_data("100")

or the parameter can be computed from others like this

jtag_load_data(tmasrc & tdosrc & tm)

Since VHDL arrays don't define the index order, I think the order the bits of data are processed within the for loop depends on the index of the data parameter when the procedure is called.

In case that wasn't clear, say a is of type std_logic_vector(3 downto 0) and b is of type std_logic_vector(0 to 3) and we do the following:

a <= "100";
b <= "100";
jtag_load_data(a);
jtag_load_data(b);

The bits processed for a will be 1, 0, 0 while for b they will be 0, 0, 1.

Back to my original two calling examples, this is a problem for the case where the parameter is a concatenation of std_logic_vectors: The expression tmasrc & tdosrc & tm (all three operands are of type std_logic_vector(n downto 0)) seems to evaluate to a std_logic_vector(0 to m), which reverses the order the bits are processed with respect to the case where I call the procedure with just one of the parameters (or a constant, which seems to default to the downto index ordering).

To fix this ambiguity, we can introduce a variable with known index order ordered_data like so:

procedure jtag_load_data(data : in std_ulogic_vector) is
  variable ordered_data : std_ulogic_vector(data'length-1 downto 0);
begin
  ordered_data := data;
  jtag_clock(1, '1', '0');
  jtag_clock(2, '0', '0');
  for i in ordered_data'length-1 downto 1 loop
    jtag_clock(1, '0', ordered_data(i));
  end loop;
  jtag_clock(2, '1', ordered_data(0));
  jtag_clock(1, '0', ordered_data(0));
end procedure;

But I am wondering if there is a more elegant VHDL syntax to say either

Upvotes: 1

Views: 85

Answers (1)

Matthew
Matthew

Reputation: 13967

If you don't specify a range on a std_ulogic_vector (or std_logic_vector) input to a procedure (or function) then inside the procedure the left hand bit is always 0 and the bit numbers increase left to right. This is because a std_ulogic_vector is declared thus:

type std_ulogic_vector is array (natural range <>) of std_ulogic;

and since the index type is a natural whose left hand value is 0, the left hand element is always numbered 0 with an unconstrained parameter such as this.It is exactly the same for a std_logic_vector, which is declared the same way.

The numbering is not passed in from outside the procedure. Whatever is on the left outside the procedure (the actual) is numbered 0 inside the procedure (the formal).

So, in your example:

In case that wasn't clear, say a is of type std_logic_vector(3 downto 0) and b is of type std_logic_vector(0 to 3) and we do the following:

a <= "100"; b <= "100"; jtag_load_data(a); jtag_load_data(b);

a and b will be processed in exactly the same way; there is no difference; the fact that a is of type std_logic_vector(3 downto 0) and b is of type std_logic_vector(0 to 3) is irrelevant.

So, to answer your specific questions: it is up to you to ensure that the inputs are passed into the procedure in the correct order. If that is no good, then you need to pass in some other parameter to control the direction.

Upvotes: 2

Related Questions