Output Formats

Basic HTML Output

HTML is used to generate documentation which can be opened in any browser.

In the selected output directory, the following files will be created:

  • An HTML file for each Component, represent the unbound Component with a base address of 0.
  • An HTML file for each MemoryMap, with a table of Instances, their offsets and sizes.
  • A subdirectory for each MemoryMap, with a Component style HTML file for each Instance representing the bound Component with a start address determined by the MemoryMap.
  • CSS styles for all of the HTML

In this way, the directory serves as a package of documentation for the register map source. It can be moved as one big atomic thing.

All HTML files have table of contents sidebars to help navigation.

Basic VHDL Output

This output makes no assumptions about what the bus type is, and expects no support packages to be available. Words below encased in <angle brackets> are meant to represent a fill-in-the-blank of the name of that thing, so a tb_<REGISTERARRAY> would be tb_BUFFER for a RegisterArray named BUFFER.

Depending on the choice of names of things in the XML, it may be necessary to change the names of things to avoid either illegal characters or VHDL reserved words. Check the header comments of the generated VHDL files for information about changed elements.

Changed names indicate characters that were not legal VHDL, and will be different in all contexts, illegal characters will be replaced with _ characters.

Changed identifiers mean only that they cannot be bare words, which means they are only different in the context of something.identifier, such as registers in components or fields in registers. Changed identifiers will get an “_0” extension.

Types

  • subtype t_addr of integer
  • subtype t_busdata of std_logic_vector, component width wide
  • t_<REGISTER>
    • subtype of std_logic_vector, unsigned, or signed OR
    • record if the register has fields
  • record tb_<REGISTERARRAY> if the registerarray has multiple registers
  • array ta_<REGISTERARRAY> of tb_<REGISTERARRAY> or t_<REGISTER>
  • record t_<COMPONENT>_regfile to hold the entire register file

Constants

  • <REGISTER>_ADDR word offsets from 0 for freestanding registers
  • <REGISTER>_ADDR word offsets from array start in a registerarray
  • <REGISTERARRAY>_BASEADDR offsets the same way REGISTER_ADDR does
  • <REGISTERARRAY>_FRAMESIZE is the number of words in each array element
  • <REGISTERARRAY>_FRAMECOUNT is the number of FRAMESIZE element in the array
  • <REGISTERARRAY>_LASTADDR is the offset for the last word in the array
  • <REGISTER>_<FIELD>_<ENUM> is a value for field <REGISTER>.<FIELD>
  • RESET_t_<REGISTER> is the reset value constant for a t_<REGISTER>
  • RESET_ta_<REGISTERARRAY> is the reset value constant for a t_<REGISTERARRAY>
  • RESET_t_<COMPONENT>_REGFILE is the reset value for a t_<COMPONENT>_regfile

Subprograms

Addresses

GET_ADDR rips the appropriate number of LSBs to make a word address from the word address on the bus:

function GET_ADDR(address: std_logic_vector) return t_addr;
function GET_ADDR(address: unsigned) return t_addr;

Component

Component level subprograms manipulate the entire t_<COMPONENT>_regfile. For register files that will be implemented entirely on flip-flops this is probably viable; to use block RAM as part or all of the storage will require some special casing around these functions. Note that these functions are unconditional; read-enable and write-enable functions should be implemented by selectively calling or not calling them:

procedure UPDATE_REGFILE(
    dat: in t_busdata; byteen : in std_logic_vector;
    offset: in t_addr;
    variable reg: inout t_<COMPONENT>_regfile;
    success: out boolean);
procedure UPDATESIG_REGFILE(
    dat: in t_busdata; byteen : in std_logic_vector;
    offset: in t_addr;
    signal reg: inout t_<COMPONENT>_regfile;
    success: out boolean);
procedure READ_REGFILE(
    offset: in t_addr;
    reg: in t_<COMPONENT>_regfile;
    dat: out t_busdata;
    success: out boolean);

UPDATE_REGFILE and UPDATESIG_REGFILE will update a single register based on the address in offset. The new data will be taken from dat on the byte lanes selected by byteen, which should be 1/8 as long as dat. Use UPDATE_REGFILE if the register are stored in a variable, or UPDATESIG_REGFILE if they are stored in a variable. There probably aren’t circumstances that warrant the use of both in the same design. In either case, success is set true if the write targeted a writeable register or false if not.

READ_REG gets the data from a single register based on the address in offset and returns it in a proper format for the data bus. dat is set with the data that has been read and success is set true if the read targeted a readable register or false if not.

RegisterArray

RegisterArray programs manipulate registers inside of a RegisterArray similarly to those in a Component. They’re a bit of an odd duck in terms of high-level vs. low-level accesses. Primarily they exist to be called by the _REGFILE routines; user use of them is mostly limited to knocking out a section of the register map to be implemented separately on BRAMs.

For each registerarray in the design there are procedures:

procedure UPDATE_<registerarray>(
    dat: in t_busdata; byteen : in std_logic_vector;
    offset: in t_addr;
    variable ra: inout ta_<registerarray>;
    success: out boolean);
procedure UPDATESIG_<registerarray>(
    dat: in t_busdata; byteen : in std_logic_vector;
    offset: in t_addr;
    signal ra: inout ta_<registerarray>;
    success: out boolean);
procedure READ_registerarray(
    offset: in t_addr;
    ra: in ta_<registerarray>;
    dat: out t_busdata;
    success: out boolean);

For all these procedures the offset parameter is relative to the baseaddress of that registerarray, available as <REGISTERARRAY>_BASEADDR, not to the start of the component.

Register

The functions available for Registers are low-level access functions. These are usable directly by users either to supplement or entirely circumvent the generated register decoding functions. For each register there are subprograms:

function DAT_TO_<register>(dat: t_busdata) return t_<register>;
function <register>_TO_DAT(reg: t_<register>) return t_busdata;
procedure UPDATE_<register>(
    dat: in t_busdata; byteen: in std_logic_vector;
    variable reg: inout t_<register>);
procedure UPDATESIG_<register>(
    dat: in t_busdata; byteen: in std_logic_vector;
    signal reg: inout t_<register>);

DAT_TO_<REGISTER> turns the abstract data on the bus into the register data type, which may be a simple type like a signed, unsigned, or std_logic_vector, or may be a record of such types, in which case the bits will be translated to the appropriate fields. <REGISTER>_TO_DAT reverses this operation, filling unused bits with ‘0’. All fields are operated on, regardless of readOnly and writeOnly settings.

UPDATE_<REGISTER> and UPDATESIG_<REGISTER> update those bits of the register data specified by the byte enable mask. Bits where byteen=‘0’ are unaltered. Again, UPDATE_<REGISTER> is used if the register storage is a VHDL variable, and UPDATESIG_<REGISTER> if it is a signal. As these functions are made to be executed in response to bus writes, readOnly fields are ignored.

AXI4-Lite VHDL

The AXI4-Lite VHDL format generates component VHDL template files. These templates rely on the packages generated by the basic VHDL output, which must be generated separately.

The template includes boilerplate bus read and write procedures, along with reset logic, but obviously no logic for the actual implementation of functionality which must be added separately.

Warning

Files from this output are made to be modified. Do not do so in the creation directory where they can be accidentally overwritten by regenerating this output. Move them manually to a working directory so that they can be safely edited.

WISHBONE (Registered Termination)

The WISHBONE Registered Termination VHDL format generates component VHDL template files for a WISHBONE B4 bus. This takes advantage of the new, simpler registered feedback mechanism in the B4 specification to provide fast pipelined transactions with minimal logic. Only the immediate address is used, the CTI_I and BTI_I are not necessary. STALL_O is provided to demonstrate that it the mechanism is used, but is always deasserted.

Only data granularity of 8 bits is supported and undefined tagged data signals TGD_I, TGD_O, TDA_I, and TGC_I need to be explicitly added by the user.

Slaves repond with ACK_O for accesses to valid register locations and ERR_O for invalid locations.

The templates rely on the packages generated by the basic VHDL output, which must be generated separately.

The template includes boilerplate bus read and write procedures, along with reset logic, but obviously no logic for the actual implementation of functionality which must be added separately.

Warning

Files from this output are made to be modified. Do not do so in the creation directory where they can be accidentally overwritten by regenerating this output. Move them manually to a working directory so that they can be safely edited.

WISHBONE (Asynchronous Termination)

The WISHBONE Asynchronous Termination VHDL format generates component VHDL template files for a WISHBONE B4 bus. This is a simpler mechanism than the registered feedback termination, but will ultimately present maximum clock frequency limitations on the bus. As such, this implementation supports only classic cycles, it does not provide the LOCK_I or STALL_O signals. Additionally, only data granularity of 8 bits is supported and undefined tagged data signals TGD_I, TGD_O, TDA_I, and TGC_I need to be explicitly added by the user.

