The synApps softGlue module (v2.5)


Table of Contents


Overview

The synApps softGlue module enables EPICS users and application developers to construct small, simple, digital electronic circuits, and to connect those circuits to field wiring, all by writing to EPICS PV's. Because the circuits and field connections are defined entirely by EPICS PV's, they can be autosaved and restored, saved as text files (for example, as BURT snapshot files), emailed from one user to another, etc. softGlue also provides safe (throttled) user control over how hardware interrupts are generated by field I/O signals, and how they are dispatched to cause EPICS processing.
The name softGlue is intended to suggest glue electronics implemented by software, where glue electronics means those little bits of digital circuitry needed to connect two or more larger pieces of digital electronics into a working whole.

softGlue does this by loading an IndustryPack FPGA-based digital I/O module with a predefined collection of circuit elements (logic gates, counters, flip-flops, etc.), whose inputs and outputs are connected to switches controlled by EPICS PV's. softGlue provides a user interface for controlling those switches, allowing inputs and outputs to be marked with user-specified names, and connecting or driving inputs and outputs according to those names.

Here's the underlying idea, schematically:

Requirements

To use softGlue, you must have the following hardware and software:

SoftGlue versions 2.1 and lower also require the EPICS calc module. Some of the databases, displays, and examples presume the availability of other synApps modules, such as calc, busy, and std, but these are not needed for any essential feature of softGlue.

You do not need to be able to program the IP-EP20x module. In the default implementation, the FPGA content is programmed automatically into the module at IOC-boot time, via the IP bus. A text file is included with softGlue for this purpose. softGlue attempts to load the FPGA on every IOC boot, but the load succeeds only on a cold boot. A warm boot leaves previously loaded content in place.

If you have a copy of Altera's "Quartus" software, you can load your own custom FPGA content into the module, and use softGlue to talk to it. softGlue was designed with this use in mind, though we don't yet have documentation on how it's done.

Capabilities

Here are a few examples of the sorts of things that can be accomplished with softGlue and EPICS:

Implemented circuit elements

In this version of softGlue, the FPGA is programmed with the following circuit elements:
Earlier versions of softGlue implented many components with both inverting and noninverting outputs. Beginning with 2.0, signal inversion is accomplished by appending '*' to a signal name, and this removes the need to implement inverted outputs. Unfortunately, this means that softGlue PV values saved from an earlier version of softGlue will not restore correctly in softGlue 2.x. The functionality of the circuit will certainly still be achievable, but signal names have changed, and the circuit will have to be re-engineered.

In addition to the above listed components, softGlue 2.x includes shift registers, up/down counters, and quadrature decoders in separate FPGA packages. Currently, we don't have the capability of loading more than one FPGA-content file (the IP-EP20x FPGA does not support this), but we can combine the standard softGlue FPGA content with any one add-on package, and load that. Thus, there's a clear path to standard softGlue plus application-specific FPGA content and support. softGlue databases and MEDM-display files are engineered to simplify the development of support for add-on packages.


Installation and deployment

softGlue is a synApps module, so if you've used any other synApps module, you probably already know how to install and deploy it. The important thing is that softGlue is pure support: you are not expected to run an IOC directly with it, but instead to draw from the module into your own IOC application.
Unlike most other synApps modules, however, softGlue publishes the text files needed to boot an IOC in its db directory (as an EPICS module really should, I suppose — most synApps modules are nonstandard in this respect), rather than in the softGlueApp/Db directory.

How to get the software

softGlue is available as part of synApps 5.5 and higher, as a tar file from the softGlue web page, or directly from the synApps subversion repository. To export version 2.2 from the repository, for example, run the following command:

svn export https://subversion.xray.aps.anl.gov/synApps/softGlue/tags/R2-2 softGlue-2-2

Building softGlue

Deploying softGlue to an IOC

To configure an EPICS IOC application to use softGlue, you must make modifications in the following directories, and then rebuild the application:

Configuring hardware

The IP-EP20x board must be configured to permit programming the FPGA via the IndustryPack bus, by moving the DIP jumper to "IP BUS". (This is the factory default setting.)

Configuring softGlue (editing softGlue.cmd)

User Callable Functions:


User's Manual

Most of the essential user-interface information — how to connect signals, what the display elements mean, etc. — is contained in the descriptions of the "User Menu" and "AND" sections below. The remaining sections are mostly for completeness, though some circuit elements do require further explanation, and the counter sections introduce new display elements for registers containing decimal numbers.

We're going to have a little trouble with the meanings of "input" and "output", because they imply a viewpoint, and because we're going to be taking three different viewpoints: those of EPICS records, circuit elements, and field-wiring connectors. Usually, in EPICS, we think of an output as something to which an EPICS record can write, but that definition would be awkward here, because it would eventually require us, for example, to refer to the output of an AND gate as an "input". You just can't discuss digital circuitry intelligibly from that viewpoint.

Therefore, in this documentation, "input" and "output" will normally be from the viewpoint of one of the circuit elements we'll be wiring. Field I/O will be an exception, because it's most conveniently discussed from the viewpoint of the field-wiring connector.

