docs: automate parameters and interfaces tables

Uses Vivado generated components.xml files.
If the file is not found/generated, there is a fallback method.
Also, define bibliography per project, not globally.

Signed-off-by: Jorge Marques <jorge.marques@analog.com>
main
Jorge Marques 2023-08-01 17:39:09 -03:00 committed by Jorge Marques
parent ef9c98f9b9
commit 83d2bf9603
14 changed files with 581 additions and 416 deletions

View File

@ -1,6 +0,0 @@
Bibliography
======================================================
.. bibliography::
:all:

View File

@ -1,97 +0,0 @@
Glossary
======================================================
.. glossary::
SVG
Scalable Vector Graphics
reST
reStructuredText Primer
HDL
hardware description language
S
Start
PS
Processing System
Sr
Repeated Start
P
Stop
ACK
Acknowledge
IBI
In-band Interrupt
DAA
Dynamic Address Assignment
ADC
analog-digital converter
SoC
system-on-a-chip
SAR
succesive-approximation-register
IP
intellectual-property
PMOD
peripheral module interface
SOM
system on module
SDR
standard data rate
DDR
double data rate
HDR
high data rate
ID
identification
PID
Provisioned ID
MIPI
Manufacturer ID
MDB
Mandatory data byte
I/O
input/output
PUR
Pull-Up Resistor
CCC
Common Command Codes
T-bit
Transaction bit
SCL
Serial Clock
SDA
Serial Data
SPI
Serial Peripheral Interface
GPIO
General Purpose Input/Output

View File

