VHDL Basic Question

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?

TIA

Jon

--------------------------------------- Posted through

formatting link

Reply to
maxascent
Loading thread data ...

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
Reply to
Jonathan Bromley

0)

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 create a generic mux. So for example, I may want 3, 64 bit slv.

Thanks

Jon

--------------------------------------- Posted through

formatting link

Reply to
maxascent

Looks good.

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
Reply to
Jonathan Bromley

--------------------------------------- Posted through

formatting link

Reply to
maxascent

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?

TIA

Jon

--------------------------------------- Posted through

formatting link

Reply to
maxascent

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
Reply to
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?

Thanks

Jon

--------------------------------------- Posted through

formatting link

Reply to
maxascent

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=.)
--------------------------------------------------------------
Reply to
Nico Coesel

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.

Jon

--------------------------------------- Posted through

formatting link

Reply to
maxascent

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

Reply to
Jonathan Bromley

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.

Jon

--------------------------------------- Posted through

formatting link

Reply to
maxascent

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
Reply to
Jonathan Bromley

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.