How to make a Microblaze+DDR3 design for Raggedstone2 in EDK.
- Start Xilinx EDK, select “Create new XPS project using BSB Wizard”.
Select AXI System and the project file location, click OK.
- In the next window, select “Create a System for a Custom Board”, architecture Spartan6, device xc6slx45t, package fgg484. Select reference clock frequency equal to installed oscillator in your board (to be able to use DDR3 the clock have to be 50 MHz or multiple of it, limitations of spartan6 PLLs). New oscillators bought for the Raggedstone are 50 Mhz.
- If your board does not have the reset (pusbuttons on Raggedstone do not have external pullup and do not fit for reset), select the reset ‘active high’ (and don’t forget to add a pulldown on selected pin). But it is better to have external button with pullup (pressing button shorts to ground). In that case select reset as ‘Active Low’.
- Click Next, in the next window press ‘Add Device’ and select DDR3_SDRAM as a peripheral.
- Click ‘OK’ and you will see the MCB_DDR3 in the ‘Included Peripherals’ list. Select Local Memory size for the processor. This memory is for the code to be run on Microblaze, so choose appropriate size. 32Kb normally is enough for peripheral control and LwIP stack. To be able to run large programs or operating systems on Microblaze you need to add external Flash memory to the design.
- Add the UART core by pressing ‘Add Device…’ one more time. After adding it, select the desired baud rate. This will be your primary console (stdin/stdout) on the processor.
- If necessary, change processor frequency, and click ‘Finish’.You will get the system configured like on the picture:
You can see the 2 AXI buses, one solely for DDR3, second is for peripherals like RS232.
- Now double-click on the MCB_DDR3 instance. Memory Interface Generator will start. Click ‘Next’ until Port Configuration page.
If you want a dual-port design, mark another port in the Port Selection.
- Click Next several times, if you don’t want to change bus options and arbitration (normally you don’t need this). On the FPGA Options for C3-DDR3 page select SDRAM Un-calibrated Input Termination, RZQ pin as K7. Click Finish.
- Now click on Ports tab in the System assembly view. Expand clock_generator_0 module.
- Right click on the CLKIN port and select ‘No connection’. After that right click one more time and select ‘Make External’ . You should see one External Ports::clock_generator_0_CLKIN_pin now.
- Expand External Ports section (on the top of the ports list). Delete CLK_N, CLK_P ports. Rename clock_generator_0_CLKIN_pininto a CLK, if you want.
- This step is done for fail-safe designs, you can skip it if you want. Xilinx memory IP-core does not support Chip Select input in DDR3, assuming that the memory is always active. But on Raggedstone2 this pin is connected to a P4 port. Theoretically you can leave this pin undefined, and it will work, but for 100% guarantee you should drive this pin low. To do this, click ‘Add external port…’ button in the top left corner of System Assembly view:
And add the port ‘DDR3_CS_N’ to the external ports. In step 15 add a pulldown constraint for this pin and port or uncomment this in the provided .ucf.
- Now open a ‘Project’ tab in Project window and double click ‘UCF File: data\system.ucf’.
- Now you should add the constraints for pins and nets. If you did step 13, uncomment “DDR3_CS_N” net. If you do not have reset, assign the reset to unused pin and turn on pullup. The .ucf file for this design is next, you can copy and paste it:
#
# pin constraints
#
NET CLK LOC = "M19" | IOSTANDARD = "LVTTL";
NET "CLK" TNM_NET = sys_clk_pin;
TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 50000 kHz;
NET RESET LOC = "Y6" | IOSTANDARD = "LVTTL" | TIG | PULLDOWN ;
# RS232 constraint for FTDI on the raggedstone board
NET RS232_Uart_1_sin LOC = "H21" | IOSTANDARD = "LVTTL";
NET RS232_Uart_1_sout LOC = "J20" | IOSTANDARD = "LVTTL";
##################################################################################
# Timing Ignore constraints for paths crossing the clock domain
##################################################################################
NET "*/mcb_raw_wrapper_inst/selfrefresh_mcb_mode" TIG;
############################################################################
## Memory Controller 3
## Memory Device: DDR3_SDRAM->MT41J64M16XX-187E
## Frequency: 333.333 MHz
## Time Period: 3000 ps
## Supported Part Numbers: MT41J64M16LA-187E
############################################################################
############################################################################
## I/O TERMINATION
############################################################################
NET "MCB_DDR3_dram_dq[*]" IN_TERM = NONE;
NET "MCB_DDR3_dram_dqs" IN_TERM = NONE;
NET "MCB_DDR3_dram_dqs_n" IN_TERM = NONE;
NET "MCB_DDR3_dram_udqs" IN_TERM = NONE;
NET "MCB_DDR3_dram_udqs_n" IN_TERM = NONE;
############################################################################
# I/O STANDARDS
############################################################################
NET "MCB_DDR3_dram_dq[*]" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_addr[*]" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_ba[*]" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_dqs" IOSTANDARD = DIFF_SSTL15_II;
NET "MCB_DDR3_dram_udqs" IOSTANDARD = DIFF_SSTL15_II;
NET "MCB_DDR3_dram_dqs_n" IOSTANDARD = DIFF_SSTL15_II;
NET "MCB_DDR3_dram_udqs_n" IOSTANDARD = DIFF_SSTL15_II;
NET "MCB_DDR3_dram_clk" IOSTANDARD = DIFF_SSTL15_II;
NET "MCB_DDR3_dram_clk_n" IOSTANDARD = DIFF_SSTL15_II;
NET "MCB_DDR3_dram_cke" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_ras_n" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_cas_n" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_we_n" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_odt" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_ddr3_rst" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_ldm" IOSTANDARD = SSTL15_II;
NET "MCB_DDR3_dram_udm" IOSTANDARD = SSTL15_II;
#NET "rzq" IOSTANDARD = SSTL15_II;
#NET "zio" IOSTANDARD = SSTL15_II;
############################################################################
# MCB 3
# Pin Location Constraints for Clock, Masks, Address, and Controls
############################################################################
NET "MCB_DDR3_dram_addr[0]" LOC = "K2" ;
NET "MCB_DDR3_dram_addr[1]" LOC = "K1" ;
NET "MCB_DDR3_dram_addr[2]" LOC = "K5" ;
NET "MCB_DDR3_dram_addr[3]" LOC = "M6" ;
NET "MCB_DDR3_dram_addr[4]" LOC = "H3" ;
NET "MCB_DDR3_dram_addr[5]" LOC = "M3" ;
NET "MCB_DDR3_dram_addr[6]" LOC = "L4" ;
NET "MCB_DDR3_dram_addr[7]" LOC = "K6" ;
NET "MCB_DDR3_dram_addr[8]" LOC = "G3" ;
NET "MCB_DDR3_dram_addr[9]" LOC = "G1" ;
NET "MCB_DDR3_dram_addr[10]" LOC = "J4" ;
NET "MCB_DDR3_dram_addr[11]" LOC = "E1" ;
NET "MCB_DDR3_dram_addr[12]" LOC = "F1" ;
NET "MCB_DDR3_dram_ba[0]" LOC = "J3" ;
NET "MCB_DDR3_dram_ba[1]" LOC = "J1" ;
NET "MCB_DDR3_dram_ba[2]" LOC = "H1" ;
NET "MCB_DDR3_dram_cas_n" LOC = "M4" ;
NET "MCB_DDR3_dram_clk" LOC = "K4" ;
NET "MCB_DDR3_dram_clk_n" LOC = "K3" ;
NET "MCB_DDR3_dram_cke" LOC = "F2" ;
NET "MCB_DDR3_dram_ldm" LOC = "N4" ;
NET "MCB_DDR3_dram_dq[0]" LOC = "R3" ;
NET "MCB_DDR3_dram_dq[1]" LOC = "R1" ;
NET "MCB_DDR3_dram_dq[2]" LOC = "P2" ;
NET "MCB_DDR3_dram_dq[3]" LOC = "P1" ;
NET "MCB_DDR3_dram_dq[4]" LOC = "L3" ;
NET "MCB_DDR3_dram_dq[5]" LOC = "L1" ;
NET "MCB_DDR3_dram_dq[6]" LOC = "M2" ;
NET "MCB_DDR3_dram_dq[7]" LOC = "M1" ;
NET "MCB_DDR3_dram_dq[8]" LOC = "T2" ;
NET "MCB_DDR3_dram_dq[9]" LOC = "T1" ;
NET "MCB_DDR3_dram_dq[10]" LOC = "U3" ;
NET "MCB_DDR3_dram_dq[11]" LOC = "U1" ;
NET "MCB_DDR3_dram_dq[12]" LOC = "W3" ;
NET "MCB_DDR3_dram_dq[13]" LOC = "W1" ;
NET "MCB_DDR3_dram_dq[14]" LOC = "Y2" ;
NET "MCB_DDR3_dram_dq[15]" LOC = "Y1" ;
NET "MCB_DDR3_dram_dqs" LOC = "N3" ;
NET "MCB_DDR3_dram_dqs_n" LOC = "N1" ;
NET "MCB_DDR3_dram_odt" LOC = "L6" ;
NET "MCB_DDR3_dram_ras_n" LOC = "M5" ;
NET "MCB_DDR3_dram_ddr3_rst" LOC = "E3" ;
NET "MCB_DDR3_dram_udm" LOC = "P3" ;
NET "MCB_DDR3_dram_udqs" LOC = "V2" ;
NET "MCB_DDR3_dram_udqs_n" LOC = "V1" ;
NET "MCB_DDR3_dram_we_n" LOC = "H2" ;
#NET "DDR3_CS_N"LOC="P4"| PULLDOWN | IOSTANDARD = SSTL15_II;## CS_N, described in step 13
##################################################################################
#RZQ is required for all MCB designs. Do not move the location #
#of this pin for ES devices.For production devices, RZQ can be moved to any #
#valid package pin within the MCB bank.For designs using Calibrated Input Termination, #
#a 2R resistor should be connected between RZQand ground, where R is the desired#
#input termination value. Otherwise, RZQ should be left as a no-connect (NC) pin.#
##################################################################################
NET "MCB_DDR3_rzq" LOC = "K7" ;
##################################################################################
#ZIO is only required for MCB designs using Calibrated Input Termination.#
#ZIO can be moved to any valid package pin (i.e. bonded IO) within the#
#MCB bank but must be left as a no-connect (NC) pin.#
##################################################################################
#NET "zio" LOC = "AA2" ;
#########################################################################
# TIG synchronizer signals #
#########################################################################
### have to comment out, otherwise fail ngdbuild INST "MCB_DDR3/mcb_ui_top_0/P?_UI_AXI.axi_mcb_synch/synch_d1*" TNM="TNM_MCB_DDR3_SYNCH";
TIMESPEC "TS_MCB_DDR3_SYNCH" = FROM FFS TO "TNM_MCB_DDR3_SYNCH" TIG;
#########################################################################
# Config for Extended Performance #
#########################################################################
CONFIG MCB_PERFORMANCE=STANDARD;
- After you done with the .ucf, press Ctrl+S to save the file and click Project->Export Hardware Design to SDK. After this the dialog will appear, choose Export&Launch SDK. Normally this process takes couple of minutes. If you did everything correct and your Luck was high enough, the process will end with starting the SDK (Eclipse) and asking for the default workspace.
Beware that SDK likes to create workspace in different places like root directory, so better check where it is going to create it.
- After the launch you will get an empty workspace with hardware platform files.
- Right click in the Project Explorer window and select ‘New..->Project’. Select Xilinx C Project.
- Select Memory Tests template for the project.
- Click Finish and SDK automatically create the Board Support Package for your project. BSP contains all low-level drivers and configs for your hardware, so it will be changed every time as hardware description changes.
- After the creation of new project, you should get the next workspace:
- Open memory_tests_0 project and memorytest.c file. Contemplate the code and say ‘Thank you!’ for Xilinx guys writing it for you.
- Now connect Raggedstone board mini-USB to the PC, and connect Xilinx Platform Cable to the JTAG port. Make sure Raggedstone is powered and green light is on the Xilinx Platform Cable. If not, check your connection and Xilinx drivers.
- I’m assuming that FTDI USB-UART was automatically recognized by your PC as generic CDC port and you have it in your system (COMx in windows, TTYusbx in linux). Run the terminal program (in windows I recommend Termite) with the settings matching the ones you set in step 6.
- Now right click memory_tests_0project and select Debug As->Debug configurations. In the debug configuration window double-click ‘Xilinx C/C++ ELF’ to add new configuration.
- If you don’t have the terminal program, you can use debug console. For this, open the SDIO Connection tab and select your serial port.
- Now click Xilinx Tools->Program FPGA.
- bootloop programs the FPGA with debug code, allowing you to debug the program in the same way as on PC. Selecting .elf file will actually program FPGA to run the code without the debugger. Select bootloop.
- After this you are ready to try to run your program. Pray nicely and click Run->Debug, or press F11. After this agree to switch perspective. If you didn’t screwed the reset, and gdb was able to connect with the board you will see the debug perspective:
If you are getting the message saying ‘Microblaze is under RESET’, it means that you set up your reset pull-up or pulldown wrong, or polarity wrong. Remember, that ACTIVE LOW reset with internal pullup is better then ACTIVE HIGH with internal pulldown – for EMC reasons. Internal pull-ups and downs are really weak in Spartans and should not be used for mechanically switched I/Os or long lines.
- Now run your code step-by-step by pressing F6 or Step over, or press F8 to run the whole code. Observe your console. If you did everything right, you will get:
--Starting Memory Test Application--
NOTE: This application runs with D-Cache disabled.As a result, cacheline requests will not be generated
Testing memory region: mcb_ddr3
Memory Controller: axi_s6_ddrx
Base Address: 0xa8000000
Size: 0x08000000 bytes
32-bit test: PASSED!
16-bit test: PASSED!
8-bit test: PASSED!
--Memory Test Application Complete--
- If you don’t see anything, check your USB-UART setup.
- If you see test:FAILED! it means that something wrong with DDR3 Memory, check your UCF file and try to do step 13, if you didn’t it yet.
- Keep hacking….