Tutorial #2 Adding Memory Using Quartus II 9.0 SOPC Builder and NIOS II IDE 9.0 For the DE2 Development Board Adam F., Paul S. and Larry S. 6/11/2009 1 The goal of this tutorial is to show how to implement the external flash memory, SRAM, and SDRAM . To test this, the developer will use mega-functions, new component editor, and add components to the NIOS II. Also be implementing the 16x2 LCD on the front of the DE2. Notes: Do not declare signals in your top-level entity port list unless they are directly driving or modifying data. Make sure the pin assignments brought in correspond to correct values. If you use pin assignments from another .qsf file, the project may not assign pins appropriately. Be sure to use the .csv file included. If you get a warning claiming there is no capacitance on certain pins, it is do to the fact they are not assigned. Beware the warning “Ignored locations or region assignments to the following nodes.” Check the pin planner after compilation to make sure signals assigned in the top level match those declared in the port list. Add the .csv file to the project you are working on. Be sure to add the SRAM file to the project you are working on. Without it, the logic for the SRAM may be synthesized away. Keep the 16x2 character LCD. LCD_ON <= ‘1’, LCD_BLON <= ‘1’. Be sure to add all files from SOPC builder to you design. SOPC will place all files for the SOPC design in your present working directory. Compilation will be faster and logic will synthesize to intended results. 2 Software Open NIOS II IDE. Create a new hello world NIOS C/C++ application. Use C files provided to test your results. 1. 2. 3. 4. 5. Open the project from tutorial 1 in Quartus II. Remove the JTAG UART. Click on the SOPC builder tool bar icon (or Tools -> SOPC Builder). Change the switch inputs to 17 bits input, SW(0) will be used for the global reset. To add the 16x2 LCD character display expand peripherals-display and double click on char lcd in the components and click finish. FIGURE 1: Add LCD 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. Rename the component to char_lcd Now it’s time to add the flash To add the flash go to Bridges & Adapters -> Memory Mapped -> Avalon-MM Tri-State Bridge Select not registered Click next Click finish Rename the tristate to flash_trist Now it’s time to add the flash memory itself Go to memory and memory controllers. Expand flash Add flash memory (CFI) 3 16. 17. 18. 19. 20. 21. 22. FIGURE 2: Add Flash Memory Change the address width to 22 (222Bytes = 4MB flash) Click next Change setup time to 40ns Wait to 160ns Hold to 40ns Click finish Hover over the tristate and cfi flash connection and click the open bubble to connect FIGURE 3: Connect Flash Memory and Tri-State Bridge 23. Hold shift to select every component in SOPC. Right click and select auto assign base addresses. (This ensures there no conflicts in address space. i.e. if flash memory overlapped SRAM then the processor would write to the same memory using separate protocols. This would be a big goddamn problem) 24. Now it’s time to add the SRAM. Unfortunately the SRAM component is not available in SOPC builder. You will create your own using the template provided by us (SRAM_512.vhd). 4 25. What you want to do is copy the SRAM SOPC folder into your hardware directory. This keeps the tcl files separate from the design files and also allows SOPC to selectively auto generate components based on the language being used. SOPC components should not be added into your design system unless they are generated by SOPC builder for inclusion in your project. Trust me this will cause problems if you don’t adhere to it. 26. In the system contents tab double click Create New Component 27. Component editor will pop up. Go to the hdl tab and click the add button. Open the SRAMSOPC file in your hardware directory and click on SRAM_512.vhd it will take a second don’t worry. You’ll notice from the very beginning a lot of warnings will occur because you have not told the SOPC system how to interface properly with your new component and it makes assumptions about how to interface and they are wrong. NOTE: even though the screenshots say the component is a tristate slave, it is actually an Avalon MM slave, see SRAM screenshots 0 through 2. 28. Go to the interfaces tab and then (this is the tricky and necessary part) and click add interface. 29. You are not going to see anything right away until you scroll down. Under type select clock input and name it SRAM_clk. Also you want an Avalon memory mapped slave as one of your interfaces. Name this SRAM_interface. 30. The timing for SRAM_interface is 20 cycles setup, read-wait, write wait and hold. (GET REFERENCE) 31. Click the deprecated parameters checkbox under the deprecated list select memory device. (it does not work if you don’t) 32. For the SRAM_interface the associated clock is SRAM_clk. 5 Figure 4: SRAM Component Settings 33. Click the add interface button again. This time you want an interface from the memory device to your output. Conduit-expand. The type will be a conduit, name it SRAM_output. 6 Figure 5: More SRAM Component Settings 34. Now you’re ready to setup the signals. All of the signals with the pre-fix ‘I’ (with the exception of the clk) are part of the SRAM interface. Associate them with this interface with the drop down box. 35. All of the input signals into the vhdl file are associated with your conduit interface named SRAM_output. 7 36. Now you need to change the signal types of each of the signals listed below. iCLK SRAM_CLK clk 1 Input iADDR SRAM_Interface address 18 Input iDATA SRAM_Interface writedata 16 Input iWR_N SRAM_Interface write_n 1 Input iOE_N SRAM_Interface read_n 1 Input iCS_N SRAM_Interface chipselect_n 1 Input iBE_N SRAM_Interface byteenable_n 2 Input oDATA SRAM_Interface readdata 16 Output export 18 Output SRAM_OUTPUT export 16 Bidir SRAM_UB_N SRAM_OUTPUT export 1 Output SRAM_LB_N SRAM_OUTPUT export 1 Output SRAM_WE_N SRAM_OUTPUT export 1 Output SRAM_CE_N SRAM_OUTPUT export 1 Output SRAM_OE_N SRAM_OUTPUT export 1 Output SRAM_ADDR SRAM_OUTPUT SRAM_DQ Table 1: SRAM Signal Types 37. Note: you are building an interface just like you would in microporcessors for your nios processor. But at the same time you are building a code interface for yourself. 8 Figure 6: SRAM Signals 38. Click on the component wizard tab, set the group as memory and memory controllers/SRAM. 39. If there are no errors or warnings click finish. If there are errors then go back to the signals and interfaces tab where that is where the error is most likely located. 40. Now it’s time to figure out if the SRAM you build works. Expand Memory & controllers tab and expand SRAM and there you shall see my SRAM. 9 41. Double click to add and click finish. 42. Rename component just added to SRAM. Select all components and right click. Click on autogenerate base addresses. Just like you should do after adding every component from here on out this tutorial will assume that you do it. 43. Now it’s time to add the SDRAM. We are basing this off of a Cornell tutorial (http://instruct1.cit.cornell.edu/courses/ece576/DE2/tut_DE2_SDRAM _verilog.pdf) however we are going to update some stuff for Quartus 9.0. 44. Expand memory and memory controllers. Expand SDRAM, double click on SDRAM controller. In presets select custom. Make the following changes: data width: 16, chip select: 1, banks: 4 row: 12, columns: 8, unselect include a functional memory model in the test bench. Figure 6: SDRAM Controller 45. Click finish. Rename SDRAM _0 to SDRAM , auto assign base addresses. Your final SOPC design should look like Figure 7. 10 46. 47. 48. 49. 50. 51. Figure 7: Final SOPC Design There should be no new warnings. If this is so, click Generate and when done click close SOPC builder. Now open up top level module, it is time to add all the signals for the external memories & char_lcd. The problem with SDRAM is that it requires a 3ns leading edge on the clock in order to properly send/receive data. The only way to do this is to create a Phase Lock Loop (PLL). We will use a mega function. In the menu select tools, click mega wizard plug in manager, select create a new mega function variation. Click next. Expand I/O. Near the bottom you will see alt-pll. Select it but do not double click. For the output file make sure that you place it in your de2 hardware directory otherwise it will have to link from an external directory and your files will not be together. Name the file SDRAM _pll.vhd Click next after everything looks like Figure 8. 11 Figure 8: PLL MegaFunction 52. Keep in mind you only want to give the clock a 3ns lead to the SDRAM . So in the first tab change the freq. of inclk_0 to 50MHz. change the device speed grade to any. Everything should look like Figure 9. 12 Figure 9: ALTPLL 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. Click next. Get rid of optional inputs. Do not lock the output. Click next Click next. In the clock phase shift field enter -3, select nanoseconds. The output clock freq. change it to 50MHz. duty cycle should be 50%. Click next, next, next, next, finish. Congratulations you have successfully created a pll for your SDRAM . Add it as a component in your top level module. A good style to take on in SOPC development is to have everything auto generated as uppercase and your code lowercase… this can show the difference between your code and the auto-generated code. If the PLL VHDL file is not added to your system, add it now. Note: there are four built in pll’s for the de2, each with three outputs. Instantiate the SDRAM pll before your nios system in the nios_proc.vhd file. Give it a unique name that identifies it as a pll for your SDRAM . 13 63. As a note: you will need to modify the SDRAM pll later to accommodate a faster clock input to the nios system. Eventually it will have to be 100MHz in order to interface to the Ethernet adapter and the usb. 64. In clk_0 – clk50. C0 – SDRAM _clk. Make sure you add all the auto generated vhdl files to the project. 65. Open up nios_SOPC and modify it to accommodate the new nios_SOPC file you just generated. 66. If you have done things correctly there should be 30 lines of signals required by the nios_SOPC component. Note this is where things get a little tricky. 67. Your ultimate goal here is to create signal names that are exactly the same as the signals names in the .csv output file. 68. Open up the de2_net project file. In the main file they have all the names you need to remain consistent with the pins.csv file. Copy all these names, it will save time. Their stuff is in verilog. This presents a problem to you in that you are going to have to change the verilog syntax to vhdl. Give qualifiers to inputs. 69. This is all provided for you in vhdl if you do not want to do this step. 70. Keep in mind all the nios SOPC signals are pretty much identical to the auto generate .csv signal names. The main difference is that they have suffix's from or to appended on them. At this point it is necessary to connect the signals from your top level module to the nios sop instance. Be careful this takes a long time. Make sure to document as you are going through it. Remain consistent! 71. In the signals we have provided there is a rst_h signal this will be connected to switch 0. 72. You’re going to have to implement the logic for the bank enables yourself. It’s really just concatenation though. Create two signals BA(1 downto 0), which is the upper and lower bank enable. DQM( 1 downto 0) which is the upper and lower bank mask for the SDRAM . Even though this provided for you it is important to do it on your own. Do not take shortcuts! It will be much more difficult to understand what is going on later! 73. Suffice it to say there is a lot of this in SOPC design. 74. Once you have all of your inputs outputs and bidirectional signals names the same as the inputs outputs and bis as the .csv then you are ready to build. 75. Click synthesize. 76. Note: excessive warnings are normal, but you should give them a quick look. 77. If there are warnings in your file be concerned. Otherwise SNAFU. 78. Note every time you change a component name you are going to have to update it for the auto generate portion. 79. DRAM_CKE should be enabled, as well as the LCD back light and enable signals. 80. In the error list search for (“nios_proc.vhd”) ctrl+f. Correct anything which may be serious. 81. When all is well, program the board. Look for the “Good” LED. If it’s on, life is well. 14 Time to write some code 1) Open NIOS II IDE and switch the workspace to nios_core_2 -> DE2 -> software 2) Create a new project, just like before. File -> New NIOS II C/C++ Application. 3) Base it on “Hello World” as in Figure 10. 4) 5) 6) 7) 8) Figure 10: New NIOSII C/C++ Application Import the new “.ptf” generated from Quartus II and SOPC for this design. Click finish. Use the code provided for tutorial 2. Right Click Hello_World_0 in the NIOS II projects tab Select System Library Properties 15 9) 10) 11) 12) 13) 14) Figure 11: System Library Properties Selection Set STDOUT, STDIN, STDERR to DE2_16B2_LCD In the linker script pane: Select program memory text to FLASH Select Read-Only Data memory as SRAM Select READ/WRITE Data Memory to SDRAM Select HEAP Memory to SDRAM Select Stack Memory as RAM On Chip 16 Figure 12: System Library Properties Dialog 15) It is now time to program the FLASH 16) In the memory select tools and FLASH Programmer 17) 18) 19) 20) 21) Figure 13: Flash Programmer Selection In the FLASH programmer: Double Click the top most tree list view. A new tree list view will appear. Select this new tree list view and then click the target connection tab. For the JTAG cable: select USB Blaster. For the JTAG Device: Select EP2C35 Click Program apply then click program FLASH. A prompt will appear indicating that nothing is to be done while it is programming the FLASH. 22) If everything is running correctly (for the flash) then you will get the following message: Programmed 16KB in 0.3s (53.3KB/s) Device contents checksummed OK Leaving target processor paused 17 Figure 14: Flash Programmer Figure 15: Program Flash 18 23) NIOS II IDE does not know which cable to send the program data to send the data out on. You will need to do this by selecting RUN in the menu toolbar and select “run…”. Figure 16: Run Selection 24) A new window will appear, in this window select the target connection tab. Under JTAG cable, select USB blaster. Under JTAG Device select EP2C35. Click Apply then click Run. Figure 17: RUN 25) At this point your board should run code. If there are any errors clear them now. 19 Conclusion What we have shown you are the very basics of NIOS II programming. It has a very steep learning curve; however the pay-off is great. With this knowledge the developer should be able to create new components from the device list. The developer should also be able to create an appropriate memorymapped device for the Terasic LCD module included on this site. Realize, if there is a problem with any of the developer’s approach or code, the project will not work and there is very little help. It is recommended any NIOS developer keep very meticulous notes throughout the development process in order to track progress, functionality and results. At this time, NIOS development is very new and has not been thoroughly analyzed; therefore, the developer must extrapolate what to do from knowledge of Microprocessors, Operating Systems, as well as ASIC design. These courses reinforce knowledge and technique involved when creating a functional project. It is now your job to analyze the files we have provided and determine why the approaches were taken and why the approaches work. Since NIOS is constantly changing, a new version may prohibit functionality of later devices and boards. The developer’s current knowledge will afford the ability to extrapolate problems, analyze difficulties and create a product the developer is pleased with. Keep working, take notes and rationalize your results. With those three criteria the developer will soon become an excellent soft-core developer. 20