Jump to content
  • 0

Arty A7 MicroBlaze DDR3 tutorial


Viktor Nikolov

Question

I would like to share that I created a detailed step-by-step tutorial for making an HW design of MicroBlaze using DDR3 on the Arty A7 board (in Vivado 2023.1).

The resulting HW design is published in the repository together with a simple memory read speed test app (I wrote the critical benchmarking code in assembly).

In a hobby project of mine (I ported ILI9488 TFT display library to Xilinx SoC and FPGA), I needed to create a test HW design for MicroBlaze. I couldn't find a tutorial which I would like.
Therefore, I created one after considerable research and testing. I hope it helps other people in their learning curve.

Any feedback on the tutorial and resulting HW design is welcome. 🙂

Please note that in this HW design, I, on purpose, deviated from some parts of Arty A7 DDR3 documentation and from this tutorial.
The difference is that I'm using an external 100 MHz clock for the MIG input System Clock instead of the 166.67 MHz recommended in Arty A7 documentation. Using an internally generated clock for MIG System Clock is strongly not recommended by Xilinx documentation (I received this feedback on the Xilinx support forum).
I explain this topic in more detail here.

Edited by Viktor Nikolov
Link to comment
Share on other sites

8 answers to this question

Recommended Posts

  • 1
1 hour ago, stonehou said:

Which pins in the Nexys Video .xdc file can be used for CLK100MHZ, ck_a0 and ck_rst?

Hi!

I don't have Nexys Video board, but let me guide you through the documentation and Nexys Video .xdc.

100 MHz clock

We need a pin with 100 MHz input system clock. Nexys Video Reference Manual tells us that "the board includes a single 100 MHz crystal oscillator connected to pin R4".
The .xdc contains this definition at the very top (I uncommented the relevant lines):

## Clock Signal
set_property -dict { PACKAGE_PIN R4    IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L13P_T2_MRCC_34 Sch=sysclk
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]

So the "clk" is your 100 MHz input clock pin.
You can rename "clk" to "CLK100MHZ" in the .xdc. Or rename "CLK100MHZ" to "clk" in the block diagram. Do it per your taste. Just make sure that the name of the pin in .xdc and in the diagram are the same.

Reset pin

Information about a reset button is a bit hidden in the Basic I/O section of the reference manual. It is the button BTN6 connected to FPGA pin G4. It provides high signal when not pressed.
So we must look into Buttons section of the .xdc (I uncommented the relevant line):

## Buttons
#set_property -dict { PACKAGE_PIN B22 IOSTANDARD LVCMOS12 } [get_ports { btnc }]; #IO_L20N_T3_16 Sch=btnc
#set_property -dict { PACKAGE_PIN D22 IOSTANDARD LVCMOS12 } [get_ports { btnd }]; #IO_L22N_T3_16 Sch=btnd
#set_property -dict { PACKAGE_PIN C22 IOSTANDARD LVCMOS12 } [get_ports { btnl }]; #IO_L20P_T3_16 Sch=btnl
#set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS12 } [get_ports { btnr }]; #IO_L6P_T0_16 Sch=btnr
#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS12 } [get_ports { btnu }]; #IO_0_16 Sch=btnu
set_property -dict { PACKAGE_PIN G4  IOSTANDARD LVCMOS15 } [get_ports { cpu_resetn }]; #IO_L12N_T1_MRCC_35 Sch=cpu_resetn

I suggest that you rename "ck_rst" in the block diagram to "cpu_resetn". The pin name used in Nexys Video .xdc is more explanatory than the one from Arty A7 .xdc used in the tutorial.

The output GPIO pin

In my tutorial I use a single GPIO pin ck_a0 (i.e., the pin named A0 on the Arty A7) for the purpose of measuring memory read performance in the app provided in the tutorial's repository. An oscilloscope is supposed to be connected to this pin, see detailed explanation here.

I guess you are creating your design for something more interesting than just a single GPIO pin. 🙂
Nevertheless, if you want to replicate my design, you can select just any available output pin on the Nexys Video.

I would select pin 1 on the PMOD JA. This is because PMOD JA is protected with 200 Ohm resistors against "human interaction". See details here.
You enable PMOD JA pin 1 by uncommenting the following line in the .xdc (and have the same pin name in the block diagram):

