0

I'm trying to use a multidimensional array in VHDL and I'm having a lot of trouble getting it to work properly. My issue is that I've got an array of 17, of 16 vectors, of a given size. What I want to do is create 17 registers that are array of 16 * std_logic_vector of 32 bits (which = my b, 512). So, I'm trying to pass in something to input and output on the register instantiation that tells the compiler/synthesizer that I want to pass in something that is 512 bits worth... Similar to in C if I had:

int var[COLS][ROWS][ELEMENTS];
memcpy(&var[3].. // I'm talking about 3rd COL here, passing in memory that is ROWS*ELEMENTS long

(My actual declaration is here:)

type partial_pipeline_registers_type is array (0 to 16, 0 to 15) of std_logic_vector(iw - 1 downto 0); signal h_blk_pipelined_input : partial_pipeline_registers_type;

I tried simply using h_blk_pipelined_input(0) .. up to (16) but this doesn't work. I get the following error, which makes me see that I need to double index in to the array:

ERROR:HDLParsers:821 - (at the register) Wrong index type for h_blk_pipelined_input.

So then I tried what's below, and I get this error:

ERROR:HDLParsers:164 - (at the register code). parse error, unexpected TO, expecting COMMA or CLOSEPAR


  instantiate_h_pipelined_reg : regn
   generic map ( N=> b, init => bzeros )
   port map ( clk => clk , rst => '0', en => '1',
      input => h_blk_pipelined_input((i - 1), 0 to 15),
      output=> h_blk_pipelined_input((i),     0 to 15));
-- Changing 0 to 15 to (0 to 15) has no effect...

I'm using XST, and from their documentation (http://www.xilinx.com/itp/xilinx6/books/data/docs/xst/xst0067_9.html), the above should have worked:

...declaration:

subtype MATRIX15 is array(4 downto 0, 2 downto 0)
   of STD_LOGIC_VECTOR (7 downto 0);

 A multi-dimensional array signal or variable can be completely used:

Just a slice of one row can be specified:

MATRIX15 (4,4 downto 1) <= TAB_B (3 downto 0);

One alternative is that I can create more registers that are 16 times smaller, and instead of trying to do all '0 to 15' at once, I would just do that 15 additional times. However, I think this may lead to inefficiency in synthesis and I don't feel like this is the right solution.

EDIT:

Tried what Ben said,

instantiate_h_m_qa_pipeline_registers: for i in 1 to 16 generate

instantiate_h_pipelined_reg : regn
    generic map ( N=> b, init => bzeros )
    port map ( clk => clk , rst => '0', en => '1',
       input => h_blk_pipelined_input(i - 1),                                            
       output=> h_blk_pipelined_input(i));                                          
end generate instantiate_h_m_qa_pipeline_registers;                                                 

The signals are now defined as:

type std_logic_block is array (0 to 15) of std_logic_vector(iw - 1 downto 0) ;
type partial_pipeline_registers_type is array (0 to 16) of std_logic_block;
signal h_blk_pipelined_input : partial_pipeline_registers_type;

And the error I get from XST is:

ERROR:HDLParsers:800 - ((where the register part is)) Type of input is incompatible with type of h_blk_pipelined_input.

I'm able to do everything I was able to do before, using ()() syntax instead of ( , ) so I haven't lost anything going this way, but it still doesn't resolve my problem.

EDIT:

Took it a step further and used a conversion function on the input => and output => arguments for the register instantiation, using a function to convert between the array type and just a std_logic_vector the size that I need. It fixed the 'input => ' part, but..

Actual associated with Formal OUT mode Signal 'output' may not be a type conversion or function call. (LRM 4.3.2.2)

2 Answers 2

3

How about:

TYPE reg512_type IS ARRAY(0 TO 15) OF STD_LOGIC_VECTOR (31 DOWNTO 0);
TYPE partial_pipeline_registers_type IS ARRAY(0 TO 16) OF reg512_type;

The code on that Xilinx site obviously isn't tested. Since ARRAY OF ... are types, not subtypes, their code shouldn't compile.

EDIT: These custom types aren't going to play well with existing IP components, but that's ok, the compiler can infer registers easily enough. Try:

instantiate_h_m_qa_pipeline_registers: FOR i IN 1 TO 16 GENERATE

instantiate_h_pipelined_reg : PROCESS (clk)
BEGIN
    IF RISING_EDGE(clk) THEN
        h_blk_pipelined_input(i) <= h_blk_pipelined_input(i - 1);
    END IF;
END GENERATE instantiate_h_m_qa_pipeline_registers;   
Sign up to request clarification or add additional context in comments.

3 Comments

I think we're getting close here.. see my question edits at bottom of question for errors I'm getting now
@Nektarios: VHDL is very picky about types. Even types which are compatible, like UNSIGNED and STD_LOGIC_VECTOR, can't be used interchangeably. But you can cast between them (casting in VHDL looks like a C++ constructor-style cast). Or you can change the data type of the component parameters to reg512_type. To do that, you'll have to move the type declarations to a library module so they're visible to multiple components.
so, my register is defined with "input : in std_logic_vector(N-1 downto 0);" .. are you saying its possible that when I instantiate one of these registers and set up " input => h_blk.... " I can somehow recast my h_blk_pipelined_input to be seen as std_logic_vector(size) instead of an array of smaller std_logic_vectors? How would I do that exactly? Thanks
1

To get things to play right, I had to use a function to flatten and unflatten my data interacting with the register instantiation.

The real issue boiled down to me having an array of std_logic_vector() that resulted in a large vector which the register instantiation needed to have.. and then the register was giving me back the vector, which I needed to put in to an array of vectors.

Creating a function and then doing the following is working great.

      input => blk2vec(h_blk_pipelined_input(i - 1)),                        
      vec2blk(output) => h_blk_pipelined_input(i));

2 Comments

Unfortunately, I found that this doesn't synthesize.
But, using another intermediate signal, and then using a vec2blk type function there, does work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.