While simulation models of standard off-the-shelf memory components have taken leaps and bounds forward with respect to functionality and debug capabilities, embedded memory models have not changed significantly for many years.
Typically, embedded memory verification is supported during the functional simulation design cycle by a simulation model coded in traditional HDLs such as Verilog or VHDL. This model is automatically generated from a standard template and ends up as one of the embedded memory design view files. End users of the embedded memories are able to simulate the function and sometimes the timing characteristics of the full-embedded memory array. While these models have the advantage of being verified by the embedded memory supplier, they have a number of major drawbacks.
First of all, their memory footprint wastes system memory resources. Even if no memory locations have ever been written, the simulator has to allocate system resources for the complete memory array. Second, they lack smart verification capabilities. These models do not have capabilities that ease debug or testbench creation. Smarter verification capabilities, such as backdoor peeking and poking or even pre-loading and dumping of the memory images, are mostly nonexistent. This makes test creation a complex and time-consuming activity because nothing can be automated.
An embedded memory model should include the following characteristics:
- It must be functionally correct. The main purpose of this model is to test the interface from the design to the embedded memory. The simulation model must accurately model the physical embedded memories interface protocol.
- It must contain error, warnings and note messages. The model must inform the user of any protocol violation or error conditions. Also, debug notes significantly reduce the time the engineer spends in debugging any particular issue.
- The model must support the loading of a pre-defined image for initialization purposes. The contents of the memory array should be able to be dumped to a file anytime during simulation.
- There should be visibility into the memory array. Every address location's data should be accessible in the testbench. Read/write tests can be automated and self-checking tests created if the memory array data is accessible in the testbench.
- The model should require minimal system memory footprint. The amount of embedded memory per die is increasing. Simulating multiple instances of these arrays must be done using the smallest of system memory resources.
So what options meet the above requirements? The first option is obviously to enhance the existing HDL model to include new functions or tasks that can handle the required features. There are many issues that have to be taken into account when going down this path. Do traditional HDL's offer support for coding such capabilities? Is there technical in-house expertise to achieve this? If so, are other tasks are being neglected as engineers implement these improvements and support their deployment and usage?
A full C-based model could be used to achieve these goals. In C, dynamic system memory allocation would not be an issue, but how would these models interface to the simulator? This means that the current HDL templates, which may have taken many man-years to develop, would have to be thrown away. All function and messages would have to be recoded in a new language. This would be a huge undertaking.
Another option would be to keep the existing memory model function and messaging in the traditional HDL but incorporate an already available C-based memory core to handle the new advanced capabilities. The advantages here are that the existing HDL templates are kept and just slightly modified to include the new C-based core. Minimal time and experience is required to do this. All existing error, warning and notes messages are kept the same.
The Infineon Technologies embedded memory group based in Sophia, France, faced these issues. Their existing models were written in traditional HDL's. Users of these embedded memories requested support for these types of testbench capabilities. Infineon required a solution that met the following requirements: the model had to be supported internally; it had to have a reduced memory footprint over HDL models; it needed testbench-to-memory debug capabilities and it had to fit into their existing design flow.
Infineon's chose to incorporate an already available C-based memory core to achieve this. They converted their existing HDL embedded memory models to use the Synopsys DesignWare C-based memory core, known as memcore. This simple inclusion provides support for dynamic system memory allocation, which reduces the memory footprint and provides advanced testbench-to-memory debug capabilities.
In simplistic terms, memcore replaces both the HDL memory array declarations and the reading and writing from these arrays. The models' function is kept in the HDL and all error, warnings and notes messages are still generated from the HDL. The only real change is that the data for a read or write is stored in the C-based memcore rather than in an array in HDL code.
Easy fit, end user issues
Infineon's engineers chose this solution based on the ease in which their HDL template could be modified to include the C-based core. It fit into their existing design flow without any additional changes. In half a day, the team was able to update and validate their embedded memory compilers and resulting models. The changes needed to update existing models were minor, but the added functionalities for end users (ASIC designers) were significant. Below are some examples:
- Replacing HDL memory arrays with the Synopsys Memcore.
Example: HDL declarations for a 4M X 32 bit memory:
type mem_array is array (4095 downto 0) of std_ulogic_vector(31 downto 0);
signal mem : mem_array;
Where 12 defines the addressable range, 32 defines the data width, model_id is a unique user defined identifier for the memcore and the instance_handle is the returned unique identifier used in subsequent memcore accesses.
- Replacing HDL memory array read and writes with the Memcore functions
Example: Read from memory
data = mem[address];
data <= mem(address);
memcore_read_ext(inst_handle, address, data, A_read_cycle);
Where inst_handle is the unique identifier returned by the memcore_instance_ext command, address is the location being read from, data being the returned data value and A_read_cycle being a user defined cycle type that is captured for memory debug purposes.
Example: Write to memory
mem[address] = data;
mem(address) <= data;
memcore_write_ext(inst_handle, address, data, A_write_cycle);
Where inst_handle is the unique identifier returned by the memcore_instance_ext command, address is the location being written to, data is the data being written and A_write_cycle being a user defined cycle type that is captured for memory debug purposes.
With the above modifications made, the HDL models immediately had dynamic system memory allocation and access to all of the supported testbench-to-memory debug capabilities. The enhanced embedded memory models could now be pre-loaded, its contents could be dumped to a file anytime during simulation, and every address location could be accessed via testbench-to-memory debug commands.
Example: Testbench-to-memory debug commands
mem_poke(model_id, poke_address, data);
Existing HDL based embedded memory model simulation capabilities fall far short of today's verification requirements. The capabilities of these models can be significantly enhanced in the shortest possible time by the use of a C-based memory core such as the memcore from Synopsys. This implementation route requires minimal engineering effort but offers the maximum return on the time investment. By using these new model capabilities, total test time can be reduced as smarter verification tasks can be applied to the test creation and simulation execution.