Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17264 Discussions

RAM/ROM Initialization Using a Generic Definded External Package File.

Altera_Forum
Honored Contributor II
2,627 Views

Greetings All: 

 

I am making an entity which functions as an SPI memory chip. I have previously made several memory blocks initialized using a function within the architecture declaration portion, however my current project is slightly different, so that previously version is not applicable. My SPI entity is instantiated many times, with different initialized values for each. 

 

Each instantiation has generics to set the size for the memory, page size, and so forth... however, I haven't figured out how to use a generic to select an external vhd file with a package/function generating the contents of the memory. That's the only part that needs to be defined outside of the entity other than the generics. 

 

I thought of using an external file, reading strings, converting to integer (which I haven't done in VHDL yet anyway), however the functions VHDL uses provides the ability to generate the data, a different file would have to create the data externally. 

 

Any Suggestions?
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
1,680 Views

 

--- Quote Start ---  

 

I haven't figured out how to use a generic to select an external vhd file with a package/function generating the contents of the memory.I haven't figured out how to use a generic to select an external vhd file with a package/function generating the contents of the memory. 

 

--- Quote End ---  

 

Why does it need to be an external VHDL file? You could pass it a text file containing Intel .hex format lines. That text file could be created by a VHDL function call with a return value that is the filename, or in fact a return value that is the .hex file contents. 

 

Perhaps you could post code that demonstrates the issue you are trying to solve. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,680 Views

Thanks for the Response. 

 

My requirement is to have only one single .vhd file defining the entity/architecture, and here is the reason: I have 5 different sized and typed memory in this project, EEPROM and FLASH, interfacing with existing hardware. The generics work fine, however the data requires a function to generate information. If the creation of the data is in the entity/architecture file, the project would require 5 separate copies, each with a unique function. Since I'm still working on the SPI memory, one code change would have to update all 5 files, not the normal simulate, code change, re-compile pattern. 

 

I’m not particular if there is 1 or 5 .vhd package files or a different option I haven’t thought of yet, it’s just the functionality. I’m still using VHDL 1993, however I’m willing to upgrade if 2008 has benefits, but didn’t hear any good reports. In the end, when I use the same SPI memory in another project, the single .vhd entity/architecture file should be the one placed in the next project, and the generics and/or data function could be created separate. And sometimes I’m forced to use Block Diagram/Schematic version, which may make more difficult. 

 

The next project I am going to work on is a 31 band EQ, so I hope it works by then, updating 5 separate file is painful, updating 31 files is brutal. 

 

David K.
0 Kudos
Altera_Forum
Honored Contributor II
1,680 Views

 

--- Quote Start ---  

 

My requirement is to have only one single .vhd file defining the entity/architecture, and here is the reason 

 

--- Quote End ---  

 

Sure, that is no problem. Lets say I have generics AWIDTH and DWIDTH. Then the hex file will have 2**AWIDTH x DWIDTH entries. Each instance of your component will be different, but the HDL identical. 

 

 

--- Quote Start ---  

 

The generics work fine, however the data requires a function to generate information. 

 

--- Quote End ---  

 

 

Ok, that is fine, you could have the function in a package and pass it the same generics as the component, or just have the initialization data as another port, eg., 

 

u1: controller generic map ( TYPE => "SPI", AWIDTH => 12, DWIDTH => 32, INIT => mem_contents("SPI",12,32) ); port map ( ...  

 

If you want me to take your current attempt and modify it, post some code. 

 

 

--- Quote Start ---  

 

the single .vhd entity/architecture file should be the one placed in the next project, and the generics and/or data function could be created separate 

 

--- Quote End ---  

 

No, that is not how you should do it :) 

 

Your code should live in a versioned repository and all projects should refer to the *single* copy of the source code. The generics would be controlled by either the project specific HDL via the instance generics, or any top-level generics would be controlled by your synthesis script, i.e., from Tcl code. 

 

I'll show you how, just post a couple of examples of how you want your code to be used. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,680 Views

dwh: 

Good suggestion. Before you got back, I found a way that worked, but it was way more complicated. I used an array for each generic entry, and used an 'index' generic to select which item of all the other ones. Each generic was stored in the package, in an array of integers. I though I had something functional, I found several forums externally claiming it was not possible. Your version is way more usable. Here's what I have so far... 

 

The Generics... 

use work.mem_init_config.all; entity mem is generic( --hardware mem_bit_size : integer := 2**17;--131072 bits mem_byte_width : integer := 8; mem_init : std_logic_vector := mem_init_func(0, 2**17, 8)--must match last 2 arguments with last above 2 generics --the first is an 'index', selecting wich initialization used in the package );  

 

The function in the mem_init_config package body... 

function mem_init_func( index : in integer; mem_bit_size : in integer; mem_byte_width : in integer ) return std_logic_vector is type mem_t is array(mem_bit_size / mem_byte_width - 1 downto 0) of std_logic_vector(mem_byte_width - 1 downto 0); variable mem_contents : mem_t; variable mem_word : std_logic_vector(mem_byte_width - 1 downto 0); variable mem_vector : std_logic_vector(mem_bit_size - 1 downto 0); begin case index is when 0 => mem_contents := (others => (others => '0')); --return mem0_contents; when 1 => mem_contents := (others => (others => '1')); --return mem1_contents; when 2 => mem_word := (others => '0'); for i in 0 to mem_bit_size / mem_byte_width - 1 loop mem_contents(i) := mem_word; mem_word := std_logic_vector(unsigned(mem_word) + 1); end loop; --return mem_contents; when others =>--last one mem_word := (others => '0'); for i in 0 to mem_bit_size / mem_byte_width - 1 loop mem_contents(i) := mem_word; mem_word := std_logic_vector(unsigned(mem_word) + 1); end loop; --return mem_contents; end case; --convert byte format to vector version for i in 0 to mem_bit_size / mem_byte_width - 1 loop for j in 0 to mem_byte_width - 1 loop mem_vector(i * mem_byte_width + j) := mem_contents(i)(j); end loop; end loop; return mem_vector; end function;  

 

I used an all '1' bits, all '0' bits, count up bytes, and count down bytes for simulation. 

 

I had to convert it to a std_logic_vector in the function so the last generic would accept it, and convert it back to the memory format in the memory .vhd file, so I wouldn't have define the mem_t type in the package and pass it on to the entity, keep in mind the mem_t type is different depending of the other generic settings. 

 

The single entity generates the 131072 bits (55% of my FPGA, can't make more). I have tested it in a higher level entity making 4 different sized and I have some strange errors reaching 16384 bits on one of them so I have some homework. I also have to make sure it can run as a symbol on the block_diagram/schematic. 

 

Thank you for the good information, now I know it's possible. 

 

David K.
0 Kudos
Altera_Forum
Honored Contributor II
1,680 Views

 

--- Quote Start ---  

 

I had to convert it to a std_logic_vector in the function so the last generic would accept it, and convert it back to the memory format in the memory .vhd file, so I wouldn't have define the mem_t type in the package and pass it on to the entity, keep in mind the mem_t type is different depending of the other generic settings. 

 

--- Quote End ---  

 

I think that was the right decision. Sometimes there are several solutions to a problem, and going with the least-code is often the easiest way to go, and it makes it easier for the next person to read your code. Everyone knows what a big std_logic_vector is, and its more work to look up a package and see what the definition of the 2D array is. 

 

 

--- Quote Start ---  

 

The single entity generates the 131072 bits (55% of my FPGA, can't make more). I have tested it in a higher level entity making 4 different sized and I have some strange errors reaching 16384 bits on one of them so I have some homework. I also have to make sure it can run as a symbol on the block_diagram/schematic. 

 

--- Quote End ---  

 

Give up on schematic diagrams, they are not a good idea. You will be making life difficult for the person writing the testbench for your design. Code everything in HDL. 

 

 

--- Quote Start ---  

 

Thank you for the good information, now I know it's possible. 

 

--- Quote End ---  

 

If you want to see an example of VHDL generics and functions used in crazy ways, go and read my LFSR/PRBS tutorial and its associated source code; 

 

https://www.ovro.caltech.edu/~dwh/correlator/pdf/lfsr_tutorial.pdf 

https://www.ovro.caltech.edu/~dwh/correlator/pdf/lfsr_tutorial_src.zip 

 

Its cool that you can use VHDL pre-processing of functions to create matrices and static vectors that then get efficiently turned into logic. 

 

Cheers, 

Dave
0 Kudos
Reply