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.

Synthesis support for 3D HDL arrays

Status
Not open for further replies.
K-J,
In #15 you wrote:

Assume the following code:

Code:
signal x is array ( 0 to 2 ) of std_logic_vector ( 7 downto 0 ) ;
signal y : std_logic_vector ( 7 downto 0 ) ;  
y <= x ( 1 ) ;

Despite the fact that I left off the second boundary of x - the above will be legal.

How is it any different than:
Code:
row <= IN_FRAME ( some_row_number ) ;
?
In the code above 'x' is defined to be a one dimensional array, so 'x' only has one index. What you defined for IN_FRAME is a three dimensional array which will require specifying three indices: IN_FRAME : generic_3d_array ( 0 to ROWS_PER_FRAME - 1 , 0 to PIXELS_PER_ROW - 1 , BITS_PER_PIXEL - 1 downto 0 ) ;

Kevin Jennings
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
IN_FRAME is a three dimensional array which will require specifying three indices
But if IN_FRAME is defined as:
Code:
IN_FRAME : generic_3d_array ( 0 to ROWS_PER_FRAME - 1 , 0 to PIXELS_PER_ROW - 1 , BITS_PER_PIXEL - 1 downto 0 ) ;
and when addressing an element you specify 3 indices - won't the result be a single bit std_logic ??
std_logic == IN_FRAME ( 1 , 2 , 3 )
 
Last edited:

and when addressing an element you specify 3 indices - won't the result be a single bit std_logic ??
std_logic == IN_FRAME ( 1 , 2 , 3 )

Yes it will if the base array was declared as a 3D array of std logic. If you're trying to extract an entire std_logic_vector, why not just make a 2D array of std_logic_vectors?
What are you actually trying to do?
 

What are you actually trying to do?
I want to define IN_FRAME in such a way that I'll be able to:
1. Address specific rows,
2. Address specific pixels.
 

I want to define IN_FRAME in such a way that I'll be able to:
1. Address specific rows,
2. Address specific pixels.

IN_FRAME was defined as as rows of columns of pixels, but there is no mention of columns above but I'll assume that columns are still in the picture (pun intended).

You can do what you want either as an array of pixels or as a multi-dimensional array as has been discussed. The factors that will influence which way you should go are the following:
- Do you require (or are you prevented from using) VHDL-2008? Prior to VHDL-2008 you could not have an unconstrained array of an unconstrained array which might prevent use of the array of pixels approach and instead have to use a multi-dimensional array
- Where are the number of rows and columns going to be defined? If they are passed in as generics to an entity then you will have to use VHDL-2008 in order to use the array of pixels approach. If instead the entity defines the rows and columns then there should not be any issue with the array of array approach. The multi-dimensional array approach will work with any version of VHDL.
- Tool support of multi-dimensional arrays. You'll have to experiment with the tools to find out if there are any limitations. I don't know that there are any issues, just saying it might be a factor.

Things that should not influence your decision:
- Having to write a function to get or set a row or a pixel from a multi-dimensional array. It's not hard, you write and test it once and you're done, just use them.
- How the pixels are represented. In terms of synthesis output, it really doesn't matter which way you define things. If the definitions represent the same number of pixels you should get the same synthesis result.

Kevin Jennings
 

You can do what you want either as an array of pixels or as a multi-dimensional array as has been discussed.
Thanks Kevin,

VHDL 2008 is an option - but the design is intended for synthesis.
ALL custom types will be defined in a package and later constrained by entity generics.
Regarding Column addressing - I have no need for that in my application.
My design approach has changed so I'll describe exactly what I intend to do:

Code:
-- The following custom types will be defined in an external package.
type generic_1d_array ( natural range < > )  of std_logic_vector ;
type generic_2d_array ( natural range < > , natural range < > )  of std_logic_vector ;

-- I have an entity input:
IN_ROW : generic_1d_array ( 0 to PIXELS_PER_ROW - 1 ) ( BITS_PER_PIXEL - 1  downto 0 ) ;

-- I want to create indexed delayed copies of IN_ROW ( essentially an array of rows - with the indexed value indicating the number of delay stages ).  
signal row_array : generic_2d_array ( 0 to NUMBER_OF_ROWS - 1 , 0 to PIXELS_PER_ROW - 1 ) ( BITS_PER_PIXEL - 1  downto 0 ) ;

row_array ( 0 ) <= IN_ROW ;

process ( clock ) is 
begin
  if rising_edge ( clock ) then
     for index in 0 to NUMBER_OF_ROWS - 2
     loop
        row_array( index + 1 ) <= row_array( index ) ;
     end loop ;
  end if ;