MEDM user interface


Add-on FPGA components

The following components are not in the standard softGlue package, but in add-on packages typically made to solve specific problems.

Saving and restoring circuits

softGlue circuits can be saved and restored using autosave, autosave's configMenu facility, BURT, or any channel access client that can read and write PV's. configMenu is particularly handy, because it's driven by EPICS PVs, and because it saves a time-stamped backup copy of every file it overwrites.

Whichever method you use, you may need to clear softGlue signal names before loading a circuit, because loading over an existing circuit could temporarily exceed the available number of signal names. (Alternatively, you could simply load twice, and be confident that the second load will succeed.)

Saving and restoring circuits with autosave's configMenu facility

If you have autosave R5-1 or higher, you can use configMenu to save and restore circuits. Here are the steps needed to implement a menu of softGlue circuits, and to give the user a GUI display for saving and restoring them. (In the following, SG is the name of this instance of configMenu. The files it loads and saves will be named "SG_<config Name>.cfg". For examples, the configMenu instance pictured above has files named "SG_clear.cfg", "SG_encoderTest.cfg", etc..)

  1. In the IOC's startup directory, create an autosave request file, which I'll call "SGMenu.req", with the following content:

    file configMenu.req P=$(P),CONFIG=$(CONFIG)
    file softGlue_settings.req P=$(P),H=$(H)

  2. Uncomment the following line in the IOC's copy of softGlue.cmd:

    dbLoadRecords("$(AUTOSAVE)/asApp/Db/configMenu.db","P=xxx:,CONFIG=SG")

  3. Add the following line to st.cmd:

    create_manual_set("SGMenu.req","P=xxx:,CONFIG=SG")

  4. Add an MEDM related-display entry to bring up the configMenu.adl display.

    label="SGMenu"
    name="configMenu.adl"
    args="P=xxx:,CONFIG=SG"

softGlue includes configMenu files (*.cfg) for standard example circuits in the iocBoot/iocSoftGlue directory. In actual use, these .cfg files would be placed in your application's iocBoot/iocxxx/autosave directory. For more information on configMenu, see the autosave documentation.

Saving and restoring circuits with BURT

The BURT request file softGlueApp/op/burt/softGlue.snap can be used to save all softGlue user modifiable PV's. For example, the following command saves the state of softGlue to the file myCircuit.snap.
burtrb -f softGlue.req -DPREFIX=xxx:softGlue -o myCircuit.snap
"-f softGlue.req"
specifies that the request file softGlue.req should be used to specify the EPICS PVs whose values are to be saved. This file contains lines like this: "PREFIX:AND-1_IN1_Signal", where "PREFIX" is to be replaced by text specific to your ioc.
"-DPREFIX=xxx:softGlue"
specifies that PREFIX is to be replaced by xxx:softGlue.
"-o myCircuit.snap"
specifies that the saved PV names and values are to be written to the snapshot file "myCircuit.snap".
No doubt your PREFIX will be different from mine, but it should be $(P)$(H) from your copy of softGlue.cmd, minus the trailing ':' from $(H). BURT needs the ':' to separate "PREFIX" from the rest of the PV names it parses. If you defined H without a trailing ':', you'll need to make some adjustment to satisfy BURT.

The following commands restore the circuit:

burtwb -f clearAll.snap
burtwb -f myCircuit.snap

The first command is often needed because there is a limit to the number of signal names that softGlue will accept. If you neglect to clear all signals before restoring a circuit, the allowed number of signal names might be exceeded during the restore, if new signal names are defined before old signal names are deleted. (Alternatively, you could simply run the second command twice.)

To restore example circuits included in the softGlue module, or to restore a snapshot file emailed to you by some other softGlue user, you will need to edit the snapshot file to change PV names such as "xxx:softGlue:AND-1_IN2_Signal" to PV names in your ioc, which might look like "1ida:softGlue:AND-1_IN2_Signal".


Example circuits

