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
parent
ef9c98f9b9
commit
83d2bf9603
|
@ -1,6 +0,0 @@
|
|||
Bibliography
|
||||
======================================================
|
||||
|
||||
.. bibliography::
|
||||
:all:
|
||||
|
|
@ -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
|
|
@ -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}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
IP Template
|
||||
================================================================================
|
||||
|
||||
.. symbolator:: ../../../library/spi_engine/spi_engine_execution/spi_engine_execution.v
|
||||
:caption: spi_engine_execution
|
||||
|
||||
Features
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue