Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Support for "Jagged" array in modern HDLs

Status
Not open for further replies.

shaiko

Advanced Member level 5
Joined
Aug 20, 2011
Messages
2,644
Helped
303
Reputation
608
Reaction score
297
Trophy points
1,363
Activity points
18,302
Hello,

Do any modern HDLs ( SV / VHDL2008 ) support "jagged arrays" ?

For example - something like this :
Code:
some_jagged_array ( 0 to 7 ) ( array_of_integers_to_set_the_width ( index ) - 1 downto 0 )

"some_jagged_array" has 8 elements - however, each element can have a different length that's bound by another array of integers.
 

Nope. Neither SV or VHDL support it, and I doubt have any plans to. (unless you include dynamic arrays)
You can of do this with arrays of pointers, however.


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
type slv_array_t is array(natural range <>) std_logic_vector;
type slv_array_ptr_t is access slv_array_t;
 
type jagged_array_t is array(natural range <>) of slv_array_ptr_t;
variable jagged_array : jagged_array_t(0 to 7);
 
....
 
jagged_array(0) := new slv_array_t(0 to 2)(31 downto 0);
jagged_array(1) := new slv_array_t(0 to 100)(0 to 7);
-- etc



With VHDL 2008, its also possible to define packages that create dynamic arrays and queues for any type.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
SystemVerilog supports this using dynamically sized arrays.

Code Verilog - [expand]

1
2
3
4
bit [31:0] some_jagged_array [8][];
parameter int array_of_integers_to_set_the_width[8] = {8,7,6,5,7,8,9,4};

foreach (some_jagged_array[dim1st]) some_jagged_array[dim1st] = new[array_of_integers_to_set_the_width[dim1st]];


This may not be supported by current synthesis tools
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
TrickyDicky,

This is for synthesis - so I don't think using the access type is viable. But perhaps I'm wrong...
I'll explain what I want to do.

Component "daughter" is instantiated inside entity "mother" as follows:

Code:
entity mother is
generic
(
    array_of_integers ( 0 to 7 ) 
)
port 
(
    jagged_output_ports ( 0 to 7 ) 
)
end entity ;



architecture rtl_mother of mother is 

component daughter is
generic
(
    width : positive 
)
port 
(
    some_output : std_logic_vector ( width - 1 downto ) 
) ;
end component daughter ;

begin

create_8_daughters_width_different_output_widths : for index in 0 to 7 
generate

iterate_8_times : daughter  
generic map
(
    width => array_of_integers ( index ) 
)

port map
(
    some_output => jagged_output_ports ( index ) 
) ;

end generate ;

end architecture rtl_mother ;
 

This is not directly supported, but can be emulated. You can use a record type and a function that takes that record type, an x index, a y index, and returns an element.

This could possibly also be implemented with an array and an address conversion function.
 

TrickyDicky,

This is for synthesis - so I don't think using the access type is viable. But perhaps I'm wrong...
I'll explain what I want to do.

Component "daughter" is instantiated inside entity "mother" as follows:

For this kind of example - I would usually just make the array as large as the biggest connection, and then leave the unwanted connections unconnected. The synthesis will remove them.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
You can use a record type and a function that takes that record type, an x index, a y index, and returns an element.
Can you please show an example.
This could possibly also be implemented with an array and an address conversion function.
Can you please show an example.
 

This is not directly supported, but can be emulated. You can use a record type and a function that takes that record type, an x index, a y index, and returns an element.
This could possibly also be implemented with an array and an address conversion function.

Possibly, but I dont really see how.
If you used a record, you would lose the ability to index into the array of arrays.
Records are not really suitable for jagged arrays.
 

no. learn vhdl.
This is exactly it...me learning.
I came to the conclusion that what I want can be done in 3 ways:

1. Using a flat vector instead of an array - which IMO makes for a really ugly unreadable code.
2. What TrickyDicky suggested in #6 - does the job but leaves a lot of "fallout" in the form of hundreds of synthesis warnings and ( maybe ) simulation slow down because of uninitialized signals.
3. Using a high level scripting language to generate a tailored code that removes the need for jagged array.

So...my process of learning brought me to a conclusion that an elegant solution doesn't really exist with current HDLs.
And then you come and say: "I have a way".
Why do you consider my follow-up: "show us" not to be a part of the learning process?
 

1. Using a flat vector instead of an array - which IMO makes for a really ugly unreadable code.

You could use a flat array and use a look up function to hide the ugly code.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
Both the record and flat array in my suggestion rely on not using the built in indexing and instead using custom functions.

An example would be having a lookup table of the cumulative sum of the widths of the x indicies. eg, if the jagged array has a 5 element array, a 7 element array, and an 8 element array then you could have a lookup table with 0, 5, 5+7, 5+7+8. The total size of the array is 5+7+8 = 20. The lookup function is lut(x) + y, eg f(0, 3) gets the element at index 3 from the 5 element array (0 + 3). f(1, 2) gets index 2 from the 7 element array. (5 + 2). f(2,7) gets index 7 from the 8 element array (5+7 + 7).

Depending on the application, having a less dense ram might perform better. for my example, maybe have a 32 element array with 5 elements used, 3 skipped, 7 used, 1 skipped, 8 used, 8 skipped would be better. If this can be a DMEM, it moves the mux logic into the SLICEM and the address logic is simply 2 bits of x followed by 3 bits of y.
 

An example would be having a lookup table of the cumulative sum of the widths of the x indicies. eg, if the jagged array has a 5 element array, a 7 element array, and an 8 element array then you could have a lookup table with 0, 5, 5+7, 5+7+8. The total size of the array is 5+7+8 = 20. The lookup function is lut(x) + y, eg f(0, 3) gets the element at index 3 from the 5 element array (0 + 3). f(1, 2) gets index 2 from the 7 element array. (5 + 2). f(2,7) gets index 7 from the 8 element array (5+7 + 7).

But this will still leave you with a bunch of unused logic to be optimized away - right ?
 

But this will still leave you with a bunch of unused logic to be optimized away - right ?

Not for the implementation that you quote. However, it can imply more complex logic for non-constant indicies.

Looking at your use case, you likely just want a packed output for the module followed by packing/unpacking functions. This is again just the cumulative sum of the integer array. eg:

Code:
port map
(
    some_output => packedOutputPort ( kCSum(i+1)-1 downto kCSum(i)) 
) ;

and then the same basic logic where the data is consumed. This is what you suggest as #1. I don't think it is that bad because the ugly code is highly localized. This can also be formalized with functions if you for some reason need to pack/unpack this more than once, or you do this in several places. You might want to have intermediate version of these signals for simulation purpose -- basically you'd want to avoid ever looking at the packed version.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
I really appreciate your help so far.
Nonetheless - It's very hard to grasp your idea without a example code (one that involves the actual usage of records).

I don't want to waste your time - as this is purely for learning purposes.
But if you could post a VHDL example that involves the records - it'll be perfect.

Either way - thank you.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top