Slaves repond with ACK_O for accesses to valid register locations and ERR_O for invalid locations.

The templates rely on the packages generated by the basic VHDL output, which must be generated separately.

The template includes boilerplate bus read and write procedures, along with reset logic, but obviously no logic for the actual implementation of functionality which must be added separately.

Warning

Files from this output are made to be modified. Do not do so in the creation directory where they can be accidentally overwritten by regenerating this output. Move them manually to a working directory so that they can be safely edited.

Basic Python Output

This output makes a directory full of Python files that use the ctypes and bitfield libraries in order to create a memory-mapped structure equivalent to the register map.

This is directly useful with a register map that is connected directly into PC memory space, such as a PCI or VME card, but can also serve as a base template for the remotestruct library to work via an arbitrary transport layer.

Types

The Python outputs use the basic ctypes types of c_uint8, c_int32, and so forth to represent entire registers.

In order to create structured bitfields in registers, additional types are created with the naming convention _t_<REGISTER> using the bitfield.make_bf() function. These Bitfield objects allow attribute access to all of the fields as well, as well as dict-like methods like keys() and items(). There is also a base attribute which represents the entire register as its underlying unsigned integer. So if the component that the register is in has a data width of 32 bits, the bitfield base will be a c_uint32.

Enumeration Constants

Classes

For each component, a Python file is written defining the component as a subclass of ctypes.Structure. Fields representing gaps in the contiguous region will be named _dummy followed by a positional number.

RegisterArrays in Components are treated as arrays in standard ctypes fashion.

For each memorymap, a Python file is written defining the memorymap as a subclass of ctypes.Structure. Fields representing gaps in the contiguous region will be named _dummy followed by a positional number.

Instances in the memorymap will be the classes created by the component-level Python files, which are imported at the top of the memory map file.

Highland XML

The Highland XML output format is the same as the Highland XML input format. This means that the directory generated from the htixml format is usable as input for subsequent program invocations.

Because the placement algorithms are stable, there is no need to do this just to keep working with the same input files. However, sometimes you need to lock down register placements, particularly if they’ve already been released as a public API. You don’t want to go moving things around between revisions once the public has started writing code against them.

The regenerated XML has explicit values for all parameters including placement and sizing. This means that API compatibility is guaranteed if you use them as starting points to add additional functionality.

Text Tree Output

An extremely basic text output, primarily useful for debugging. Example output is:

component VMESPACE (size=256)
        The VMESPACE peripheral holds registers to the VMEbus. An array of 256 16bit VME registers will
        be implemented per described in the V280 manual.
        This is visible only to the internal bus.
        (0) MFR
                Highland ID
        (1) MODEL
                V280 Model ID
        (2) MODREV
                Hardware Revision
        (3) SERIAL
                Unit serial number
        (4) FIRWARE
                Programmed firmware
        (5) FREV
                Firmware revision
        (6) MCOUNT
                1KHz real-time counter
        (7) DASH
                Unit dash number
        (8) CALID
                Calibration table status
        (9) YCAL
                Calibration date: year
        (10) DCAL
                Calibration date: month/day
                Field DAY (writeOnly=None,format=bits,size=8,offset=0,readOnly=None)
                        Day (1-31)
                Field MONTH (writeOnly=None,format=bits,size=8,offset=8,readOnly=None)
                        Month (1-12)
        (12) ULED
                User LED control
        (16) MACRO
                Macro register
        RegisterArray MPARAM (writeOnly=False,count=4,offset=17,readOnly=False,size=4,framesize=1)
                Macro parameter registers
                (0) PARAMn
        RegisterArray STATUS (writeOnly=False,count=3,offset=24,readOnly=False,size=3,framesize=1)
                Current status of inputs
                (0) STATUSn
        RegisterArray RISE (writeOnly=False,count=3,offset=28,readOnly=False,size=3,framesize=1)
                Rise debounce time
                (0) RISEn
        RegisterArray FALL (writeOnly=False,count=3,offset=32,readOnly=False,size=3,framesize=1)
                Fall debouce time
                (0) FALLn
        RegisterArray BISTERROR (writeOnly=False,count=3,offset=36,readOnly=False,size=3,framesize=1)
                Error registers for BIST
                (0) BISTERRn
        RegisterArray BUFFER (writeOnly=False,count=128,offset=128,readOnly=False,size=128,framesize=1)
                Buffer registers
                (0) BUFFn