diff --git a/docs/appendix/bibliography.rst b/docs/appendix/bibliography.rst deleted file mode 100755 index 7aa7a7a8f..000000000 --- a/docs/appendix/bibliography.rst +++ /dev/null @@ -1,6 +0,0 @@ -Bibliography -====================================================== - -.. bibliography:: - :all: - diff --git a/docs/appendix/glossary.rst b/docs/appendix/glossary.rst deleted file mode 100644 index 9623d9fda..000000000 --- a/docs/appendix/glossary.rst +++ /dev/null @@ -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 diff --git a/docs/appendix/references.bib b/docs/appendix/references.bib deleted file mode 100755 index d3753068d..000000000 --- a/docs/appendix/references.bib +++ /dev/null @@ -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} -} diff --git a/docs/conf.py b/docs/conf.py index 2e4fac49f..12f56d3cd 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -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 diff --git a/docs/contributing/guidelines.rst b/docs/contributing/guidelines.rst index 1100a4fc4..23d03f2fd 100644 --- a/docs/contributing/guidelines.rst +++ b/docs/contributing/guidelines.rst @@ -6,7 +6,7 @@ A brief set-of-rules for the documentation. .. note:: The old wiki uses `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 `_ 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: + + * - + - + +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: diff --git a/docs/extensions/adi_hdl_parser.py b/docs/extensions/adi_hdl_parser.py index 78fea1ae3..252462a6c 100644 --- a/docs/extensions/adi_hdl_parser.py +++ b/docs/extensions/adi_hdl_parser.py @@ -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, diff --git a/docs/index.rst b/docs/index.rst index 4cdcfcc47..30d5f99e1 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 diff --git a/docs/library/axi_dmac/index.rst b/docs/library/axi_dmac/index.rst index a9e4e3bd3..163821bc8 100644 --- a/docs/library/axi_dmac/index.rst +++ b/docs/library/axi_dmac/index.rst @@ -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 diff --git a/docs/library/spi_engine/axi_spi_engine.rst b/docs/library/spi_engine/axi_spi_engine.rst index e558d890e..13ab419d4 100644 --- a/docs/library/spi_engine/axi_spi_engine.rst +++ b/docs/library/spi_engine/axi_spi_engine.rst @@ -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. diff --git a/docs/library/spi_engine/spi_engine_execution.rst b/docs/library/spi_engine/spi_engine_execution.rst index bd5177a17..89877c9d9 100644 --- a/docs/library/spi_engine/spi_engine_execution.rst +++ b/docs/library/spi_engine/spi_engine_execution.rst @@ -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 -------------------------------------------------------------------------------- diff --git a/docs/library/spi_engine/spi_engine_interconnect.rst b/docs/library/spi_engine/spi_engine_interconnect.rst index 5c615fd34..e6924c162 100644 --- a/docs/library/spi_engine/spi_engine_interconnect.rst +++ b/docs/library/spi_engine/spi_engine_interconnect.rst @@ -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 -------------------------------------------------------------------------------- diff --git a/docs/library/spi_engine/spi_engine_offload.rst b/docs/library/spi_engine/spi_engine_offload.rst index 4a754930f..3a161f92c 100644 --- a/docs/library/spi_engine/spi_engine_offload.rst +++ b/docs/library/spi_engine/spi_engine_offload.rst @@ -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. diff --git a/docs/library/template_ip/index.rst b/docs/library/template_ip/index.rst index 2c835ea71..323cf2e69 100644 --- a/docs/library/template_ip/index.rst +++ b/docs/library/template_ip/index.rst @@ -5,6 +5,9 @@ IP Template ================================================================================ +.. symbolator:: ../../../library/spi_engine/spi_engine_execution/spi_engine_execution.v + :caption: spi_engine_execution + Features -------------------------------------------------------------------------------- diff --git a/docs/requirements.txt b/docs/requirements.txt index 94f4c0fd3..e2d1d18b1 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -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