The following circuits have been tested and saved in BURT snapshot files, and as configMenu .cfg files, as described above (see Saving and Restoring Circuits). The snapshot files can be found in softGlueApp/op/burt; the .cfg files are in iocBoot/iocSoftGlue.

  1. Motor-pulse gate

    Positive-going pulses can be gated with an AND gate, by applying the signal to one input of the AND gate, and setting the other input to 0(1) to deny(allow) passage through the gate.

    Negative-going pulses can be gated with an OR gate, by applying the signal to one input of the OR gate, and setting the other input to 0(1) to allow(deny) passage through the gate.

  2. Gated scaler

    Files: softGlueApp/op/burt/gatedScaler.snap or iocBoot/iocSoftGlue/gatedScaler.cfg

    This circuit implements four counter channels, a time base to control counting time, an overall gate, and additional circuitry to control starting, stopping, and processing of the count-value records. Note that the scaler is controlled by a busy record from the softGlue convenience database, so that client software can discover when counting is finished in the standard EPICS way. See softGlueApp/op/burt/gatedScaler.txt for more details.

  3. Four independent start-time/stop-time pulses

    File: softGlueApp/op/burt/fourPulses.snap or iocBoot/iocSoftGlue/fourPulses.cfg

    This circuit produces four separate pulse signals, which start at specified start-delay times after (the falling edge of) an initial start pulse, and which last for specified pulse-length times. It uses four DnCntr's to implement the start-delay times, and four DivByN's to implement the pulse-length times. Times are specified as multiples of the (125 ns) clock period (PRESET for the DnCntr's; N for the DivByN's), and these numbers must be greater than or equal to 1. The pulse sequence starts on the falling edge of the signal BUF-1, written by a periodically scanned EPICS record (one of the softGlue convenience clocks). One spare signal name is available, however, so the pulse sequence could also be started by an external signal.

  4. Motor-pulse accel/decel gate

    Files: softGlueApp/op/burt/accelDecelGate.snap or iocBoot/iocSoftGlue/accelDecelGate.cfg
    (Non-softGlue support in softGlueApp/op/burt/accelDecelGate_transform.sav.)

    If you know the number of steps a stepper motor will move during its acceleration time, you can easily arrange to deliver motor pulses to some external circuit only while the motor is moving at constant speed. For a stepper motor controlled by the motor record, the number of acceleration/deceleration steps, Na, can be calculated with the following formula:

    where, VBAS, VELO, ACCL, and MRES are motorRecord fields.

    The number of constant-speed steps, Nc, is then

    where VALend and VALstart are the final and initial values of the motorRecord VAL field.

    The following circuit accepts negative-going motor pulses at input signal 1, gates out the first 11 (the value of DnCntr-1_PRESET), and from then on sends motor pulses to output pin 17 until a total of 31 (the value of DnCntr-2_PRESET) have been sent. The circuit is reset by writing "1!" (positive-going pulse) to the input of BUF-1.

    The circuit includes some diagnostics, and a mechanism for testing:

For more softGlue-circuit examples, see https://subversion.xray.aps.anl.gov/admin_bcdaext/softGlue_examples Currently, the following circuits are documented:


Field wiring

IP-EP201 (TTL)

Getting clean electrical signals from the IP-EP201 out to field wiring requires some attention to detail. The signals have short rise times (on the order of a few ns), and the IP-EP201 pinout places 48 of them on adjacent ribbon-cable conductors, with a single ground conductor at one end of the ribbon. This combination pretty much guarantees problems with crosstalk and ringing.

Firstly, sharp-edged signals produce significant crosstalk between conductors, because the magnetic fields generated by signal currents vary rapidly enough during changes of state to induce significant voltages in nearby conductors. There is also the possibility of crosstalk from the fact that return currents of all signals share a single ground conductor. The shared-ground contribution is small, compared to the magnetic-field-induced contribution, but it could be significant in long (tens of feet) ribbon cables.

Secondly, sharp-edged signals require transmission-line termination to damp reflections at impedance mismatches. Otherwise downstream electronics will see ringing, as current sloshes back and forth through the cable, which can (if it exceeds the TTL noise margin) make each transition look like two or more. But the IP-EP201 has no termination, and its pinout results in 48 coupled transmissions lines, for which effective termination is probably not possible.

Nevertheless, it's possible to get clean signals to field wiring using the following strategy:

  1. Interface the single 50-pin ribbon header to two 50-conductor twisted-pair cables, so that each signal is paired with a ground line, and all ground lines are connected to pin 50. The characteristic impedance of this configuration is around 100 Ohms for most ribbon cables.
  2. Terminate each output signal with a series resistor whose value matches the characteristic impedance.
Series termination does three very nice things for us:
  1. It permits the IP-EP201 outputs to drive the transmission line. The IP-EP201 outputs can only sink or source 24 mA -- not enough to drive a 50-Ohm load to TTL levels, so parallel termination (100-Ohm resistors to ground at each end of the ribbon) would require a buffer. Even a single 100-Ohm termination resistor to ground would reduce the noise margin considerably.
  2. It damps reflections returned from the cable end. (This only works for outputs, which are low impedance. Inputs are high impedance, and series termination cannot reduce the impedance.)
  3. It acts as a low-pass filter to soften the signal edges, effectively reducing magnetic crosstalk to values well below the TTL noise margin.

The APS BCDA group has produced three circuit boards that implement this strategy:

See the BCDA Custom Hardware web page for more information. The boards are connected together as in the diagram below.

The BC-092 plugs directly into the IP carrier's 50-pin ribbon connector. (Take care: the connector is not polarized. It's your job to plug it in the right way.) A ribbon cable goes from the BC-092 to the H1 ribbon header on the BC-020 board. (The H2 header is not used for softGlue.) The BC-091 daughter board is plugged into the BC-020, and the I/O direction is set, for groups of eight bits, with DIP jumpers on the BC-091.

The BC-020 LEMO interface. With the EP-201 board, only the first 24 LEMO connectors are used. The BC-091 daughter board is plugged into the white headers at the center of the board.

