docs: Update README, misspelings, and improvements
Update docs instructions in the README.md to recommend building the libraries before generating the documentation. Fix misspellings in the SPI Engines. Use hashlib to gen the reproducible ids, so these elements won't be committed at every build in the gh-pages branch. Get username from environment variable, to use in the symbolator local installation path, dismissing user interaction for this. Use modelParameter to extract the type from ip-xact parameters without the format field, and improve formatting. Signed-off-by: Jorge Marques <jorge.marques@analog.com>main
parent
455bfbcafb
commit
4d676ca25a
16
README.md
16
README.md
|
@ -39,7 +39,7 @@ The HDL is provided "AS IS", support is only provided on [EngineerZone](https://
|
||||||
|
|
||||||
If you feel you can not, or do not want to ask questions on [EngineerZone](https://ez.analog.com/community/fpga), you should not use or look at the HDL found in this repository. Just like you have the freedom and rights to use this software in your products (with the obligations found in individual licenses) and get support on [EngineerZone](https://ez.analog.com/community/fpga), you have the freedom and rights not to use this software and get datasheet level support from traditional ADI contacts that you may have.
|
If you feel you can not, or do not want to ask questions on [EngineerZone](https://ez.analog.com/community/fpga), you should not use or look at the HDL found in this repository. Just like you have the freedom and rights to use this software in your products (with the obligations found in individual licenses) and get support on [EngineerZone](https://ez.analog.com/community/fpga), you have the freedom and rights not to use this software and get datasheet level support from traditional ADI contacts that you may have.
|
||||||
|
|
||||||
There is no free replacement for consulting services. If you have questions that are best handed one-on-one engagement, and are time sensitive, consider hiring a consultant. If you want to find a consultant who is familar with the HDL found in this repository - ask on [EngineerZone](https://ez.analog.com/community/fpga).
|
There is no free replacement for consulting services. If you have questions that are best handed one-on-one engagement, and are time sensitive, consider hiring a consultant. If you want to find a consultant who is familiar with the HDL found in this repository - ask on [EngineerZone](https://ez.analog.com/community/fpga).
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
@ -47,15 +47,19 @@ This repository supports reference designs for different [Analog Devices boards]
|
||||||
|
|
||||||
### Building documentation
|
### Building documentation
|
||||||
|
|
||||||
Install necessary tools
|
Install the documentation tools.
|
||||||
```
|
```
|
||||||
cd docs
|
(cd docs ; pip install -r requirements.txt)
|
||||||
pip install -r requirements.txt
|
|
||||||
```
|
```
|
||||||
Then build the documentation with sphinx
|
Build the libraries (recommended).
|
||||||
```
|
```
|
||||||
make html
|
(cd library ; make)
|
||||||
```
|
```
|
||||||
|
Build the documentation with Sphinx.
|
||||||
|
```
|
||||||
|
(cd docs ; make html)
|
||||||
|
```
|
||||||
|
The generated documentation will be available at `docs/_build/html`.
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ release = 'v0.1'
|
||||||
|
|
||||||
import os, sys
|
import os, sys
|
||||||
|
|
||||||
|
user = os.environ.get("USER")
|
||||||
sys.path.append(os.path.abspath("./extensions"))
|
sys.path.append(os.path.abspath("./extensions"))
|
||||||
|
|
||||||
extensions = [
|
extensions = [
|
||||||
|
@ -40,7 +41,7 @@ todo_emit_warnings = True
|
||||||
|
|
||||||
# -- Symbolator configuration -------------------------------------------------
|
# -- Symbolator configuration -------------------------------------------------
|
||||||
|
|
||||||
symbolator_cmd = '~/.local/bin/symbolator' # Update with your installed location
|
symbolator_cmd = f"/home/{user}/.local/bin/symbolator"
|
||||||
symbolator_cmd_args = ['-t', '--scale=0.75']
|
symbolator_cmd_args = ['-t', '--scale=0.75']
|
||||||
|
|
||||||
# -- Options for HTML output --------------------------------------------------
|
# -- Options for HTML output --------------------------------------------------
|
||||||
|
|
|
@ -12,6 +12,7 @@ from sphinx.util import logging
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from adi_hdl_static import hdl_strings
|
from adi_hdl_static import hdl_strings
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
from hashlib import sha1
|
||||||
import contextlib
|
import contextlib
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -178,7 +179,7 @@ class directive_base(Directive):
|
||||||
def collapsible(self, section, text=""):
|
def collapsible(self, section, text=""):
|
||||||
env = self.state.document.settings.env
|
env = self.state.document.settings.env
|
||||||
|
|
||||||
_id = str(uuid4())
|
_id = sha1(text.encode('utf-8')).hexdigest()
|
||||||
container = nodes.container(
|
container = nodes.container(
|
||||||
"",
|
"",
|
||||||
is_div=True,
|
is_div=True,
|
||||||
|
@ -491,7 +492,7 @@ class directive_parameters(directive_base):
|
||||||
table = nodes.table()
|
table = nodes.table()
|
||||||
table += tgroup
|
table += tgroup
|
||||||
|
|
||||||
self.table_header(tgroup, ["Name", "Description", "Type", "Default Value", "Choices/Range"])
|
self.table_header(tgroup, ["Name", "Description", "Data Type", "Default Value", "Choices/Range"])
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
for key in parameter:
|
for key in parameter:
|
||||||
|
@ -501,13 +502,16 @@ class directive_parameters(directive_base):
|
||||||
self.column_entry(row, description[key], 'reST', classes=['description'])
|
self.column_entry(row, description[key], 'reST', classes=['description'])
|
||||||
else:
|
else:
|
||||||
self.column_entry(row, dot_fix(parameter[key]['description']), 'paragraph', classes=['description'])
|
self.column_entry(row, dot_fix(parameter[key]['description']), 'paragraph', classes=['description'])
|
||||||
for tag in ['type', 'default']:
|
for tag, ty in zip(['type', 'default'], ['paragraph', 'literal']):
|
||||||
self.column_entry(row, parameter[key][tag].title(), 'paragraph')
|
if parameter[key][tag] is not None:
|
||||||
|
self.column_entry(row, parameter[key][tag], ty, classes=[tag])
|
||||||
|
else:
|
||||||
|
logger.warning(f"Got empty {tag} at parameter {key}!")
|
||||||
|
self.column_entry(row, "", 'paragraph')
|
||||||
crange = []
|
crange = []
|
||||||
if parameter[key]['choices'] is not None:
|
for tag in ['choices', 'range']:
|
||||||
crange.append(parameter[key]['choices'])
|
if parameter[key][tag] is not None:
|
||||||
if parameter[key]['range'] is not None:
|
crange.append(parameter[key][tag])
|
||||||
crange.append(parameter[key]['range'])
|
|
||||||
crange = '. '.join(crange)
|
crange = '. '.join(crange)
|
||||||
self.column_entry(row, crange, 'paragraph')
|
self.column_entry(row, crange, 'paragraph')
|
||||||
|
|
||||||
|
@ -615,6 +619,15 @@ def parse_hdl_component(path, ctime):
|
||||||
def get_choice_type(name):
|
def get_choice_type(name):
|
||||||
return name[name.find('_')+1:name.rfind('_')]
|
return name[name.find('_')+1:name.rfind('_')]
|
||||||
|
|
||||||
|
def format_default_value(value, fmt):
|
||||||
|
if fmt == "bitString" and value[0:2].lower() == "0x":
|
||||||
|
return f"'h{value[2:].upper()}"
|
||||||
|
if fmt == "bitString" and value[0] == '"' and value[-1] == '"':
|
||||||
|
return f"'b{value[1:-1]}"
|
||||||
|
if fmt == "bool":
|
||||||
|
return value.title()
|
||||||
|
return value
|
||||||
|
|
||||||
root = etree.parse(path).getroot()
|
root = etree.parse(path).getroot()
|
||||||
spirit, xilinx, _ = get_namespaces(root)
|
spirit, xilinx, _ = get_namespaces(root)
|
||||||
vendor = get(root, 'vendor').text
|
vendor = get(root, 'vendor').text
|
||||||
|
@ -673,15 +686,28 @@ def parse_hdl_component(path, ctime):
|
||||||
if param_description is not None:
|
if param_description is not None:
|
||||||
param_name = get(parameter, 'name').text
|
param_name = get(parameter, 'name').text
|
||||||
param_value = get(parameter, 'value')
|
param_value = get(parameter, 'value')
|
||||||
|
param_format = sattrib(param_value, 'format')
|
||||||
pr[param_name] = {
|
pr[param_name] = {
|
||||||
'description': param_description.text,
|
'description': param_description.text,
|
||||||
'default': param_value.text,
|
'default': format_default_value(param_value.text, param_format),
|
||||||
'type': sattrib(param_value, 'format'),
|
'type': param_format,
|
||||||
'_choice_ref': sattrib(param_value, 'choiceRef'),
|
'_choice_ref': sattrib(param_value, 'choiceRef'),
|
||||||
'choices': None,
|
'choices': None,
|
||||||
'range': get_range(param_value)
|
'range': get_range(param_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for parameter in get_all(root, 'model/modelParameters/modelParameter'):
|
||||||
|
param_name = get(parameter, 'name').text
|
||||||
|
param_type = sattrib(parameter, 'dataType')
|
||||||
|
if param_type == "std_logic_vector":
|
||||||
|
param_type = "logic vector"
|
||||||
|
if param_type is not None and param_name in pr:
|
||||||
|
if pr[param_name]['type'] is None:
|
||||||
|
pr[param_name]['type'] = param_type.capitalize()
|
||||||
|
else:
|
||||||
|
param_format = pr[param_name]['type']
|
||||||
|
pr[param_name]['type'] = param_format[0].upper()+param_format[1:]
|
||||||
|
|
||||||
for choice in get_all(root, 'choices/choice'):
|
for choice in get_all(root, 'choices/choice'):
|
||||||
name = get(choice, 'name').text
|
name = get(choice, 'name').text
|
||||||
for key in pr:
|
for key in pr:
|
||||||
|
|
|
@ -7,10 +7,10 @@ The SPI Engine instruction set is a simple 16-bit instruction set of which
|
||||||
12-bit is currently allocated (bits 15,14,11,10 are always 0).
|
12-bit is currently allocated (bits 15,14,11,10 are always 0).
|
||||||
|
|
||||||
Instructions
|
Instructions
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Transfer Instruction
|
Transfer Instruction
|
||||||
--------------------------------------------------------------------------------
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
== == == == == == = = = = = = = = = =
|
== == == == == == = = = = = = = = = =
|
||||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||||
|
|
|
@ -6,7 +6,7 @@ SPI Engine Tutorial - PulSAR-ADC
|
||||||
The goal of this tutorial is to present the process of adding
|
The goal of this tutorial is to present the process of adding
|
||||||
:ref:`spi_engine` support for an ADI precision converter or family of converters
|
:ref:`spi_engine` support for an ADI precision converter or family of converters
|
||||||
using a few simple steps.
|
using a few simple steps.
|
||||||
The target carrier is the Digilent Cora-z7s board using a Pmod connector.
|
The target carrier is the Digilent Cora-z7s board using a PMOD connector.
|
||||||
|
|
||||||
Evaluating the target device
|
Evaluating the target device
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -73,7 +73,7 @@ each IP individually or by using the function provided by the
|
||||||
Using the script ensures that the correct connections are being made and that
|
Using the script ensures that the correct connections are being made and that
|
||||||
the IP cores will receive the correct parameter configuration since certain
|
the IP cores will receive the correct parameter configuration since certain
|
||||||
parameters need to be set to the same value. The function takes the following
|
parameters need to be set to the same value. The function takes the following
|
||||||
argumets
|
arguments:
|
||||||
|
|
||||||
.. code:: tcl
|
.. code:: tcl
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ and some of them require 18bit transfers, this value will be rounded to 32bit.
|
||||||
|
|
||||||
**async_spi_clk** will chose the reference clock for the SPI Engine. Setting
|
**async_spi_clk** will chose the reference clock for the SPI Engine. Setting
|
||||||
this parameter to 0 will configure the hierarchy to use the axi clock (100MHz)
|
this parameter to 0 will configure the hierarchy to use the axi clock (100MHz)
|
||||||
as the reference clock. Setting it to 1 will allow for an external referece
|
as the reference clock. Setting it to 1 will allow for an external reference
|
||||||
clock (spi_clk). Because some devices need 80MHz SCLK, a 160MHz reference clock
|
clock (spi_clk). Because some devices need 80MHz SCLK, a 160MHz reference clock
|
||||||
is required which implies an external reference.
|
is required which implies an external reference.
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ Sample rate control
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The T_CYC parameter is the what sets the maximum sample rate (1/750 => 1333
|
The T_CYC parameter is the what sets the maximum sample rate (1/750 => 1333
|
||||||
KSPS). To achieve precise control over the the sample rate we will use a PWM
|
KSPS). To achieve precise control over the sample rate we will use a PWM
|
||||||
generator (AXI PWM GEN) using the spi_clk as reference. The spi_clock is used to
|
generator (AXI PWM GEN) using the spi_clk as reference. The spi_clock is used to
|
||||||
avoid clock domain crossing mechanisms which will introduce latency, decreasing
|
avoid clock domain crossing mechanisms which will introduce latency, decreasing
|
||||||
the overall performance of the system.
|
the overall performance of the system.
|
||||||
|
@ -199,13 +199,13 @@ wide range of options.
|
||||||
The PWM output will be used as a trigger signal for the offload IP core.
|
The PWM output will be used as a trigger signal for the offload IP core.
|
||||||
|
|
||||||
The CS signal will be used to drive CNV and will have the same frequency as the
|
The CS signal will be used to drive CNV and will have the same frequency as the
|
||||||
PWM-trgger signal.
|
PWM-trigger signal.
|
||||||
|
|
||||||
DMA setup
|
DMA setup
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
DMA destination bus (connection to Zynq – DDR memory) shall always be 64 bit
|
DMA destination bus (connection to Zynq – DDR memory) shall always be 64 bit
|
||||||
wide AXI4 MM and source bus shall be data_wdth \* num_sdi = 32 bit, AXI4 Stream.
|
wide AXI4 MM and source bus shall be data_width \* num_sdi = 32 bit, AXI4 Stream.
|
||||||
|
|
||||||
.. code:: tcl
|
.. code:: tcl
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ System Top
|
||||||
|
|
||||||
This is a layer on top of the system_wrapper generated by Vivado used to
|
This is a layer on top of the system_wrapper generated by Vivado used to
|
||||||
instantiate IO buffers, I/ODDRs or to create some custom connections which would
|
instantiate IO buffers, I/ODDRs or to create some custom connections which would
|
||||||
be harder to do in the block design. It also alows for more consistency across
|
be harder to do in the block design. It also allows for more consistency across
|
||||||
projects. In this particular case we use it to place an IO buffer for the ADC
|
projects. In this particular case we use it to place an IO buffer for the ADC
|
||||||
power down signal (pulsar_adc_spi_pd).
|
power down signal (pulsar_adc_spi_pd).
|
||||||
|
|
||||||
|
@ -247,10 +247,9 @@ design for the carrier board which has a separate constraints file (i.e. DDR
|
||||||
pins, Ethernet, UART etc). It also contains some timing constraints specific to
|
pins, Ethernet, UART etc). It also contains some timing constraints specific to
|
||||||
the SPI Engine.
|
the SPI Engine.
|
||||||
|
|
||||||
create_generated_clock -name spi_clk -source [get_pins -filter name=~*CLKIN1 -of
|
.. code::
|
||||||
[get_cells -hier -filter name=~*spi_clkgen*i_mmcm]] -master_clock clk_fpga_0
|
|
||||||
[get_pins -filter name=~*CLKOUT0 -of [get_cells -hier -filter
|
create_generated_clock -name spi_clk -source [get_pins -filter name=~*CLKIN1 -of [get_cells -hier -filter name=~*spi_clkgen*i_mmcm]] -master_clock clk_fpga_0 [get_pins -filter name=~*CLKOUT0 -of [get_cells -hier -filter name=~*spi_clkgen*i_mmcm]]
|
||||||
name=~*spi_clkgen*i_mmcm]]
|
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
|
@ -292,7 +291,7 @@ Holding CS high for 500ns ensures that we always meet T_CONV minimum.
|
||||||
.. image:: tutorial/pulsar_hdl_timing_3.png
|
.. image:: tutorial/pulsar_hdl_timing_3.png
|
||||||
:width: 100%
|
:width: 100%
|
||||||
|
|
||||||
The 250ns minimum T_ACQ is alse met with a slightly higher value of 256.25ns.
|
The 250ns minimum T_ACQ is also met with a slightly higher value of 256.25ns.
|
||||||
|
|
||||||
.. image:: tutorial/pulsar_hdl_timing_4.png
|
.. image:: tutorial/pulsar_hdl_timing_4.png
|
||||||
:width: 100%
|
:width: 100%
|
||||||
|
|
|
@ -60,6 +60,9 @@ table.regmap {
|
||||||
table.regmap .caption-text{
|
table.regmap .caption-text{
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
|
th, td.type, td.default {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
td.description {
|
td.description {
|
||||||
width: 45%;
|
width: 45%;
|
||||||
font-size:.8em;
|
font-size:.8em;
|
||||||
|
|
Loading…
Reference in New Issue