end process ;

-- I define another array:
signal pixel_array : generic_1d_array ( 0 to NUMBER_OF_ROWS - 1 ) ( BITS_PER_PIXEL - 1  downto 0 ) ;

-- At this point - I want to map [U]some[/U] of the pixel elements of [B]row_array[/B] into pixel elements of [B]pixel_array[/B].
-- I write "some" because row_array will have more pixel elements than pixel_array.  

pixel_array ( some_pixel_number ) <= row_array ( some_row_number , some_pixel_number_inside_a_row ) ;

How can this be done?
 
Last edited:

How long are your rows? If you are intended to shift entire rows in the FPGA then your logic use is going to explode very quickly.
But for what you're doing I wouldnt bother with 2d arrays at all. As I understand it you could just do it with 2008 and 1d types as it makes your life easier with slicing. Afaik, both Vivado and Quartus support unconstrained array types. Just stick with this:

Code:
library ieee;
use ieee.std_logic_1164.all;

entity test2008 is
end entity;

architecture test of test2008 is

  signal clock : std_logic;

  type row_t is array(natural range <>) of std_logic_vector; --wouldnt this make more sense to be an unsigned or signed if you're doing pixel arithmatic?
  type row_array_t is array(natural range <>) of row_t;
  
  signal row_array : row_array_t(0 to 7)(0 to 7)(7 downto 0);
  
  signal pel_array : row_t(0 to 3)(7 downto 0);
  
begin

  process(clock)
  begin
    for i in 0 to 5 loop
      row_array(i+1) <= row_array(i);
    end loop;
  end process;
    
  pel_array <= row_array(6)(3 to 6);
end architecture;

- - - Updated - - -

On a side note - if you want to do some imaging in testbenches you can do all of your array sizing on the fly using access types - this is a nice way you can load bitmaps into your testbenches without caring about the image size before you start the sim.
 

How long are your rows? If you are intended to shift entire rows in the FPGA then your logic use is going to explode very quickly.
Sure.
It's a building block. The smallest row length is 3 pixels. The number of instances will have to take resource usage into consideration .
wouldn't this make more sense to be an unsigned or signed if you're doing pixel arithmetic?
Good point. It should be the same type as the input port of the FPGA's DSP block.

I'll try to write my code according to your notes and see how it works.
Thanks!

- - - Updated - - -

TrickDicky,

In #28, one line before the last:
Code:
pel_array <= row_array(6)(3 to 6);
This maps one array into the other array - not my intention.
What I want to do - is map individual pixel elements from row_array into individual pixel elements of pel_array...
In other words: I want to be able to access row_array on the pixel level. This will enable me to wire a specific pixel from row_array into a specific location in pel_array.
 

In that case, do what you wish - 2d or 1d. But given the ease of slicing if you need it 1d may be more beneficial.
 

In that case, do what you wish - 2d or 1d. But given the ease of slicing if you need it 1d may be more beneficial.
Can you show an example of how to do what I want in 1d ?
 

If you can abstract into higher dimensions by declaring 1d arrays of -> 1d arrays of -> 1d arrays of etc...
In what situation would you bother using true 2D+ arrays?
 

Probably not very often.
I have used it as a nice way to contain a 3x3 filter, but thats the only ever time Ive used it for synthesisable code. There is just no point anywhere else. If you stray to far outside the coding guidelines and it doesnt work, the answer to the service request is usually "thats not in the coding guidelines - Ill file an enhancement request but dont expect it to work any time soon".

I have used it plenty in testbench code though - to contain test images.
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
My code compiles correctly...
Thanks for your help.

If it was a true 2d array I should have written:
pixel_array(n) <= row_array(a,b);
instead of:
pixel_array(n) <= row_array(a)(b);
?
 

If you can abstract into higher dimensions by declaring 1d arrays of -> 1d arrays of -> 1d arrays of etc...
In what situation would you bother using true 2D+ arrays?
If VHDL-2008 is not an option and you need unconstrained vector sizes.

Kevin Jennings
 
  • Like
Reactions: shaiko

    shaiko

    Points: 2
    Helpful Answer Positive Rating
TrickyDicky, K-J

The array of array approach compiled correctly in Modelsim.
Now, I want to try the true 2D approach.

Can you please leave your input regarding what I asked in #35?
 

You'll be creating a large number of FF and possibly muxes without much effort.
A "large amount" of FFs is kind of my goal here...
Regarding MUXes - I see no reason for any to be inffered. Only FFs with wires.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top