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.

vhdl varable lengh Arrays wih STD_LOGIC_VECTOR indexing

Status
Not open for further replies.

jmoore

Newbie level 3
Joined
Sep 24, 2010
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,354
Hi
I have been trying to make a clean variable size memory bank with little to no success.
What i am trying to replace is the classic case statement :
process(clk_40,reset,wr,data,address)
begin
if clk_40'event and clk_40 = '1' then
if reset = '1' then
registers_int <= (others =>(others => '0'));
elsif wr = '1' then
case address is
when "00000000" => registers_int(0) <= data;
when "00000001" => registers_int(1) <= data;
....

with something that does not require adding new cases like this:
begin
out_regs <= registers_int;
process(clk,reset,wr,data,address)
begin
if clk'event and clk = '1' then
if reset = '1' then
registers_int <= (others =>(others => '0'));
elsif wr = '1' then
registers_int( conv_integer(address)) <= data;
end if;
end if;

I am getting the flowing error when I try and compile:

ERROR:HDLCompiler:432 - "/home/jmoore/devel/xilinx/hep015a_doric/arb_mem_bank.vhd" Line 57: Formal <arg> has no actual or default value.
INFO:HDLCompiler:1408 - "/build/xfndry10/O.61xd/rtf/vhdl/xst/src/syn_arit.vhd" Line 162. arg is declared here
INFO:HDLCompiler:1408 - "/build/xfndry10/O.61xd/rtf/vhdl/xst/src/syn_arit.vhd" Line 162. arg is declared here
ERROR:HDLCompiler:541 - "/home/jmoore/devel/xilinx/hep015a_doric/arb_mem_bank.vhd" Line 57: Type integer is not an array type and cannot be indexed.

I know this I probably a dead horse around here but any help would be appreciated.
 

It's a little hard to debug without knowing what line numbers are. Which line(s) are causing the error? Also, we need to see your signal declarations; we have no idea what your signal types are. And I've never seen that "(others=>(others=>'0')) construct before. (That doesn't mean it's wrong, but I'm not sure what that does)
 

Sory I am terrible at giving details..

the oringanal long way of doing it is as follows :

entity control_registers is
Port ( clk_40 : in STD_LOGIC;
reset : in STD_LOGIC;
wr : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (15 downto 0);
address : in STD_LOGIC_VECTOR (7 downto 0);
registers : out array_of16b(0 to 65);
read_back_data : out STD_LOGIC_VECTOR (15 downto 0));
end control_registers;

architecture Behavioral of control_registers is
signal registers_int : array_of16b(0 to 65);
begin
registers<= registers_int;
process(clk_40,reset,wr,data,address)
begin
if clk_40'event and clk_40 = '1' then
if reset = '1' then
registers_int <= (others =>(others => '0'));
elsif wr = '1' then
case address is
when "00000000" => registers_int(0) <= data;
when "00000001" => registers_int(1) <= data;
when "00000010" => registers_int(2) <= data;


......
array_of16b is defined as:
type array_of16b is array(natural range<>) of STD_LOGIC_VECTOR (15 downto 0);

_________________________________________________________________________
the new shorter way is :

entity arb_mem_bank is
generic( length_of_reg : integer := 7 );
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
wr : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (15 downto 0);
address : in STD_LOGIC_VECTOR (15 downto 0);
out_regs : out array_of16b(0 to length_of_reg);
rd_back_data : out STD_LOGIC_VECTOR (15 downto 0));
end arb_mem_bank;

architecture Behavioral of arb_mem_bank is

signal registers_int : array_of16b(0 to length_of_reg);

begin
out_regs <= registers_int;
process(clk,reset,wr,data,address)
begin
if clk'event and clk = '1' then
if reset = '1' then
registers_int <= (others =>(others => '0'));
elsif wr = '1' then
registers_int( conv_integer(address)) <= data;
end if;
end if;
end process;
process(clk,address)
begin
if clk'event and clk = '1' then
rd_back_data <= registers_int(address) ;
end if;
end process;
end Behavioral;


____________________________________________________
the error
ERROR:HDLCompiler:432 - "/home/jmoore/devel/xilinx/hep015a_doric/arb_mem_bank.vhd" Line 57: Formal <arg> has no actual or default value.
was being thrown on
registers_int( conv_integer(address)) <= data;

I have never had a compiler play nicely when using a std_logic_vector for indexing anything with out making an explicit case statement as in the first example above. Is this just the nature of the beast(VHDL)? If this is the case and you want to used an std_logic_vector to do addressing on a "variable size" register bank, where the size if fixed at compile time, you need to make a script to generate the case statement code before compiling? In this case the register bank would not be variable in the sense of setting a generic variable but rather a crude hack workaround.
 

I think I've run into similar problems, it's due to the compiler not being as smart as you think it is. I believe what I tried in the past was have a dummy variable/signal where I did the conversion, e.g.,

signal dummy: integer range 0 to 100
.
.
.
dummy<=conv_int(address)
registers_int(dummy)<=data;

Not really sure if this is what I did, but it looks familiar.

Let me know if this works.

Barry
 

you have several problems here:

The first is not really a problem, its more of a gripe. Why are you using a std_logic_vector? its not a number, and treating it as a number means you have to include the non-standard std_logic_unsigned/signed package which means you can never do signed and unsigned things in the same file. The IEEE standard package to do this is numeric_std that defines signed and unsigned types.

