-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
83d1e59
commit 0103506
Showing
2 changed files
with
74 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,148 +1,133 @@ | ||
Basic usage | ||
=========== | ||
|
||
.. ATTENTION:: | ||
Project Configuration | ||
--------------------- | ||
|
||
(2024-08-08) To be updated. | ||
The first steps involve importing the necessary module to support the desired tool and instantiating the corresponding *class*: | ||
|
||
Project Creation | ||
---------------- | ||
.. code-block:: python | ||
from pyfpga.vivado import Vivado | ||
prj = Vivado('PRJNAME', odir='OUTDIR') | ||
The first steps are import the module and instantiate the ``Project`` *class*, | ||
specifying the *TOOL* to use and, optionally, a *PROJECT NAME* (the *tool* | ||
name is used when *no name* is provided). | ||
In the example, we are using Vivado, specifying the optional parameter *project name* (*tool name* if omitted) and *output directory* (*results* by default). | ||
|
||
Next step is to specify the target FPGA device: | ||
|
||
.. code-block:: python | ||
from fpga.project import Project | ||
prj.set_part('xc7k160t-3-fbg484') | ||
.. note:: | ||
|
||
prj = Project('vivado', 'projectName') | ||
Default parts are provided for each supported tool. | ||
|
||
By default, the directory where the project is generated is called ``build`` | ||
and is located in the same place that the script, but another name and location | ||
can be specified. | ||
HDL source files are added using one of the following methods: | ||
|
||
.. code-block:: python | ||
prj.set_outdir('../temp') | ||
prj.add_vhdl('PATH_TO_FILES_GLOB_COMPATIBLE', 'OPTIONAL_LIBNAME') | ||
prj.add_vlog('PATH_TO_FILES_GLOB_COMPATIBLE') | ||
prj.add_slog('PATH_TO_FILES_GLOB_COMPATIBLE') | ||
Next, the FPGA part would be specified: | ||
In these methods, you provide a path to the files. The path can include wildcards (like `*.vhdl`), allowing you to match multiple files at once. | ||
|
||
.. code-block:: python | ||
For `add_vhdl`, you can also optionally specify a library name where the files will be included. | ||
|
||
prj.set_part('xc7k160t-3-fbg484') | ||
.. note:: | ||
|
||
Internally, the methods that specify files use `glob`_ to support wildcards and `Path`_ to obtain absolute paths. | ||
|
||
.. NOTE:: | ||
.. _glob: https://docs.python.org/3/library/glob.html | ||
.. _Path: https://docs.python.org/3/library/pathlib.html | ||
|
||
You can use the default FPGA part for a quick test or make a lazy comparison | ||
between tools, but generally, you will want to specify a particular one. | ||
Examples about how to specify a part according the tool, are (default values | ||
when ``set_part`` is not employed): | ||
Generics/parameters can be specified with: | ||
|
||
.. code-block:: python | ||
* **Ise:** ``xc7k160t-3-fbg484`` (*device-speed-package*) | ||
* **Libero:** ``mpf100t-1-fcg484`` (*device-speed-package*) | ||
* **Openflow:** ``hx8k-ct256`` (*device-package*) | ||
* **Quartus:** ``10cl120zf780i8g`` (*part*) | ||
* **Vivado:** ``xc7k160t-3-fbg484`` (*part*) | ||
prj.add_param('PARAMNAME', 'PARAMVALUE') | ||
The files addition method allows specifying one or more HDL or constraint files | ||
(also block designs in case of Vivado). | ||
It uses ``glob`` internally, which makes available the use of wildcards. | ||
The path to their location must be relative to the Python script, and there | ||
are optional parameters to indicate the file type (``vhdl``, ``verilog``, | ||
``constraint`` or ``design``), which is automatically detected based on the | ||
file extension, and if it is a member of a VHDL package. | ||
For Verilog and SystemVerilog, the following methods are also available: | ||
|
||
.. code-block:: python | ||
prj.add_files('hdl/blinking.vhdl', library='examples') | ||
prj.add_files('hdl/examples_pkg.vhdl', library='examples') | ||
prj.add_files('hdl/top.vhdl') | ||
prj.add_include('PATH_TO_A_DIRECTORY') | ||
prj.add_define('DEFNAME', 'DEFVALUE') | ||
.. NOTE:: | ||
Constraint source files are included using the following: | ||
|
||
* In some cases, the files order could be a problem, so take into account to | ||
change the order if needed. | ||
* If a file seems unsupported, you can always use the ``prefile`` or | ||
``project`` :ref:`hooks`. | ||
* In case of Verilog, ``add_vlog_include`` can be used to specify where to | ||
search for included files. | ||
.. code-block:: python | ||
prj.add_cons('PATH_TO_FILES_GLOB_COMPATIBLE') | ||
Finally, the top-level must be specified: | ||
Finally, the top-level can be specified as follows: | ||
|
||
.. code-block:: python | ||
prj.set_top('Top') | ||
.. NOTE:: | ||
.. note:: | ||
|
||
A relative path to a valid VHDL/Verilog file is also accepted by ``set_top``, | ||
to automatically extract the top-level name. | ||
The order of the methods described in this section is not significant. | ||
They will be arranged in the required order by the underlying template. | ||
|
||
Project generation | ||
------------------ | ||
Bitstream generation | ||
-------------------- | ||
|
||
Next step if to generate the project. In the most basic form, you can run the | ||
following to get a bitstream: | ||
After configuring the project, you can run the following to generate a bitstream: | ||
|
||
.. code-block:: python | ||
prj.generate() | ||
prj.make() | ||
Additionally, you can specify which task to perform: | ||
By default, this method performs *project creation*, *synthesis*, *place and route*, and *bitstream generation*. | ||
However, you can optionally specify both the initial and final stages, as follows: | ||
|
||
.. code-block:: python | ||
prj.generate('syn') | ||
.. NOTE:: | ||
|
||
The valid values are: | ||
prj.make(first='syn', last='par') | ||
* ``prj``: to generate only a project file (only supported for privative tools) | ||
* ``syn``: to performs synthesis. | ||
* ``imp``: to performs synthesis and implementation (place and route, | ||
optimizations and static timming analysis when available). | ||
* ``bit``: (default) to perform synthesis, implementation and bitstream generation. | ||
.. note:: | ||
|
||
Bitstream transfer | ||
------------------ | ||
Valid values are: | ||
|
||
This method is in charge of run the needed tool to transfer a bitstream to a | ||
device (commonly an FPGA, but memories are also supported in some cases). | ||
It has up to four main optional parameters: | ||
* ``cfg``: generates the project file | ||
* ``syn``: performs synthesis | ||
* ``par``: performs place and route | ||
* ``bit``: performs bitstream generation | ||
|
||
.. code-block:: python | ||
.. note:: | ||
|
||
prj.transfer(devtype, position, part, width) | ||
After executing this method, you will find the file `<TOOL>.tcl` (or `sh` in some cases) in the output directory. | ||
For debugging purposes, if things do not work as expected, you can review this file. | ||
|
||
Where *devtype* is ``fpga`` by default but can also be ``spi``, ``bpi``, etc, if | ||
supported. An integer number can be used to specify the *position* (1) in the | ||
Jtag chain. When a memory is used as *devtype*, the *part* name and the | ||
*width* in bits must be also specified. | ||
Bitstream programming | ||
--------------------- | ||
|
||
.. NOTE:: | ||
The final step is programming the FPGA: | ||
|
||
* In Xilinx, `spi` and `bpi` memories are out of the Jtag chain and are | ||
programmed through the FPGA. You must specify the FPGA *position*. | ||
* In a Linux systems, you need to have permission over the device | ||
(udev rule, be a part of a group, etc). | ||
.. code-block:: python | ||
Logging capabilities | ||
-------------------- | ||
prj.prog('BITSTREAM', 'POSITION') | ||
PyFPGA uses the `logging <https://docs.python.org/3/library/logging.html>`_ | ||
module, with a *NULL* handler and the *INFO* level by default. | ||
Messages can be enabled with: | ||
Both `BITSTREAM` and `POSITION` are optional. | ||
If `BITSTREAM` is not specified, PyFPGA will attempt to discover it based on project information. | ||
The `POSITION` parameter is not always required (depends on the tool being used). | ||
|
||
.. code-block:: python | ||
.. note:: | ||
|
||
import logging | ||
After executing this method, you will find the file `<TOOL>prog.tcl` (or `sh` in some cases) in the output directory. | ||
For debugging purposes, if things do not work as expected, you can review this file. | ||
|
||
logging.basicConfig() | ||
Debugging | ||
--------- | ||
|
||
You can enable *DEBUG* messages adding: | ||
Under the hood, `logging`_ is employed. To enable debug messages, you can use: | ||
|
||
.. code-block:: python | ||
logging.getLogger('fpga.project').level = logging.DEBUG | ||
prj.set_debug() | ||
.. _logging: https://docs.python.org/3/library/logging.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters