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

How to initial onchip_memory in modelsim post-simulation?

Altera_Forum
Honored Contributor II
3,450 Views

Hi all, 

I known how to Pre-Simulating NiosII System with modelsim tool. 

Now, I am tring to do Post-Simulation for NiosII System in modelsim. I have completed the following steps: 

 

1. set EDA tools option in QuartusII and select Modelsim-Altera 

2. After full compilation for QuartusII project, modelsim ran automatically and load *.vho and all the library associated with the QuartusII project. 

3. In modelsim's workspace window library TAB, I select the top-level entity to simulate 

4. after simulation starting, I try to observe content of onchip_memory 

 

(note:my 64KB onchip_memory has been devided into 128 M4K modules, the following show you the first M4K declaration in *.vho), 

ram_block1a0 : cycloneii_ram_block 

-- pragma translate_off 

GENERIC MAP ( 

mem_init1 => X"5307BBFFA37BFB1BDFD8CD8CD8D41F8C63EC6FCCBCCBF9999965FEEFD8F73FFFE9CCBFA38C7 

7FD8EDADBFFD1EE7FFFD3997F4718EFFB1BFB1BFB1F4D4C3530E492124D991D1D1D1D3A6749BE61A 

6749BE61A1285BDFE8EE7CE5D7D1DCF9CBAFA3BF77DF3E72E5D7BE8F2963D086A8DF9C67A94F63D4 

BB630D8F7BD3871F5468D1B80458AAE6FA3000000C6FF7697ADDDABD671327A3747BB1EE7EC794B1 

E0CD8F2963C19B1E52C7FFFFEA0CEC7D0000C0600C060000003530610887E500080203F800240000 

F945002DDA0E3B5006C4E70CF05C921820E460433000F81002539009000A002808016A024B000005 

1000001520016E80200A5F08010000A03FF0C", 

mem_init0 => X"14000106B47FF1E3C0087CA60C8A4F8002814A4148B6C83000008314400125419BE514002C4 

00A0900882BB91CE008401088000203B500049305084400007329007FE01FF810806020609818001 

2980A830804080000000000004000000D062042029230000849860C2211C6300183032E48CB92C66 

C60018BFEA8C000060D09CD8A3474606C791179AF35E6B63000628A28D434D8D4CD8D536300618E8 

BD14791179EEE36B3AE971B59D75D8D536396BD6BA3AA9B198F2B272E564E5628DB1D633198D05B1 

8E0E7CCFE0CDC6ED2F5D1BB57AE8FCB928EA5972763CBFCFB1E5FE7D8E1F8FB1A0B1C1C41C70638B 

FF5466C00C7E5A71083BF31FFFDD817FDFE00", 

data_interleave_offset_in_bits => 1, 

data_interleave_width_in_bits => 1, 

init_file => "onchip_mem.hex", 

init_file_layout => "port_a", 

logical_ram_name => "FreqMeasure_NiosII:inst|onchip_mem:the_onchip_mem|altsyncram:the_altsyncram 

|altsyncram_mmb1:auto_generated|ALTSYNCRAM", 

operation_mode => "single_port", 

port_a_address_clear => "none", 

port_a_address_width => 12, 

port_a_byte_enable_clear => "none", 

port_a_byte_enable_mask_width => 1, 

port_a_byte_size => 1, 

port_a_data_in_clear => "none", 

port_a_data_out_clear => "none", 

port_a_data_out_clock => "none", 

port_a_data_width => 1, 

port_a_first_address => 0, 

port_a_first_bit_number => 0, 

port_a_last_address => 4095, 

port_a_logical_ram_depth => 16384, 

port_a_logical_ram_width => 32, 

port_a_write_enable_clear => "none", 

port_b_address_width => 12, 

port_b_data_width => 1, 

ram_block_type => "M4K", 

safe_write => "err_on_2clk") 

 

and I observe content of the first M4K module, but it's value didn't equal to the content of 'onchip_memory.hex' , it equal to  

mem_init0 => X"14000106B47FF1E3C0087CA60C8A4F8002814A4148B6C83000008314400125419BE514002C4 

00A0900882BB91CE008401088000203B500049305084400007329007FE01FF810806020609818001 

2980A830804080000000000004000000D062042029230000849860C2211C6300183032E48CB92C66 

C60018BFEA8C000060D09CD8A3474606C791179AF35E6B63000628A28D434D8D4CD8D536300618E8 

BD14791179EEE36B3AE971B59D75D8D536396BD6BA3AA9B198F2B272E564E5628DB1D633198D05B1 

8E0E7CCFE0CDC6ED2F5D1BB57AE8FCB928EA5972763CBFCFB1E5FE7D8E1F8FB1A0B1C1C41C70638B 

FF5466C00C7E5A71083BF31FFFDD817FDFE00", 

 

Anybody teach me how to initial the onchip_memory with the 'onchip_memory.hex' created by NiosII IDE? 

 

