VHDL Basic Question

M

maxascent

Guest
I am new to VHDL and need some advice on connecting a vector array on a
entity using a port map.I have an array of std_logic_vectors(63 downto 0
as a port. There are 3 of these in the array. How do I connect these
vectors using a port map?

TIA

Jon


---------------------------------------
Posted through http://www.FPGARelated.com
 
On Sat, 20 Aug 2011 09:47:16 -0500, "maxascent"
<maxascent@n_o_s_p_a_m.n_o_s_p_a_m.yahoo.co.uk> wrote:

I am new to VHDL and need some advice on connecting a vector array on an
entity using a port map.I have an array of std_logic_vectors(63 downto 0)
as a port. There are 3 of these in the array. How do I connect these 3
vectors using a port map?
So it's something like this:

library ieee;
use ieee.std_logic_1164.all;
package vec_array_pkg is
type a_3x64 is array(0 to 2) of std_logic_vector(63 downto 0);
end package;

library ieee;
use ieee.std_logic_1164.all;
use work.vec_array_pkg.all;
entity has_array_port is
port ( p: in a_3x64; ...

If your external signal is also an array of three 64-bit SLVs, then
simply connect the external array signal to the port. They have
the same type, and so can be connected.

If your external signal is really three separate 64-bit
signals, then proceed like this:

signal P,Q,R: std_logic_vector(63 downto 0);
...
my_instance: entity work.has_array_port
port map ( p(0) => P, p(1) => Q, p(2) => R, ...

--
Jonathan Bromley
 
On Sat, 20 Aug 2011 09:47:16 -0500, "maxascent"
maxascent@n_o_s_p_a_m.n_o_s_p_a_m.yahoo.co.uk> wrote:

I am new to VHDL and need some advice on connecting a vector array on an
entity using a port map.I have an array of std_logic_vectors(63 downt
0)
as a port. There are 3 of these in the array. How do I connect these 3
vectors using a port map?

So it's something like this:

library ieee;
use ieee.std_logic_1164.all;
package vec_array_pkg is
type a_3x64 is array(0 to 2) of std_logic_vector(63 downto 0);
end package;

library ieee;
use ieee.std_logic_1164.all;
use work.vec_array_pkg.all;
entity has_array_port is
port ( p: in a_3x64; ...

If your external signal is also an array of three 64-bit SLVs, then
simply connect the external array signal to the port. They have
the same type, and so can be connected.

If your external signal is really three separate 64-bit
signals, then proceed like this:

signal P,Q,R: std_logic_vector(63 downto 0);
...
my_instance: entity work.has_array_port
port map ( p(0) => P, p(1) => Q, p(2) => R, ...

--
Jonathan Bromley
I really want the type to be something like this

constant M : positive := 64;
type a_nxm is array(natural range <>) of std_logic_vector(M-1 downto 0);

and then

entity has_array_port is
generic(
IP_NUM : integer := 3;
);
port ( p: in a_nxm(0 to IP_NUM-1)

Not sure if I have written this correctly? What I am trying to do is creat
a generic mux. So for example, I may want 3, 64 bit slv.

Thanks

Jon

---------------------------------------
Posted through http://www.FPGARelated.com
 
On Sat, 20 Aug 2011 10:24:33 -0500, "maxascent" wrote:

I really want the type to be something like this

constant M : positive := 64;
type a_nxm is array(natural range <>) of std_logic_vector(M-1 downto 0);

and then

entity has_array_port is
generic(
IP_NUM : integer := 3;
);
port ( p: in a_nxm(0 to IP_NUM-1)

Not sure if I have written this correctly?
Looks good.

What I am trying to do is create
a generic mux. So for example, I may want 3, 64 bit slv.
This is still fine. At the point where you instance
the mux, you know exactly what you plan to connect
to it:

signal P, Q, R, S: std_logic_vector(M-1 downto 0);
...
my_4way_mux: entity work.has_array_port
generic_map(IP_NUM => 4)
port map (p(0) => P, ..., p(3) => S, ...

The problems will start if you want THIS higher level
entity also to be configurable, because then it makes
no sense whatever to list out the port elements one
by one - such a list would be broken for any different
number of inputs than you wrote it for. So you'll need
an array signal up there in that top module too. But
that's fine:

constant SIZE: integer := 6;
signal A: array(0 to SIZE-1) of std_logic_vector(M-1 downto 0);
...
my_Nway_mux: entity work.has_array_port
generic_map(IP_NUM => SIZE)
port map (p => A, ...

Now, of course, you have the exquisite problem of
how to attach your miscellany of 64-bit signals
to the elements of A... but hey, things have to
get specific somewhere, don't they? This is a
typical problem with things like data readback
muxes for a register file - the mux can be generic,
but the individual registers are all different and
it's hard to parameterize their existence.

Sometimes you can partially solve this by using
an enum type as the array index. The enum names
then denote individual registers. It doesn't
solve the problem entirely, but it can make your
eventual solution look less ugly.
--
Jonathan Bromley
 
On Sat, 20 Aug 2011 10:24:33 -0500, "maxascent" wrote:

I really want the type to be something like this

constant M : positive := 64;
type a_nxm is array(natural range <>) of std_logic_vector(M-1 downto 0);

and then

entity has_array_port is
generic(
IP_NUM : integer := 3;
);
port ( p: in a_nxm(0 to IP_NUM-1)

Not sure if I have written this correctly?

Looks good.

What I am trying to do is create
a generic mux. So for example, I may want 3, 64 bit slv.

This is still fine. At the point where you instance
the mux, you know exactly what you plan to connect
to it:

signal P, Q, R, S: std_logic_vector(M-1 downto 0);
...
my_4way_mux: entity work.has_array_port
generic_map(IP_NUM => 4)
port map (p(0) => P, ..., p(3) => S, ...

The problems will start if you want THIS higher level
entity also to be configurable, because then it makes
no sense whatever to list out the port elements one
by one - such a list would be broken for any different
number of inputs than you wrote it for. So you'll need
an array signal up there in that top module too. But
that's fine:

constant SIZE: integer := 6;
signal A: array(0 to SIZE-1) of std_logic_vector(M-1 downto 0);
...
my_Nway_mux: entity work.has_array_port
generic_map(IP_NUM => SIZE)
port map (p => A, ...

Now, of course, you have the exquisite problem of
how to attach your miscellany of 64-bit signals
to the elements of A... but hey, things have to
get specific somewhere, don't they? This is a
typical problem with things like data readback
muxes for a register file - the mux can be generic,
but the individual registers are all different and
it's hard to parameterize their existence.

Sometimes you can partially solve this by using
an enum type as the array index. The enum names
then denote individual registers. It doesn't
solve the problem entirely, but it can make your
eventual solution look less ugly.
--
Jonathan Bromley
---------------------------------------
Posted through http://www.FPGARelated.com
 
On Sat, 20 Aug 2011 10:24:33 -0500, "maxascent" wrote:

I really want the type to be something like this

constant M : positive := 64;
type a_nxm is array(natural range <>) of std_logic_vector(M-1 downto 0);

and then

entity has_array_port is
generic(
IP_NUM : integer := 3;
);
port ( p: in a_nxm(0 to IP_NUM-1)

Not sure if I have written this correctly?

Looks good.

What I am trying to do is create
a generic mux. So for example, I may want 3, 64 bit slv.

This is still fine. At the point where you instance
the mux, you know exactly what you plan to connect
to it:

signal P, Q, R, S: std_logic_vector(M-1 downto 0);
...
my_4way_mux: entity work.has_array_port
generic_map(IP_NUM => 4)
port map (p(0) => P, ..., p(3) => S, ...

The problems will start if you want THIS higher level
entity also to be configurable, because then it makes
no sense whatever to list out the port elements one
by one - such a list would be broken for any different
number of inputs than you wrote it for. So you'll need
an array signal up there in that top module too. But
that's fine:

constant SIZE: integer := 6;
signal A: array(0 to SIZE-1) of std_logic_vector(M-1 downto 0);
...
my_Nway_mux: entity work.has_array_port
generic_map(IP_NUM => SIZE)
port map (p => A, ...

Now, of course, you have the exquisite problem of
how to attach your miscellany of 64-bit signals
to the elements of A... but hey, things have to
get specific somewhere, don't they? This is a
typical problem with things like data readback
muxes for a register file - the mux can be generic,
but the individual registers are all different and
it's hard to parameterize their existence.

Sometimes you can partially solve this by using
an enum type as the array index. The enum names
then denote individual registers. It doesn't
solve the problem entirely, but it can make your
eventual solution look less ugly.
--
Jonathan Bromley
Ok so I have done the above and have and instantiate the mux with 3, 64-bi
inputs. I try and connect a 64-bit vector to one of the inputs and when
try and simulate I get the following error.

Signal "app_rd_data_i" is type ieee.std_logic_1164.std_logic_vector
expecting type ieee.std_logic_1164.std_logic.

The signal "app_rd_data_i" is a 64-bit slv and I try and connect it to on
of the mux inputs. Not quite sure why it thinks the mux input i
std_logic?

TIA

Jon

---------------------------------------
Posted through http://www.FPGARelated.com
 
On Sat, 20 Aug 2011 14:10:54 -0500, "maxascent" wrote:

Ok so I have done the above and have and instantiate the mux with 3, 64-bit
inputs. I try and connect a 64-bit vector to one of the inputs and when I
try and simulate I get the following error.

Signal "app_rd_data_i" is type ieee.std_logic_1164.std_logic_vector;
expecting type ieee.std_logic_1164.std_logic.

The signal "app_rd_data_i" is a 64-bit slv and I try and connect it to one
of the mux inputs. Not quite sure why it thinks the mux input is
std_logic?
Sounds as though you have put a std_logic_vector port on
your mux entity, rather than an array port. The basic
idea is perfectly sound; something must be messed up
somewhere.
--
Jonathan Bromley
 
Sounds as though you have put a std_logic_vector port on
your mux entity, rather than an array port. The basic
idea is perfectly sound; something must be messed up
somewhere.
--
Jonathan Bromley
I fixed the problem; I had left an old component declaration in th
package. I just have one final question. If I have the following type in
package :-

constant MUX_DATA_BITS : integer := 64;
constant MUX_IP_NUM : integer := 8;
type mux_array is array(0 to MUX_IP_NUM-1) o
std_logic_vector(MUX_DATA_BITS-1 downto 0);

How do I override the two constants when I instantiate my mux so that I ca
have different input vectors and input numbers?

Thanks

Jon

---------------------------------------
Posted through http://www.FPGARelated.com
 
"maxascent" <maxascent@n_o_s_p_a_m.n_o_s_p_a_m.yahoo.co.uk> wrote:

Sounds as though you have put a std_logic_vector port on
your mux entity, rather than an array port. The basic
idea is perfectly sound; something must be messed up
somewhere.
--
Jonathan Bromley


I fixed the problem; I had left an old component declaration in the
package. I just have one final question. If I have the following type in a
package :-

constant MUX_DATA_BITS : integer := 64;
constant MUX_IP_NUM : integer := 8;
type mux_array is array(0 to MUX_IP_NUM-1) of
std_logic_vector(MUX_DATA_BITS-1 downto 0);

How do I override the two constants when I instantiate my mux so that I can
have different input vectors and input numbers?
These sort of 'problems' are best solved by creating a function.

--
Failure does not prove something is impossible, failure simply
indicates you are not using the right tools...
nico@nctdevpuntnl (punt=.)
--------------------------------------------------------------
 
I am trying to create a generic mux that I can just instantiate in an
design. I have done this in Verilog quite easily, but it seems VHDL is
different matter.

Jon

---------------------------------------
Posted through http://www.FPGARelated.com
 
On Sun, 21 Aug 2011 08:13:29 -0500, "maxascent" wrote:

I am trying to create a generic mux that I can just instantiate in any
design. I have done this in Verilog quite easily, but it seems VHDL is a
different matter.
It's actually much *easier* and *better* in VHDL, but to
see why you must be prepared to try some new ideas.

Here's your generic mux, done without any generics.

Assume there's a package containing the
following declarations (there is, isn't there?):

constant M: positive := 64; -- bit width
subtype word_M is std_logic_vector(M-1 downto 0);
type word_M_array is array(natural range <>) of word_M;

Now we can do this:

entity M_bit_generic_mux is
-- note: no generics (parameters) needed
port (data: in word_M_array; -- no bounds
selector: in std_logic_vector;
result: out word_M);
end;
architecture A of M_bit_generic_mux is
begin
-- Paranoia first.
assert 2**selector'length >= data'high
and data'low >= 0
report integer'image(selector'length)
& "-bit selector is too narrow for range "
& integer'image(data'low) & " TO "
& integer'image(data'high)
severity failure;
-- Now do the real mux
process (data, selector)
variable r: word_M;
begin
r := (others => '0'); -- or other default value
for i in data'range loop
if i = to_integer(unsigned(selector)) then
r := r or data(i);
end if;
end loop;
result <= r;
end process;
end;

The ports without bounds are known as "unconstrained"
array ports, and each instance of the entity gets its
port's size from the size of whatever signals you choose
to connect to that port. So now I can hook up the mux
like this:

signal sig0, sig1, sig2: word_M;
signal selector: std_Logic_vector(1 downto 0);
signal result; word_M;
...
three_input_mux: entity work.M_bit_generic_mux
port map (data(0) => sig0, data(1) => sig1, data(2) =>sig2,
selector => selector, result => result);

and the design automatically resizes itself to suit the (0 to 2)
input array. Equally you could use an array signal for the inputs:

signal in_sigs: word_M_array(4 to 7);
signal selector3: std_logic_vector(2 downto 0);
signal result4to7: word_M;
...
four_input_mux : entity work.M_bit_generic_mux
port map (data => in_sigs,
selector => selector3,
result => result4to7);

Note that the assertion would have tripped if you had
tried to use signal "selector" in this case, because its
two bits can't address elements 4 to 7.

Hope this helps.
--
Jonathan Bromley
 
Thanks for the explanation Jonathan. The one thing I still don't understan
is what you would do if you want to change the bit width of the vectors. I
my Verilog mux I can just instantiate it and override the parameters t
create a different mux. If I want 5 mux in my design, all with differen
sizes then thats not a problem. I dont quite see how you would do that i
VHDL using the constant in the package.

Jon

---------------------------------------
Posted through http://www.FPGARelated.com
 
On Sun, 21 Aug 2011 13:09:15 -0500, "maxascent" wrote:

Thanks for the explanation Jonathan. The one thing I still don't understand
is what you would do if you want to change the bit width of the vectors. In
my Verilog mux I can just instantiate it and override the parameters to
create a different mux. If I want 5 mux in my design, all with different
sizes then thats not a problem. I dont quite see how you would do that in
VHDL using the constant in the package.
Well, you're right that this is a slightly awkward feature of
design parameterization in VHDL. You can deal with it in various
ways. VHDL-2008 package generics (not very widely supported yet)
handle it nicely. The more portable, but slightly more wordy way
is to use true 2-dimensional arrays; these let you do the
parameterization with complete generality, but force you into
writing conversion functions or blocks to shuttle between "array of
std_logic_vector" and "2-d array of std_logic". It's not really
difficult, and it doesn't cost you any extra logic, but it looks
a bit convoluted. The type declaration would be

type multi_SLV is array(
natural range <>, -- choose a word
natural range <>) -- choose a bit in a word
of std_logic;

and you can put one of those on an unconstrained port, or use
generics to constrain its dimensions. But you can't directly
slice it to give you a std_logic_vector. Instead you need a
selector function, which of course you squirrel away in the same
package that defines the array:

-- Get one SLV slice out of the 2-d array
function get_vector(the_array: in multi_SLV; slice: in natural)
return std_logic_vector is
-- Make a variable that matches one row of the array
variable v: std_logic_vector(the_array'range(2));
begin
for bit_num in v'range loop
v(bit_num) := the_array(slice, bit_num);
end loop;
return v;
end;

And probably an updater function too:

-- Update one SLV slice in a 2-D array, returning the
-- updated array as a whole
function set_vector(the_array: in multi_SLV; slice: in natural;
new_slice_contents: in std_logic_vector)
return multi_SLV is
variable a: multi_SLV(the_array'range(1), the_array'range(2));
variable v: std_logic_vector(the_array'range(2);
begin
v := new_slice_contents; -- normalizes the vector range
a := the_array;
for bit_num in v'range loop
a(slice, bit_num) := v(bit_num);
end loop;
return a;
end;

Looks clunky, but once you've written the package it's all
quite neat and tidy - and it's only bit-twiddling so there's
no additional logic overhead.
--
Jonathan Bromley
 

Welcome to EDABoard.com

Sponsor

Back
Top