Secondly, you do not have a "variable" length memory - it is fixed at compile time (defaulting to 8). The problem is you have a 16 bit address bus that converts to 0 to 2^16-1, way more than you have spaces in the memory. When you put in an address higher than 7, you will get an error when simulating because of the out of range error. Why not declare address as an integer instead? you know you're allowed types other than std_logic_vectors on ports right?

Code:
entity arb_mem_bank is
port (
  ...
  address : integer range 0 to length_of_reg;
);

end entity arb_mem_bank;

Next error - you cannot reset a memory, in either Xilinx or Altera, so unless you want this to synthesize to registers (and take a long time and a lot of resources as the memory gets bigger) remove the synchronous reset on the memory. There is usually no need to reset a memory as contents just get over-written.

Next point - you only need clk in the sensitivity list of the process.

next - do not output the entire memory. The contents should only be visible via the read address, not the entire lot. This is probably causing the compiler problems.

So overall - you have several problems. Creating infered memories in FPGAs is very simple in VHDL, as long as you follow the following template (some things may be slightly altered, depending on your FPGA target - but please read their coding guidelines)

Code:
entity my_mem is
  generic (
  	MEM_BITS : natural;
  	D_WIDTH  : natural
  	);
  	
 port ( 	 
 	 clk     : in std_logic;
 	           
 	 rd_addr : in  integer range 0 to 2**MEM_BITS-1;
 	 rd_en   : in  std_logic;
 	 rd_data : out std_logic_vector(D_WIDTH-1 downto 0);
 	 
 	 wr_addr : in  integer range 0 to 2**MEM_BITS-1;
 	 wr_en   : in  std_logic;
 	 wr_data : in  std_logic_vector(D_WIDTH-1 downto 0)
 	 	
 	);
 	
end entity my_mem;
	
architecture rtl of my_mem is
	type mem_array_t is array(0 to 2**MEM_BITS-1) of std_logic_vector(D_WIDTH-1 downto 0);
	signal mem    : mem_array_t;
begin
	
	process(clk)
	begin
		if rising_edge(clk) then
			
			if wr_en = '1' then
				mem(wr_addr)  <= wr_data;
			end if;
				
		  ------------------------------------------------------------------------
		  --Altera may require you to register the rd_addr before reading
		  ------------------------------------------------------------------------
		  if rd_en = '1' then
		  	rd_data       <= mem(rd_addr);
		  end if;
			
		end if;
	end process;
	
end architecture rtl;
 

Although TrickyDicky is right about a number of issues, I think that the quoted error is of a more simple kind. Of course, it's no problem to convert a std_logic_vector adress to an integer index. You're not showing the imported libraries but assuming
Code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

conv_integer(address) has to be changed into conv_integer(unsigned(address))
 

Thanks I am probably doing dumb things here as mentioned above. This is no so much a memory bank for say as a bank of control registers. The reason I am outpointing the whole thing is I was having trouble a wile back with control registers not being written in some sub blocks. Therefore I made all the control lines asynchronous in my sub blocks and then wired it up to a large "flat memory" space which I knew I could read and write to at will. It worked so I ran with it.... go ahead and flame on.

Yes I know I have a larger address space than number of registers used. The 16 bit adr and data are from the external world (i.e. control lies written from lab view) I could pare them down before ruining them in to the block but just assume let the compiler optimise it out...( yes dumb and lazy)

The reason I am using STD_LOGIC_vector the control lines are coming from an external micro and changing type is a pain if not impossible in VHDL hens my original question.
 

conv_integer(address) has to be changed into conv_integer(unsigned(address))

conv_integer will actually work with the std_logic_unsigned package directly on std_logic_vectors, so it should be fine as it is.

type conversion is only a pain when you have to do it all the time. Its actaully very easy when you dont have to do it all the tiem (ie. dont use std_logic_vectors all the time).

If you're doing registers, have you considered using a record type to store them, that way yuo can have much more meaningful names. You will need a case statement to decode the address though:

Code:
type reg_record_t is record
  reg1 : std_logic_vector(7 downto 0);
  reg2 : std_logic_vector(15 downto 0);
  reg3 : boolean;
  reg4 : integer;
  --etc
end record reg_record_t;
 

conv_integer will actually work with the std_logic_unsigned package directly on std_logic_vectors, so it should be fine as it is.
You are guessing about imported libraries. You can say, it would be fine, if... How do you know, that std_logic_unsigned is used?

Apart from discussing possible issues, the original poster was asking what caused the said error. Although you mentioned important points, I didn't notice a clear explanation of this point.


P.S.: Just as an observation, the code from post#3 compiles in Altera Quartus, if the type conversion problem is fixed. Of course it's not inferring RAM. But the original poster didn't even say, if he expected this.
 
Last edited:

the register interface is fairly common. I always suggest a simple microcontroller for designs because the simple register interface rarely remains simple.

There are several features that get added to command and control interfaces. If you look at things like TCP/IP and the web, you see several of the same concepts. eg, data integrity, retransmissions, sessions, security, asynchronous communications, larger data accesses, etc... All of these more advanced features are easier to implement in a micro than an FPGA. but for the main register interface, you should be ok. Just make sure to be careful as certain code changes can infer significantly more registers if the synthesizer can't optimize out the unused ones.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top