@ -1,13 +0,0 @@
@misc{adi:hdl,
organization = {Analog Devices Inc},
title = {HDL Reference Designs},
howpublished = {\url{https://github.com/analogdevicesinc/hdl}},
year = {2023}
}
@misc{adi:i2c-quick-guide,
organization = {Analog Devices Inc},
title = {I²C Quick Guide},
howpublished = {\url{https://www.analog.com/media/en/technical-documentation/product-selector-card/i2Cb.pdf}},
year = {2017},
month = {April}
}

View File

@ -18,7 +18,6 @@ sys.path.append(os.path.abspath("./extensions"))
extensions = [
"sphinx.ext.todo",
"sphinx.ext.viewcode",
"sphinxcontrib.bibtex",
"sphinxcontrib.mermaid",
"sphinxcontrib.wavedrom",
"symbolator_sphinx",
@ -32,7 +31,6 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Custom extensions configuration -------------------------------------------
# -- todo configuration -------------------------------------------------------
todo_include_todos = True

View File

@ -6,7 +6,7 @@ A brief set-of-rules for the documentation.
.. note::
The old wiki uses `dokuwiki <https://www.dokuwiki.org/dokuwiki>`_. When
importing text from there, consider the automated options that are provided
in this page to convert it to :term:`reST`.
in this page to convert it to reST.
Templates
--------------------------------------------------------------------------------
@ -36,7 +36,7 @@ Notice how neither *library* nor *project* are present in the label, since there
naming collision between libraries or projects (no project will ever be named
*axi_dmac*).
Also, for project, libraries and :term:`IP`\s, the names should be exactly the
Also, for project, libraries and IPs, the names should be exactly the
name of its folders, e.g. ``axi_pwm_gen`` and not ``axi-pwm-gen`` or ``AXI_PWM_GEN``,
this helps avoid broken references.
@ -106,7 +106,7 @@ For example,
string = "Hello world"
print(string)
renders as
Renders as
.. code-block:: python
:linenos:
@ -120,14 +120,14 @@ renders as
Images
--------------------------------------------------------------------------------
Prefer the :term:`SVG` format for images, and save it as *Optimized SVG* in
Prefer the SVG format for images, and save it as *Optimized SVG* in
`inkscape <https://inkscape.org/>`_ to use less space.
Vivado block-diagrams
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Vivado block-diadrams can be exported as PDF and then converted to SVG with
inkscape. See :ref:`spi_engine tutorial` for a "final result" example.
Vivado block-diagrams can be exported as PDF and then converted to SVG with
Inkscape. See :ref:`spi_engine tutorial` for a "final result" example.
Vivado waveform data
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -142,7 +142,7 @@ disabled.
Always use the *Export As..* ``Ctrl+Shift+E`` option.
To reduce even further the size, you can use *Color > Dither..* to reduce the
number of colors in the png.
number of colors in the PNG.
Saving as greyscale also reduces the PNG size, but might reduce readability and
it is not recommended.
@ -242,14 +242,13 @@ The name parameter is optional, if absent, the file name will be used as the nam
HDL parameters directive
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The HDL parameters directive parses the *\*_hw.tcl* library files to generate a
table with the IP parameters.
The HDL parameters directive gets information parsed from *component.xml* library
and generates a table with the IP parameters.
.. attention::
.. note::
This directive does not support parameters generated in a foreach loop yet
(e.g. :git-hdl:`library/axi_dmac/axi_dmac_hw.tcl#L90`).
Manually create the parameters table in these cases.
The *component.xml* files are generated by Vivado during the library build
and not by the documentation tooling.
The directive syntax is:
@ -273,7 +272,7 @@ For example:
* - NUM_OF_SDI
- Number of SDI lines on the physical SPI interface.
renders as:
Renders as:
.. hdl-parameters::
:path: library/spi_engine/spi_engine_interconnect
@ -283,13 +282,55 @@ renders as:
* - NUM_OF_SDI
- Number of SDI lines on the physical SPI interface.
Notice how the *Type* and *Default* values are obtained from the *\*_hw.tcl*.
Parameters not listed in the directive are also added to the table, but
will have an empty description, unless a comment follows the ``ad_ip_parameter``
method in the source file.
Descriptions in the directive have higher precedece tha in the *component.xml*
file.
If you are felling adventurous, the ``:path:`` option is optional, and the
extension will guess the path to the library.
The ``:path:`` option is optional, and should **not** be included if the
documentation file path matches the *component.xml* hierarchically.
HDL interface directive
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The HDL interfaces directive gets information parsed from *component.xml* library
and generates tables with the IP interfaces, both buses and ports.
.. note::
The *component.xml* files are generated by Vivado during the library build
and not by the documentation tooling.
The directive syntax is:
.. code:: rst
.. hdl-interfaces::
:path: <ip_path>
* - <parameter>
- <description>
For example:
.. code:: rst
.. hdl-interfaces::
:path: library/spi_engine/spi_engine_interconnect
Renders as:
::
.. hdl-interfaces::
:path: library/spi_engine/spi_engine_interconnect
Descriptions in the directive have higher precedece than in the *component.xml*
file.
You can provide description to a port or a bus, but not for a bus port.
The ``:path:`` option is optional, and should **not** be included if the
documentation file path matches the *component.xml* hierarchically.
.. _installing_pandoc:

View File

@ -1,105 +1,76 @@
import os.path
from docutils import nodes
from docutils.statemachine import ViewList
from docutils.parsers.rst import Directive, directives
from sphinx.util.nodes import nested_parse_with_titles
from sphinx.util import logging
import os.path
from lxml import etree
logger = logging.getLogger(__name__)
class node_parameters(nodes.Structural, nodes.Element):
pass
class directive_parameters(Directive):
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
def dot_fix(string):
if (string.rfind('.') != len(string)-1):
return string + '.'
else:
return string
def pretty_dep(string):
if string is None:
return ''
return string.replace("'MODELPARAM_VALUE.",'').replace("'",'')
class directive_base(Directive):
option_spec = {'path': directives.unchanged}
has_content = True
add_index = True
current_doc = ''
final_argument_whitespace = True
def warning(self, msg):
logger.warning(msg + f" Current file: {self.current_doc}")
def info(self, msg):
logger.info(msg + f" Current file: {self.current_doc}")
def table_parameters(self, path, content):
description = {}
tag = ''
def get_descriptions(self, content):
items = {}
key = ''
for line in content:
if line.startswith('* -'):
tag = line[line.find('* -')+3:].split()[0]
description[tag] = []
key = line[line.find('* -')+3:].split()[0]
items[key] = []
else:
description[tag].append(line)
for tag in description:
description[tag] = ' '.join(description[tag]).strip().replace('- ', '', 1)
items[key].append(line)
for key in items:
items[key] = ' '.join(items[key]).strip().replace('- ', '', 1)
return items
table = nodes.table()
parameters = {}
full_path = path+'/'+path[path.rfind('/')+1:]+'_hw.tcl'
if not os.path.isfile('../'+full_path):
self.warning(f"{full_path} does not exist!")
return table
with open('../'+full_path, 'r') as file:
for line in file:
line = line.strip()
if line.startswith('ad_ip_parameter'):
line_ = line.split(' ', 4)
if len(line_) == 4:
line_.append('')
_, name, type_, default, comment = line_
comment = comment.replace('#','',1).strip()
if comment != '' and comment[-1] != '.':
comment += '.'
parameters[name] = {'type':type_, 'default':default, 'comment':comment}
for tag in description:
if tag not in parameters:
self.warning(f"{tag} does not exist in {full_path}!")
elif parameters[tag]['comment'] != '':
description[tag] = ' '.join([parameters[tag]['comment'], description[tag]])
tgroup = nodes.tgroup(cols=4)
for _ in range(4):
def generic_table(self, description):
tgroup = nodes.tgroup(cols=2)
for _ in range(2):
colspec = nodes.colspec(colwidth=1)
tgroup.append(colspec)
table = nodes.table()
table += tgroup
thead = nodes.thead()
tgroup += thead
row = nodes.row()
for header_name in ["Name", "Description", "Type", "Default Value"]:
entry = nodes.entry()
entry += nodes.paragraph(text=header_name)
row += entry
thead.append(row)
self.table_header(tgroup, ["Name", "Description"])
rows = []
for key in parameters:
for key in description:
row = nodes.row()
entry = nodes.entry()
entry += nodes.literal(text="{:s}".format(key))
row += entry
entry = nodes.entry()
if key in description:
rst = ViewList()
rst.append(description[key], "virtual_"+path, 0)
node = nodes.section()
node.document = self.state.document
nested_parse_with_titles(self.state, rst, node)
entry += node
else:
entry += ''
rst = ViewList()
rst.append(description[key], "virtual_"+self.current_doc, 0)
node = nodes.section()
node.document = self.state.document
nested_parse_with_titles(self.state, rst, node)
entry += node
row += entry
for tag in ['type', 'default']:
entry = nodes.entry()
entry += nodes.paragraph(text=parameters[key][tag].title())
row += entry
rows.append(row)
tbody = nodes.tbody()
@ -108,15 +79,121 @@ class directive_parameters(Directive):
return table
def guess_path(self):
path = self.current_doc
for key in ['library', 'projects']:
start_index = path.find(key)
if start_index != -1:
break
def table_header(self, tgroup, columns):
thead = nodes.thead()
tgroup += thead
row = nodes.row()
end_index = path.rfind('.')
return path[start_index:end_index]
for header_name in columns:
entry = nodes.entry()
entry += nodes.paragraph(text=header_name)
row += entry
thead.append(row)
class directive_interfaces(directive_base):
required_arguments = 0
optional_arguments = 0
def tables(self, content, component):
description = self.get_descriptions(content)
if component is None:
return self.generic_table(description)
node_tables = nodes.section()
bs = component['bus_interface']
for tag in bs:
section = nodes.section(ids=[f"virtual_{self.current_doc}_bus_interface_{tag}"])
title = nodes.title(text=tag)
section += title
if bs[tag]['dependency'] is not None:
dependency = nodes.paragraph(text=f"Depends on {pretty_dep(bs[tag]['dependency'])}.")
section += dependency
if tag in description:
rst = ViewList()
rst.append(description[tag], "virtual_"+self.current_doc, 0)
node = nodes.section()
node.document = self.state.document
nested_parse_with_titles(self.state, rst, node)
section += node
tgroup = nodes.tgroup(cols=3)
for _ in range(3):
colspec = nodes.colspec(colwidth=1)
tgroup.append(colspec)
table = nodes.table()
table += section
table += tgroup
self.table_header(tgroup, ["Physical Port", "Logical Port", "Direction"])
rows = []
pm = bs[tag]['port_map']
for key in pm:
row = nodes.row()
entry = nodes.entry()
entry += nodes.literal(text=key)
row += entry
entry = nodes.entry()
entry += nodes.literal(text=pm[key]['logical_port'])
row += entry
entry = nodes.entry()
entry += nodes.paragraph(text=pm[key]['direction'])
row += entry
rows.append(row)
tbody = nodes.tbody()
tbody.extend(rows)
tgroup += tbody
node_tables += table
section = nodes.section(ids=[f"virtual_{self.current_doc}_ports"])
title = nodes.title(text="Ports")
section += title
tgroup = nodes.tgroup(cols=4)
for _ in range(4):
colspec = nodes.colspec(colwidth=1)
tgroup.append(colspec)
table = nodes.table()
table += section
table += tgroup
self.table_header(tgroup, ["Physical Port", "Description", "Direction", "Dependency"])
rows = []
pr = component['ports']
for key in pr:
row = nodes.row()
entry = nodes.entry()
entry += nodes.literal(text=key)
row += entry
entry = nodes.entry()
if key in description:
rst = ViewList()
rst.append(description[key], "virtual_"+self.current_doc, 0)
node = nodes.section()
node.document = self.state.document
nested_parse_with_titles(self.state, rst, node)
entry += node
else:
entry += nodes.paragraph(text='')
row += entry
entry = nodes.entry()
entry += nodes.paragraph(text=pr[key]['direction'])
row += entry
entry = nodes.entry()
entry += nodes.paragraph(text=pretty_dep(pr[key]['dependency']))
row += entry
rows.append(row)
tbody = nodes.tbody()
tbody.extend(rows)
tgroup += tbody
node_tables += table
return node_tables
def run(self):
env = self.state.document.settings.env
@ -124,21 +201,101 @@ class directive_parameters(Directive):
node = node_parameters()
if 'path' not in self.options:
path = self.guess_path()
if not os.path.isdir('../'+path):
self.warning(f"Guessed path {path}, but it does not exist, set the path option explicitely!")
return [ node ]
if 'path' in self.options:
lib_name = self.options['path']
else:
path = self.options['path']
if not os.path.isdir('../'+path):
self.warning(f"Path {path} does not exist!")
return [ node ]
lib_name = env.docname.replace('/index', '')
node_table = nodes.section(ids=["hdl-parameters"])
subnode = nodes.section(ids=["hdl-interfaces"])
if lib_name in env.component:
subnode += self.tables(self.content, env.component[lib_name])
else:
subnode += self.tables(self.content, None)
node_table += self.table_parameters(path, self.content)
node += node_table
node += subnode
return [ node ]
class directive_parameters(directive_base):
required_arguments = 0
optional_arguments = 0
def tables(self, content, parameter):
description = self.get_descriptions(content)
if parameter is None:
return self.generic_table(description)
tgroup = nodes.tgroup(cols=5)
for _ in range(5):
colspec = nodes.colspec(colwidth=1)
tgroup.append(colspec)
table = nodes.table()
table += tgroup
self.table_header(tgroup, ["Name", "Description", "Type", "Default Value", "Choices/Range"])
rows = []
for key in parameter:
row = nodes.row()
entry = nodes.entry()
entry += nodes.literal(text="{:s}".format(key))
row += entry
entry = nodes.entry()
if key in description:
rst = ViewList()
rst.append(description[key], "virtual_"+self.current_doc, 0)
node = nodes.section()
node.document = self.state.document
nested_parse_with_titles(self.state, rst, node)
entry += node
else:
entry += nodes.paragraph(text=dot_fix(parameter[key]['description']))
row += entry
for tag in ['type', 'default']:
entry = nodes.entry()
entry += nodes.paragraph(text=parameter[key][tag].title())
row += entry
crange = []
if parameter[key]['choices'] is not None:
crange.append(parameter[key]['choices'])
if parameter[key]['range'] is not None:
crange.append(parameter[key]['range'])
crange = '. '.join(crange)
entry = nodes.entry()
entry += nodes.paragraph(text=crange)
row += entry
rows.append(row)
tbody = nodes.tbody()
tbody.extend(rows)
tgroup += tbody
for tag in description:
if tag not in parameter:
self.warning(f"{tag} does not exist in {file_2}!")
return table
def run(self):
env = self.state.document.settings.env
self.current_doc = env.doc2path(env.docname)
node = node_parameters()
if 'path' in self.options:
lib_name = self.options['path']
else:
lib_name = env.docname.replace('/index', '')
subnode = nodes.section(ids=["hdl-parameters"])
if lib_name in env.component:
subnode += self.tables(self.content, env.component[lib_name]['parameters'])
else:
subnode += self.tables(self.content, None)
node += subnode
return [ node ]
@ -148,13 +305,181 @@ def visit_node_parameters(self, node):
def depart_node_parameters(self, node):
pass
def parse_hdl_component(path, ctime):
component = {
'bus_interface':{},
'ports': {},
'parameters': {},
'ctime': ctime
}
def get_namespaces( item):
nsmap = item.nsmap
for i in ['spirit', 'xilinx', 'xsi']:
if i not in nsmap:
raise Exception(f"Required namespace {i} not in file!")
return (nsmap['spirit'], nsmap['xilinx'], nsmap['xsi'])
def get( item, local_name):
items = get_all(item, local_name)
if len(items) == 0:
return None
else:
return items[0]
def get_all( item, local_name):
template = "/*[local-name()='%s']"
if not isinstance(local_name, str):
raise Exception("Got wrong type, only Strings are allowed")
local_name = local_name.split('/')
return item.xpath('.' + ''.join([template % ln for ln in local_name]))
def sattrib( item, attr):
nonlocal spirit
return item.get(f"{{{spirit}}}{attr}")
def xattrib( item, attr):
nonlocal xilinx
return item.get(f"{{{xilinx}}}{attr}")
def stag( item):
nonlocal spirit
return item.tag.replace(f"{{{spirit}}}",'')
def xtag( item):
nonlocal xilinx
return item.tag.replace(f"{{{xilinx}}}",'')
def clean_dependency( string):
return string[string.find("'"): string.rfind(')')].replace(')','')
def get_dependency( item, type_=None):
if type_ is None:
type_ = stag(item)
dependency = get(item, f"vendorExtensions/{type_}Info/enablement/isEnabled")
if dependency is None:
return None
else:
return clean_dependency(xattrib(dependency, 'dependency'))
def get_range( item):
min_ = sattrib(item, 'minimum')
max_ = sattrib(item, 'maximum')
if max_ == None or min_ == None:
return None
else:
return f"From {min_} to {max_}."
def get_choice_type( name):
return name[name.find('_')+1:name.rfind('_')]
root = etree.parse(path).getroot()
spirit, xilinx, _ = get_namespaces(root)
vendor = get(root, 'vendor').text
name = get(root, 'name').text
bs = component['bus_interface']
for bus_interface in get_all(root, 'busInterfaces/busInterface'):
bus_name = get(bus_interface, 'name').text
bs[bus_name] = {
'name': sattrib(get(bus_interface, 'busType'), 'name'),
'dependency': get_dependency(bus_interface, 'busInterface'),
'port_map': {}
}
pm = bs[bus_name]['port_map']
for port_map in get_all(bus_interface, 'portMaps/portMap'):
pm[get(port_map, 'physicalPort/name').text] = {
'logical_port': get(port_map, 'logicalPort/name').text,
'direction': None
}
lport = component['ports']
for port in get_all(root, 'model/ports/port'):
port_name = get(port, 'name').text
port_direction = get(port, 'wire/direction').text
found = False
for bus in bs:
if port_name in bs[bus]['port_map']:
found = True
bs[bus]['port_map'][port_name]['direction'] = port_direction
break;
if found == False:
lport[port_name] = {
'direction': port_direction,
'dependency': get_dependency(port, 'port')
}
pr = component['parameters']
for parameter in get_all(root, 'parameters/parameter'):
param_description = get(parameter, 'displayName')
if param_description is not None:
param_name = get(parameter, 'name').text
param_value = get(parameter, 'value')
pr[param_name] = {
'description': param_description.text,
'default': param_value.text,
'type': sattrib(param_value, 'format'),
'_choice_ref': sattrib(param_value, 'choiceRef'),
'choices': None,
'range': get_range(param_value)
}
for choice in get_all(root, 'choices/choice'):
name = get(choice, 'name').text
for key in pr:
if pr[key]['_choice_ref'] == name:
type_ = get_choice_type(name)
values = get_all(choice, 'enumeration')
string = []
if type_ == 'pairs':
for v in values:
string.append(f"{sattrib(v, 'text')} ({v.text})")
elif type_ == 'list':
for v in values:
string.append(v.text)
else:
break
pr[key]['choices'] = ', '.join(string)
break
return component
def manage_hdl_components(app, env, docnames):
libraries = [[k.replace('/index',''), k] for k in env.found_docs if k.find('library/') == 0]
if not hasattr(env, 'component'):
env.component = {}
cp = env.component
for lib in list(cp):
f = f"../{lib}/component.xml"
if not os.path.isfile(f):
del cp[lib]
for lib, doc in libraries:
f = f"../{lib}/component.xml"
if not os.path.isfile(f):
continue
ctime = os.path.getctime(f)
if lib in cp and cp[lib]['ctime'] >= ctime:
pass
else:
cp[lib] = parse_hdl_component(f, ctime)
docnames.append(doc)
def setup(app):
app.add_directive('hdl-parameters', directive_parameters)
app.add_directive('hdl-interfaces', directive_interfaces)
app.add_node(node_parameters,
html=(visit_node_parameters, depart_node_parameters),
latex=(visit_node_parameters, depart_node_parameters),
text=(visit_node_parameters, depart_node_parameters))
app.connect('env-before-read-docs', manage_hdl_components)
return {
'version': '0.1',
'parallel_read_safe': True,

View File

@ -16,13 +16,6 @@ HDL Reference Designs
contributing/guidelines
.. toctree::
:caption: Appendix
:hidden:
appendix/glossary
appendix/bibliography
.. attention::
Work-in-progress, not all content available at the

View File

@ -1,6 +1,9 @@
High-Speed DMA Controller
================================================================================
.. symbolator:: ../../../library/axi_dmac/axi_dmac.v
:caption: axi_dmac
The AXI DMAC is a high-speed, high-throughput, general purpose DMA controller
intended to be used to transfer data between system memory and other peripherals
like high-speed converters.
@ -64,67 +67,47 @@ Block Diagram
Configuration Parameters
--------------------------------------------------------------------------------
.. list-table::
:header-rows: 1
.. hdl-parameters::
:path: library/axi_dmac
* - Name
- Description
- Default
* - ``ID``
* - ID
- Instance identification number.
- 0
* - ``DMA_DATA_WIDTH_SRC``
* - DMA_DATA_WIDTH_SRC
- Data path width of the source interface in bits.
- 64
* - ``DMA_DATA_WIDTH_DEST``
* - DMA_DATA_WIDTH_DEST
- Data path width of the destination interface in bits.
- 64
* - ``DMA_LENGTH_WIDTH``
* - DMA_LENGTH_WIDTH
- Width of transfer length control register in bits.
Limits length of the transfers to 2*\*\ ``DMA_LENGTH_WIDTH``.
- 24
* - ``DMA_2D_TRANSFER``
* - DMA_2D_TRANSFER
- Enable support for 2D transfers.
- 1
* - ``ASYNC_CLK_REQ_SRC``
* - ASYNC_CLK_REQ_SRC
- Whether the request and source clock domains are asynchronous.
- 1
* - ``ASYNC_CLK_SRC_DEST``
* - ASYNC_CLK_SRC_DEST
- Whether the source and destination clock domains are asynchronous.
- 1
* - ``ASYNC_CLK_DEST_REQ``
* - ASYNC_CLK_DEST_REQ
- Whether the destination and request clock domains are asynchronous.
- 1
* - ``AXI_SLICE_DEST``
* - AXI_SLICE_DEST
- Whether to insert a extra register slice on the source data path.
- 0
* - ``AXI_SLICE_SRC``
* - AXI_SLICE_SRC
- Whether to insert a extra register slice on the destination data path.
- 0
* - ``SYNC_TRANSFER_START``
* - SYNC_TRANSFER_START
- Enable the transfer start synchronization feature.
- 0
* - ``CYCLIC``
* - CYCLIC
- Enable support for Cyclic transfers.
- 1
* - ``DMA_AXI_PROTOCOL_SRC``
* - DMA_AXI_PROTOCOL_SRC
- AXI protocol version of the source interface (0 = AXI4, 1 = AXI3).
- 0
* - ``DMA_AXI_PROTOCOL_DEST``
* - DMA_AXI_PROTOCOL_DEST
- AXI protocol version of the destionation interface (0 = AXI4, 1 = AXI3).
- 0
* - ``DMA_TYPE_SRC``
* - DMA_TYPE_SRC
- Interface type for the source interface
(0 = AXI-MM, 1 = AXI-Streaming, 2 = ADI-FIFO).
- 2
* - ``DMA_TYPE_DEST``
* - DMA_TYPE_DEST
- Interface type for the destination interface
(0 = AXI-MM, 1 = AXI-Streaming, 2 = ADI-FIFO).
- 0
* - ``DMA_AXI_ADDR_WIDTH``
* - DMA_AXI_ADDR_WIDTH
- Maximum address width for AXI interfaces.
- 32
* - ``MAX_BYTES_PER_BURST``
* - MAX_BYTES_PER_BURST
- Maximum size of bursts in bytes. Must be power of 2 in a range of 2
beats to 4096 bytes
The size of the burst is limited by the largest burst that both source
@ -133,100 +116,71 @@ Configuration Parameters
non AXI interfaces the maximum beats per burst is in theory unlimited
but it is set to 1024 to provide a reasonable upper threshold.
This limitation is done internally in the core.
- 128
* - ``FIFO_SIZE``
* - FIFO_SIZE
- Size of the store-and-forward memory in bursts. Size of a burst is
defined by the ``MAX_BYTES_PER_BURST`` parameter. Must be power of 2 in
the range of 2 to 32.
- 4
* - ``DISABLE_DEBUG_REGISTERS``
* - DISABLE_DEBUG_REGISTERS
- Disable debug registers.
- 0
* - ``ENABLE_DIAGNOSTICS_IF``
* - ENABLE_DIAGNOSTICS_IF
- Add insight into internal operation of the core, for debug purposes
only.
- 0
Interface
--------------------------------------------------------------------------------
.. list-table::
:header-rows: 1
.. hdl-interfaces::
* - Name
- Type
- Description
* - ``s_axi_aclk``
- Clock
* - s_axi_aclk
- All ``s_axi`` signals and ``irq`` are synchronous to this clock.
* - ``s_axi_aresetn``
- Synchronous active low reset
* - s_axi_aresetn
- Resets the internal state of the peripheral.
* - ``s_axi``
- AXI4-Lite bus slave
* - s_axi
- Memory mapped AXI-lite bus that provides access to modules register map.
* - ``irq``
- Level-High Interrupt
* - irq
- Interrupt output of the module. Is asserted when at least one of the
modules interrupt is pending and enabled.
* - ``m_src_axi_aclk``
- Clock
- The ``m_src_axi`` interface is synchronous to this clock.
* - m_src_axi_aclk
- The m_src_axi interface is synchronous to this clock.
Only present when ``DMA_TYPE_SRC`` parameter is set to AXI-MM (0).
* - ``m_src_axi_aresetn``
- Synchronous active low reset
* - m_src_axi_aresetn
- Reset for the ``m_src_axi`` interface.
Only present when ``DMA_TYPE_SRC`` parameter is set to AXI-MM (0).
* - ``m_src_axi``
- AXI3/AXI4 bus master
* - m_src_axi
-
* - ``m_dest_axi_aclk``
- Clock
* - m_dest_axi_aclk
- The ``m_src_axi`` interface is synchronous to this clock.
Only present when ``DMA_TYPE_DEST`` parameter is set to AXI-MM (0).
* - ``m_dest_axi_aresetn``
- Synchronous active low reset
* - m_dest_axi_aresetn
- Reset for the ``m_dest_axi`` interface.
Only present when ``DMA_TYPE_DEST`` parameter is set to AXI-MM (0).
* - ``m_dest_axi``
- AXI3/AXI4 bus master
* - m_dest_axi
-
* - ``s_axis_aclk``
- Clock
* - s_axis_aclk
- The ``s_axis`` interface is synchronous to this clock.
Only present when ``DMA_TYPE_SRC`` parameter is set to AXI-Streaming
(1).
* - ``s_axis``
- AXI-streaming bus slave
-
Only present when ``DMA_TYPE_SRC`` parameter is set to AXI-Streaming
* - s_axis
- Only present when ``DMA_TYPE_SRC`` parameter is set to AXI-Streaming
(1).
* - ``m_axis_aclk``
- Clock
* - m_axis_aclk
- The ``m_axis`` interface is synchronous to this clock.
Only present when ``DMA_TYPE_DEST`` parameter is set to AXI-Streaming
(1).
* - ``m_axis``
- AXI-streaming bus master
* - m_axis
- Only present when ``DMA_TYPE_DEST`` parameter is set to AXI-Streaming
(1).
* - ``fifo_wr_clk``
- Clock
- The ``fifo_wr`` interface is synchronous to this clock.
* - fifo_wr_clk
- The fifo_wr interface is synchronous to this clock.
Only present when ``DMA_TYPE_SRC`` parameter is set to FIFO (2).
* - ``fifo_wr``
- FIFO write interface
-
Only present when ``DMA_TYPE_SRC`` parameter is set to FIFO (2).
* - ``fifo_rd_clk``
- Clock
* - fifo_wr
- Only present when ``DMA_TYPE_SRC`` parameter is set to FIFO (2).
* - fifo_rd_clk
- The ``fifo_rd`` interface is synchronous to this clock.
Only present when ``DMA_TYPE_DEST`` parameter is set to FIFO (2).
* - ``fifo_rd``
- FIFO read interface
* - fifo_rd
- Only present when ``DMA_TYPE_DEST`` parameter is set to FIFO (2).
* - ``dest_diag_level_bursts``
- Diagnostics interface
* - dest_diag_level_bursts
- Only present when ``ENABLE_DIAGNOSTICS_IF`` parameter is set.
Register Map

View File

@ -32,7 +32,6 @@ Configuration Parameters
--------------------------------------------------------------------------------
.. hdl-parameters::
:path: library/spi_engine/axi_spi_engine
* - ASYNC_SPI_CLK
- If set to 1 the ``s_axi_aclk`` and ``spi_clk`` clocks are assumed
@ -49,36 +48,28 @@ Configuration Parameters
Signal and Interface Pins
--------------------------------------------------------------------------------
.. list-table::
:widths: 10 25 65
:header-rows: 1
.. hdl-interfaces::
* - Name
- Type
- Description
* - ``s_axi_aclk``
- Clock
* - s_axi_aclk
- All ``s_axi`` signals and ``irq`` are synchronous to this clock.
* - ``s_axi_aresetn``
- Synchronous active-low reset
- Resets the internal state of the peripheral.
* - ``s_axi``
- AXI-Lite bus slave
- Memory-mapped AXI-lite bus that provides access to modules register map.
* - ``irq``
- Level-High Interrupt
- Interrupt output of the module. Is asserted when at least one of the
* - s_axi_aresetn
- Synchronous active-low reset.
Resets the internal state of the peripheral.
* - s_axi
- AXI-Lite bus slave.
Memory-mapped AXI-lite bus that provides access to modules register map.
* - irq
- Level-High Interrupt.
Interrupt output of the module. Is asserted when at least one of the
modules interrupt is pending and unmasked.
* - ``spi_clk``
- Clock
* - spi_clk
- All ``spi_engine_ctrl`` signals and ``spi_resetn`` are
synchronous to this clock.
* - ``spi_engine_ctrl``
- :ref:`spi_engine control-interface` slave
- SPI Engine Control stream that contains commands and data for the
* - spi_engine_ctrl
- :ref:`spi_engine control-interface` slave.
SPI Engine Control stream that contains commands and data for the
execution module.
* - ``spi_resetn``
- Output
* - spi_resetn
- This signal is asserted when the module is disabled through the ENABLE
register. Typically used as the reset for the SPI Engine modules
connected to these modules.

View File

@ -28,7 +28,6 @@ Configuration Parameters
--------------------------------------------------------------------------------
.. hdl-parameters::
:path: library/spi_engine/spi_engine_execution
* - NUM_OF_CS
- Number of chip-select signals for the SPI bus (min: 1, max: 8).
@ -47,30 +46,22 @@ Configuration Parameters
Signal and Interface Pins
--------------------------------------------------------------------------------
.. list-table::
:widths: 10 25 65
:header-rows: 1
.. hdl-interfaces::
* - Name
- Type
- Description
* - ``clk``
- Clock
* - clk
- All other signals are synchronous to this clock.
* - ``resetn``
- Synchronous active-low reset
* - resetn
- Resets the internal state machine of the core.
* - ``active``
- Output
* - active
- Indicates whether the peripheral is currently active and processing
commands.
* - ``ctrl``
- :ref:`spi_engine control-interface` slave
- SPI Engine Control stream that contains commands and data for the
* - ctrl
- :ref:`spi_engine control-interface` slave.
SPI Engine Control stream that contains commands and data for the
execution module.
* - ``spi``
- :ref:`spi_engine spi-bus-interface` master
- Low-level SPI bus interface that is controlled by peripheral.
* - spi
- :ref:`spi_engine spi-bus-interface` master.
Low-level SPI bus interface that is controlled by peripheral.
Theory of Operation
--------------------------------------------------------------------------------

View File

@ -49,28 +49,22 @@ Configuration Parameters
Signal and Interface Pins
--------------------------------------------------------------------------------
.. list-table::
:widths: 10 25 65
:header-rows: 1
.. hdl-interfaces::
* - Name
- Type
- Description
* - ``clk``
- Clock
* - clk
- A signals of the module are synchronous to this clock.
* - ``resetn``
- Synchronous active-low reset
- Resets the internal state of the module.
* - ``s0_ctrl``
- :ref:`spi_engine control-interface` slave
- Connects to the first control interface master
* - ``s1_ctrl``
- :ref:`spi_engine control-interface` slave
- Connects to the second control interface master
* - ``m_ctrl``
- :ref:`spi_engine control-interface` master
- Connects to the control interface slave
* - resetn
- Synchronous active-low reset.
Resets the internal state of the module.
* - s0_ctrl
- :ref:`spi_engine control-interface` slave.
Connects to the first control interface master.
* - s1_ctrl
- :ref:`spi_engine control-interface` slave.
Connects to the second control interface master.
* - m_ctrl
- :ref:`spi_engine control-interface` master.
Connects to the control interface slave.
Theory of Operation
--------------------------------------------------------------------------------

View File

@ -29,7 +29,6 @@ Configuration Parameters
--------------------------------------------------------------------------------
.. hdl-parameters::
:path: library/spi_engine/spi_engine_offload
* - ASYNC_SPI_CLK
- If set to 1 the ``ctrl_clk`` and ``spi_clk`` are assumed to be
@ -44,34 +43,26 @@ Configuration Parameters
Signal and Interface Pins
--------------------------------------------------------------------------------
.. list-table::
:widths: 10 25 65
:header-rows: 1
.. hdl-interfaces::
* - Name
- Type
- Description
* - ``ctrl_clk``
- Clock
* - ctrl_clk
- The ``spi_engine_offload_ctrl`` signals are synchronous to this clock.
* - ``spi_clk``
- Clock
* - spi_clk
- The ``spi_engine_ctrl`` signals, ``offload_sdi`` signals and
trigger are synchronous to this clock.
* - ``spi_resetn``
* - spi_resetn
- Synchronous active low reset
- Resets the internal state machine of the core.
* - ``trigger``
- Input
* - trigger
- When asserted the stored command and data stream is send out on the
``spi_engine_ctrl`` interface.
* - ``spi_engine_offload_ctrl``
- :ref:`spi_engine offload-control-interface` slave
- Control interface which allows to re-program the stored command and SDO
* - spi_engine_offload_ctrl
- :ref:`spi_engine offload-control-interface` slave.
Control interface which allows to re-program the stored command and SDO
data stream.
* - ``spi_engine_ctrl``
- :ref:`spi_engine control-interface` master
- SPI Engine Control stream that contains commands and data.
* - ``offload_sdi``
* - spi_engine_ctrl
- :ref:`spi_engine control-interface` master.
SPI Engine Control stream that contains commands and data.
* - offload_sdi
- Streaming AXI master
- Output stream of the received SPI data.
Output stream of the received SPI data.

View File

@ -5,6 +5,9 @@
IP Template
================================================================================
.. symbolator:: ../../../library/spi_engine/spi_engine_execution/spi_engine_execution.v
:caption: spi_engine_execution
Features
--------------------------------------------------------------------------------

View File

@ -1,9 +1,9 @@
sphinx
lxml
furo
wavedrom
sphinxcontrib-wavedrom
sphinxcontrib-mermaid
sphinxcontrib-bibtex
sphinxcontrib-svg2pdfconverter
furo
https://github.com/hdl/pyhdlparser/tarball/master
https://github.com/hdl/symbolator/tarball/master