A BC-020 board with the BC-091 daughter board installed. Note the DIP jumpers near the center of the daughter board. With this setting, I/O pins 1-16 are inputs (jumper on), and pins 17-24 are outputs.

Closeup of the BC-092 board, with SIP resistor packs installed. Normally, 100-Ohm resistors are used, because this is the nominal impedance of many ribbon cables. Although the terminating resistors are useful only for outputs, they are usually installed for all I/O pins.

Closeup showing how to connect the BC-092 to the TEWS TVME-200 IP carrier.

Closeup of the other side of the BC-092 board. The ribbon connector closest to the IP carrier (the J2 connector) handles I/O pins 1-24.

IP-EP202 (RS-485/422)

This section not yet written.

IP-EP241 (lvds)

This section not yet written.


Custom Interrupt Handlers

softGlue's normal interrupt-response mechanism allows you to specify the execution of an EPICS output link, which will write to and possibly process a specified EPICS record, whenever an enabled interrupt occurs. This mechanism is unreliable for interrupts that are spaced in time by less than a few milliseconds, because the EPICS processing is dispatched through message queues, and requires several task switches before the target record gets processed.

For interrupts that may occur more closly spaced in time, you can write a custom interrupt-handler routine, and tell softGlue to call it at interrupt level whenever an enabled interrupt occurs. There is an example in the softGlueApp/src directory: sampleCustomInterruptHandler.c, which handles the following application requirement:

When an enabled interrupt occurs on a specified bit of a specified IP_EP20x board, read a number from an array, write that number to the N register of a specified softGlue DivByN component on that same IP_EP20x board, and increment the array index for the next read.

sampleCustomInterruptHandler.c contains two functions:

sampleCustomInterruptPrepare()
This function gathers some information for use by sampleCustomInterruptRoutine(), and tells softGlue to call sampleCustomInterruptRoutine() from its interrupt-service routine when a specified interrupt occurs. The interrupt is specified by carrier and slot, which specify the IP_EP20x board; sopcAddress, which specifies the address of one of three I/O registers on the board; and mask, which specifies one or more bits of the specified I/O register.
sampleCustomInterruptRoutine()
This function executes at interrupt level, reads a number from an array, writes that number to the N register whose VME addresses were calculated by sampleCustomInterruptPrepare(), and increments the array index.

Other files in softGlueApp/src that help implement sampleCustomInterruptHandler are Makefile, which builds it, and softGlueSupport.dbd, which contains the line registrar(sampleCustomInterruptRegistrar).


Implementation

FPGA-content files

This version of softGlue contains four FPGA-content files, only one of which can be loaded at a time.

SoftGlue_2_2.hex
This file contains all standard softGlue components.
SoftGlue_2_2_0_Octupole_0_0.hex
This file contains everything in SoftGlue_2_2.hex, plus two 32-bit shift registers.
SoftGlue_2_2_Encoder.hex
This file contains everything in SoftGlue_2_2.hex, plus two 32-bit up/down counters, plus two quadrature decoders.
SoftGlue_2_2_1ID_Vgate_0_1.hex
This file contains everything in SoftGlue_2_2.hex, plus two 32-bit up/down counters.

Database files

softGlue_FPGAContent.substitutions
This substitutions file is run through msi at build time to produce the database file softGlue_FPGAContent.db. The database file loads records matching most of the FPGA content that is loaded at cold-boot time from SoftGlue_2_2.hex.

softGlue_FPGAContent_octupole.substitutions
This substitutions file is run through msi at build time to produce the database file softGlue_FPGAContent_octupole.db. The database file loads records for the two 32-bit shift registers in SoftGlue_2_2_Octupole_0_0.hex.

softGlue_FPGAContent_Encoder.substitutions
This substitutions file is run through msi at build time to produce the database file softGlue_FPGAContent_Encoder.db. The database file loads records for the two 32-bit up/down counters in SoftGlue_2_2_Encoder.hex.

softGlue_FPGAContent_s1ID_Vgate.substitutions
This substitutions file is run through msi at build time to produce the database file softGlue_FPGAContent_s1ID_Vgate.db. The database file loads records for the two 32-bit up/down counters in SoftGlue_2_2_1ID_Vgate_0_1.hex.

softGlue_FPGAInt.substitutions
This substitutions file is run through msi at build time to produce the database file softGlue_FPGAInt.db. The database file loads records matching the field-I/O register components loaded into the FPGA. These components control the field I/O registers which softGlue uses to connect with external wiring. The file also loads records by which the user can control the period at which the driver's poller thread wakes up to read any I/O bits that have not been enabled to generate interrupts.

softGlue_Input.db
softGlue_Output.db
These databases each support a single softGlue circuit-element I/O bit.

softGlue_FieldInput.db
softGlue_FieldOutput.db
These databases each support a single field I/O bit.

softGlue_InRegister.db
This database supports reads from a 16-bit register. (Currently, no softGlue circuit element uses this database.)

softGlue_InRegister32.db
This database supports reads from a 32-bit register, implemented in the FPGA as two 16-bit registers.

