Zynq Part 2: The Adventure Starts
I've been excited to play with the new Zedboard I mentioned last week. It's a very capable board with a Xilinx Zynq 7000 device at the center of it. I said device, because the Zynq chip isn't just a CPU nor is it just an FPGA. Xilinx calls it a SoC (System on Chip), but I think that's somewhat misleading, too. Not that it doesn't fulfill that function, but it is really something more. I've also heard Xilinx call the device an "Extensible Processing Platform (EPP)" and that's probably a more accurate characterization.
The Zynq 7000 has two ARM CPUs inside. If you've used the ARM ecosystem, you won't find many surprises there. The standard ARM-style devices and external interfaces are all available. Xilinx calls this the Processing System or PS. There are more devices than there are external connections to the PS (multiplexed I/O or MIO), so you have to configure the system to include the devices you want.
What if you want more? Well, there is also an FPGA onboard called the PL (programmable logic). This is the FPGA portion. It isn't the most glamorous use of the FPGA, but you can use it to simply route PS devices to additional pins. Doing this is known as extended MIO or EMIO.
Of course, you can do other things with the FPGA and interface them to the processor. Need high resolution PWM? No problem. A fast video algorithm? Move it to the FPGA. The possibilities are mind boggling.
Many years ago I created a product that was a Microchip PIC board interfaced with a small programmable logic core. I'll have to be hones — it wasn't a very popular item. What I did notice is that people who "got it" loved it. But it was really hard to find people who did get it (especially in those days) and even harder to make people understand the value and how to manage the tools to make it all work.
I think Xilinx gets this, as the Zynq has some pretty interesting support tools that are aimed at making the process manageable by people who might be most comfortable with software. The tools are Vivado and the SDK (Software Development Kit). Of course, these are also the tools that were very painful to install under Linux. The JTAG drivers (using the Adept JTAG from Digilent) were apparently slightly different from the ones on the Digilent web site. However, the Xilinx plug in library was missing from the distribution. This caused the installer to fail, although it managed to install everything else.
Installing the "stock" Adept drivers didn't help so I wound up having to edit the driver install script to make it stop trying to install the plugin. This allowed the main drivers to install correctly. Then the plugin install from the Digilent website ran and left me with a working system. Almost. I'll tell you more about the install troubles after you hear more about the workflow.
If you want to write software for the Zynq, the first job is to design your CPU. This sounds daunting, but the tools make it pretty easy. You fire up Vivado (which looks familiar if you've used Xilinx's ISE tools before). You won't write any code in Vivado. What you will do is start a "block diagram" with a block on it representing the Zynq's dual ARM CPUs. At the top level, that's just a box:
If you edit that box, you'll see you have a lot of I/O devices that you can configure. You can add or delete items and you can route selected devices to different I/O pins. There's quite a bit of things as you can see (a big monitor helps):
Before you break out the manuals, you might notice there is a presets button near the top of the screen. It has default settings for different boards including the Zedboard I'm working with. In fact, when you start the project in Vivado, you can select a board instead of a chip and you'll get the default with no effort on your part. Realistically, that means that unless you want to remove something, you probably don't have much work to do in the block diagram for the CPU.
The real fun is when you want to add new devices to the PL. These show up as different boxes in the block diagram. At first, you will probably want to focus on loading predefined IP modules (intellectual property — think software libraries for hardware). There are plenty of them and they are already set to talk to the PS. You might add timers, general-purpose I/O, DMA, DSP blocks, a PCI bus interface, or some video processing blocks. If you are rolling your own FPGA code, there are blocks for the standard ARM AXI interface and other predefined IP that can help you and your FPGA designs can show up as blocks, as well.
Once you have the blocks in the block diagram, you connect them with the mouse. The tool helps you see which pins might connect to which other pins (you can't hook outputs to other outputs, for example). You wind up with something like this:
This diagram has an AXI timer and an AXI I/O port. There are also some external connections (some of which, like the DDR RAM interface, were put in automatically). Each block has customizable parameters. For example, you can customize the timer's bit width and number of timers:
When you are done, you will have to assign external connections for things you've added and you generate an "HDL wrapper." HDL is your language of choice to describe an FPGA design (Verilog or VHDL). This wrapper is basically a top-level description of the system.
You can export the hardware design to the SDK. The SDK is the usual Eclipse-based editor. However, when you import a hardware design, you can automatically build a board support package for the hardware design. This is a great time saver since you can change the CPU configuration on a whim. You can also target a standalone system or an operating system-based system (usually Linux). Since the board support is automatic, once you load the SDK, you are ready to just start writing pretty ordinary C or C++ code.
I've talked many times about how tools abstract us from details and while that's mostly good, it is sometimes a hindrance. There is a lot of abstraction going on here. From an ease-of-use standpoint, it is very impressive. It also means there is a lot more to go wrong and it is hard to figure that out.
My first attempts to export an example design into the SDK seemed to work. However, I couldn't get the compile of a very simple "hello world" program to work. It turns out, the JTAG drivers were not the only thing that the installer missed. There was a device tree compiler that didn't install and there was no real indication of that problem other than compiles failed. The answer (after some serious time with Google) was to load the dtc compiler from a git repo and install it:
git clone git://www.jdl.com/software/dtc.git dtc cd dtc make
After compiling, I had to go to the SDK and use the Window | Preference menu. Under Xilinx SDK, there is a Repositories item. Adding the dtc directory to the Global Repositories allowed me to successfully build.
The SDK provides a "data sheet" for the board support package it builds, including documentation and examples (which, sadly, fail to load on my installation; you can find the information — I think — here). Because of the level of abstraction, I haven't figured out how much help it gives you when you are rolling your own FPGA elements, but I intend to find out in the coming weeks.
I can't overemphasize how much work the tools are doing on our behalf. They build all the configurations for the processor and the PL, arrange to load them, and provide callable subroutines to set everything up at runtime. If it all works, it is a great time saver.
Don't get me wrong — I've been very impressed with the whole system. I just wish it wasn't so hard to get it up and running on a Linux system. But now it is running and I'm looking forward to building some real apps which I will share in future blogs.