Carefully managed revision control is an important aspect of electronic systems development. Revision control enables the developer to intelligently merge new contributions, analyze project history, and step backwards in time piece-by-piece when working to identify the root cause / introduction of a design defect (e.g., software / Verilog bug).
Although it may not be readily evident, FPGA development with Lattice Diamond is well suited for revision control due to the fact that many of the Diamond project source files (e.g., *.ldf, *.rvl, *.sty) are XML encoded text files, and the majority of the XML element leaf nodes are written on their own line (CR follows an end tag). This XML encoded text format is friendly for performing critical "diff" operations, where the revision control tool displays each difference, line-by-line, between two versions of the same file.
There are many good choices for revision control sysems, however due to our extensive experience with Linux and Web development, we have grown accustomed to Git.
To show how we use Git with Diamond, we'll work with the Lattice ECP5 Versa SERDES Eye Demo project.
We use git for windows in a Windows 10 PowerShell, which provides a nice command line environment similar to what a Linux user might expect. We installed Git with the "Use Git from the Windows Command Prompt" and "Use Windows default console window" options. We accepted the other installation defaults regarding SSL and line endings.
Note that this article assumes that the reader is already familiar with Lattice Diamond and the Versa Eye demo project. For detailed information on either, please refer to Lattice's Diamond and Demo User Guide documentation.
To start our example, we copy the ECP5 demo SERDES project to C:\Projects\ECP5_Serdes:
PS C:\Projects\ECP5_Serdes> dir Directory: C:\Projects\ECP5_Serdes Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 10/18/2017 12:40 PM impl1 d----- 10/18/2017 12:40 PM source d----- 10/18/2017 12:40 PM test2 -a---- 10/18/2017 12:02 PM 18 eye.ccl -a---- 10/18/2017 12:02 PM 1649 eye.ldf -a---- 10/18/2017 12:02 PM 908 eye.lpf -a---- 10/18/2017 12:02 PM 551 Serdes_debug.rvl -a---- 10/18/2017 12:02 PM 125 Serdes_debug.rvs -a---- 10/18/2017 12:02 PM 763 untitled.rva
Next we want to both check the version of Git to make sure we're using what we installed and initialize our Git repository (repo).
PS C:\Projects\ECP5_Serdes> git version git version 2.14.2.windows.3 PS C:\Projects\ECP5_Serdes> git init Initialized empty Git repository in C:/Projects/ECP5_Serdes/.git/
When using revision control, one of the core concepts is to only store source files. These are the files that are required to regenerate the desired outputs (e.g., bit file) and all intermediate files in between. If you have been using Diamond, you probably realize that it creates many, many intermediate files, and we do not want to store these files in our repository.
The primary method for instructing Git to only include our source files is to supply a ".gitignore" text file that lists the file specifiers to ignore (one on each line). Note that many of the file types used by the Diamond tool suite are defined in an appendix of the Diamond User Guide. These file type definitions are driven by the file suffix (e.g., '.edf' is an EDIF file). Also included in the appendix is information on whether a particular file is required for generating a specific bitstream.
Provided below is the '.gitignore' file we copy to the top level of our Lattice project (same level as the .git directory that was created during "git init"). We are continuing to tweak this file, so please use it as starting point / template. If you err on the side of leaving out a particular suffix, then you may experience repo bloat with unecessary (binary) files added to your repository. However, if you incorrectly add a specifier for a required source file type, then you may experience errors when going back in history & rebuilding your project.
impl1 syn_results archiv .recovery *_tcr.dir .*.ini *.asd *.asdb *.awb *.awc *.bak *.ccl *.cfg *.cmd *.cst *.fdc *.htm *.html *.log *.ngd *.ngo *.tcl *.svf *.trc *.vhm *.xml *.zip *~
Note that these file specifiers become a general rule. The user still has the option to include specific files that match one of these specifiers by using "git add -f <filename>". This may be useful when customizing a file that drives a third-party tool (e.g, a tcl file that is used with Synplify Pro). "git diff" is then useful to see how the generated file changes between builds.
In order to test that we have properly captured all of the necessary source files, we will commit our project to our local Git repo, clone it to another directory, build both, and compare the two generated ROM files.
PS C:\Projects\ECP5_Serdes> git add . warning: LF will be replaced by CRLF in eye.ldf. The file will have its original line endings in your working directory. ... PS C:\Projects\ECP5_Serdes> git commit -m 'initial commit' [master (root-commit) 87faf1f] initial commit 18 files changed, 4564 insertions(+) create mode 100644 .gitignore create mode 100644 Serdes_debug.rvl create mode 100644 Serdes_debug.rvs create mode 100644 eye.ldf create mode 100644 eye.lpf create mode 100644 source/counter_check_20b.v create mode 100644 source/prbs_7_20bit.v create mode 100644 source/top.v create mode 100644 test2/test2/refclk/refclk.fdc create mode 100644 test2/test2/refclk/refclk.v create mode 100644 test2/test2/test1/test1.fdc create mode 100644 test2/test2/test1/test1.v create mode 100644 test2/test2/test1/test1_softlogic.v create mode 100644 test2/test2/test2.sbx create mode 100644 test2/test2/test2.v create mode 100644 test2/test2/test2_tmpl.v create mode 100644 test2/test2/test2_tmpl.vhd create mode 100644 untitled.rva
As you can see above, no files were stored that matched the specifiers in our .gitignore file.
Next we'll clone our project to another directoy:
PS C:\Projects> git clone .\ECP5_Serdes .\ECP5_Serdes_clone Cloning into '.\ECP5_Serdes_clone'... done. PS C:\Projects>
Now we'll use Diamond via the IDE Process window to build each project (one at a time). We perform the following steps:
- File -> Open "eye.ldf"
- Double click "PROM File" under "Export Files" in the Process window to start the build.
We chose to create a PROM file for this exercise, so we can use "git diff" to compare the generated eye_impl1.mcs files. Note that the ".mcs" file is an ASCII Intel Hex text file.
PS C:\> git diff C:\projects\ECP5_Serdes\impl1\eye_impl1.mcs C:\Projects\ECP5_Serdes_clone\impl1\eye_impl1.mcs PS C:\>
If there had been a difference in the two hex files, the different lines would have been displayed.
You may have noticed that our cloned project is missing the impl1.xcf programming file. This is because the file is located under impl1, and impl1 is listed in our .gitignore file. For cases like this, we have a choice to either manually add it to our repo using "git add -f impl1\impl1.xcf" or move it outside the impl1 directory. The latter choice is the better one.
Clarity deserves some additional explanation and care. From experimentation, we have found that the source files inside a Clarity project are the "*.sbx" file and the "*.lpc" files, which contain the configuration of each IP block. We also choose to keep around the generated Verilog files (*.v) because we find that we sometimes need to manually tweak them, and they don't change until the files are regenerated inside the Clarity tool.
Diamond also offers a useful project archive / export option under the File menu. The Archive dialog box is shown in the figure below. Note the check box in the lower left, which specifies whether to include all files. It appears that when this box is left unselected, the archive stores primarily the source files. However, we find that the Clarity trees / directories contain various build artifacts that we wouldn't consider source files.
We'll continue to update this page as we continue to work with Git and Diamond for our Private Island project.