softGlue_IntBit.db
This database supports a single input bit, with an interrupt-driven bi record to read the bit value, and a forward linked bo record to write that value to some user specified EPICS PV.

softGlue_IntEdge.db
This database controls the interrupt-enable mask for a single input bit.

softGlue_PollTime.db
This database controls the polling period for a field I/O register set. This period is the rate at which I/O bits that do not generate interrupts are read.

softGlue_Register.db
This database supports writes to a 16-bit register. (Currently, no softGlue circuit element uses this database.)

softGlue_Register32.db
This database supports writes to a 32-bit register, such as the "N" value for a divide-by-N circuit element.

softGlue_SignalShow.db
This database implements part of softGlue's mechanism for showing users which signals are connected together. When a user presses a signal's "= button", the signal's name is written to a PV in this database, against which PV all softGlue signals compare their own signal names, to determine whether or not to display their "connected" boxes.

softGlue_convenience.db
This database contains two busy records by which softGlue can signal completion to EPICS, two software pulse generators, and two software clock generators.

softGlue_FPGAContentDev.substitutions
softGlue_FPGAIntDev.substitutions
These files are not used in a standard deployment of softGlue, but are provided for developers and deployers of custom FPGA-content. They are essentially the same as softGlue_FPGAContent.substitutions, and softGlue_FPGAInt.substitutions, but are intended to be used directly in dbLoadTemplate() commands, rather than run through msi to produce partially resolved databases loaded by dbLoadRecords().

Autosave-request files

softGlue_FPGAContent_settings.req
softGlue_FPGAContent_octupole_settings.req
softGlue_FPGAContent_Encoder_settings.req
softGlue_FPGAContent_s1ID_Vgate_settings.req
softGlue_FPGAInt_settings.req
softGlue_SignalShow_settings.req
softGlue_convenience_settings.req
These autosave request files correspond with similarly named database or substitutions files, and take the same macro definitions.

softGlue_settings.req
This autosave-request file includes softGlue_SignalShow_settings.req, softGlue_FPGAContent_settings.req, softGlue_FPGAInt_settings.req, and softGlue_convenience_settings.req. For standard softGlue, this is the only autosave-request file an IOC needs.

Display files (MEDM, CSS-BOY, and caQtDM)

There are too many display files to describe individually, and many are similar, so I'll just describe classes of display files, and the overall implementation strategy. Displays whose names begin with "softGlue_" support individual circuit elements. Displays whose names are of the form "softGlueXxx" (no underscore after "softGlue") support collections of circuit elements, either by implementing menus for calling up other displays, or by including several "softGlue_" displays. ("Include", in this context, means specified as a "Composite File", with macro arguments, in the definition of an MEDM grouped item, or specified as a "linkgroup" in CSS-BOY.)

In the rest of this display-file documentation, I'll give MEDM examples. For CSS-BOY examples, just substitute ".opi" for ".adl". For caQtDM, substitute ".ui".

The display of a softGlue circuit element is built in layers, from instances of softGlue_Input.adl and softGlue_Output.adl, which are included in softGlue_<element name>_bare.adl, which in turn is included in one of the user displays (for example, softGlueAll.adl, softGlue_AND.adl, etc.).

softGlueMenu.adl
softGlueTop.adl
softGlueMenu.adl contains related-display menus for everything in softGlue. softGlueTop.adl is an example of how softGlueMenu.adl can be called up.
softGlue_Input.adl
softGlue_Output.adl
These displays support a single 16-bit register component (see "Driver", below) in the FPGA, and most softGlue circuit-element displays include several instances of these displays. For example, softGlue_AND_bare.adl includes two instances of softGlue_Input.adl, and one instance of softGlue_Output.adl.
softGlue_*.adl
softGlue_*_bare.adl, where * is one of AND, BUFFER, DEMUX2, DFF, DivByN, DnCntr, MUX2, MUX4, OR, Shift32, UpCntr, XOR
These files each support a single circuit element, such as an AND gate. The "_bare.adl" displays are intended to be included in some other display.
softGlue_Field*.adl
softGlue_Field*_bare.adl, where * is one of FieldInput, FieldOutput, IntBit. The "_bare.adl" displays are intended to be included in some other display.
These files support a single field-I/O bit, or the interrupt control and dispatch records associated with a field-I/O bit.

Driver

softGlue's driver implements four asyn ports to connect EPICS records with registers implemented in the IP-EP20x module's FPGA. Three ports connect with "fieldIO_registerSet" components, which provide comprehensive control over digital I/O bits implemented in the module, including data direction (i.e., read or write), interrupt enable, and status. The fourth asyn port connects with "single 16-bit register" components, with which all softGlue signal connections are implemented.

