Customizing the Makefiles¶
A powerful tool in creating your own designs is understanding how to generate your own Makefile to compile projects. This tutorial walks you through how to do that.
If you would like to use methods other than a Makefile to build and compile your designs (such as python or bash scripts) or if you would like to learn more about the various F4PGA commands used by the common Makefile to build and compile designs take a look at the F4PGA Documentation page.
Example¶
By including F4PGA’s provided common Makefile in your designs, running the commands necessary for building your personal projects is incredibly simple. All you have to do is run a few simple commands and set a few variables.
Create a makefile for your project by running touch Makefile
, and add the following to the contents.
1 current_dir := ${CURDIR}
2 TOP := <put the name of your top module here>
3 SOURCES := ${current_dir}/<put your HDL sources here>
4
5 # Include your constraint file path(s) below. Use either an XDC file
6 # or a PCF+SDC pair. Don't use all three file types.
7 XDC := ${current_dir}/<name of your pcf file if applicable>
8 PCF := ${current_dir}/<name of your xdc file if applicable>
9 SDC := ${current_dir}/<name of your sdc file if applicable>
10
11 include <path to f4pga-examples root directory>/common/common.mk
Lets talk briefly about each of the commands in the above makefile
Adding HDL Sources and Specifying the Top Module¶
Line 2 in the Makefile shows how to define the name for your top level module.
For example, if your top module was named module switches ( ...
then you would simply uncomment
line 3 and change the text in <>
to TOP := switches
.
Line 3 in the Makefile shows how to add HDL files to the design. The general
syntax is: SOURCES:=${current_dir}/<your HDL file path>
. You can also add multiple HDL files to a
design using the following syntax:
SOURCES := ${current_dir}/<HDL file 1> \ ${current_dir}/<HDL file 2> \ ${current_dir}/<HDL file 3> \ ... ${current_dir}/<HDL file n> \
You could also use wildcards to collect all HDL file types of a specific extension and add them to your design. For example, if you wanted to add all verilog files within the current directory to your design, you could replace line 3 in the Makefile with:
SOURCES := ${current_dir}/*.v
To include SystemVerilog HDL in your designs simply change the .v
extension in the examples
above to a .sv
.
Note
As of this writing, F4PGA only offers full support for Verilog by default. SystemVerilog can also be run through the toolchain but more complicated designs may not be fully supported.
Constraint files¶
Lines 7-9 show how you can specify what constraint files are being used for your design. The general syntax depends on whether you are using XDC files or a SDC+PCF pair:
XDC := ${current_dir}/<name of XDC file>
PCF := ${current_dir}/<name of PCF file>
SDC := ${current_dir}/<name of SDC file>
A Note on the example designs use of ifeq/else ifeq blocks¶
If you look at the Makefiles from the example designs within F4PGA (i.e. counter test, Picosoc, etc.), you will find an ifeq else ifeq block. The following snippet is from lines 9-39 of the Makefile from counter test:
5 ifeq ($(TARGET),arty_35)
6 XDC := ${current_dir}/arty.xdc
7 else ifeq ($(TARGET),arty_100)
8 XDC := ${current_dir}/arty.xdc
9 else ifeq ($(TARGET),nexys4ddr)
10 XDC := ${current_dir}/nexys4ddr.xdc
11 else ifeq ($(TARGET),zybo)
12 XDC := ${current_dir}/zybo.xdc
13 SOURCES:=${current_dir}/counter_zynq.v
14 else ifeq ($(TARGET),nexys_video)
15 XDC := ${current_dir}/nexys_video.xdc
16 else
17 XDC := ${current_dir}/basys3.xdc
18 endif
This snippet of code is an if else block used to set device specific constraints (i.e. basys3.xdc
,
nexys_video.xdc
). The code block determines what type of hardware is being used based upon a
TARGET variable which is assumed to be defined before running make. For example, you may recall
running TARGET="<board type>" make -C counter_test
before building the counter test example.
This command sets the TARGET variable to the type of hardware you are using.
The if else block is completely optional. If you are only using one type of hardware for your designs you could just specify the TARGET variable within your makefile like so:
1 current_dir := ${CURDIR}
2 TARGET := basys3
3 TOP := ${current_dir}/# put the name of your top module here
4 SOURCES := ${current_dir}/# put your HDL sources here
5 ...
By setting the TARGET
variable within the Makefile itself, you don’t even have to specify
the TARGET variable before calling make. You can just use make -C <path to directory containing
your design>