In this tutorial we'll be programming the Terasic DE0-Nano FPGA development board using the functional hardware description language CλaSH. The end result of this tutorial is demonstrated in the video below:
This tutorial is not a general introduction to CλaSH, nor to programming FPGAs. It is meant to demonstrate how to use ofTopEntity annotations (added in version 0.5.5 of CλaSH) to configure your CλaSH designs for an FPGA, without writing a single line of VHDL or (System)Verilog. Even then, this tutorial is already almost too long for single blog post, but here goes:
This tutorial used to be specified in terms of .topentity files, a method which is now superseded by TopEntity annotions. You can still see the old version on github
We start with some general information about the DE0-Nano board:
The circuit that we are making will repeatedly do one of two things:
We switch between these two modes when the KEY1 button on the board is pressed and subsequently released. We reset the circuit by pressing the KEY0 button.
The Blinker.hs file given below implements the behaviour of circuit (sansreset behaviour) we just described. As the clock is running at 50 MHz, we shouldn’t update the state of the LEDs every clock cycle, as they will just seem to to all be turned on all the time to the human eye. We hence use a counter that counts up to a certain amount of clock cycles, and only update the state of the LEDs when the desired number of cycles is reached and the count is reset.
Now that we’ve created our CλaSH design, it’s time to move on to the important part of this tutorial, elaboration of the TopEntity annotation. The TopEntity is a Haskell data type that guides the CλaSH compiler in generating port names and setting up clocks. These annotations are applied using the ANN pragma:
{-# ANN foo (TopEntity {t_name = .., .., ..}) #-}
In our example, we extend the minimalist defTop annotation with:
We create a single clock source by instantiating the default template for the Altera PPL component altpll for the Cyclone IV. The first argument of this function is the name, the second an expression corresponding to the clock pin to connect, and the third the expression corresponding to the reset pin to connect. So to elaborate the arguments in order:
Now it’s time to generate some VHDL, yay! Make sure that the Blinker.hs file is in your current working directory, and then run the CλaSH compiler to generate VHDL:
clash --vhdl Blinker.hs
This will create a ./vhdl/Blinker/ directory, of which, for this tutorial, the most interesting file is within that directory is:
It’s almost time to start programming our FPGA. But first we need to setup how the component ports are connected to the right pins on the FPGA. For this we will use the DE0_Nano_SystemBuilder which you can find on the DE0-Nano CD-ROM. This will create both a pin/port map file, and a Quartus II project file. Note that I work on OS X, so both DE0_Nano_SystemBuilder and Quartus II are running inside a VirtualBox VM running Windows 8.
In DE0_Nano_SystemBuilder, call the project blinker, and ensure that onlyCLOCK, Button x 2, and LED x 8 are selected. Then press the Generatebutton, this will open a save dialog window: select a location where you want to create the project and hit the save button. You can now closeDE0_Nano_SystemBuilder.
In the directory to which you saved the project you will find the files:
You can delete blinker.v as we will be using our blinker.vhdl. The port/pin mappings that are generated by DE0_Nano_SystemBuilder do not completely correspond to our port names. We will hence need to update the mapping fileblinker.qsf:
The final blinker.qsf file will look like:
Also, since we will be using the PLL for clocks, you can replace the entire contents of blinker.sdc by:
derive_pll_clocks
We now open the blinker.qpf file in Quartus II. For this tutorial, I will be using version 14.1 of the Quartus II software. The first thing we will do is add the VHDL files generated by CλaSH to our design. In the menu bar, go to,Project -> Add/Remove Files in Project..., press the ... button next toFile name, in the load dialog, select all the files generated by clash, and pressOpen. Then press OK to close the Settings dialog.
Next we will create a PLL component. On the right of the Quartus II main window you will see the IP Catalog. Go to Installed IP > Library > Basic Functions > Clocks; PLLs and Resets > PLL, and double click on ALTPLL.
This opens a dialog called Save IP Variation, at the end of the line enteraltpll50 and press OK.
This opens the MegaWizard dialog for the PLL. Change What is the frequency of the inclk0 input? to 50.000
Then press Finish twice. This closes the MegaWizard dialog, and opens a new dialog asking if you want to add this IP block to your project. We want this, so select ‘Yes’.
Finally, we’re finished with configuration, and we can start creating the configuration file for the FPGA. In the menu bar, click: 'Processing -> Start Compilation’. In my extremely slow VM this compilation/synthesis process will take a while, if but might be much faster on your machine.
After synthesis has finished, it is time to program our FPGA board. Connect the FPGA board to a USB port, and start the programmer from the menu bar: Tools -> Programmer. Press the Start button on the left to program your FPGA and wait until the progress bar says 100% (Successful).
Your FPGA should now be fully configured with the CλaSH generated design for you to play with. So yeah, go press those buttons!
This ends the tutorial on the use of TopEntity annotations to program your FPGA devices with CλaSH designs. I hope you got the gist of it. If/When I get my hands on a Xilinx FPGA board, I hope to make an alternate version of this tutorial, but then use Xilinx’ ISE/Vivado tool-flow instead.