The following is copied from drvIP-EP201.c:

    This driver cooperates with specific FPGA firmware loaded into the Acromag
    IP-EP201 (and probably other IP-EP200-series modules).  The loaded FPGA
    firmware includes Eric Norum's IndustryPack Bridge, which is an interface
    between the IndustryPack bus and the Altera FPGA's Avalon bus.  The
    IndustryPack Bridge does not define anything we can write to in the FPGA. 
    It's job is to support additional firmware loaded into the FPGA.  The
    additional firmware defines registers that we can read and write, and it can
    take one of the two forms (sopc components) supported by this driver:

        1) fieldIO_registerSet component

           A set of seven 16-bit registers defined by 'fieldIO_registerSet'
           below.  This register set provides bit-level I/O direction and
           interrupt-generation support, and is intended primarily to
           implement field I/O registers.

        2) single 16-bit register component

           a single 16-bit register, which has no interrupt service or bit-level
           I/O direction.  This type of sopc component is just a plain 16-bit
           register, which can be written to or read.  This driver doesn't know
           or care what the register might be connected to inside the FPGA.

    Each fieldIO_registerSet component must be initialized by a separate call to
    initIP_EP201(), because the component's sopc address must be specified at
    init time, so that the interrupt-service routine associated with the
    component can use the sopc address.  Currently, each call to initIP_EP201()
    defines a new asyn port, connects an interrupt-service routine, creates a
    message queue, and launches a thread.

    Single 16-bit register components, on the other hand, need not have their
    sopc addresses known at init time, because they are not associated with an
    interrupt service routine.  As a consequence, many such single-register
    components can be served by a single asyn port.  Users of this port must
    specify the sopc address of the register they want to read or write in
    their asynUser structure. Records do this by including the address in the
    definition of the record's OUT or INP field.  For example, the ADDR macro in
    the following field definition should be set to the register's sopc address:
    field(OUT,"@asynMask($(PORT),$(ADDR),0x2f)")

    The addressing of sopc components requires some explanation.  When a
    component is loaded into the FPGA, it is given an sopc address, which is a
    number in one of two regions of the Avalon address space.  These regions of
    Avalon memory space are mapped by the IndustryPack Bridge to specific ranges
    of the IndustryPack module's IO and MEM spaces.  The IO and MEM spaces, in
    turn, are mapped by the IndustryPack carrier, and by the ipac-module
    software, to corresponding ranges in a VME address space.  The lowest
    address in the IndustryPack module's IO space is mapped to the VME A16
    address given by ipmBaseAddr(carrier, slot, ipac_addrIO), which I'll call
    IOBASE in the following table.  The lowest address in the IndustryPack
    module's MEM space is mapped to the VME A32 address given by
    ipmBaseAddr(carrier, slot, ipac_addrMem), which I'll call MEMBASE in the
    following table.  (The module's MEM space could also have been mapped to the
    VME A24 space.  This code doesn't know or care, because it just gets the VME
    address by making a function call to code provided by the ipac module.)
    
    Note that IOBASE and MEMBASE depend on the IndustryPack carrier and slot
    into which the IP-EP200 module has been placed.

    Avalon_address | IP_space  IP_address  | VME_space   VME_address
    (sopc address) |                       |                 
    ---------------|-----------------------|-----------------------------
    0x000000       | IO        0x000000    | A16         IOBASE+0x000000     
    ...            | IO        ...         | A16         ...             
    0x00007f       | IO        0x00007f    | A16         IOBASE+0x00007f     
                   |                       |                                        
    0x800000       | MEM       0x000000    | A32         MEMBASE+0x000000
    ...            | MEM       ...         | A32         ...
    0xffffff       | MEM       0x7fffff    | A32         MEMBASE+0x7fffff
    
    Thus, if a component is created with the sopc address 0x000010, it can be
    accessed at the IO-space address 0x000010, which is mapped to the VME
    address IOBASE+0x000010.  If a component is created with the sopc address
    0x800003, it can be accessed at MEM-space address 0x000003, which is
    mapped to the VME address MEMBASE+0x000003.

    Note that users of this code are not expected to know anything about this
    address-mapping business.  The only address users ever specify is the sopc
    address, exactly as it was specified to Quartus.

		

Device support

softGlue uses standard asyn device support for everything except signal names, which are handled by devAsynSoftGlue.c. The driver supports asynInt32 and asynUInt32Digital interfaces; devAsynSoftGlue.c uses asynUInt32Digital.

devAsynSoftGlue.c maintains lists of signal names and associates each signal name with one of 15 bus lines implemented in the FPGA. When a new signal name is encountered, it is assigned to an unused bus line (or ignored if there are no unused bus lines). The bus line number is written to a register, in the FPGA, which controls a multiplexer (for input signals) or demultiplexer (for output signals).

If an input signal name ends with '*', a register bit is set that causes the output of the multiplexer to be routed through an inverter before being connected to the circuit element. If an input signal is numeric, it is assigned to multiplexer address 0, which is driven not by a bus line, but by a register bit set according to the numeric value. (If '*' is appended to a numeric signal, it's ignored.)

Field I/O

Field inputs and outputs are supported by two independent sets of binary input and output records:

softGlue-supported records
These records are part of a database that also includes signal-wiring fields (the softGlue_FPGAContent.db database); they are connected to hardware via softGlue's asyn port (the port initialized by the function initIP_EP201SingleRegisterPort()), and no interrupt support is provided for them. They are polled at a rate determined by the READ PERIOD menu on the softGlueMenu.adl display.
non-softGlue-supported records
These records are loaded separately from the records described above (they are loaded by the softGlue_FPGAInt.db database); they are connected to hardware via the asyn port initialized by the function initIP_EP201(), and they can be interrupt driven. They are also polled periodically. The polling period's initial value is specified as an argument to initIP_EP201(), and it can be modified by the user via the POLL TIME (MS) text entry on softGlueFieldIO*.adl displays.

FPGA content

IndustryPack bus interface

All communication between EPICS and the FPGA goes through Eric Norum's IP-bus interface, which is described in IndustryPackBridge.html.

Single-register component

Most of softGlue is implemented with single-register FPGA components connecting to standard digital circuitry, such as AND gates, counters, etc., through interface circuitry of the following three types:

Input
An input is essentially a 16-input multiplexer controlled by a register that softGlue can write to and read from. Inputs 1-15 of all input multiplexers are connected together to form a 15-line bus, so that all inputs with the same multiplexer address are connected together.

Input 0 of the multiplexer is special: it connects to the "U" bit of the signal's control register, instead of to a bus line, and is the means by which softGlue implements direct user control of the signal value. When the user writes "0" or "1" as a signal name, softGlue sets the multiplexer address to zero, and sets the "U" bit to 0 or 1.

A second register bit, "N", controls whether or not the multiplexer output is routed through an inverter before connecting to the payload digital circuit element input; this bit is the means by which softGlue implements names like "reset*", which connects the input to an inverted copy of the signal, "reset". The invert bit could be, but currently is not, used with the "U" bit.

bit:151413121110 9 8 7 6 5 4 3 2 1 0
function:                  NRUA3A2A1A0

where

Ninvert-signal bit
Rread bit
Uuser-write bit
Anbus-line address bit

Output
An output is a signal routed via a demultiplexer to any of 15 bus lines. No connection is made to the demultiplexer output selected by the address 0; this address is used to implement unconnected output signals.

bit:151413121110 9 8 7 6 5 4 3 2 1 0
function:                    R  A3A2A1A0

where R and An are as defined above for the input register.

16-bit register
integer value written by EPICS to a parameter register with a fixed connection to a specific device instance. softGlue uses two 16-bit registers to implement the 32-bit up counter.

Field I/O register set component ("IP_EP20x")

This SOPC component supports 16 bits of field I/O
Registers
Address OffsetFunctionDescriptionRead/Write
0Control/StatusField-I/O direction, IRQ statusRead/Write
1Field I/O Write Data OR Diff/Dir registerWrite Field I/O or differential/direction register, depending on the FPGA content and how "DIFF_DIR" is defined in drvIP_EP201.cRead/Write
2Field I/O Read DataRead Field I/O ONLY when dir = 0Read
3Rising IRQ Status BitsWhich Bits are causing interrupt from field I/O on transition to 1Read/Write*
4Rising IRQ Interrupt-Enable BitsWhich Rising edge bits have IRQ EnabledRead/Write
5Falling IRQ Status BitsWhich bits are causing interrupt from field I/O on transition to 0Read/Write*
6Falling IRQ Interrupt-enable bitsWhich bits have falling IRQ enabledRead/Write
* A write to this register clears interrupts for nonzero bits. For example, after servicing a rising-edge interrupt from bit 0, the interrupt-service routine writes 0x01 to register 3 before re-enabling interrupts.
Control/Status-register bits
BitFunctionValueDescription
0Field I/O Direction Lower 8-Bits0=Input, 1=OutputSets I/O direction for the lower 8 field-I/O bits (single-ended signals only)
1 0 
2 0 
3 0 
4 0 
5Falling Edge IRQ Present1=PresentFalling Edge interrupt from bits 0-7 sets bit to 1
6Rising Edge IRQ Present1=PresentRising Edge interrupt from bits 0-7 sets bit to 1
7Lower 8-bits IRQ Present1=PresentInterrupt from bits 0-7 sets bit to 1
8Field I/O Direction Upper 8-Bits0=Input, 1=OutputSets I/O direction for the upper 8 field-I/O bits (single-ended signals only)
9 0 
10 0 
11 0 
12 0 
13Falling Edge IRQ Present Upper 8-Bits1=PresentFalling Edge interrupt from bits 8-15 sets bit to 1
14Rising Edge IRQ Present Upper 8-Bits1=PresentRising Edge interrupt from bits 8-15 sets bit to 1
15Upper 8-bits IRQ Present1=PresentInterrupt from bits 8-15 sets bit to 1
Diff/Dir-register bits
BitFunctionValueDescription
0Field I/O Direction Bit 00=Input, 1=OutputSets I/O direction for differential signals only
1Field I/O Direction Bit 10=Input, 1=OutputSets I/O direction for differential signals only
2Field I/O Direction Bit 20=Input, 1=OutputSets I/O direction for differential signals only
3Field I/O Direction Bit 30=Input, 1=OutputSets I/O direction for differential signals only
4Field I/O Direction Bit 40=Input, 1=OutputSets I/O direction for differential signals only
5Field I/O Direction Bit 50=Input, 1=OutputSets I/O direction for differential signals only
6Differential1=lower eight bits represent four differential signalsSee Diff/Dir note below
7Differential1=upper eight bits represent four differential signalsSee Diff/Dir note below
8 0 
9 0 
10 0 
11 0 
12 0 
13 0 
14 0 
15 0 

Diff/Dir note

Field-I/O data direction for IP_EP200-series modules is awkward and unfortunate, and is different for the different module types. The module types differ in which I/O bits are single ended and which are differential. Bit numbering can be a little confusing in this context, because two single ended signals from one module type use the same pins as a single differential signal from another module type. In this documentation, I'll just talk about field I/O connector pins, which are numbered 1-48, and which are the same for all module types.

IP_EP201
pins 1-48 are single ended.
IP_EP202 & IP_EP204
pins 1-48 are differential. The software acts like it's driving only odd numbered pins, because the even numbered pins are their differential pairs.
IP_EP203
pins 1-24 are single ended, pins 25-48 are differential. For differential pins, the software acts like it's driving only odd numbered pins, because the even numbered pins are their differential pairs.

For single ended pins, data direction is controlled by the Control/Status register of a "Field I/O register set" component. Each component controls 16 I/O pins. Bit 0 of Control/Status controls the direction of the lower eight I/O pins, bit 8 controls the direction of the upper eight pins.

For differential pins, data direction is controlled by bits 0-5 of the Diff/Dir register of the first (lowest SOPC address) "Field I/O register set" component.

FPGA content must be told which pins are single ended and which are differential. Bits 6-7 of the Diff/Dir register of a "Field I/O register set" component are used for this purpose. If bit 6 is 1, the lower eight I/O pins are differential. If bit 7 is 1, the upper eight I/O pins are differential.

Miscellaneous notes

The following notes have not been integrated into the documentation yet. They are included for completeness.



------------------------------------------------------------------------------
Deployment considerations

We need to ensure that the software agrees with the FPGA programming.  Software
dependence on FPGA content is of three kinds:

1) Dependence on the register set with which SOPC components are implemented. There are two
   different register sets currently in use: Marty Smith's original register set (called
   'fieldIO_registerSet' in comments within drvIP_EP201.c), and Kurt Goetze's register set (called
   'single 16-bit register' — a misnomer, because there are several registers in the component, but
   thus far only one register is used.) This dependence is restricted to the driver code,
   drvIP_EP201.c.