## Pmod header JA
set_property -dict { PACKAGE_PIN AB22  IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L10N_T1_D15_14 Sch=ja[1]

Since you probably want to use the pin as scalar, I would change "ja[0]" to "ja_1" as follows: 

set_property -dict { PACKAGE_PIN AB22  IOSTANDARD LVCMOS33 } [get_ports { ja_1 }]; #IO_L10N_T1_D15_14 Sch=ja[1]

Viktor

Edited by Viktor Nikolov
Link to comment
Share on other sites

  • 0

Hi Viktor,

Thanks for posting this guide, it looks really clean and you've clearly put in a lot of work. So far I've followed as far as generating a bitstream, with a couple of minor deviations, in that I specified no buffer in the clocking wizard and did not use the real-time preset. It seems to have built great (other than a hiccup where I initially capitalized the name of the CLK100MHZ port wrong, simple user error) and I'll be testing the project further. The same steps and design should be applicable to any Digilent board with a 100 MHz system clock and a DDR interface, including Nexys A7, Arty S7, Nexys Video, USB104 A7. Some comments and a couple of questions follow:

Quote

2. We can't connect the external system clock to MIG directly

It is possible to connect the external clock to the MIG, but still requires manually creating the clock port and adding a constraint like you do for CLK100MHZ in order to override the 2.5 V logic standard that the MIG tries to set. That said, it looks like your approach is better than wiring the clock port directly to sys_clk_i, for reasons described below.

Quote

In fact, the A7-35 .xdc on GitHub seems to be wrong to me. It differs in the names of pins ck_io20..25, which are printed as ck_a6..11 on my specimen of A7-35. Do use A7-100 .xdc.

I've updated the 35T's template constraints on GitHub to use the correct naming convention.

Quote

Connect ck_rst to MIG.ck_rst

This should be the MIG's sys_rst port.

Do you set the clocking wizard input clock source to No Buffer? I might be missing where this happens in the guide. Not positive if the setting is ignored in this case, but warnings or errors can crop up on Zynq devices if a clocking wizard is fed by an fclk pin and the input source is left as a single-ended clock-capable pin.

image.png

Which version of the Arty A7 board files did you work with? I imagine that either 1.1 or 1.2 will be fine with the guide since you change the MIG configuration. On the off chance that someone uses v1.1, they will need to manually set the clock period to 3077 ps on the "Options for Controller 0 - DDR3 SDRAM" page of the MIG configuration.

It's also notable that having a clocking wizard fed from a "clean" 100 MHz signal should make it easier to generate a 25 MHz clock for the Ethernet reference clock when attempting to follow the Microblaze servers guide. The approach recommended by this guide, https://digilent.com/reference/programmable-logic/guides/getting-started-with-ipi, a "loopback" configuration where the PLL inside of the MIG is used to generate the reference clock, isn't quite able to do this the same way - the frequencies for the clocks output from the MIG are calculated based on the 3077 ps period, rather than on the 325 MHz frequency. This leads to weird rounding errors in how the clock frequencies are displayed in the block design, and can make it look like a 25 MHz clock generated off of the "324.99 MHz" clock is out of spec for the Ethernet PHY, at something around 24.8 MHz. It's more complex than what I've just described, since some displayed frequencies are derived from periods and some periods are derived from frequencies, and the MIG wizard doesn't seem to tell you what the underlying representation is. Post-implementation clock reports will show that the frequencies are actually okay, but the UI is misleading until you've nearly finished generating a bitstream. This is all to say that your implementation looks great since it lets you divide more clocks that show their frequencies correctly off of the 100 MHz system clock.

For reference, this is what the alternate approach looks like after the MIG clocks are wired up (image comes from the baremetal software guide, linked above):

image.png

 

Do you mind if we link to your guide from the reference site to help point others in the right direction?

Thanks!

Arthur

Link to comment
Share on other sites

  • 0

Hi Arthur,

Thank you for your kind feedback. I did a few updates based on it. It's now all published in the repository.

I added a note that this tutorial and design applies also to other Digilent boards.
I removed the note about the error in Arty-A7-35-Master.xdc. Now, the A7-35.xdc and A7-100.xdc are virtually the same.
I corrected the typo in "Connect ck_rst to MIG.ck_rst".

Quote

Do you set the clocking wizard input clock source to No Buffer? 

No, I missed that. Thanks for pointing this out. I added a step to the tutorial for setting the "No Buffer". I modified the project files accordingly. Vivado outputs were generated fine and the app works as before.

Quote

Which version of the Arty A7 board files did you work with?

Version 1.1. I followed Install Digilent's Board Files article on Digilent.com. The master.zip linked there contains files 1.1, as does the repository linked from the article.
I didn't need to manually set the clock period to 3077 ps in the MIG configuration. It was set automatically (as it should be to allow a MIG Input Clock of 100 MHz).

Quote

Do you mind if we link to your guide from the reference site to help point others in the right direction?

I will be very glad if you link my guide from your site. My motivation was exactly to point others in the right direction. 😃

Viktor

Edited by Viktor Nikolov
Link to comment
Share on other sites

  • 0

Awesome!

7 hours ago, Viktor Nikolov said:

I didn't need to manually set the clock period to 3077 ps in the MIG configuration. It was set automatically (as it should be to allow a MIG Input Clock of 100 MHz).

This means it's the newer board file version, which is good, don't need to suggest that readers revert to the old version or update the clock period setting.

Should be able to have some links up in the next few days. I confirmed today that the test project I'd put together based on the tutorial functions in hardware, with a simple software app running out of DDR.

Cheers,

Arthur

Link to comment
Share on other sites

  • 0
16 hours ago, rarow said:

Hi,

Thank you for the guide, it will be very useful for a university project of mine. I was wondering how one could attempt to solve the timing requirements?

Best regards,

Hi!

I must admit that I'm not an expert on FPGA timing. Nevertheless, let me share my observations.

I see in the timing report that the only issue is negative setup slack on the intra-clock paths of the main 200 MHz clock. See the attached screenshot.
All these paths seem to be within the MicroBlaze. My guess is that this is a result of my pushing the MicroBlaze to 200 MHz.

MicroBlaze Reference Guide UG984 says in Table A-1,  that max. frequency of MicroBlaze on Artix 7 (the chip used on the Arty A7 board) is 267 MHz. However, 267 MHz is probably a best-case scenario with MicroBlaze of minimum complexity (no caches, all options set to minimum).
Nevertheless, the 200 MHz I used is not in an "overclocking range".

When I reduce the main clock from 200 MHz to 100 MHz, all timing warnings disappear!
When I reduce the main clock to 150 MHz, warnings remain; however, negative slack values are reduced to half.
When I change the MicroBlaze Real-time Preset to a less complex Microcontroller Preset (and keep the clock on 200 MHz), warnings remain, but the negative slack values are reduced by about 30%.

If timing warnings are a concern for you (even though the design works in practice), simply run the design at 100 MHz. That is the safest option. 🙂

Viktor

Intra-Clock Paths.png

Edited by Viktor Nikolov
Link to comment
Share on other sites

  • 0

Hi Viktor,

Thanks for creating this tutorial! I have a Nexys Video that I'm trying to get started with, and I was redirected to your tutorial from here.

I'm stuck on the following step of your tutorial:

Quote

Download Arty-A7-100-Master.xdc from the Digilent GitHub.
The .xdc file for A7-100 works also for A7-35. The pin connections are the same. A7-100 and A7-35 .xdc files differ only slightly in some comments.

Add Arty-A7-100-Master.xdc as the constraints file to Vivado (window Sources, "+" button). Do not forget to check "Copy constraints file into project". We want to have a copy of the file in the project because we are going to edit it.

Open the .xdc file in the editor. Uncomment the two lines for port CLK100MHZ and the lines for ports ck_a0 and ck_rst.
So the effective content of the .xdc file will be as follows:

## Clock signal set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { CLK100MHZ }]; #IO_L12P_T1_MRCC_35 Sch=gclk[100] create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { CLK100MHZ }]; ## ChipKit Outer Analog Header - as Digital I/O set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 } [get_ports { ck_a0 }]; #IO_0_35 Sch=ck_a[0] ## Misc. ChipKit Ports set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { ck_rst }]; #IO_L16P_T2_35 Sch=ck_rst

The Nexys Video .xdc file seems quite different (to my untrained eye) to the Arty A7-100 file, and I'm assuming that I can't just use the A7-100 file for a different board. Which pins in the Nexys Video .xdc file can be used for CLK100MHZ, ck_a0 and ck_rst?

Apologies if the answer is obvious; I tried searching for similarities between the two .xdc files and didn't find any, and I'm new to FPGA boards, so I'm still learning.

Thanks in advance for your help! 

Link to comment
Share on other sites

  • 0

Hi Viktor!

I just wanted to write a quick message to thank you for your detailed help. After some trial and error, and finding an oscilloscope to borrow, I managed to get everything working. You're right, I'd like to use my board for something more complex, but this was a great introduction for a beginner. Thanks again!

Kim

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...