Thanks in advance...
0 Kudos
9 Replies
Altera_Forum
Honored Contributor II
2,710 Views

The ATOM simulation models don't read the HEX or MIF directly. Rather, as you've discovered, they load their contents from the mem_init<num> generics. If you update your HEX or MIF, run processing -> update memory initialization file, then generate your VHO. The mem_init<num> generics will be updated to reflect your changes. Be careful about trying to correlate the generic values to the original file. The mapping isn't documented in the Quartus II software and depends on the way your logical RAM was organized into individual RAM blocks.

0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

So, if i put the onchip_memory.hex file created by NiosII IDE in QuartusII project directory, then QuartusII software will use it directly to initial The mem_init<num> generics of ligical RAM, am I right? 

 

I have another question: 

how to ensure that onchip_memory has been initialed correctly during modelsim post-simulation? 

 

The following is my idea: 

In NiosII IDE, I set code/data... memory to onchip_memory, so I hope to observe the CPU signals to ensure that CPU is excuting my code. 

In modelsim Pre-simulation, it's easy to implement, because SOPC Builder has bring these signals into modelsim wave window for observing, as the following shows: 

# Display signals from module cpu 

add wave -noupdate -divider {cpu} 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/i_readdata 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/i_readdatavalid 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/i_waitrequest 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/i_address 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/i_read 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_dataa 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_datab 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_ipending 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_status 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_estatus 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_n 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_a 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_b 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_c 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_readra 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_readrb 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_writerc 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_result 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_clk_en 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_start 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/A_ci_multi_done 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/clk 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/reset_n 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_readdata 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_waitrequest 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_irq 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_address 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_byteenable 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_read 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_write 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_writedata 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/d_readdatavalid 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/the_cpu_test_bench/W_pcb 

add wave -noupdate -format Logic -radix ascii /test_bench/DUT/the_cpu/the_cpu_test_bench/W_vinst 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/the_cpu_test_bench/W_valid 

add wave -noupdate -format Logic -radix hexadecimal /test_bench/DUT/the_cpu/the_cpu_test_bench/W_iw 

 

But in modelsim Post-Simulation, I can't find the signals listed above. May be after fitting, their names have been changed(Is there any rule or datasheet can explain how name change before and after QuartusII Fitting operation?) or some of them have been optimized. 

 

BTW. how could SOPC Builder bring the signals listed above into modelsim wave window automatically? 

 

Could you also guide me how to decide the time resolution during modelsim Post-simulation? In modelsim handbook, it says that: "Choosing the resolution 

You should choose the coarsest resolution limit possible that does not result in undesired 

rounding of your delays. The time precision should not be unnecessarily small because it will limit the maximum simulation time limit, and it will degrade performance in some 

cases." As I know, the unit of *.sdf file created by QuartusII is 'ps', base on the words "You should choose the coarsest resolution limit possible that does not result in undesired rounding of your delays." Does it mean that I should choose 'ps' for modelsim simulator resolution limit? 

 

 

 

Sorry for so many questions... 

P.S. : the red color of word represents my questions. :) 

Wish you a happy Christmas!! 

Thanks again!
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Yes, the Quartus II software will initialize the memory with your HEX file. If you change the HEX file, remember to run Update Memory Initialization File and re-run the Assembler to generate a new programming file (or re-run the EDA Netlist Writer to generate your VHO) . The ATOM models initialize from the mem_init parameters in order to mimic this behavior - if you don't Update Memory Initialization File, then you won't get updated initial contents in your memories.  

 

Now for your questions: 

 

How to ensure that onchip_memory has been initialed correctly during modelsim post-simulation? 

 

Do you have a specific concern that the on-chip memory isn't initialized correctly? That would be a fairly significant bug in the software itself. In general, I give software the benefit of the doubt until there's no other explanation. If you're just being cautious or curious, I can understand. Even so, your time might be spent elsewhere, I think. 

 

 

Is there any rule or datasheet can explain how name change before and after QuartusII Fitting operation? 

 

Nope. Pin names are generally sacred, for obvious reasons. Register names often survive without transformation, unless packed into a macro block (RAM, DSP, I/O), merged with a duplicate, or retimed. RAM outputs are particularly troublesome because the actual names attached to the physical RAM blocks come from the inferred megafunctions and not the user source, and Quartus II has many different ways to implement a large RAM into the available RAM blocks. I would normally route the RAM output to a debug port on my design or make sure it fed a set of well-named registers with a Preserve attribute to prevent any compiler optimizations. You can also preserve combinational nets with the Keep attribute. Essentially, you tell the software that you care about a select number of names and it keeps them around for you. 

 

 

BTW. how could SOPC Builder bring the signals listed above into modelsim wave window automatically? 

 

That's a novel idea but I doubt enough users will ever clamor for this feature to make it a priority. I feel your pain. I've debugged plenty of post-fitting simulations in Modelsim and finding the signals you want can be a challenge. The astute use of Preserve and Keep are the best solutions in my toolbox.  

 