2) Dependence on the user circuits attached to 'single 16-bit register' SOPC components.  For
   example, the version 2.0 implementation of softGlue has several AND gates, several OR
   gates, some counters, etc., controlled by 'single 16-bit register' components.

   This dependence is restricted to the database, autosave-request file, and MEDM displays, which
   should have an analog for each 'single 16-bit register' component, and which should know which
   component address corresponds with which user circuit, and with which part of the user circuit.
   For example, the inverting output of AND gate #1 is associated by address with a 'single
   16-bit register' component.

3) Dependence on field I/O direction settings.  In softGlue 2.x, field I/O direction is not
adjustable by the user, but is fixed at boot time.  All databases and MEDM-display files are
compatible with any choice of field I/O direction settings, though MEDM displays don't give
the user any information about which bits are inputs and which are outputs.

Currently, the only strategy in use for ensuring that EPICS support agrees with FPGA content is the
inclusion of FPGA content with softGlue.  Deployers are expected to copy files from
softGlue/iocBoot/iocSoftGlue for initial deployment, and to copy them again for any version
upgrades, or else to take responsibility themselves for agreement between software and firmware.

------------------------------------------------------------------------------
Programming the FPGA via the IP bus.

The IP-EP20x board has to be prepared for this by moving the DIP jumper to
"IP BUS".  (This is the factory default setting.)

The hex file to be loaded is included in the softGlueApp/Db directory.
It was prepared as follows, in Quartus, according to an email from Marty Smith:

1. Under programming type select the Hexadecimal file format for Intel
2. Select your file name
3. Add your .sof file
4. Select the sof file and hit the properties button
5. Select the compression box
6. Make sure that you have selected 1-bit Passive Serial above for the mode
7. Select the options button under programming file type
    make sure that you have a start address of 0x0 and that the count up
    radio button is selected
8. Generate your file

Credits

The essential enabling work underlying softGlue is Eric Norum's IndustryPack Bridge. David Kline engineered a proof-of-principle implementation, working from another of Eric's bus-interface solutions, for a non-VME architecture. Marty Smith wrote a driver to talk to custom FPGA content interfaced to Eric's IndustryPack Bridge. Kurt Goetze and Marty Smith implemented the FPGA content included with softGlue, and Tim Mooney extended Marty's driver and wrote the EPICS application.
Suggestions and Comments to:
Tim Mooney : ([email protected])