Could you also guide me how to decide the time resolution during modelsim Post-simulation?  

 

I think 1ps will be more than adequate. I believe some of the ATOM models use (or used) a 1ps delay to resolve race conditions that normally shouldn't occur if you simulate WITH delays. I imagine most delays in the SDF are more several hundred ps. Still, better to aim for a slower simulation that works than a faster simulation that doesn't. :)  

 

Happy Simulating!
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Wow...I don't know how to express my appreciation! Thanks very very very much for all you replies. 

 

I'm a newer in QuartusII & Modelsim! I have lots of question need answer. :( 

 

Today, I got another question: 

How to write testbench so that I can observe signals of sub-module during modelsim post-simulation? 

My system is NiosII system, and I integreted a custom IP into the NiosII system. 

In modelsim, I create a testbench for top-level module automatically. Then I add stimulus in the testbench. But I hope to observe my custom IP signals to check if it's correct.  

How could I do? 

My idea is that: 

Create another testbench for custom IP and check the signals. 

But is doing this way, another two problems come up: 

1. Due to modelsim post-simulation, so the custom IP testbench is based on post-fitting netlist file, the signals become hard to observe and check. 

2. In modelsim, as I know, if I want to apply '*.sdo' during simulation, I have to select the design entity(means top-level entity, right?) the corresponds to the standard delay format output file. 

which means that if I want to apply '*.sdo', I could only simulate top-level entity, am I right?? 

If yes, how could I integreted testbench files while applying '*.sdo' in modelsim post-simulation.  

If no, could you kindly figure out where I understand wrong. 

 

 

 

Happy Christmas and Thanks again.
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

I'm still a bit perplexed that you want to debug the post-fitting netlists in Modelsim. It's like debugging a C++ after its been compiled to heavily optimized machine code. I'm all for simulating a post-fitting netlists, but I generally dread tracing into the netlist to isolate a testbench failure. You should verify your RTL in Modelsim, where you can work out any functional kinks in your design. The post-fitting simulation should be a sanity check. If it fails, any number of issues could be at fault. For example, you may need to add/modify timing constraints, or you may need to review the Quartus II warning messages for any design issues. Look especially close at any critical warning messages. I'd explore all these avenues before I ever start probing internal signals in the post-fitting simulation. Sometimes it's almost easier to route those signals to top-level debug pins rather than make sense of the compiler-generated names.  

 

Regarding your custom IP: I suggest you verify it separately, then integrate it into your full system. If something doesn't work, then follow the steps out lined about - check your timing constraints, look for suspicious warnings.
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Great answer... You correct my direction:) 

 

BTW, I have found the methods to allows access to any signal from any other hierarchical block without having to route it via the interface in modelsim. 

The answer locates in Chapter 9 signal spy in Modelsim User's Manual. 

The following is the introduction of this chapter, FYI. 

 

 

The Verilog language allows access to any signal from any other hierarchical block without 

having to route it via the interface. This means you can use hierarchical notation to either 

assign or determine the value of a signal in the design hierarchy from a testbench. This 

capability fails when a Verilog testbench attempts to reference a signal in a VHDL block 

or reference a signal in a Verilog block through a VHDL level of hierarchy. 

This limitation exists because VHDL does not allow hierarchical notation. In order to 

reference internal hierarchical signals, you have to resort to defining signals in a global 

package and then utilize those signals in the hierarchical blocks in question. But, this 

requires that you keep making changes depending on the signals that you want to reference. 

The Signal Spy procedures and system tasks overcome the aforementioned limitations. 

They allow you to monitor (spy), drive, force, or release hierarchical objects in a VHDL or 

mixed design.
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Well, routing debug signals to your top-level interface is a way to debug internal points in your post-fit netlist without hunting for and grouping together the individual nodes that comprise your "point of interest", which can be damn near impossible without inside knowledge about the way the compiler optimizes a design. An arbitrary hierarchical reference into your original RTL will be most likely be invalid after compilation. Still, you've hit upon a good technique for debugging your RTL more deeply within your Verilog testbench itself. In VHDL, you're simply stuck with adding internal nodes to the waveform viewer or manually routing them to the design boundary, even when debugging just the RTL.  

 

It sounds like you're making good progress!
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

With Modelsim SIGNAL SPY LIBRARY, you can also access to any signal from any other hierarchical block without having to route it via the interface in a VHDL or 

mixed design. 

 

Just to comfirm whether you have gotten my information.
0 Kudos
Altera_Forum
Honored Contributor II
2,710 Views

Ahh, I'd never used Signal Spy before. Looks pretty snazzy from the documentation. Let me know how useful you find it. I tend to avoid tool-specific extensions to the language unless they are undeniably useful. Sometimes I want to run my testbench + RTL in another simulator for a second opinion. :) But hey, use whatever makes you most productive.

0 Kudos
Reply